mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-05-09 07:38:09 +03:00
Compare commits
17 Commits
nightly
...
e3b6e4eaf0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3b6e4eaf0 | ||
|
|
0388d00ad3 | ||
|
|
1e2d2c5146 | ||
|
|
96797742f2 | ||
|
|
682e347be0 | ||
|
|
b3f43f55c1 | ||
|
|
016a0b1141 | ||
|
|
fd7bcf54bd | ||
|
|
db3f5fe816 | ||
|
|
0d3016fcd8 | ||
|
|
1abc897c45 | ||
|
|
ab64a32f30 | ||
|
|
52b66e71d1 | ||
|
|
41ab5bbdd8 | ||
|
|
732b250815 | ||
|
|
157dbdc543 | ||
|
|
6ba23683d5 |
2
.github/workflows/flutter-build.yml
vendored
2
.github/workflows/flutter-build.yml
vendored
@@ -40,7 +40,7 @@ env:
|
|||||||
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||||
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" # 2025.01.13, got "/opt/artifacts/vcpkg/vcpkg: No such file or directory" with latest version
|
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" # 2025.01.13, got "/opt/artifacts/vcpkg/vcpkg: No such file or directory" with latest version
|
||||||
VERSION: "1.4.6"
|
VERSION: "1.4.6"
|
||||||
NDK_VERSION: "r27c"
|
NDK_VERSION: "r28c"
|
||||||
#signing keys env variable checks
|
#signing keys env variable checks
|
||||||
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
|
||||||
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}"
|
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}"
|
||||||
|
|||||||
354
Cargo.lock
generated
354
Cargo.lock
generated
@@ -33,6 +33,12 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler2"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aead"
|
name = "aead"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@@ -293,8 +299,8 @@ dependencies = [
|
|||||||
"image 0.25.1",
|
"image 0.25.1",
|
||||||
"log",
|
"log",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit 0.2.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"serde 1.0.228",
|
"serde 1.0.228",
|
||||||
@@ -637,7 +643,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.7.4",
|
||||||
"object",
|
"object",
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
@@ -860,6 +866,15 @@ dependencies = [
|
|||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block2"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
||||||
|
dependencies = [
|
||||||
|
"objc2 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blocking"
|
name = "blocking"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
@@ -1182,7 +1197,7 @@ dependencies = [
|
|||||||
"js-sys",
|
"js-sys",
|
||||||
"num-traits 0.2.19",
|
"num-traits 0.2.19",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-link",
|
"windows-link 0.1.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1290,8 +1305,8 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit 0.2.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
@@ -2216,6 +2231,15 @@ dependencies = [
|
|||||||
"dirs-sys 0.4.1",
|
"dirs-sys 0.4.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys 0.5.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-next"
|
name = "dirs-next"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@@ -2233,7 +2257,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"redox_users",
|
"redox_users 0.4.5",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2245,10 +2269,22 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users",
|
"redox_users 0.4.5",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"option-ext",
|
||||||
|
"redox_users 0.5.2",
|
||||||
|
"windows-sys 0.61.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys-next"
|
name = "dirs-sys-next"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@@ -2256,7 +2292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"redox_users",
|
"redox_users 0.4.5",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2266,6 +2302,16 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dispatch2"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"objc2 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "displaydoc"
|
name = "displaydoc"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
@@ -2715,7 +2761,7 @@ dependencies = [
|
|||||||
"flume",
|
"flume",
|
||||||
"half",
|
"half",
|
||||||
"lebe",
|
"lebe",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.7.4",
|
||||||
"rayon-core",
|
"rayon-core",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"zune-inflate",
|
"zune-inflate",
|
||||||
@@ -2801,12 +2847,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.30"
|
version = "1.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
|
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.8.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4041,7 +4087,7 @@ dependencies = [
|
|||||||
"gif",
|
"gif",
|
||||||
"jpeg-decoder",
|
"jpeg-decoder",
|
||||||
"num-traits 0.2.19",
|
"num-traits 0.2.19",
|
||||||
"png",
|
"png 0.17.13",
|
||||||
"qoi",
|
"qoi",
|
||||||
"tiff",
|
"tiff",
|
||||||
]
|
]
|
||||||
@@ -4055,7 +4101,7 @@ dependencies = [
|
|||||||
"bytemuck",
|
"bytemuck",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"num-traits 0.2.19",
|
"num-traits 0.2.19",
|
||||||
"png",
|
"png 0.17.13",
|
||||||
"tiff",
|
"tiff",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4766,6 +4812,16 @@ dependencies = [
|
|||||||
"simd-adler32",
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||||
|
dependencies = [
|
||||||
|
"adler2",
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.11"
|
version = "0.8.11"
|
||||||
@@ -4816,21 +4872,23 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "muda"
|
name = "muda"
|
||||||
version = "0.13.5"
|
version = "0.17.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86b959f97c97044e4c96e32e1db292a7d594449546a3c6b77ae613dc3a5b5145"
|
checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa 0.25.0",
|
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"dpi",
|
"dpi",
|
||||||
"gtk",
|
"gtk",
|
||||||
"keyboard-types",
|
"keyboard-types",
|
||||||
"libxdo",
|
"libxdo",
|
||||||
"objc",
|
"objc2 0.6.4",
|
||||||
|
"objc2-app-kit 0.3.2",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-foundation 0.3.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"png",
|
"png 0.17.13",
|
||||||
"thiserror 1.0.61",
|
"thiserror 2.0.17",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5374,7 +5432,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804"
|
checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"objc-sys 0.3.5",
|
"objc-sys 0.3.5",
|
||||||
"objc2-encode 4.0.3",
|
"objc2-encode 4.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
|
||||||
|
dependencies = [
|
||||||
|
"objc2-encode 4.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5389,10 +5456,22 @@ dependencies = [
|
|||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-core-data",
|
"objc2-core-data",
|
||||||
"objc2-core-image",
|
"objc2-core-image",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-quartz-core",
|
"objc2-quartz-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-app-kit"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"objc2 0.6.4",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-foundation 0.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-cloud-kit"
|
name = "objc2-cloud-kit"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -5403,7 +5482,7 @@ dependencies = [
|
|||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-core-location",
|
"objc2-core-location",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5414,7 +5493,7 @@ checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5426,7 +5505,28 @@ dependencies = [
|
|||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-core-foundation"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"dispatch2",
|
||||||
|
"objc2 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-core-graphics"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"objc2-core-foundation",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5437,7 +5537,7 @@ checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-metal",
|
"objc2-metal",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -5450,7 +5550,7 @@ dependencies = [
|
|||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-contacts",
|
"objc2-contacts",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5464,9 +5564,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-encode"
|
name = "objc2-encode"
|
||||||
version = "4.0.3"
|
version = "4.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8"
|
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-foundation"
|
name = "objc2-foundation"
|
||||||
@@ -5481,6 +5581,18 @@ dependencies = [
|
|||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-foundation"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"block2 0.6.2",
|
||||||
|
"objc2 0.6.4",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-link-presentation"
|
name = "objc2-link-presentation"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -5489,8 +5601,8 @@ checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit 0.2.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5502,7 +5614,7 @@ dependencies = [
|
|||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5514,7 +5626,7 @@ dependencies = [
|
|||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-metal",
|
"objc2-metal",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -5525,7 +5637,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
|
checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5541,7 +5653,7 @@ dependencies = [
|
|||||||
"objc2-core-data",
|
"objc2-core-data",
|
||||||
"objc2-core-image",
|
"objc2-core-image",
|
||||||
"objc2-core-location",
|
"objc2-core-location",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-link-presentation",
|
"objc2-link-presentation",
|
||||||
"objc2-quartz-core",
|
"objc2-quartz-core",
|
||||||
"objc2-symbols",
|
"objc2-symbols",
|
||||||
@@ -5557,7 +5669,7 @@ checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5570,7 +5682,7 @@ dependencies = [
|
|||||||
"block2 0.5.1",
|
"block2 0.5.1",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-core-location",
|
"objc2-core-location",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6178,7 +6290,20 @@ dependencies = [
|
|||||||
"crc32fast",
|
"crc32fast",
|
||||||
"fdeflate",
|
"fdeflate",
|
||||||
"flate2",
|
"flate2",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.7.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.18.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"crc32fast",
|
||||||
|
"fdeflate",
|
||||||
|
"flate2",
|
||||||
|
"miniz_oxide 0.8.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6863,6 +6988,17 @@ dependencies = [
|
|||||||
"thiserror 1.0.61",
|
"thiserror 1.0.61",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.2.15",
|
||||||
|
"libredox",
|
||||||
|
"thiserror 2.0.17",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
@@ -7981,8 +8117,8 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit 0.2.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-quartz-core",
|
"objc2-quartz-core",
|
||||||
"raw-window-handle 0.6.2",
|
"raw-window-handle 0.6.2",
|
||||||
"redox_syscall 0.5.2",
|
"redox_syscall 0.5.2",
|
||||||
@@ -8312,7 +8448,7 @@ dependencies = [
|
|||||||
"objc",
|
"objc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"png",
|
"png 0.17.13",
|
||||||
"raw-window-handle 0.6.2",
|
"raw-window-handle 0.6.2",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
"tao-macros",
|
"tao-macros",
|
||||||
@@ -8566,7 +8702,7 @@ dependencies = [
|
|||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"log",
|
"log",
|
||||||
"png",
|
"png 0.17.13",
|
||||||
"tiny-skia-path",
|
"tiny-skia-path",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -8939,21 +9075,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tray-icon"
|
name = "tray-icon"
|
||||||
version = "0.14.3"
|
version = "0.21.3"
|
||||||
source = "git+https://github.com/tauri-apps/tray-icon#d4078696edba67b0ab42cef67e6a421a0332c96f"
|
source = "git+https://github.com/tauri-apps/tray-icon#0a5835b0e6828e37a1f781de9c2d671ae7a939e6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-graphics 0.23.2",
|
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"dirs 5.0.1",
|
"dirs 6.0.0",
|
||||||
"libappindicator",
|
"libappindicator",
|
||||||
"muda",
|
"muda",
|
||||||
"objc2 0.5.2",
|
"objc2 0.6.4",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit 0.3.2",
|
||||||
"objc2-foundation",
|
"objc2-core-foundation",
|
||||||
|
"objc2-core-graphics",
|
||||||
|
"objc2-foundation 0.3.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"png",
|
"png 0.18.1",
|
||||||
"thiserror 1.0.61",
|
"thiserror 2.0.17",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10058,7 +10195,7 @@ dependencies = [
|
|||||||
"windows-collections",
|
"windows-collections",
|
||||||
"windows-core 0.61.0",
|
"windows-core 0.61.0",
|
||||||
"windows-future",
|
"windows-future",
|
||||||
"windows-link",
|
"windows-link 0.1.1",
|
||||||
"windows-numerics",
|
"windows-numerics",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -10107,7 +10244,7 @@ checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-implement 0.60.0",
|
"windows-implement 0.60.0",
|
||||||
"windows-interface 0.59.1",
|
"windows-interface 0.59.1",
|
||||||
"windows-link",
|
"windows-link 0.1.1",
|
||||||
"windows-result 0.3.2",
|
"windows-result 0.3.2",
|
||||||
"windows-strings 0.4.0",
|
"windows-strings 0.4.0",
|
||||||
]
|
]
|
||||||
@@ -10119,7 +10256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
|
checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-core 0.61.0",
|
"windows-core 0.61.0",
|
||||||
"windows-link",
|
"windows-link 0.1.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10172,6 +10309,12 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-numerics"
|
name = "windows-numerics"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -10179,7 +10322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-core 0.61.0",
|
"windows-core 0.61.0",
|
||||||
"windows-link",
|
"windows-link 0.1.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10197,7 +10340,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link 0.1.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10217,7 +10360,7 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
|
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link 0.1.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10226,7 +10369,7 @@ 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 = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
|
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link 0.1.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10256,6 +10399,24 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.60.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.53.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.61.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link 0.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@@ -10295,13 +10456,30 @@ dependencies = [
|
|||||||
"windows_aarch64_gnullvm 0.52.6",
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
"windows_aarch64_msvc 0.52.6",
|
"windows_aarch64_msvc 0.52.6",
|
||||||
"windows_i686_gnu 0.52.6",
|
"windows_i686_gnu 0.52.6",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm 0.52.6",
|
||||||
"windows_i686_msvc 0.52.6",
|
"windows_i686_msvc 0.52.6",
|
||||||
"windows_x86_64_gnu 0.52.6",
|
"windows_x86_64_gnu 0.52.6",
|
||||||
"windows_x86_64_gnullvm 0.52.6",
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
"windows_x86_64_msvc 0.52.6",
|
"windows_x86_64_msvc 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.53.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link 0.2.1",
|
||||||
|
"windows_aarch64_gnullvm 0.53.1",
|
||||||
|
"windows_aarch64_msvc 0.53.1",
|
||||||
|
"windows_i686_gnu 0.53.1",
|
||||||
|
"windows_i686_gnullvm 0.53.1",
|
||||||
|
"windows_i686_msvc 0.53.1",
|
||||||
|
"windows_x86_64_gnu 0.53.1",
|
||||||
|
"windows_x86_64_gnullvm 0.53.1",
|
||||||
|
"windows_x86_64_msvc 0.53.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-version"
|
name = "windows-version"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -10338,6 +10516,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_gnullvm"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.32.0"
|
version = "0.32.0"
|
||||||
@@ -10368,6 +10552,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_aarch64_msvc"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.32.0"
|
version = "0.32.0"
|
||||||
@@ -10398,12 +10588,24 @@ 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 = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnullvm"
|
name = "windows_i686_gnullvm"
|
||||||
version = "0.52.6"
|
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_gnullvm"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.32.0"
|
version = "0.32.0"
|
||||||
@@ -10434,6 +10636,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_i686_msvc"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.32.0"
|
version = "0.32.0"
|
||||||
@@ -10464,6 +10672,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 = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
@@ -10482,6 +10696,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_gnullvm"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.32.0"
|
version = "0.32.0"
|
||||||
@@ -10512,6 +10732,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 = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winit"
|
name = "winit"
|
||||||
version = "0.30.9"
|
version = "0.30.9"
|
||||||
@@ -10536,8 +10762,8 @@ dependencies = [
|
|||||||
"memmap2",
|
"memmap2",
|
||||||
"ndk 0.9.0",
|
"ndk 0.9.0",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit 0.2.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-ui-kit",
|
"objc2-ui-kit",
|
||||||
"orbclient",
|
"orbclient",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ piet-coregraphics = "0.6"
|
|||||||
foreign-types = "0.3"
|
foreign-types = "0.3"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dependencies]
|
[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dependencies]
|
||||||
tray-icon = { git = "https://github.com/tauri-apps/tray-icon" }
|
tray-icon = { git = "https://github.com/tauri-apps/tray-icon", version = "0.21.3" }
|
||||||
tao = { git = "https://github.com/rustdesk-org/tao", branch = "dev" }
|
tao = { git = "https://github.com/rustdesk-org/tao", branch = "dev" }
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ target/release/rustdesk
|
|||||||
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: графический пользовательский интерфейс на Sciter (устаревшее)
|
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: графический пользовательский интерфейс на Sciter (устаревшее)
|
||||||
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: сервисы аудио, буфера обмена, ввода, видео и сетевых подключений
|
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: сервисы аудио, буфера обмена, ввода, видео и сетевых подключений
|
||||||
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: одноранговое соединение
|
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: одноранговое соединение
|
||||||
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: связь с [сервером Rustdesk](https://github.com/rustdesk/rustdesk-server), ожидает удаленного прямого (через TCP hole punching) или ретранслируемого соединения
|
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: связь с [сервером RustDesk](https://github.com/rustdesk/rustdesk-server), ожидает удаленного прямого (через TCP hole punching) или ретранслируемого соединения
|
||||||
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: специфичный для платформы код
|
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: специфичный для платформы код
|
||||||
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: код Flutter для ПК-версии и мобильных устройств
|
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: код Flutter для ПК-версии и мобильных устройств
|
||||||
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/v1/js)**: JavaScript для Web-клиента Flutter
|
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/v1/js)**: JavaScript для Web-клиента Flutter
|
||||||
|
|||||||
@@ -4118,3 +4118,43 @@ String mouseButtonsToPeer(int buttons) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build an avatar widget from an avatar URL or data URI string.
|
||||||
|
/// Returns [fallback] if avatar is empty or cannot be decoded.
|
||||||
|
/// [borderRadius] defaults to [size]/2 (circle).
|
||||||
|
Widget? buildAvatarWidget({
|
||||||
|
required String avatar,
|
||||||
|
required double size,
|
||||||
|
double? borderRadius,
|
||||||
|
Widget? fallback,
|
||||||
|
}) {
|
||||||
|
final trimmed = avatar.trim();
|
||||||
|
if (trimmed.isEmpty) return fallback;
|
||||||
|
|
||||||
|
ImageProvider? imageProvider;
|
||||||
|
if (trimmed.startsWith('data:image/')) {
|
||||||
|
final comma = trimmed.indexOf(',');
|
||||||
|
if (comma > 0) {
|
||||||
|
try {
|
||||||
|
imageProvider = MemoryImage(base64Decode(trimmed.substring(comma + 1)));
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
} else if (trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
|
||||||
|
imageProvider = NetworkImage(trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageProvider == null) return fallback;
|
||||||
|
|
||||||
|
final radius = borderRadius ?? size / 2;
|
||||||
|
return ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(radius),
|
||||||
|
child: Image(
|
||||||
|
image: imageProvider,
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
errorBuilder: (_, __, ___) =>
|
||||||
|
fallback ?? SizedBox.shrink(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ enum UserStatus { kDisabled, kNormal, kUnverified }
|
|||||||
class UserPayload {
|
class UserPayload {
|
||||||
String name = '';
|
String name = '';
|
||||||
String displayName = '';
|
String displayName = '';
|
||||||
|
String avatar = '';
|
||||||
String email = '';
|
String email = '';
|
||||||
String note = '';
|
String note = '';
|
||||||
String? verifier;
|
String? verifier;
|
||||||
@@ -35,6 +36,7 @@ class UserPayload {
|
|||||||
UserPayload.fromJson(Map<String, dynamic> json)
|
UserPayload.fromJson(Map<String, dynamic> json)
|
||||||
: name = json['name'] ?? '',
|
: name = json['name'] ?? '',
|
||||||
displayName = json['display_name'] ?? '',
|
displayName = json['display_name'] ?? '',
|
||||||
|
avatar = json['avatar'] ?? '',
|
||||||
email = json['email'] ?? '',
|
email = json['email'] ?? '',
|
||||||
note = json['note'] ?? '',
|
note = json['note'] ?? '',
|
||||||
verifier = json['verifier'],
|
verifier = json['verifier'],
|
||||||
@@ -49,6 +51,7 @@ class UserPayload {
|
|||||||
final Map<String, dynamic> map = {
|
final Map<String, dynamic> map = {
|
||||||
'name': name,
|
'name': name,
|
||||||
'display_name': displayName,
|
'display_name': displayName,
|
||||||
|
'avatar': avatar,
|
||||||
'status': status == UserStatus.kDisabled
|
'status': status == UserStatus.kDisabled
|
||||||
? 0
|
? 0
|
||||||
: status == UserStatus.kUnverified
|
: status == UserStatus.kUnverified
|
||||||
|
|||||||
@@ -2026,28 +2026,65 @@ class _AccountState extends State<_Account> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget useInfo() {
|
Widget useInfo() {
|
||||||
text(String key, String value) {
|
|
||||||
return Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: SelectionArea(child: Text('${translate(key)}: $value'))
|
|
||||||
.marginSymmetric(vertical: 4),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Obx(() => Offstage(
|
return Obx(() => Offstage(
|
||||||
offstage: gFFI.userModel.userName.value.isEmpty,
|
offstage: gFFI.userModel.userName.value.isEmpty,
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
padding: const EdgeInsets.all(12),
|
||||||
if (gFFI.userModel.displayName.value.trim().isNotEmpty &&
|
decoration: BoxDecoration(
|
||||||
gFFI.userModel.displayName.value.trim() !=
|
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||||
gFFI.userModel.userName.value.trim())
|
borderRadius: BorderRadius.circular(10),
|
||||||
text('Display Name', gFFI.userModel.displayName.value.trim()),
|
),
|
||||||
text('Username', gFFI.userModel.userName.value),
|
child: Builder(builder: (context) {
|
||||||
// text('Group', gFFI.groupModel.groupName.value),
|
final avatarWidget = _buildUserAvatar();
|
||||||
],
|
return Row(
|
||||||
|
children: [
|
||||||
|
if (avatarWidget != null) avatarWidget,
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
gFFI.userModel.displayNameOrUserName,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
SelectionArea(
|
||||||
|
child: Text(
|
||||||
|
'@${gFFI.userModel.userName.value}',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color:
|
||||||
|
Theme.of(context).textTheme.bodySmall?.color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
)).marginOnly(left: 18, top: 16);
|
)).marginOnly(left: 18, top: 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget? _buildUserAvatar() {
|
||||||
|
// Resolve relative avatar path at display time
|
||||||
|
final avatar =
|
||||||
|
bind.mainResolveAvatarUrl(avatar: gFFI.userModel.avatar.value);
|
||||||
|
return buildAvatarWidget(
|
||||||
|
avatar: avatar,
|
||||||
|
size: 44,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Checkbox extends StatefulWidget {
|
class _Checkbox extends StatefulWidget {
|
||||||
|
|||||||
@@ -462,23 +462,7 @@ class _CmHeaderState extends State<_CmHeader>
|
|||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
_buildClientAvatar().marginOnly(right: 10.0),
|
||||||
width: 70,
|
|
||||||
height: 70,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: str2color(client.name),
|
|
||||||
borderRadius: BorderRadius.circular(15.0),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
client.name[0],
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 55,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).marginOnly(right: 10.0),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
@@ -582,6 +566,36 @@ class _CmHeaderState extends State<_CmHeader>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool get wantKeepAlive => true;
|
bool get wantKeepAlive => true;
|
||||||
|
|
||||||
|
Widget _buildClientAvatar() {
|
||||||
|
return buildAvatarWidget(
|
||||||
|
avatar: client.avatar,
|
||||||
|
size: 70,
|
||||||
|
borderRadius: 15,
|
||||||
|
fallback: _buildInitialAvatar(),
|
||||||
|
) ??
|
||||||
|
_buildInitialAvatar();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInitialAvatar() {
|
||||||
|
return Container(
|
||||||
|
width: 70,
|
||||||
|
height: 70,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: str2color(client.name),
|
||||||
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
client.name.isNotEmpty ? client.name[0] : '?',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 55,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PrivilegeBoard extends StatefulWidget {
|
class _PrivilegeBoard extends StatefulWidget {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:ui' as ui;
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -65,9 +64,7 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
|
|||||||
bool _showGestureHelp = false;
|
bool _showGestureHelp = false;
|
||||||
String _value = '';
|
String _value = '';
|
||||||
Orientation? _currentOrientation;
|
Orientation? _currentOrientation;
|
||||||
double _viewInsetsBottom = 0;
|
|
||||||
final _uniqueKey = UniqueKey();
|
final _uniqueKey = UniqueKey();
|
||||||
Timer? _timerDidChangeMetrics;
|
|
||||||
Timer? _iosKeyboardWorkaroundTimer;
|
Timer? _iosKeyboardWorkaroundTimer;
|
||||||
|
|
||||||
final _blockableOverlayState = BlockableOverlayState();
|
final _blockableOverlayState = BlockableOverlayState();
|
||||||
@@ -140,7 +137,6 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
|
|||||||
_physicalFocusNode.dispose();
|
_physicalFocusNode.dispose();
|
||||||
await gFFI.close();
|
await gFFI.close();
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
_timerDidChangeMetrics?.cancel();
|
|
||||||
_iosKeyboardWorkaroundTimer?.cancel();
|
_iosKeyboardWorkaroundTimer?.cancel();
|
||||||
gFFI.dialogManager.dismissAll();
|
gFFI.dialogManager.dismissAll();
|
||||||
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
@@ -167,26 +163,6 @@ class _RemotePageState extends State<RemotePage> with WidgetsBindingObserver {
|
|||||||
gFFI.invokeMethod("try_sync_clipboard");
|
gFFI.invokeMethod("try_sync_clipboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeMetrics() {
|
|
||||||
// If the soft keyboard is visible and the canvas has been changed(panned or scaled)
|
|
||||||
// Don't try reset the view style and focus the cursor.
|
|
||||||
if (gFFI.cursorModel.lastKeyboardIsVisible &&
|
|
||||||
gFFI.canvasModel.isMobileCanvasChanged) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final newBottom = MediaQueryData.fromView(ui.window).viewInsets.bottom;
|
|
||||||
_timerDidChangeMetrics?.cancel();
|
|
||||||
_timerDidChangeMetrics = Timer(Duration(milliseconds: 100), () async {
|
|
||||||
// We need this comparation because poping up the floating action will also trigger `didChangeMetrics()`.
|
|
||||||
if (newBottom != _viewInsetsBottom) {
|
|
||||||
gFFI.canvasModel.mobileFocusCanvasCursor();
|
|
||||||
_viewInsetsBottom = newBottom;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// to-do: It should be better to use transparent color instead of the bgColor.
|
// to-do: It should be better to use transparent color instead of the bgColor.
|
||||||
// But for now, the transparent color will cause the canvas to be white.
|
// But for now, the transparent color will cause the canvas to be white.
|
||||||
// I'm sure that the white color is caused by the Overlay widget in BlockableOverlay.
|
// I'm sure that the white color is caused by the Overlay widget in BlockableOverlay.
|
||||||
|
|||||||
@@ -841,13 +841,7 @@ class ClientInfo extends StatelessWidget {
|
|||||||
flex: -1,
|
flex: -1,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(right: 12),
|
padding: const EdgeInsets.only(right: 12),
|
||||||
child: CircleAvatar(
|
child: _buildAvatar(context))),
|
||||||
backgroundColor: str2color(
|
|
||||||
client.name,
|
|
||||||
Theme.of(context).brightness == Brightness.light
|
|
||||||
? 255
|
|
||||||
: 150),
|
|
||||||
child: Text(client.name[0])))),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -860,6 +854,20 @@ class ClientInfo extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildAvatar(BuildContext context) {
|
||||||
|
final fallback = CircleAvatar(
|
||||||
|
backgroundColor: str2color(client.name,
|
||||||
|
Theme.of(context).brightness == Brightness.light ? 255 : 150),
|
||||||
|
child: Text(client.name.isNotEmpty ? client.name[0] : '?'),
|
||||||
|
);
|
||||||
|
return buildAvatarWidget(
|
||||||
|
avatar: client.avatar,
|
||||||
|
size: 40,
|
||||||
|
fallback: fallback,
|
||||||
|
) ??
|
||||||
|
fallback;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void androidChannelInit() {
|
void androidChannelInit() {
|
||||||
|
|||||||
@@ -617,7 +617,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
|||||||
onToggle: (bool v) async {
|
onToggle: (bool v) async {
|
||||||
await mainSetLocalBoolOption(kOptionEnableShowTerminalExtraKeys, v);
|
await mainSetLocalBoolOption(kOptionEnableShowTerminalExtraKeys, v);
|
||||||
final newValue =
|
final newValue =
|
||||||
mainGetLocalBoolOptionSync(kOptionEnableShowTerminalExtraKeys);
|
mainGetLocalBoolOptionSync(kOptionEnableShowTerminalExtraKeys);
|
||||||
setState(() {
|
setState(() {
|
||||||
_showTerminalExtraKeys = newValue;
|
_showTerminalExtraKeys = newValue;
|
||||||
});
|
});
|
||||||
@@ -689,7 +689,17 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
|||||||
title: Obx(() => Text(gFFI.userModel.userName.value.isEmpty
|
title: Obx(() => Text(gFFI.userModel.userName.value.isEmpty
|
||||||
? translate('Login')
|
? translate('Login')
|
||||||
: '${translate('Logout')} (${gFFI.userModel.accountLabelWithHandle})')),
|
: '${translate('Logout')} (${gFFI.userModel.accountLabelWithHandle})')),
|
||||||
leading: Icon(Icons.person),
|
leading: Obx(() {
|
||||||
|
final avatar = bind.mainResolveAvatarUrl(
|
||||||
|
avatar: gFFI.userModel.avatar.value);
|
||||||
|
return buildAvatarWidget(
|
||||||
|
avatar: avatar,
|
||||||
|
size: 28,
|
||||||
|
borderRadius: null,
|
||||||
|
fallback: Icon(Icons.person),
|
||||||
|
) ??
|
||||||
|
Icon(Icons.person);
|
||||||
|
}),
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
if (gFFI.userModel.userName.value.isEmpty) {
|
if (gFFI.userModel.userName.value.isEmpty) {
|
||||||
loginDialog();
|
loginDialog();
|
||||||
@@ -829,10 +839,12 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
|||||||
),
|
),
|
||||||
if (!incomingOnly)
|
if (!incomingOnly)
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: Text(translate('keep-awake-during-outgoing-sessions-label')),
|
title:
|
||||||
|
Text(translate('keep-awake-during-outgoing-sessions-label')),
|
||||||
initialValue: _preventSleepWhileConnected,
|
initialValue: _preventSleepWhileConnected,
|
||||||
onToggle: (v) async {
|
onToggle: (v) async {
|
||||||
await mainSetLocalBoolOption(kOptionKeepAwakeDuringOutgoingSessions, v);
|
await mainSetLocalBoolOption(
|
||||||
|
kOptionKeepAwakeDuringOutgoingSessions, v);
|
||||||
setState(() {
|
setState(() {
|
||||||
_preventSleepWhileConnected = v;
|
_preventSleepWhileConnected = v;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -348,6 +348,12 @@ class InputModel {
|
|||||||
final _trackpadAdjustPeerLinux = 0.06;
|
final _trackpadAdjustPeerLinux = 0.06;
|
||||||
// This is an experience value.
|
// This is an experience value.
|
||||||
final _trackpadAdjustMacToWin = 2.50;
|
final _trackpadAdjustMacToWin = 2.50;
|
||||||
|
// Ignore directional locking for very small deltas on both axes (including
|
||||||
|
// tiny single-axis movement) to avoid over-filtering near zero.
|
||||||
|
static const double _trackpadAxisNoiseThreshold = 0.2;
|
||||||
|
// Lock to dominant axis only when one axis is clearly stronger.
|
||||||
|
// 1.6 means the dominant axis must be >= 60% larger than the other.
|
||||||
|
static const double _trackpadAxisLockRatio = 1.6;
|
||||||
int _trackpadSpeed = kDefaultTrackpadSpeed;
|
int _trackpadSpeed = kDefaultTrackpadSpeed;
|
||||||
double _trackpadSpeedInner = kDefaultTrackpadSpeed / 100.0;
|
double _trackpadSpeedInner = kDefaultTrackpadSpeed / 100.0;
|
||||||
var _trackpadScrollUnsent = Offset.zero;
|
var _trackpadScrollUnsent = Offset.zero;
|
||||||
@@ -1172,6 +1178,7 @@ class InputModel {
|
|||||||
if (isMacOS && peerPlatform == kPeerPlatformWindows) {
|
if (isMacOS && peerPlatform == kPeerPlatformWindows) {
|
||||||
delta *= _trackpadAdjustMacToWin;
|
delta *= _trackpadAdjustMacToWin;
|
||||||
}
|
}
|
||||||
|
delta = _filterTrackpadDeltaAxis(delta);
|
||||||
_trackpadLastDelta = delta;
|
_trackpadLastDelta = delta;
|
||||||
|
|
||||||
var x = delta.dx.toInt();
|
var x = delta.dx.toInt();
|
||||||
@@ -1204,6 +1211,24 @@ class InputModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Offset _filterTrackpadDeltaAxis(Offset delta) {
|
||||||
|
final absDx = delta.dx.abs();
|
||||||
|
final absDy = delta.dy.abs();
|
||||||
|
// Keep diagonal intent when movement is tiny on both axes.
|
||||||
|
if (absDx < _trackpadAxisNoiseThreshold &&
|
||||||
|
absDy < _trackpadAxisNoiseThreshold) {
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
// Dominant-axis lock to reduce accidental cross-axis scrolling noise.
|
||||||
|
if (absDy >= absDx * _trackpadAxisLockRatio) {
|
||||||
|
return Offset(0, delta.dy);
|
||||||
|
}
|
||||||
|
if (absDx >= absDy * _trackpadAxisLockRatio) {
|
||||||
|
return Offset(delta.dx, 0);
|
||||||
|
}
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
void _scheduleFling(double x, double y, int delay) {
|
void _scheduleFling(double x, double y, int delay) {
|
||||||
if (isViewCamera) return;
|
if (isViewCamera) return;
|
||||||
if ((x == 0 && y == 0) || _stopFling) {
|
if ((x == 0 && y == 0) || _stopFling) {
|
||||||
|
|||||||
@@ -2152,6 +2152,9 @@ class CanvasModel with ChangeNotifier {
|
|||||||
ViewStyle _lastViewStyle = ViewStyle.defaultViewStyle();
|
ViewStyle _lastViewStyle = ViewStyle.defaultViewStyle();
|
||||||
|
|
||||||
Timer? _timerMobileFocusCanvasCursor;
|
Timer? _timerMobileFocusCanvasCursor;
|
||||||
|
Timer? _timerMobileRestoreCanvasOffset;
|
||||||
|
Offset? _offsetBeforeMobileSoftKeyboard;
|
||||||
|
double? _scaleBeforeMobileSoftKeyboard;
|
||||||
|
|
||||||
// `isMobileCanvasChanged` is used to avoid canvas reset when changing the input method
|
// `isMobileCanvasChanged` is used to avoid canvas reset when changing the input method
|
||||||
// after showing the soft keyboard.
|
// after showing the soft keyboard.
|
||||||
@@ -2639,6 +2642,9 @@ class CanvasModel with ChangeNotifier {
|
|||||||
_scale = 1.0;
|
_scale = 1.0;
|
||||||
_lastViewStyle = ViewStyle.defaultViewStyle();
|
_lastViewStyle = ViewStyle.defaultViewStyle();
|
||||||
_timerMobileFocusCanvasCursor?.cancel();
|
_timerMobileFocusCanvasCursor?.cancel();
|
||||||
|
_timerMobileRestoreCanvasOffset?.cancel();
|
||||||
|
_offsetBeforeMobileSoftKeyboard = null;
|
||||||
|
_scaleBeforeMobileSoftKeyboard = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateScrollPercent() {
|
updateScrollPercent() {
|
||||||
@@ -2667,6 +2673,31 @@ class CanvasModel with ChangeNotifier {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveMobileOffsetBeforeSoftKeyboard() {
|
||||||
|
_timerMobileRestoreCanvasOffset?.cancel();
|
||||||
|
_offsetBeforeMobileSoftKeyboard = Offset(_x, _y);
|
||||||
|
_scaleBeforeMobileSoftKeyboard = _scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void restoreMobileOffsetAfterSoftKeyboard() {
|
||||||
|
_timerMobileRestoreCanvasOffset?.cancel();
|
||||||
|
_timerMobileFocusCanvasCursor?.cancel();
|
||||||
|
final targetOffset = _offsetBeforeMobileSoftKeyboard;
|
||||||
|
final targetScale = _scaleBeforeMobileSoftKeyboard;
|
||||||
|
if (targetOffset == null || targetScale == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_timerMobileRestoreCanvasOffset = Timer(Duration(milliseconds: 100), () {
|
||||||
|
updateSize();
|
||||||
|
_x = targetOffset.dx;
|
||||||
|
_y = targetOffset.dy;
|
||||||
|
_scale = targetScale;
|
||||||
|
_offsetBeforeMobileSoftKeyboard = null;
|
||||||
|
_scaleBeforeMobileSoftKeyboard = null;
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// mobile only
|
// mobile only
|
||||||
// Move the canvas to make the cursor visible(center) on the screen.
|
// Move the canvas to make the cursor visible(center) on the screen.
|
||||||
void _moveToCenterCursor() {
|
void _moveToCenterCursor() {
|
||||||
@@ -2919,8 +2950,13 @@ class CursorModel with ChangeNotifier {
|
|||||||
_lastIsBlocked = true;
|
_lastIsBlocked = true;
|
||||||
}
|
}
|
||||||
if (isMobile && _lastKeyboardIsVisible != keyboardIsVisible) {
|
if (isMobile && _lastKeyboardIsVisible != keyboardIsVisible) {
|
||||||
parent.target?.canvasModel.mobileFocusCanvasCursor();
|
if (keyboardIsVisible) {
|
||||||
parent.target?.canvasModel.isMobileCanvasChanged = false;
|
parent.target?.canvasModel.saveMobileOffsetBeforeSoftKeyboard();
|
||||||
|
parent.target?.canvasModel.mobileFocusCanvasCursor();
|
||||||
|
parent.target?.canvasModel.isMobileCanvasChanged = false;
|
||||||
|
} else {
|
||||||
|
parent.target?.canvasModel.restoreMobileOffsetAfterSoftKeyboard();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_lastKeyboardIsVisible = keyboardIsVisible;
|
_lastKeyboardIsVisible = keyboardIsVisible;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -820,6 +820,7 @@ class Client {
|
|||||||
bool isTerminal = false;
|
bool isTerminal = false;
|
||||||
String portForward = "";
|
String portForward = "";
|
||||||
String name = "";
|
String name = "";
|
||||||
|
String avatar = "";
|
||||||
String peerId = ""; // peer user's id,show at app
|
String peerId = ""; // peer user's id,show at app
|
||||||
bool keyboard = false;
|
bool keyboard = false;
|
||||||
bool clipboard = false;
|
bool clipboard = false;
|
||||||
@@ -847,6 +848,7 @@ class Client {
|
|||||||
isTerminal = json['is_terminal'] ?? false;
|
isTerminal = json['is_terminal'] ?? false;
|
||||||
portForward = json['port_forward'];
|
portForward = json['port_forward'];
|
||||||
name = json['name'];
|
name = json['name'];
|
||||||
|
avatar = json['avatar'] ?? '';
|
||||||
peerId = json['peer_id'];
|
peerId = json['peer_id'];
|
||||||
keyboard = json['keyboard'];
|
keyboard = json['keyboard'];
|
||||||
clipboard = json['clipboard'];
|
clipboard = json['clipboard'];
|
||||||
@@ -870,6 +872,7 @@ class Client {
|
|||||||
data['is_terminal'] = isTerminal;
|
data['is_terminal'] = isTerminal;
|
||||||
data['port_forward'] = portForward;
|
data['port_forward'] = portForward;
|
||||||
data['name'] = name;
|
data['name'] = name;
|
||||||
|
data['avatar'] = avatar;
|
||||||
data['peer_id'] = peerId;
|
data['peer_id'] = peerId;
|
||||||
data['keyboard'] = keyboard;
|
data['keyboard'] = keyboard;
|
||||||
data['clipboard'] = clipboard;
|
data['clipboard'] = clipboard;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ bool refreshingUser = false;
|
|||||||
class UserModel {
|
class UserModel {
|
||||||
final RxString userName = ''.obs;
|
final RxString userName = ''.obs;
|
||||||
final RxString displayName = ''.obs;
|
final RxString displayName = ''.obs;
|
||||||
|
final RxString avatar = ''.obs;
|
||||||
final RxBool isAdmin = false.obs;
|
final RxBool isAdmin = false.obs;
|
||||||
final RxString networkError = ''.obs;
|
final RxString networkError = ''.obs;
|
||||||
bool get isLogin => userName.isNotEmpty;
|
bool get isLogin => userName.isNotEmpty;
|
||||||
@@ -33,6 +34,7 @@ class UserModel {
|
|||||||
}
|
}
|
||||||
return '$preferred (@$username)';
|
return '$preferred (@$username)';
|
||||||
}
|
}
|
||||||
|
|
||||||
WeakReference<FFI> parent;
|
WeakReference<FFI> parent;
|
||||||
|
|
||||||
UserModel(this.parent) {
|
UserModel(this.parent) {
|
||||||
@@ -114,6 +116,7 @@ class UserModel {
|
|||||||
if (userInfo != null) {
|
if (userInfo != null) {
|
||||||
userName.value = (userInfo['name'] ?? '').toString();
|
userName.value = (userInfo['name'] ?? '').toString();
|
||||||
displayName.value = (userInfo['display_name'] ?? '').toString();
|
displayName.value = (userInfo['display_name'] ?? '').toString();
|
||||||
|
avatar.value = (userInfo['avatar'] ?? '').toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,11 +129,13 @@ class UserModel {
|
|||||||
}
|
}
|
||||||
userName.value = '';
|
userName.value = '';
|
||||||
displayName.value = '';
|
displayName.value = '';
|
||||||
|
avatar.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
_parseAndUpdateUser(UserPayload user) {
|
_parseAndUpdateUser(UserPayload user) {
|
||||||
userName.value = user.name;
|
userName.value = user.name;
|
||||||
displayName.value = user.displayName;
|
displayName.value = user.displayName;
|
||||||
|
avatar.value = user.avatar;
|
||||||
isAdmin.value = user.isAdmin;
|
isAdmin.value = user.isAdmin;
|
||||||
bind.mainSetLocalOption(key: 'user_info', value: jsonEncode(user));
|
bind.mainSetLocalOption(key: 'user_info', value: jsonEncode(user));
|
||||||
if (isWeb) {
|
if (isWeb) {
|
||||||
|
|||||||
@@ -2034,5 +2034,9 @@ class RustdeskImpl {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String mainResolveAvatarUrl({required String avatar, dynamic hint}) {
|
||||||
|
return js.context.callMethod('getByName', ['resolve_avatar_url', avatar])?.toString() ?? avatar;
|
||||||
|
}
|
||||||
|
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ impl KeyboardControllable for Enigo {
|
|||||||
for pos in 0..mod_len {
|
for pos in 0..mod_len {
|
||||||
let rpos = mod_len - 1 - pos;
|
let rpos = mod_len - 1 - pos;
|
||||||
if flag & (0x0001 << rpos) != 0 {
|
if flag & (0x0001 << rpos) != 0 {
|
||||||
self.key_up(modifiers[pos]);
|
self.key_up(modifiers[rpos]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +298,18 @@ impl KeyboardControllable for Enigo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn key_up(&mut self, key: Key) {
|
fn key_up(&mut self, key: Key) {
|
||||||
keybd_event(KEYEVENTF_KEYUP, self.key_to_keycode(key), 0);
|
match key {
|
||||||
|
Key::Layout(c) => {
|
||||||
|
let code = self.get_layoutdependent_keycode(c);
|
||||||
|
if code as u16 != 0xFFFF {
|
||||||
|
let vk = code & 0x00FF;
|
||||||
|
keybd_event(KEYEVENTF_KEYUP, vk, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
keybd_event(KEYEVENTF_KEYUP, self.key_to_keycode(key), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_key_state(&mut self, key: Key) -> bool {
|
fn get_key_state(&mut self, key: Key) -> bool {
|
||||||
|
|||||||
Submodule libs/hbb_common updated: 5e07db7444...48c37de3e6
@@ -33,7 +33,7 @@ use crate::{
|
|||||||
create_symmetric_key_msg, decode_id_pk, get_rs_pk, is_keyboard_mode_supported,
|
create_symmetric_key_msg, decode_id_pk, get_rs_pk, is_keyboard_mode_supported,
|
||||||
kcp_stream::KcpStream,
|
kcp_stream::KcpStream,
|
||||||
secure_tcp,
|
secure_tcp,
|
||||||
ui_interface::{get_builtin_option, use_texture_render},
|
ui_interface::{get_builtin_option, resolve_avatar_url, use_texture_render},
|
||||||
ui_session_interface::{InvokeUiSession, Session},
|
ui_session_interface::{InvokeUiSession, Session},
|
||||||
};
|
};
|
||||||
#[cfg(feature = "unix-file-copy-paste")]
|
#[cfg(feature = "unix-file-copy-paste")]
|
||||||
@@ -2625,6 +2625,20 @@ impl LoginConfigHandler {
|
|||||||
} else {
|
} else {
|
||||||
(my_id, self.id.clone())
|
(my_id, self.id.clone())
|
||||||
};
|
};
|
||||||
|
let mut avatar = get_builtin_option(keys::OPTION_AVATAR);
|
||||||
|
if avatar.is_empty() {
|
||||||
|
avatar = serde_json::from_str::<serde_json::Value>(&LocalConfig::get_option(
|
||||||
|
"user_info",
|
||||||
|
))
|
||||||
|
.ok()
|
||||||
|
.and_then(|x| {
|
||||||
|
x.get("avatar")
|
||||||
|
.and_then(|x| x.as_str())
|
||||||
|
.map(|x| x.trim().to_owned())
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
}
|
||||||
|
avatar = resolve_avatar_url(avatar);
|
||||||
let mut display_name = get_builtin_option(keys::OPTION_DISPLAY_NAME);
|
let mut display_name = get_builtin_option(keys::OPTION_DISPLAY_NAME);
|
||||||
if display_name.is_empty() {
|
if display_name.is_empty() {
|
||||||
display_name =
|
display_name =
|
||||||
@@ -2684,6 +2698,7 @@ impl LoginConfigHandler {
|
|||||||
})
|
})
|
||||||
.into(),
|
.into(),
|
||||||
hwid,
|
hwid,
|
||||||
|
avatar,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
match self.conn_type {
|
match self.conn_type {
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ pub fn core_main() -> Option<Vec<String>> {
|
|||||||
}
|
}
|
||||||
Ok(false) => "Update failed!".to_string(),
|
Ok(false) => "Update failed!".to_string(),
|
||||||
Ok(true) => match platform::update_me(false) {
|
Ok(true) => match platform::update_me(false) {
|
||||||
Ok(_) => "Update successfully!".to_string(),
|
Ok(_) => "Updated successfully!".to_string(),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("Failed with error: {err}");
|
log::error!("Failed with error: {err}");
|
||||||
"Update failed!".to_string()
|
"Update failed!".to_string()
|
||||||
@@ -335,8 +335,8 @@ pub fn core_main() -> Option<Vec<String>> {
|
|||||||
log::info!("Starting update process...");
|
log::info!("Starting update process...");
|
||||||
let _text = match platform::update_me() {
|
let _text = match platform::update_me() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("{}", translate("Update successfully!".to_string()));
|
println!("{}", translate("Updated successfully!".to_string()));
|
||||||
log::info!("Update successfully!");
|
log::info!("Updated successfully!");
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("Update failed with error: {}", err);
|
eprintln!("Update failed with error: {}", err);
|
||||||
|
|||||||
@@ -1101,6 +1101,10 @@ pub fn main_get_api_server() -> String {
|
|||||||
get_api_server()
|
get_api_server()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main_resolve_avatar_url(avatar: String) -> SyncReturn<String> {
|
||||||
|
SyncReturn(resolve_avatar_url(avatar))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main_http_request(url: String, method: String, body: Option<String>, header: String) {
|
pub fn main_http_request(url: String, method: String, body: Option<String>, header: String) {
|
||||||
http_request(url, method, body, header)
|
http_request(url, method, body, header)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ lazy_static::lazy_static! {
|
|||||||
|
|
||||||
const QUERY_INTERVAL_SECS: f32 = 1.0;
|
const QUERY_INTERVAL_SECS: f32 = 1.0;
|
||||||
const QUERY_TIMEOUT_SECS: u64 = 60 * 3;
|
const QUERY_TIMEOUT_SECS: u64 = 60 * 3;
|
||||||
|
|
||||||
const REQUESTING_ACCOUNT_AUTH: &str = "Requesting account auth";
|
const REQUESTING_ACCOUNT_AUTH: &str = "Requesting account auth";
|
||||||
const WAITING_ACCOUNT_AUTH: &str = "Waiting account auth";
|
const WAITING_ACCOUNT_AUTH: &str = "Waiting account auth";
|
||||||
const LOGIN_ACCOUNT_AUTH: &str = "Login account auth";
|
const LOGIN_ACCOUNT_AUTH: &str = "Login account auth";
|
||||||
@@ -82,6 +83,8 @@ pub struct UserPayload {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub display_name: Option<String>,
|
pub display_name: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub avatar: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub note: Option<String>,
|
pub note: Option<String>,
|
||||||
@@ -273,6 +276,7 @@ impl OidcSession {
|
|||||||
serde_json::json!({
|
serde_json::json!({
|
||||||
"name": auth_body.user.name,
|
"name": auth_body.user.name,
|
||||||
"display_name": auth_body.user.display_name,
|
"display_name": auth_body.user.display_name,
|
||||||
|
"avatar": auth_body.user.avatar,
|
||||||
"status": auth_body.user.status
|
"status": auth_body.user.status
|
||||||
})
|
})
|
||||||
.to_string(),
|
.to_string(),
|
||||||
|
|||||||
@@ -286,10 +286,14 @@ fn heartbeat_url() -> String {
|
|||||||
|
|
||||||
fn handle_config_options(config_options: HashMap<String, String>) {
|
fn handle_config_options(config_options: HashMap<String, String>) {
|
||||||
let mut options = Config::get_options();
|
let mut options = Config::get_options();
|
||||||
|
let default_settings = config::DEFAULT_SETTINGS.read().unwrap().clone();
|
||||||
config_options
|
config_options
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
if v.is_empty() {
|
// Priority: user config > default advanced options.
|
||||||
|
// Only when default advanced options are also empty, remove user option (fallback to built-in default);
|
||||||
|
// otherwise insert an empty value so user config remains present.
|
||||||
|
if v.is_empty() && default_settings.get(k).map_or("", |v| v).is_empty() {
|
||||||
options.remove(k);
|
options.remove(k);
|
||||||
} else {
|
} else {
|
||||||
options.insert(k.to_string(), v.to_string());
|
options.insert(k.to_string(), v.to_string());
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ pub enum Data {
|
|||||||
is_terminal: bool,
|
is_terminal: bool,
|
||||||
peer_id: String,
|
peer_id: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
avatar: String,
|
||||||
authorized: bool,
|
authorized: bool,
|
||||||
port_forward: String,
|
port_forward: String,
|
||||||
keyboard: bool,
|
keyboard: bool,
|
||||||
@@ -1583,6 +1584,6 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn verify_ffi_enum_data_size() {
|
fn verify_ffi_enum_data_size() {
|
||||||
println!("{}", std::mem::size_of::<Data>());
|
println!("{}", std::mem::size_of::<Data>());
|
||||||
assert!(std::mem::size_of::<Data>() <= 96);
|
assert!(std::mem::size_of::<Data>() <= 120);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -738,5 +738,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Changelog", "Változáslista"),
|
("Changelog", "Változáslista"),
|
||||||
("keep-awake-during-outgoing-sessions-label", "Képernyő aktív állapotban tartása a kimenő munkamenetek során"),
|
("keep-awake-during-outgoing-sessions-label", "Képernyő aktív állapotban tartása a kimenő munkamenetek során"),
|
||||||
("keep-awake-during-incoming-sessions-label", "Képernyő aktív állapotban tartása a bejövő munkamenetek során"),
|
("keep-awake-during-incoming-sessions-label", "Képernyő aktív állapotban tartása a bejövő munkamenetek során"),
|
||||||
|
("Continue with {}", "Folytatás ezzel: {}"),
|
||||||
|
("Display Name", "Kijelző név"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -859,9 +859,10 @@ on run {app_name, cur_pid, app_dir, user_name}
|
|||||||
set app_dir_q to quoted form of app_dir
|
set app_dir_q to quoted form of app_dir
|
||||||
set user_name_q to quoted form of user_name
|
set user_name_q to quoted form of user_name
|
||||||
|
|
||||||
|
set check_source to "test -d " & app_dir_q & " || exit 1;"
|
||||||
set kill_others to "pids=$(pgrep -x '" & app_name & "' | grep -vx " & cur_pid & " || true); if [ -n \"$pids\" ]; then echo \"$pids\" | xargs kill -9 || true; fi;"
|
set kill_others to "pids=$(pgrep -x '" & app_name & "' | grep -vx " & cur_pid & " || true); if [ -n \"$pids\" ]; then echo \"$pids\" | xargs kill -9 || true; fi;"
|
||||||
set copy_files to "rm -rf " & app_bundle_q & " && ditto " & app_dir_q & " " & app_bundle_q & " && chown -R " & user_name_q & ":staff " & app_bundle_q & " && (xattr -r -d com.apple.quarantine " & app_bundle_q & " || true);"
|
set copy_files to "rm -rf " & app_bundle_q & " && ditto " & app_dir_q & " " & app_bundle_q & " && chown -R " & user_name_q & ":staff " & app_bundle_q & " && (xattr -r -d com.apple.quarantine " & app_bundle_q & " || true);"
|
||||||
set sh to "set -e;" & kill_others & copy_files
|
set sh to "set -e;" & check_source & kill_others & copy_files
|
||||||
|
|
||||||
do shell script sh with prompt app_name & " wants to update itself" with administrator privileges
|
do shell script sh with prompt app_name & " wants to update itself" with administrator privileges
|
||||||
end run
|
end run
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ on run {daemon_file, agent_file, user, cur_pid, source_dir}
|
|||||||
set daemon_plist to "/Library/LaunchDaemons/com.carriez.RustDesk_service.plist"
|
set daemon_plist to "/Library/LaunchDaemons/com.carriez.RustDesk_service.plist"
|
||||||
set app_bundle to "/Applications/RustDesk.app"
|
set app_bundle to "/Applications/RustDesk.app"
|
||||||
|
|
||||||
|
set check_source to "test -d " & quoted form of source_dir & " || exit 1;"
|
||||||
set resolve_uid to "uid=$(id -u " & quoted form of user & " 2>/dev/null || true);"
|
set resolve_uid to "uid=$(id -u " & quoted form of user & " 2>/dev/null || true);"
|
||||||
set unload_agent to "if [ -n \"$uid\" ]; then launchctl bootout gui/$uid " & quoted form of agent_plist & " 2>/dev/null || launchctl bootout user/$uid " & quoted form of agent_plist & " 2>/dev/null || launchctl unload -w " & quoted form of agent_plist & " || true; else launchctl unload -w " & quoted form of agent_plist & " || true; fi;"
|
set unload_agent to "if [ -n \"$uid\" ]; then launchctl bootout gui/$uid " & quoted form of agent_plist & " 2>/dev/null || launchctl bootout user/$uid " & quoted form of agent_plist & " 2>/dev/null || launchctl unload -w " & quoted form of agent_plist & " || true; else launchctl unload -w " & quoted form of agent_plist & " || true; fi;"
|
||||||
set unload_service to "launchctl unload -w " & daemon_plist & " || true;"
|
set unload_service to "launchctl unload -w " & daemon_plist & " || true;"
|
||||||
@@ -19,7 +20,7 @@ on run {daemon_file, agent_file, user, cur_pid, source_dir}
|
|||||||
set kickstart_agent to "if [ -n \"$uid\" ]; then launchctl kickstart -k gui/$uid/$agent_label 2>/dev/null || launchctl kickstart -k user/$uid/$agent_label 2>/dev/null || true; fi;"
|
set kickstart_agent to "if [ -n \"$uid\" ]; then launchctl kickstart -k gui/$uid/$agent_label 2>/dev/null || launchctl kickstart -k user/$uid/$agent_label 2>/dev/null || true; fi;"
|
||||||
set load_agent to agent_label_cmd & bootstrap_agent & kickstart_agent
|
set load_agent to agent_label_cmd & bootstrap_agent & kickstart_agent
|
||||||
|
|
||||||
set sh to "set -e;" & resolve_uid & unload_agent & unload_service & kill_others & copy_files & write_daemon_plist & write_agent_plist & load_service & load_agent
|
set sh to "set -e;" & check_source & resolve_uid & unload_agent & unload_service & kill_others & copy_files & write_daemon_plist & write_agent_plist & load_service & load_agent
|
||||||
|
|
||||||
do shell script sh with prompt "RustDesk wants to update itself" with administrator privileges
|
do shell script sh with prompt "RustDesk wants to update itself" with administrator privileges
|
||||||
end run
|
end run
|
||||||
|
|||||||
@@ -560,7 +560,9 @@ impl Connection {
|
|||||||
match data {
|
match data {
|
||||||
ipc::Data::Authorize => {
|
ipc::Data::Authorize => {
|
||||||
conn.require_2fa.take();
|
conn.require_2fa.take();
|
||||||
conn.send_logon_response().await;
|
if !conn.send_logon_response_and_keep_alive().await {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if conn.port_forward_socket.is_some() {
|
if conn.port_forward_socket.is_some() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1338,9 +1340,66 @@ impl Connection {
|
|||||||
crate::post_request(url, v.to_string(), "").await
|
crate::post_request(url, v.to_string(), "").await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_logon_response(&mut self) {
|
fn normalize_port_forward_target(pf: &mut PortForward) -> (String, bool) {
|
||||||
|
let mut is_rdp = false;
|
||||||
|
if pf.host == "RDP" && pf.port == 0 {
|
||||||
|
pf.host = "localhost".to_owned();
|
||||||
|
pf.port = 3389;
|
||||||
|
is_rdp = true;
|
||||||
|
}
|
||||||
|
if pf.host.is_empty() {
|
||||||
|
pf.host = "localhost".to_owned();
|
||||||
|
}
|
||||||
|
(format!("{}:{}", pf.host, pf.port), is_rdp)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn connect_port_forward_if_needed(&mut self) -> bool {
|
||||||
|
if self.port_forward_socket.is_some() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let Some(login_request::Union::PortForward(pf)) = self.lr.union.as_ref() else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
let mut pf = pf.clone();
|
||||||
|
let (mut addr, is_rdp) = Self::normalize_port_forward_target(&mut pf);
|
||||||
|
self.port_forward_address = addr.clone();
|
||||||
|
match timeout(3000, TcpStream::connect(&addr)).await {
|
||||||
|
Ok(Ok(sock)) => {
|
||||||
|
self.port_forward_socket = Some(Framed::new(sock, BytesCodec::new()));
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
log::warn!("Port forward connect failed for {}: {}", addr, e);
|
||||||
|
if is_rdp {
|
||||||
|
addr = "RDP".to_owned();
|
||||||
|
}
|
||||||
|
self.send_login_error(format!(
|
||||||
|
"Failed to access remote {}. Please make sure it is reachable/open.",
|
||||||
|
addr
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
false
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Port forward connect timed out for {}: {}", addr, e);
|
||||||
|
if is_rdp {
|
||||||
|
addr = "RDP".to_owned();
|
||||||
|
}
|
||||||
|
self.send_login_error(format!(
|
||||||
|
"Failed to access remote {}. Please make sure it is reachable/open.",
|
||||||
|
addr
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns whether this connection should be kept alive.
|
||||||
|
// `true` does not necessarily mean authorization succeeded (e.g. REQUIRE_2FA case).
|
||||||
|
async fn send_logon_response_and_keep_alive(&mut self) -> bool {
|
||||||
if self.authorized {
|
if self.authorized {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
if self.require_2fa.is_some() && !self.is_recent_session(true) && !self.from_switch {
|
if self.require_2fa.is_some() && !self.is_recent_session(true) && !self.from_switch {
|
||||||
self.require_2fa.as_ref().map(|totp| {
|
self.require_2fa.as_ref().map(|totp| {
|
||||||
@@ -1371,7 +1430,11 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.send_login_error(crate::client::REQUIRE_2FA).await;
|
self.send_login_error(crate::client::REQUIRE_2FA).await;
|
||||||
return;
|
// Keep the connection alive so the client can continue with 2FA.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if !self.connect_port_forward_if_needed().await {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
self.authorized = true;
|
self.authorized = true;
|
||||||
let (conn_type, auth_conn_type) = if self.file_transfer.is_some() {
|
let (conn_type, auth_conn_type) = if self.file_transfer.is_some() {
|
||||||
@@ -1494,7 +1557,7 @@ impl Connection {
|
|||||||
res.set_peer_info(pi);
|
res.set_peer_info(pi);
|
||||||
msg_out.set_login_response(res);
|
msg_out.set_login_response(res);
|
||||||
self.send(msg_out).await;
|
self.send(msg_out).await;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
if self.is_remote() {
|
if self.is_remote() {
|
||||||
@@ -1517,7 +1580,7 @@ impl Connection {
|
|||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
msg_out.set_login_response(res);
|
msg_out.set_login_response(res);
|
||||||
self.send(msg_out).await;
|
self.send(msg_out).await;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
@@ -1671,6 +1734,7 @@ impl Connection {
|
|||||||
self.try_sub_monitor_services();
|
self.try_sub_monitor_services();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_sub_camera_displays(&mut self) {
|
fn try_sub_camera_displays(&mut self) {
|
||||||
@@ -1813,6 +1877,7 @@ impl Connection {
|
|||||||
port_forward: self.port_forward_address.clone(),
|
port_forward: self.port_forward_address.clone(),
|
||||||
peer_id,
|
peer_id,
|
||||||
name,
|
name,
|
||||||
|
avatar: self.lr.avatar.clone(),
|
||||||
authorized,
|
authorized,
|
||||||
keyboard: self.keyboard,
|
keyboard: self.keyboard,
|
||||||
clipboard: self.clipboard,
|
clipboard: self.clipboard,
|
||||||
@@ -2178,33 +2243,8 @@ impl Connection {
|
|||||||
sleep(1.).await;
|
sleep(1.).await;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let mut is_rdp = false;
|
let (addr, _is_rdp) = Self::normalize_port_forward_target(&mut pf);
|
||||||
if pf.host == "RDP" && pf.port == 0 {
|
self.port_forward_address = addr;
|
||||||
pf.host = "localhost".to_owned();
|
|
||||||
pf.port = 3389;
|
|
||||||
is_rdp = true;
|
|
||||||
}
|
|
||||||
if pf.host.is_empty() {
|
|
||||||
pf.host = "localhost".to_owned();
|
|
||||||
}
|
|
||||||
let mut addr = format!("{}:{}", pf.host, pf.port);
|
|
||||||
self.port_forward_address = addr.clone();
|
|
||||||
match timeout(3000, TcpStream::connect(&addr)).await {
|
|
||||||
Ok(Ok(sock)) => {
|
|
||||||
self.port_forward_socket = Some(Framed::new(sock, BytesCodec::new()));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if is_rdp {
|
|
||||||
addr = "RDP".to_owned();
|
|
||||||
}
|
|
||||||
self.send_login_error(format!(
|
|
||||||
"Failed to access remote {}, please make sure if it is open",
|
|
||||||
addr
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if !self.check_privacy_mode_on().await {
|
if !self.check_privacy_mode_on().await {
|
||||||
@@ -2235,9 +2275,7 @@ impl Connection {
|
|||||||
// `is_logon_ui()` is a fallback for logon UI detection on Windows.
|
// `is_logon_ui()` is a fallback for logon UI detection on Windows.
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let is_logon = || {
|
let is_logon = || {
|
||||||
crate::platform::is_prelogin()
|
crate::platform::is_prelogin() || crate::platform::is_locked() || {
|
||||||
|| crate::platform::is_locked()
|
|
||||||
|| {
|
|
||||||
match crate::platform::is_logon_ui() {
|
match crate::platform::is_logon_ui() {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -2276,7 +2314,9 @@ impl Connection {
|
|||||||
if err_msg.is_empty() {
|
if err_msg.is_empty() {
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
self.linux_headless_handle.wait_desktop_cm_ready().await;
|
self.linux_headless_handle.wait_desktop_cm_ready().await;
|
||||||
self.send_logon_response().await;
|
if !self.send_logon_response_and_keep_alive().await {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
self.try_start_cm(lr.my_id.clone(), lr.my_name.clone(), self.authorized);
|
self.try_start_cm(lr.my_id.clone(), lr.my_name.clone(), self.authorized);
|
||||||
} else {
|
} else {
|
||||||
self.send_login_error(err_msg).await;
|
self.send_login_error(err_msg).await;
|
||||||
@@ -2312,7 +2352,9 @@ impl Connection {
|
|||||||
if err_msg.is_empty() {
|
if err_msg.is_empty() {
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
self.linux_headless_handle.wait_desktop_cm_ready().await;
|
self.linux_headless_handle.wait_desktop_cm_ready().await;
|
||||||
self.send_logon_response().await;
|
if !self.send_logon_response_and_keep_alive().await {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
self.try_start_cm(lr.my_id, lr.my_name, self.authorized);
|
self.try_start_cm(lr.my_id, lr.my_name, self.authorized);
|
||||||
} else {
|
} else {
|
||||||
self.send_login_error(err_msg).await;
|
self.send_login_error(err_msg).await;
|
||||||
@@ -2330,7 +2372,9 @@ impl Connection {
|
|||||||
self.update_failure(failure, true, 1);
|
self.update_failure(failure, true, 1);
|
||||||
self.require_2fa.take();
|
self.require_2fa.take();
|
||||||
raii::AuthedConnID::set_session_2fa(self.session_key());
|
raii::AuthedConnID::set_session_2fa(self.session_key());
|
||||||
self.send_logon_response().await;
|
if !self.send_logon_response_and_keep_alive().await {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
self.try_start_cm(
|
self.try_start_cm(
|
||||||
self.lr.my_id.to_owned(),
|
self.lr.my_id.to_owned(),
|
||||||
self.lr.my_name.to_owned(),
|
self.lr.my_name.to_owned(),
|
||||||
@@ -2381,7 +2425,9 @@ impl Connection {
|
|||||||
if let Some((_instant, uuid_old)) = uuid_old {
|
if let Some((_instant, uuid_old)) = uuid_old {
|
||||||
if uuid == uuid_old {
|
if uuid == uuid_old {
|
||||||
self.from_switch = true;
|
self.from_switch = true;
|
||||||
self.send_logon_response().await;
|
if !self.send_logon_response_and_keep_alive().await {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
self.try_start_cm(
|
self.try_start_cm(
|
||||||
lr.my_id.clone(),
|
lr.my_id.clone(),
|
||||||
lr.my_name.clone(),
|
lr.my_name.clone(),
|
||||||
@@ -5347,9 +5393,8 @@ mod raii {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_wake_lock_on_setting_changed() {
|
pub fn check_wake_lock_on_setting_changed() {
|
||||||
let current = config::Config::get_bool_option(
|
let current =
|
||||||
keys::OPTION_KEEP_AWAKE_DURING_INCOMING_SESSIONS,
|
config::Config::get_bool_option(keys::OPTION_KEEP_AWAKE_DURING_INCOMING_SESSIONS);
|
||||||
);
|
|
||||||
let cached = *WAKELOCK_KEEP_AWAKE_OPTION.lock().unwrap();
|
let cached = *WAKELOCK_KEEP_AWAKE_OPTION.lock().unwrap();
|
||||||
if cached != Some(current) {
|
if cached != Some(current) {
|
||||||
Self::check_wake_lock();
|
Self::check_wake_lock();
|
||||||
|
|||||||
@@ -809,7 +809,7 @@ fn record_key_is_control_key(record_key: u64) -> bool {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn record_key_is_chr(record_key: u64) -> bool {
|
fn record_key_is_chr(record_key: u64) -> bool {
|
||||||
record_key < KEY_CHAR_START
|
record_key >= KEY_CHAR_START
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -1513,6 +1513,27 @@ fn get_control_key_value(key_event: &KeyEvent) -> i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn has_hotkey_modifiers(key_event: &KeyEvent) -> bool {
|
||||||
|
key_event.modifiers.iter().any(|ck| {
|
||||||
|
let v = ck.value();
|
||||||
|
v == ControlKey::Control.value()
|
||||||
|
|| v == ControlKey::RControl.value()
|
||||||
|
|| v == ControlKey::Meta.value()
|
||||||
|
|| v == ControlKey::RWin.value()
|
||||||
|
|| {
|
||||||
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
|
{
|
||||||
|
v == ControlKey::Alt.value() || v == ControlKey::RAlt.value()
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn release_unpressed_modifiers(en: &mut Enigo, key_event: &KeyEvent) {
|
fn release_unpressed_modifiers(en: &mut Enigo, key_event: &KeyEvent) {
|
||||||
let ck_value = get_control_key_value(key_event);
|
let ck_value = get_control_key_value(key_event);
|
||||||
fix_modifiers(&key_event.modifiers[..], en, ck_value);
|
fix_modifiers(&key_event.modifiers[..], en, ck_value);
|
||||||
@@ -1572,7 +1593,7 @@ fn need_to_uppercase(en: &mut Enigo) -> bool {
|
|||||||
get_modifier_state(Key::Shift, en) || get_modifier_state(Key::CapsLock, en)
|
get_modifier_state(Key::Shift, en) || get_modifier_state(Key::CapsLock, en)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_chr(en: &mut Enigo, chr: u32, down: bool) {
|
fn process_chr(en: &mut Enigo, chr: u32, down: bool, _hotkey: bool) {
|
||||||
// On Wayland with uinput mode, use clipboard for character input
|
// On Wayland with uinput mode, use clipboard for character input
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
if !crate::platform::linux::is_x11() && wayland_use_uinput() {
|
if !crate::platform::linux::is_x11() && wayland_use_uinput() {
|
||||||
@@ -1587,6 +1608,16 @@ fn process_chr(en: &mut Enigo, chr: u32, down: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||||
|
if !_hotkey {
|
||||||
|
if down {
|
||||||
|
if let Ok(chr) = char::try_from(chr) {
|
||||||
|
en.key_sequence(&chr.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let key = char_value_to_key(chr);
|
let key = char_value_to_key(chr);
|
||||||
|
|
||||||
if down {
|
if down {
|
||||||
@@ -1856,7 +1887,7 @@ fn legacy_keyboard_mode(evt: &KeyEvent) {
|
|||||||
|
|
||||||
let record_key = chr as u64 + KEY_CHAR_START;
|
let record_key = chr as u64 + KEY_CHAR_START;
|
||||||
record_pressed_key(KeysDown::EnigoKey(record_key), down);
|
record_pressed_key(KeysDown::EnigoKey(record_key), down);
|
||||||
process_chr(&mut en, chr, down)
|
process_chr(&mut en, chr, down, has_hotkey_modifiers(evt))
|
||||||
}
|
}
|
||||||
Some(key_event::Union::Unicode(chr)) => {
|
Some(key_event::Union::Unicode(chr)) => {
|
||||||
// Same as Chr: release Shift for Unicode input
|
// Same as Chr: release Shift for Unicode input
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ div.icon {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img.icon {
|
||||||
|
size: 96px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
div.id {
|
div.id {
|
||||||
@ELLIPSIS;
|
@ELLIPSIS;
|
||||||
color: color(green-blue);
|
color: color(green-blue);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ impl InvokeUiCM for SciterHandler {
|
|||||||
client.port_forward.clone(),
|
client.port_forward.clone(),
|
||||||
client.peer_id.clone(),
|
client.peer_id.clone(),
|
||||||
client.name.clone(),
|
client.name.clone(),
|
||||||
|
client.avatar.clone(),
|
||||||
client.authorized,
|
client.authorized,
|
||||||
client.keyboard,
|
client.keyboard,
|
||||||
client.clipboard,
|
client.clipboard,
|
||||||
|
|||||||
@@ -42,9 +42,11 @@ class Body: Reactor.Component
|
|||||||
return <div .content style="size:*">
|
return <div .content style="size:*">
|
||||||
<div .left-panel>
|
<div .left-panel>
|
||||||
<div .icon-and-id>
|
<div .icon-and-id>
|
||||||
|
{c.avatar ?
|
||||||
|
<img .icon src={c.avatar} /> :
|
||||||
<div .icon style={"background: " + string2RGB(c.name, 1)}>
|
<div .icon style={"background: " + string2RGB(c.name, 1)}>
|
||||||
{c.name[0].toUpperCase()}
|
{c.name[0].toUpperCase()}
|
||||||
</div>
|
</div>}
|
||||||
<div>
|
<div>
|
||||||
<div .id style="font-weight: bold; font-size: 1.2em;">{c.name}</div>
|
<div .id style="font-weight: bold; font-size: 1.2em;">{c.name}</div>
|
||||||
<div .id>({c.peer_id})</div>
|
<div .id>({c.peer_id})</div>
|
||||||
@@ -366,7 +368,7 @@ function bring_to_top(idx=-1) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.addConnection = function(id, is_file_transfer, is_view_camera, is_terminal, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, restart, recording, block_input) {
|
handler.addConnection = function(id, is_file_transfer, is_view_camera, is_terminal, port_forward, peer_id, name, avatar, authorized, keyboard, clipboard, audio, file, restart, recording, block_input) {
|
||||||
stdout.println("new connection #" + id + ": " + peer_id);
|
stdout.println("new connection #" + id + ": " + peer_id);
|
||||||
var conn;
|
var conn;
|
||||||
connections.map(function(c) {
|
connections.map(function(c) {
|
||||||
@@ -385,6 +387,7 @@ handler.addConnection = function(id, is_file_transfer, is_view_camera, is_termin
|
|||||||
conn = {
|
conn = {
|
||||||
id: id, is_file_transfer: is_file_transfer, is_view_camera: is_view_camera, is_terminal: is_terminal, peer_id: peer_id,
|
id: id, is_file_transfer: is_file_transfer, is_view_camera: is_view_camera, is_terminal: is_terminal, peer_id: peer_id,
|
||||||
port_forward: port_forward,
|
port_forward: port_forward,
|
||||||
|
avatar: avatar,
|
||||||
name: name, authorized: authorized, time: new Date(), now: new Date(),
|
name: name, authorized: authorized, time: new Date(), now: new Date(),
|
||||||
keyboard: keyboard, clipboard: clipboard, msgs: [], unreaded: 0,
|
keyboard: keyboard, clipboard: clipboard, msgs: [], unreaded: 0,
|
||||||
audio: audio, file: file, restart: restart, recording: recording,
|
audio: audio, file: file, restart: restart, recording: recording,
|
||||||
|
|||||||
@@ -1451,6 +1451,9 @@ function set_local_user_info(user) {
|
|||||||
if (user.display_name) {
|
if (user.display_name) {
|
||||||
user_info.display_name = user.display_name;
|
user_info.display_name = user.display_name;
|
||||||
}
|
}
|
||||||
|
if (user.avatar) {
|
||||||
|
user_info.avatar = user.avatar;
|
||||||
|
}
|
||||||
if (user.status) {
|
if (user.status) {
|
||||||
user_info.status = user.status;
|
user_info.status = user.status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ pub struct Client {
|
|||||||
pub is_terminal: bool,
|
pub is_terminal: bool,
|
||||||
pub port_forward: String,
|
pub port_forward: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub avatar: String,
|
||||||
pub peer_id: String,
|
pub peer_id: String,
|
||||||
pub keyboard: bool,
|
pub keyboard: bool,
|
||||||
pub clipboard: bool,
|
pub clipboard: bool,
|
||||||
@@ -220,6 +221,7 @@ impl<T: InvokeUiCM> ConnectionManager<T> {
|
|||||||
port_forward: String,
|
port_forward: String,
|
||||||
peer_id: String,
|
peer_id: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
avatar: String,
|
||||||
authorized: bool,
|
authorized: bool,
|
||||||
keyboard: bool,
|
keyboard: bool,
|
||||||
clipboard: bool,
|
clipboard: bool,
|
||||||
@@ -240,6 +242,7 @@ impl<T: InvokeUiCM> ConnectionManager<T> {
|
|||||||
is_terminal,
|
is_terminal,
|
||||||
port_forward,
|
port_forward,
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
|
avatar,
|
||||||
peer_id: peer_id.clone(),
|
peer_id: peer_id.clone(),
|
||||||
keyboard,
|
keyboard,
|
||||||
clipboard,
|
clipboard,
|
||||||
@@ -500,9 +503,9 @@ impl<T: InvokeUiCM> IpcTaskRunner<T> {
|
|||||||
}
|
}
|
||||||
Ok(Some(data)) => {
|
Ok(Some(data)) => {
|
||||||
match data {
|
match data {
|
||||||
Data::Login{id, is_file_transfer, is_view_camera, is_terminal, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, file_transfer_enabled: _file_transfer_enabled, restart, recording, block_input, from_switch} => {
|
Data::Login{id, is_file_transfer, is_view_camera, is_terminal, port_forward, peer_id, name, avatar, authorized, keyboard, clipboard, audio, file, file_transfer_enabled: _file_transfer_enabled, restart, recording, block_input, from_switch} => {
|
||||||
log::debug!("conn_id: {}", id);
|
log::debug!("conn_id: {}", id);
|
||||||
self.cm.add_connection(id, is_file_transfer, is_view_camera, is_terminal, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, restart, recording, block_input, from_switch, self.tx.clone());
|
self.cm.add_connection(id, is_file_transfer, is_view_camera, is_terminal, port_forward, peer_id, name, avatar, authorized, keyboard, clipboard, audio, file, restart, recording, block_input, from_switch, self.tx.clone());
|
||||||
self.conn_id = id;
|
self.conn_id = id;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
@@ -823,6 +826,7 @@ pub async fn start_listen<T: InvokeUiCM>(
|
|||||||
port_forward,
|
port_forward,
|
||||||
peer_id,
|
peer_id,
|
||||||
name,
|
name,
|
||||||
|
avatar,
|
||||||
authorized,
|
authorized,
|
||||||
keyboard,
|
keyboard,
|
||||||
clipboard,
|
clipboard,
|
||||||
@@ -843,6 +847,7 @@ pub async fn start_listen<T: InvokeUiCM>(
|
|||||||
port_forward,
|
port_forward,
|
||||||
peer_id,
|
peer_id,
|
||||||
name,
|
name,
|
||||||
|
avatar,
|
||||||
authorized,
|
authorized,
|
||||||
keyboard,
|
keyboard,
|
||||||
clipboard,
|
clipboard,
|
||||||
|
|||||||
@@ -245,7 +245,20 @@ pub fn get_builtin_option(key: &str) -> String {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_local_option(key: String, value: String) {
|
pub fn set_local_option(key: String, value: String) {
|
||||||
LocalConfig::set_option(key.clone(), value.clone());
|
LocalConfig::set_option(key.clone(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve relative avatar path (e.g. "/avatar/xxx") to absolute URL
|
||||||
|
/// by prepending the API server address.
|
||||||
|
pub fn resolve_avatar_url(avatar: String) -> String {
|
||||||
|
let avatar = avatar.trim().to_owned();
|
||||||
|
if avatar.starts_with('/') {
|
||||||
|
let api_server = get_api_server();
|
||||||
|
if !api_server.is_empty() {
|
||||||
|
return format!("{}{}", api_server.trim_end_matches('/'), avatar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avatar
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||||
|
|||||||
Reference in New Issue
Block a user