feat: connecting animation and error dialog
This commit is contained in:
3
components.d.ts
vendored
3
components.d.ts
vendored
@@ -11,7 +11,10 @@ declare module 'vue' {
|
|||||||
PageContainer: typeof import('./src/components/PageContainer.vue')['default']
|
PageContainer: typeof import('./src/components/PageContainer.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
ScanningDevice: typeof import('./src/components/ScanningDevice.vue')['default']
|
||||||
SignalIndicator: typeof import('./src/components/SignalIndicator.vue')['default']
|
SignalIndicator: typeof import('./src/components/SignalIndicator.vue')['default']
|
||||||
|
SvgSpinnersPulse2: typeof import('./src/components/icons/SvgSpinnersPulse2.vue')['default']
|
||||||
|
SvgSpinnersWifiFade: typeof import('./src/components/icons/SvgSpinnersWifiFade.vue')['default']
|
||||||
SystemUiconsSignalFull: typeof import('./src/components/icons/SystemUiconsSignalFull.vue')['default']
|
SystemUiconsSignalFull: typeof import('./src/components/icons/SystemUiconsSignalFull.vue')['default']
|
||||||
SystemUiconsSignalLow: typeof import('./src/components/icons/SystemUiconsSignalLow.vue')['default']
|
SystemUiconsSignalLow: typeof import('./src/components/icons/SystemUiconsSignalLow.vue')['default']
|
||||||
SystemUiconsSignalMedium: typeof import('./src/components/icons/SystemUiconsSignalMedium.vue')['default']
|
SystemUiconsSignalMedium: typeof import('./src/components/icons/SystemUiconsSignalMedium.vue')['default']
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": "^1",
|
"@tauri-apps/api": "^1",
|
||||||
|
"@vueuse/core": "^10.11.0",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
"vue-router": "^4.4.0"
|
"vue-router": "^4.4.0"
|
||||||
|
|||||||
36
pnpm-lock.yaml
generated
36
pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
|||||||
'@tauri-apps/api':
|
'@tauri-apps/api':
|
||||||
specifier: ^1
|
specifier: ^1
|
||||||
version: 1.6.0
|
version: 1.6.0
|
||||||
|
'@vueuse/core':
|
||||||
|
specifier: ^10.11.0
|
||||||
|
version: 10.11.0(vue@3.4.31(typescript@5.5.3))
|
||||||
pinia:
|
pinia:
|
||||||
specifier: ^2.1.7
|
specifier: ^2.1.7
|
||||||
version: 2.1.7(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3))
|
version: 2.1.7(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3))
|
||||||
@@ -415,6 +418,9 @@ packages:
|
|||||||
'@types/estree@1.0.5':
|
'@types/estree@1.0.5':
|
||||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||||
|
|
||||||
|
'@types/web-bluetooth@0.0.20':
|
||||||
|
resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
|
||||||
|
|
||||||
'@vitejs/plugin-vue@5.0.5':
|
'@vitejs/plugin-vue@5.0.5':
|
||||||
resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==}
|
resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
@@ -471,6 +477,15 @@ packages:
|
|||||||
'@vue/shared@3.4.31':
|
'@vue/shared@3.4.31':
|
||||||
resolution: {integrity: sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==}
|
resolution: {integrity: sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==}
|
||||||
|
|
||||||
|
'@vueuse/core@10.11.0':
|
||||||
|
resolution: {integrity: sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==}
|
||||||
|
|
||||||
|
'@vueuse/metadata@10.11.0':
|
||||||
|
resolution: {integrity: sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==}
|
||||||
|
|
||||||
|
'@vueuse/shared@10.11.0':
|
||||||
|
resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==}
|
||||||
|
|
||||||
acorn@8.12.1:
|
acorn@8.12.1:
|
||||||
resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
|
resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
@@ -1317,6 +1332,8 @@ snapshots:
|
|||||||
|
|
||||||
'@types/estree@1.0.5': {}
|
'@types/estree@1.0.5': {}
|
||||||
|
|
||||||
|
'@types/web-bluetooth@0.0.20': {}
|
||||||
|
|
||||||
'@vitejs/plugin-vue@5.0.5(vite@5.3.3(sass@1.77.8))(vue@3.4.31(typescript@5.5.3))':
|
'@vitejs/plugin-vue@5.0.5(vite@5.3.3(sass@1.77.8))(vue@3.4.31(typescript@5.5.3))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 5.3.3(sass@1.77.8)
|
vite: 5.3.3(sass@1.77.8)
|
||||||
@@ -1403,6 +1420,25 @@ snapshots:
|
|||||||
|
|
||||||
'@vue/shared@3.4.31': {}
|
'@vue/shared@3.4.31': {}
|
||||||
|
|
||||||
|
'@vueuse/core@10.11.0(vue@3.4.31(typescript@5.5.3))':
|
||||||
|
dependencies:
|
||||||
|
'@types/web-bluetooth': 0.0.20
|
||||||
|
'@vueuse/metadata': 10.11.0
|
||||||
|
'@vueuse/shared': 10.11.0(vue@3.4.31(typescript@5.5.3))
|
||||||
|
vue-demi: 0.14.8(vue@3.4.31(typescript@5.5.3))
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@vue/composition-api'
|
||||||
|
- vue
|
||||||
|
|
||||||
|
'@vueuse/metadata@10.11.0': {}
|
||||||
|
|
||||||
|
'@vueuse/shared@10.11.0(vue@3.4.31(typescript@5.5.3))':
|
||||||
|
dependencies:
|
||||||
|
vue-demi: 0.14.8(vue@3.4.31(typescript@5.5.3))
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@vue/composition-api'
|
||||||
|
- vue
|
||||||
|
|
||||||
acorn@8.12.1: {}
|
acorn@8.12.1: {}
|
||||||
|
|
||||||
ansi-regex@5.0.1: {}
|
ansi-regex@5.0.1: {}
|
||||||
|
|||||||
101
src-tauri/Cargo.lock
generated
101
src-tauri/Cargo.lock
generated
@@ -1893,6 +1893,17 @@ dependencies = [
|
|||||||
"objc_exception",
|
"objc_exception",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc-foundation"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||||
|
dependencies = [
|
||||||
|
"block",
|
||||||
|
"objc",
|
||||||
|
"objc_id",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc_exception"
|
name = "objc_exception"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@@ -2425,6 +2436,30 @@ version = "0.8.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rfd"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea"
|
||||||
|
dependencies = [
|
||||||
|
"block",
|
||||||
|
"dispatch",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"gtk-sys",
|
||||||
|
"js-sys",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"objc",
|
||||||
|
"objc-foundation",
|
||||||
|
"objc_id",
|
||||||
|
"raw-window-handle",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
"windows 0.37.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
@@ -2948,6 +2983,7 @@ dependencies = [
|
|||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"regex",
|
"regex",
|
||||||
|
"rfd",
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -3550,6 +3586,18 @@ dependencies = [
|
|||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-futures"
|
||||||
|
version = "0.4.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.92"
|
version = "0.2.92"
|
||||||
@@ -3579,6 +3627,16 @@ version = "0.2.92"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webkit2gtk"
|
name = "webkit2gtk"
|
||||||
version = "0.18.2"
|
version = "0.18.2"
|
||||||
@@ -3695,6 +3753,19 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_msvc 0.37.0",
|
||||||
|
"windows_i686_gnu 0.37.0",
|
||||||
|
"windows_i686_msvc 0.37.0",
|
||||||
|
"windows_x86_64_gnu 0.37.0",
|
||||||
|
"windows_x86_64_msvc 0.37.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
@@ -3860,6 +3931,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
@@ -3884,6 +3961,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
@@ -3914,6 +3997,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
@@ -3938,6 +4027,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
@@ -3980,6 +4075,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.39.0"
|
version = "0.39.0"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ edition = "2021"
|
|||||||
tauri-build = { version = "1", features = [] }
|
tauri-build = { version = "1", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "1", features = [ "window-show", "window-hide", "window-maximize", "window-unmaximize", "window-unminimize", "window-start-dragging", "window-minimize", "window-close", "shell-open"] }
|
tauri = { version = "1", features = [ "dialog-all", "window-show", "window-hide", "window-maximize", "window-unmaximize", "window-unminimize", "window-start-dragging", "window-minimize", "window-close", "shell-open"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
btleplug = { version = "0.11.5", features = ["serde"] }
|
btleplug = { version = "0.11.5", features = ["serde"] }
|
||||||
|
|||||||
@@ -154,10 +154,16 @@ impl BleConnection {
|
|||||||
.emit_all("device-discovered", Some(device))
|
.emit_all("device-discovered", Some(device))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
DeviceDisconnected(_) => {
|
DeviceDisconnected(peripheral) => {
|
||||||
// 在这里引用 self
|
let mut p = self_clone.peripheral.lock().await;
|
||||||
let mut peripheral = self_clone.peripheral.lock().await;
|
if let Some(peri) = p.as_ref() {
|
||||||
*peripheral = None;
|
if peri.id() == peripheral {
|
||||||
|
app_handle
|
||||||
|
.emit_all("device-disconnected", peripheral.to_string())
|
||||||
|
.unwrap();
|
||||||
|
*p = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@
|
|||||||
"unmaximize": true,
|
"unmaximize": true,
|
||||||
"unminimize": true,
|
"unminimize": true,
|
||||||
"startDragging": true
|
"startDragging": true
|
||||||
|
},
|
||||||
|
"dialog": {
|
||||||
|
"all": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"windows": [
|
"windows": [
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ listen("device-discovered", (event) => {
|
|||||||
listen("device-connected", (event) => {
|
listen("device-connected", (event) => {
|
||||||
console.log('device-connected', event.payload);
|
console.log('device-connected', event.payload);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
listen("device-disconnected", (event) => {
|
||||||
|
console.log('device-disconnected', event.payload);
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
39
src/components/ScanningDevice.vue
Normal file
39
src/components/ScanningDevice.vue
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { Device, useBrcatStore } from '../stores';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
device: {
|
||||||
|
type: Object as PropType<Device>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['connect']);
|
||||||
|
const store = useBrcatStore();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="item w-full px-3 py-3 flex justify-between items-center bg-white rounded" :key="device.address">
|
||||||
|
<div class="h-full">
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
<span class="flex items-center gap-1 text-sm leading-none">
|
||||||
|
{{ device.name }}
|
||||||
|
</span>
|
||||||
|
<span class="flex items-center gap-1 text-2xs text-neutral-400">
|
||||||
|
<SignalIndicator :rssi="device.rssi" />
|
||||||
|
{{ device.address }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="h-full flex items-center">
|
||||||
|
<button class="btn outline" :disabled="store.is_connected" @click="emit('connect', device.address)">连接</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.item {
|
||||||
|
border: 1px solid rgb(220, 220, 220);
|
||||||
|
box-shadow: 2px 2px 6px -2px rgba(200, 200, 200, 0.385);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
10
src/components/icons/SvgSpinnersPulse2.vue
Normal file
10
src/components/icons/SvgSpinnersPulse2.vue
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><circle cx="12" cy="12" r="0" fill="currentColor"><animate id="svgSpinnersPulse20" fill="freeze" attributeName="r" begin="0;svgSpinnersPulse21.begin+0.6s" calcMode="spline" dur="1.2s" keySplines=".52,.6,.25,.99" values="0;11"></animate><animate fill="freeze" attributeName="opacity" begin="0;svgSpinnersPulse21.begin+0.6s" calcMode="spline" dur="1.2s" keySplines=".52,.6,.25,.99" values="1;0"></animate></circle><circle cx="12" cy="12" r="0" fill="currentColor"><animate id="svgSpinnersPulse21" fill="freeze" attributeName="r" begin="svgSpinnersPulse20.begin+0.6s" calcMode="spline" dur="1.2s" keySplines=".52,.6,.25,.99" values="0;11"></animate><animate fill="freeze" attributeName="opacity" begin="svgSpinnersPulse20.begin+0.6s" calcMode="spline" dur="1.2s" keySplines=".52,.6,.25,.99" values="1;0"></animate></circle></svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'SvgSpinnersPulse2'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
10
src/components/icons/SvgSpinnersWifiFade.vue
Normal file
10
src/components/icons/SvgSpinnersWifiFade.vue
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
<template>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12,21L15.6,16.2C14.6,15.45 13.35,15 12,15C10.65,15 9.4,15.45 8.4,16.2L12,21" opacity="0"><animate id="svgSpinnersWifiFade0" fill="freeze" attributeName="opacity" begin="0;svgSpinnersWifiFade1.end+0.2s" dur="0.25s" values="0;1"></animate><animate id="svgSpinnersWifiFade1" fill="freeze" attributeName="opacity" begin="svgSpinnersWifiFade3.end+0.5s" dur="0.1s" values="1;0"></animate></path><path fill="currentColor" d="M12,9C9.3,9 6.81,9.89 4.8,11.4L6.6,13.8C8.1,12.67 9.97,12 12,12C14.03,12 15.9,12.67 17.4,13.8L19.2,11.4C17.19,9.89 14.7,9 12,9Z" opacity="0"><animate id="svgSpinnersWifiFade2" fill="freeze" attributeName="opacity" begin="svgSpinnersWifiFade0.end" dur="0.25s" values="0;1"></animate><animate fill="freeze" attributeName="opacity" begin="svgSpinnersWifiFade3.end+0.5s" dur="0.1s" values="1;0"></animate></path><path fill="currentColor" d="M12,3C7.95,3 4.21,4.34 1.2,6.6L3,9C5.5,7.12 8.62,6 12,6C15.38,6 18.5,7.12 21,9L22.8,6.6C19.79,4.34 16.05,3 12,3" opacity="0"><animate id="svgSpinnersWifiFade3" fill="freeze" attributeName="opacity" begin="svgSpinnersWifiFade2.end" dur="0.25s" values="0;1"></animate><animate fill="freeze" attributeName="opacity" begin="svgSpinnersWifiFade3.end+0.5s" dur="0.1s" values="1;0"></animate></path></svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'SvgSpinnersWifiFade'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -1,18 +1,28 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { invoke } from '@tauri-apps/api/tauri';
|
import { invoke } from '@tauri-apps/api/tauri';
|
||||||
|
import { message } from '@tauri-apps/api/dialog';
|
||||||
import { useBrcatStore } from '../stores';
|
import { useBrcatStore } from '../stores';
|
||||||
import { onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
const store = useBrcatStore();
|
const store = useBrcatStore();
|
||||||
const is_connecting = ref(false);
|
const is_connecting = ref(false);
|
||||||
|
|
||||||
|
const scanning_devices = computed(() => store.scanning_devices.filter(d => d.name !== 'Unknown'));
|
||||||
|
|
||||||
async function connect(address: String) {
|
async function connect(address: String) {
|
||||||
is_connecting.value = true;
|
is_connecting.value = true;
|
||||||
|
store.stopScan();
|
||||||
invoke('connect', { address })
|
invoke('connect', { address })
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error(err);
|
message(`${err}`, {
|
||||||
|
type: 'error',
|
||||||
|
title: '连接设备失败'
|
||||||
|
});
|
||||||
|
store.startScan();
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
setTimeout(() => {
|
||||||
is_connecting.value = false;
|
is_connecting.value = false;
|
||||||
|
}, 500);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +32,7 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PageContainer title="设备连接" content-class="">
|
<PageContainer title="设备连接" content-class="relative">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<button class="text-[var(--primary-color)]"
|
<button class="text-[var(--primary-color)]"
|
||||||
@@ -31,6 +41,7 @@ onMounted(() => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<Transition name="fade">
|
||||||
<div v-if="store.is_connected" class="w-full h-full flex flex-col gap-4 justify-center items-center bg-white">
|
<div v-if="store.is_connected" class="w-full h-full flex flex-col gap-4 justify-center items-center bg-white">
|
||||||
<TablerBluetoothConnected class="icon text-5xl text-emerald-500" />
|
<TablerBluetoothConnected class="icon text-5xl text-emerald-500" />
|
||||||
<span class="flex flex-col items-center">
|
<span class="flex flex-col items-center">
|
||||||
@@ -41,33 +52,56 @@ onMounted(() => {
|
|||||||
<button class="btn outline" @click="invoke('disconnect')">断开连接</button>
|
<button class="btn outline" @click="invoke('disconnect')">断开连接</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="store.is_scanning && scanning_devices.length === 0"
|
||||||
|
class="w-full h-full flex flex-col gap-4 justify-center items-center">
|
||||||
|
<SvgSpinnersPulse2 class="icon text-5xl text-neutral-400" />
|
||||||
|
<span class="text-sm font-semibold text-neutral-400">正在扫描蓝牙设备</span>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="is_connecting"
|
||||||
|
class="w-full h-full flex flex-col gap-4 justify-center items-center">
|
||||||
|
<SvgSpinnersWifiFade class="icon text-5xl text-neutral-400" />
|
||||||
|
<span class="text-sm font-semibold text-neutral-400">正在连接到设备</span>
|
||||||
|
</div>
|
||||||
<div class="p-4" v-else>
|
<div class="p-4" v-else>
|
||||||
<ul class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2 relative">
|
||||||
<li class="item w-full px-3 py-3 flex justify-between items-center bg-white rounded"
|
<TransitionGroup name="scan-device">
|
||||||
v-for="device in store.scanning_devices.filter(d => d.name !== 'Unknown')" :key="device.address">
|
<ScanningDevice v-for="(device, _) in scanning_devices.filter(d => d.name !== 'Unknown')"
|
||||||
<div class="h-full">
|
:key="device.address" :device="device" @connect="connect" />
|
||||||
<div class="flex flex-col gap-1">
|
</TransitionGroup>
|
||||||
<span class="flex items-center gap-1 text-sm leading-none">
|
|
||||||
{{ device.name }}
|
|
||||||
</span>
|
|
||||||
<span class="flex items-center gap-1 text-2xs text-neutral-400">
|
|
||||||
<SignalIndicator :rssi="device.rssi" />
|
|
||||||
{{ device.address }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="h-full flex items-center">
|
</Transition>
|
||||||
<button class="btn outline" :disabled="store.is_connected" @click="connect(device.address)">连接</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.item {
|
.fade-enter-active,
|
||||||
border: 1px solid rgb(220, 220, 220);
|
.fade-leave-active {
|
||||||
box-shadow: 2px 2px 6px -2px rgba(200, 200, 200, 0.385);
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: transform 0.3s;
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scan-device-enter-active,
|
||||||
|
.scan-device-leave-active {
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scan-device-enter-from,
|
||||||
|
.scan-device-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scan-device-move {
|
||||||
|
transition: transform 0.3s;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { ref, watchEffect } from "vue";
|
import { ref, watchEffect } from "vue";
|
||||||
import { invoke } from "@tauri-apps/api/tauri";
|
import { invoke } from "@tauri-apps/api/tauri";
|
||||||
|
import { useThrottleFn } from "@vueuse/core";
|
||||||
|
|
||||||
export interface Device {
|
export interface Device {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -34,6 +35,12 @@ export const useBrcatStore = defineStore("brcat", () => {
|
|||||||
stopScan();
|
stopScan();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const throttledSort = useThrottleFn(() => {
|
||||||
|
scanning_devices.value = scanning_devices.value.sort(
|
||||||
|
(a, b) => Math.round(b.rssi / 10) - Math.round(a.rssi / 10)
|
||||||
|
);
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
function pushDevice(device: Device) {
|
function pushDevice(device: Device) {
|
||||||
if (scanning_devices.value.some((d) => d.address === device.address)) {
|
if (scanning_devices.value.some((d) => d.address === device.address)) {
|
||||||
scanning_devices.value = scanning_devices.value.map((d) =>
|
scanning_devices.value = scanning_devices.value.map((d) =>
|
||||||
@@ -42,21 +49,18 @@ export const useBrcatStore = defineStore("brcat", () => {
|
|||||||
} else {
|
} else {
|
||||||
scanning_devices.value.push(device);
|
scanning_devices.value.push(device);
|
||||||
}
|
}
|
||||||
// scanning_devices.value = scanning_devices.value.sort(
|
|
||||||
// (a, b) => b.rssi - a.rssi
|
throttledSort();
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function startScan() {
|
function startScan() {
|
||||||
invoke("start_scan");
|
invoke("start_scan");
|
||||||
is_scanning.value = true;
|
is_scanning.value = true;
|
||||||
console.log("start scan");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopScan() {
|
function stopScan() {
|
||||||
invoke("stop_scan");
|
invoke("stop_scan");
|
||||||
is_scanning.value = false;
|
is_scanning.value = false;
|
||||||
console.log("stop scan");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user