Prechádzať zdrojové kódy

🎨 优化TV导航

快乐的梦鱼 4 týždňov pred
rodič
commit
a7d3c83cd1
7 zmenil súbory, kde vykonal 99 pridanie a 3 odobranie
  1. 7 0
      env.d.ts
  2. 10 2
      pack/manifest.json
  3. 7 0
      package-lock.json
  4. 1 0
      package.json
  5. 4 1
      src/App.vue
  6. 68 0
      src/composeable/TvFocusImprovement.ts
  7. 2 0
      src/main.ts

+ 7 - 0
env.d.ts

@@ -1 +1,8 @@
 /// <reference types="vite/client" />
+
+declare const plus: any;
+declare module 'spatial-navigation-js';
+
+declare interface Window {
+  plus: any;
+}

+ 10 - 2
pack/manifest.json

@@ -80,13 +80,21 @@
         "NativeObj" : {
             "description" : "原生对象"
         },
-        "VideoPlayer" : {}
+        "VideoPlayer" : {},
+        "Webview-x5" : {}
     },
     "plus" : {
         "splashscreen" : {
             "autoclose" : true, /*是否自动关闭程序启动界面,true表示应用加载应用入口页面后自动关闭;false则需调plus.navigator.closeSplashscreen()关闭*/
             "waiting" : true /*是否在程序启动界面显示等待雪花,true表示显示,false表示不显示。*/
         },
+        "webView" : {
+            "x5" : {
+                "timeOut" : 3000,
+                "showTipsWithoutWifi" : true,
+                "allowDownloadWithoutWiFi" : false
+            }
+        },
         "popGesture" : "close", /*设置应用默认侧滑返回关闭Webview窗口,"none"为无侧滑返回功能,"hide"为侧滑隐藏Webview窗口。参考http://ask.dcloud.net.cn/article/102*/
         "runmode" : "normal", /*应用的首次启动运行模式,可取liberate或normal,liberate模式在第一次启动时将解压应用资源(Android平台File API才可正常访问_www目录)*/
         "signature" : "Sk9JTiBVUyBtYWlsdG86aHIyMDEzQGRjbG91ZC5pbw==", /*可选,保留给应用签名,暂不使用*/
@@ -115,7 +123,7 @@
                     "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
                     "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>"
                 ],
-                "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a" ],
                 "targetSdkVersion" : 25,
                 "minSdkVersion" : 23
             },

+ 7 - 0
package-lock.json

@@ -21,6 +21,7 @@
         "commander": "^14.0.0",
         "md5": "^2.3.0",
         "pinia": "^3.0.3",
+        "spatial-navigation-js": "^1.0.0",
         "sweetalert2": "^11.22.4",
         "three": "^0.178.0",
         "vue": "^3.5.17",
@@ -6689,6 +6690,12 @@
         "source-map": "^0.6.0"
       }
     },
+    "node_modules/spatial-navigation-js": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/spatial-navigation-js/-/spatial-navigation-js-1.0.0.tgz",
+      "integrity": "sha512-RZ0/q7LCL/x4Hz8oUEwkkBIOx4YZt6Nn6o1YhXm6bVDjxZykJQ2tDeVZrYCbq+jDaneszRctl55WedO+l1LePg==",
+      "license": "ISC"
+    },
     "node_modules/speakingurl": {
       "version": "14.0.1",
       "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",

+ 1 - 0
package.json

@@ -31,6 +31,7 @@
     "commander": "^14.0.0",
     "md5": "^2.3.0",
     "pinia": "^3.0.3",
+    "spatial-navigation-js": "^1.0.0",
     "sweetalert2": "^11.22.4",
     "three": "^0.178.0",
     "vue": "^3.5.17",

+ 4 - 1
src/App.vue

@@ -1,5 +1,8 @@
 <script setup lang="ts">
-import { RouterView } from 'vue-router'
+import { RouterView } from 'vue-router';
+import { useTvFocusImprovement } from './composeable/TvFocusImprovement';
+
+useTvFocusImprovement(true);
 </script>
 
 <template>

+ 68 - 0
src/composeable/TvFocusImprovement.ts

@@ -0,0 +1,68 @@
+import { Debounce } from "@imengyu/imengyu-utils";
+import { onBeforeUnmount, onMounted } from "vue";
+import { useRouter } from "vue-router";
+import SpatialNavigation from 'spatial-navigation-js';
+
+/**
+ * 安卓电视焦点控制帮助类
+ * @param fromApp 是否从应用启动
+ * @returns 
+ */
+export function useTvFocusImprovement(fromApp = false) {
+  
+  const router = useRouter()
+  if (fromApp) {
+    router.afterEach((to, from) => {
+      setTimeout(initSpatialNavigation, 500);
+    });
+  }
+
+  function initSpatialNavigation() {
+    SpatialNavigation.add({
+      selector: '.focusable, a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
+    });
+    // Make the *currently existing* navigable elements focusable.
+    SpatialNavigation.makeFocusable();
+    // Focus the first navigable element.
+    SpatialNavigation.focus();
+  }
+
+  const backDebounce = new Debounce(1000, () => router.back());
+
+  function handleKeyUp(e: KeyboardEvent) {
+    if (e.key === 'Enter') {
+      if (document.activeElement)
+        (document.activeElement as HTMLElement).click();
+    } else if (e.key === 'Backspace') {
+      handleBackButton();
+    }
+  }
+  function handleBackButton() {
+    if (router.currentRoute.value.name === 'Home')
+      plus.runtime.quit();
+    else
+      backDebounce.execute();
+  }
+
+  
+  if (fromApp) {
+    if(window.plus) {
+      plusReady();  
+    } else {
+      document.addEventListener("plusready", plusReady, false);  
+    }  
+    // 扩展API准备完成后要执行的操作  
+    function plusReady(){ 
+      console.log('plusReady!');
+      plus.key.addEventListener("backbutton", handleBackButton);
+    }  
+
+    onMounted(() => {
+      window.addEventListener('keyup', handleKeyUp);
+      setTimeout(initSpatialNavigation, 2000);
+    })
+    onBeforeUnmount(() => {
+      window.removeEventListener('keyup', handleKeyUp);
+    });
+  }
+}

+ 2 - 0
src/main.ts

@@ -9,6 +9,7 @@ import { createPinia } from 'pinia'
 
 import Vue3Marquee from 'vue3-marquee'
 import VueScrollRect from '@imengyu/vue-scroll-rect';
+import SpatialNavigation from 'spatial-navigation-js';
 import App from './App.vue'
 import router from './router'
 import { registryConvert } from './common/ConvertRgeistry';
@@ -21,6 +22,7 @@ app.use(VueScrollRect);
 app.use(Vue3Marquee);
 
 app.mount('#app').$nextTick(() => {
+  SpatialNavigation.init();
   registryConvert();
 })