@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "scrcpy-mask",
|
"name": "scrcpy-mask",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@ -12,6 +12,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tauri-apps/api": ">=2.0.0-beta.8",
|
"@tauri-apps/api": ">=2.0.0-beta.8",
|
||||||
|
"@tauri-apps/plugin-clipboard-manager": "2.1.0-beta.1",
|
||||||
"@tauri-apps/plugin-http": "2.0.0-beta.3",
|
"@tauri-apps/plugin-http": "2.0.0-beta.3",
|
||||||
"@tauri-apps/plugin-process": "2.0.0-beta.2",
|
"@tauri-apps/plugin-process": "2.0.0-beta.2",
|
||||||
"@tauri-apps/plugin-shell": "2.0.0-beta.3",
|
"@tauri-apps/plugin-shell": "2.0.0-beta.3",
|
||||||
|
BIN
public/favicon.ico
Executable file → Normal file
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 6.3 KiB |
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scrcpy-mask"
|
name = "scrcpy-mask"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
description = "A Tauri App"
|
description = "A Tauri App"
|
||||||
authors = ["AkiChase"]
|
authors = ["AkiChase"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@ -21,3 +21,4 @@ tokio = { version = "1.36.0", features = ["rt-multi-thread", "net", "macros", "i
|
|||||||
tauri-plugin-process = "2.0.0-beta"
|
tauri-plugin-process = "2.0.0-beta"
|
||||||
tauri-plugin-shell = "2.0.0-beta"
|
tauri-plugin-shell = "2.0.0-beta"
|
||||||
tauri-plugin-http = "2.0.0-beta"
|
tauri-plugin-http = "2.0.0-beta"
|
||||||
|
tauri-plugin-clipboard-manager = "2.1.0-beta.2"
|
||||||
|
@ -34,11 +34,16 @@
|
|||||||
{
|
{
|
||||||
"identifier": "http:default",
|
"identifier": "http:default",
|
||||||
"allow": [
|
"allow": [
|
||||||
{ "url": "https://api.github.com/repos/AkiChase/scrcpy-mask/*" }
|
{
|
||||||
|
"url": "https://api.github.com/repos/AkiChase/scrcpy-mask/*"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"http:allow-fetch",
|
"http:allow-fetch",
|
||||||
"app:default",
|
"app:default",
|
||||||
"app:allow-version"
|
"app:allow-version",
|
||||||
|
"clipboard-manager:default",
|
||||||
|
"clipboard-manager:allow-read-text",
|
||||||
|
"clipboard-manager:allow-write-text"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 742 B |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 4.3 KiB |
@ -1,5 +1,6 @@
|
|||||||
[
|
[
|
||||||
{"list":[{"key":{"down":"KeyS","left":"KeyA","right":"KeyD","up":"KeyW"},"note":"方向轮盘","offset":175,"pointerId":1,"posX":183,"posY":566,"type":"SteeringWheel"},{"key":"KeyQ","note":"技能1","pointerId":2,"posX":951,"posY":636,"range":30,"type":"DirectionalSkill"},{"key":"KeyE","note":"技能2","pointerId":2,"posX":1025,"posY":500,"range":30,"type":"DirectionalSkill"},{"key":"AltLeft","note":"技能3","pointerId":2,"posX":1160,"posY":420,"range":30,"type":"DirectionalSkill"},{"key":"Space","note":"取消技能","pointerId":2,"posX":1160,"posY":140,"type":"CancelSkill"},{"key":"KeyB","note":"回城","pointerId":3,"posX":650,"posY":650,"time":80,"type":"Tap"},{"key":"KeyC","note":"回复","pointerId":3,"posX":740,"posY":650,"time":80,"type":"Tap"},{"key":"KeyF","note":"召唤师技能","pointerId":2,"posX":838,"posY":647,"range":50,"type":"DirectionalSkill"},{"key":"M2","note":"攻击","pointerId":3,"posX":1174,"posY":618,"time":80,"type":"Tap"},{"key":"Digit1","note":"技能1升级","pointerId":3,"posX":880,"posY":560,"time":80,"type":"Tap"},{"key":"Digit2","note":"技能2升级","pointerId":3,"posX":960,"posY":430,"time":80,"type":"Tap"},{"key":"Digit3","note":"技能3升级","pointerId":3,"posX":1090,"posY":350,"time":80,"type":"Tap"},{"key":"Digit5","note":"快速购买1","pointerId":3,"posX":133,"posY":289,"time":80,"type":"Tap"},{"key":"Digit6","note":"快速购买2","pointerId":3,"posX":130,"posY":370,"time":80,"type":"Tap"},{"key":"M3","note":"观察","pointerId":4,"posX":1000,"posY":200,"scale":1,"type":"Observation"},{"key":"Tab","macro":{"down":[{"args":["default",5,1185,40,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1220,100,80],"type":"touch"}]},"note":"战绩面板","posX":1185,"posY":40,"type":"Macro"},{"key":"ShiftLeft","macro":{"down":[{"args":["default",5,40,300,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1200,60,80],"type":"touch"}]},"note":"商店","posX":44,"posY":302,"type":"Macro"},{"key":"KeyZ","macro":{"down":[{"args":["default",5,250,230,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,640,150,80],"type":"touch"}]},"note":"地图","posX":250,"posY":230,"type":"Macro"},{"key":"Backquote","macro":{"down":[{"args":["default",5,40,300,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,510,630,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,1165,575,80],"type":"touch"},{"args":["default",5,1200,65,80],"type":"touch"},{"args":[200],"type":"sleep"},{"args":["default",5,125,300,80],"type":"touch"}],"loop":null,"up":null},"note":"换装2","posX":236,"posY":66,"type":"Macro"},{"directional":false,"key":"ControlLeft","note":"","pointerId":2,"posX":839,"posY":647,"rangeOrTime":80,"type":"TriggerWhenPressedSkill"},{"directional":false,"key":"M4","note":"","pointerId":2,"posX":952,"posY":636,"rangeOrTime":80,"type":"TriggerWhenPressedSkill"},{"directional":false,"key":"WheelDown","note":"","pointerId":2,"posX":1155,"posY":280,"rangeOrTime":80,"type":"TriggerWhenPressedSkill"},{"key":"Enter","macro":{"down":[{"args":["default",5,1245,280,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,1160,560,80],"type":"touch"},{"args":[],"type":"key-input-mode"}],"loop":null,"up":null},"note":"聊天","posX":1244,"posY":281,"type":"Macro"}],"relativeSize":{"h":720,"w":1280},"title":"AVD-王者荣耀-三技能-导入默认"},
|
{"list":[{"key":{"down":"KeyS","left":"KeyA","right":"KeyD","up":"KeyW"},"note":"方向轮盘","offset":175,"pointerId":1,"posX":183,"posY":566,"type":"SteeringWheel"},{"key":"KeyQ","note":"技能1","pointerId":2,"posX":951,"posY":636,"range":30,"type":"DirectionalSkill"},{"key":"KeyE","note":"技能2","pointerId":2,"posX":1025,"posY":500,"range":30,"type":"DirectionalSkill"},{"key":"AltLeft","note":"技能3","pointerId":2,"posX":1160,"posY":420,"range":30,"type":"DirectionalSkill"},{"key":"Space","note":"取消技能","pointerId":2,"posX":1160,"posY":140,"type":"CancelSkill"},{"key":"KeyB","note":"回城","pointerId":3,"posX":650,"posY":650,"time":80,"type":"Tap"},{"key":"KeyC","note":"回复","pointerId":3,"posX":740,"posY":650,"time":80,"type":"Tap"},{"key":"KeyF","note":"召唤师技能","pointerId":2,"posX":838,"posY":647,"range":50,"type":"DirectionalSkill"},{"key":"M2","note":"攻击","pointerId":3,"posX":1174,"posY":618,"time":80,"type":"Tap"},{"key":"Digit1","note":"技能1升级","pointerId":3,"posX":880,"posY":560,"time":80,"type":"Tap"},{"key":"Digit2","note":"技能2升级","pointerId":3,"posX":960,"posY":430,"time":80,"type":"Tap"},{"key":"Digit3","note":"技能3升级","pointerId":3,"posX":1090,"posY":350,"time":80,"type":"Tap"},{"key":"Digit5","note":"快速购买1","pointerId":3,"posX":133,"posY":289,"time":80,"type":"Tap"},{"key":"Digit6","note":"快速购买2","pointerId":3,"posX":130,"posY":370,"time":80,"type":"Tap"},{"key":"M3","note":"观察","pointerId":4,"posX":1000,"posY":200,"scale":1,"type":"Observation"},{"key":"Tab","macro":{"down":[{"args":["default",5,1185,40,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1220,100,80],"type":"touch"}]},"note":"战绩面板","posX":1185,"posY":40,"type":"Macro"},{"key":"ShiftLeft","macro":{"down":[{"args":["default",5,40,300,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1200,60,80],"type":"touch"}]},"note":"商店","posX":44,"posY":302,"type":"Macro"},{"key":"KeyZ","macro":{"down":[{"args":["default",5,250,230,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,640,150,80],"type":"touch"}]},"note":"地图","posX":250,"posY":230,"type":"Macro"},{"key":"Backquote","macro":{"down":[{"args":["default",5,40,300,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,510,630,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,1165,575,80],"type":"touch"},{"args":["default",5,1200,65,80],"type":"touch"},{"args":[200],"type":"sleep"},{"args":["default",5,125,300,80],"type":"touch"}],"loop":null,"up":null},"note":"换装2","posX":236,"posY":66,"type":"Macro"},{"directional":false,"key":"ControlLeft","note":"","pointerId":2,"posX":839,"posY":647,"rangeOrTime":80,"type":"TriggerWhenPressedSkill"},{"directional":false,"key":"M4","note":"","pointerId":2,"posX":952,"posY":636,"rangeOrTime":80,"type":"TriggerWhenPressedSkill"},{"directional":false,"key":"WheelDown","note":"","pointerId":2,"posX":1155,"posY":280,"rangeOrTime":80,"type":"TriggerWhenPressedSkill"},{"key":"Enter","macro":{"down":[{"args":["default",5,1245,280,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,1160,560,80],"type":"touch"},{"args":[],"type":"key-input-mode"}],"loop":null,"up":null},"note":"聊天","posX":1244,"posY":281,"type":"Macro"}],"relativeSize":{"h":720,"w":1280},"title":"AVD-王者荣耀-三技能-导入默认"},
|
||||||
{"list":[{"key":{"down":"KeyS","left":"KeyA","right":"KeyD","up":"KeyW"},"note":"方向轮盘","offset":175,"pointerId":1,"posX":183,"posY":566,"type":"SteeringWheel"},{"key":"KeyQ","note":"技能1","pointerId":2,"posX":952,"posY":636,"range":50,"type":"DirectionalSkill"},{"key":"AltLeft","note":"技能2","pointerId":2,"posX":979,"posY":526,"range":50,"type":"DirectionalSkill"},{"key":"KeyE","note":"技能3","pointerId":2,"posX":1074,"posY":438,"range":50,"type":"DirectionalSkill"},{"key":"Space","note":"取消技能","pointerId":2,"posX":1160,"posY":140,"type":"CancelSkill"},{"key":"KeyB","note":"回城","pointerId":3,"posX":644,"posY":650,"time":80,"type":"Tap"},{"key":"KeyC","note":"回复","pointerId":3,"posX":742,"posY":650,"time":80,"type":"Tap"},{"key":"KeyF","note":"召唤师技能","pointerId":2,"posX":838,"posY":647,"range":50,"type":"DirectionalSkill"},{"key":"M2","note":"攻击","pointerId":3,"posX":1179,"posY":621,"time":80,"type":"Tap"},{"key":"Digit1","note":"技能1升级","pointerId":3,"posX":895,"posY":564,"time":80,"type":"Tap"},{"key":"Digit2","note":"技能2升级","pointerId":3,"posX":922,"posY":456,"time":80,"type":"Tap"},{"key":"Digit3","note":"技能3升级","pointerId":3,"posX":1015,"posY":376,"time":80,"type":"Tap"},{"key":"Digit5","note":"快速购买1","pointerId":3,"posX":133,"posY":289,"time":80,"type":"Tap"},{"key":"Digit6","note":"快速购买2","pointerId":3,"posX":130,"posY":370,"time":80,"type":"Tap"},{"key":"M3","note":"观察","pointerId":4,"posX":1000,"posY":200,"scale":1,"type":"Observation"},{"key":"Tab","macro":{"down":[{"args":["default",5,1185,40,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1220,100,80],"type":"touch"}]},"note":"战绩面板","posX":1185,"posY":40,"type":"Macro"},{"key":"ShiftLeft","macro":{"down":[{"args":["default",5,40,300,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1200,60,80],"type":"touch"}]},"note":"商店","posX":44,"posY":302,"type":"Macro"},{"key":"KeyZ","macro":{"down":[{"args":["default",5,250,230,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,640,150,80],"type":"touch"}]},"note":"地图","posX":250,"posY":230,"type":"Macro"},{"key":"Backquote","macro":{"down":[{"args":["default",5,40,300,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,510,630,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,1165,575,80],"type":"touch"},{"args":["default",5,1200,65,80],"type":"touch"},{"args":[200],"type":"sleep"},{"args":["default",5,125,300,80],"type":"touch"}],"loop":null,"up":null},"note":"换装2","posX":236,"posY":66,"type":"Macro"},{"key":"WheelDown","note":"","pointerId":2,"posX":1189,"posY":422,"range":50,"type":"DirectionalSkill"},{"directional":false,"key":"M4","note":"","pointerId":2,"posX":951,"posY":636,"rangeOrTime":80,"type":"TriggerWhenPressedSkill"},{"type":"Macro","key":"Enter","note":"聊天","posX":1250,"posY":307,"macro":{"down":[{"args":["default",5,1245,280,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,1160,560,80],"type":"touch"},{"args":[],"type":"key-input-mode"}],"loop":null,"up":null}},{"type":"TriggerWhenPressedSkill","key":"WheelUp","note":"装备技能","posX":1157,"posY":276,"pointerId":2,"directional":false,"rangeOrTime":80}],"relativeSize":{"h":720,"w":1280},"title":"AVD-王者荣耀-四技能-导入默认"},
|
{"list":[{"key":{"down":"KeyS","left":"KeyA","right":"KeyD","up":"KeyW"},"note":"方向轮盘","offset":175,"pointerId":1,"posX":183,"posY":566,"type":"SteeringWheel"},{"key":"KeyQ","note":"技能1","pointerId":2,"posX":952,"posY":636,"range":50,"type":"DirectionalSkill"},{"key":"AltLeft","note":"技能2","pointerId":2,"posX":979,"posY":526,"range":50,"type":"DirectionalSkill"},{"key":"KeyE","note":"技能3","pointerId":2,"posX":1074,"posY":438,"range":50,"type":"DirectionalSkill"},{"key":"Space","note":"取消技能","pointerId":2,"posX":1160,"posY":140,"type":"CancelSkill"},{"key":"KeyB","note":"回城","pointerId":3,"posX":644,"posY":650,"time":80,"type":"Tap"},{"key":"KeyC","note":"回复","pointerId":3,"posX":742,"posY":650,"time":80,"type":"Tap"},{"key":"KeyF","note":"召唤师技能","pointerId":2,"posX":838,"posY":647,"range":50,"type":"DirectionalSkill"},{"key":"M2","note":"攻击","pointerId":3,"posX":1179,"posY":621,"time":80,"type":"Tap"},{"key":"Digit1","note":"技能1升级","pointerId":3,"posX":895,"posY":564,"time":80,"type":"Tap"},{"key":"Digit2","note":"技能2升级","pointerId":3,"posX":922,"posY":456,"time":80,"type":"Tap"},{"key":"Digit3","note":"技能3升级","pointerId":3,"posX":1015,"posY":376,"time":80,"type":"Tap"},{"key":"Digit5","note":"快速购买1","pointerId":3,"posX":133,"posY":289,"time":80,"type":"Tap"},{"key":"Digit6","note":"快速购买2","pointerId":3,"posX":130,"posY":370,"time":80,"type":"Tap"},{"key":"M3","note":"观察","pointerId":4,"posX":1000,"posY":200,"scale":1,"type":"Observation"},{"key":"Tab","macro":{"down":[{"args":["default",5,1185,40,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1220,100,80],"type":"touch"}]},"note":"战绩面板","posX":1185,"posY":40,"type":"Macro"},{"key":"ShiftLeft","macro":{"down":[{"args":["default",5,40,300,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1200,60,80],"type":"touch"}]},"note":"商店","posX":44,"posY":302,"type":"Macro"},{"key":"KeyZ","macro":{"down":[{"args":["default",5,250,230,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,640,150,80],"type":"touch"}]},"note":"地图","posX":250,"posY":230,"type":"Macro"},{"key":"Backquote","macro":{"down":[{"args":["default",5,40,300,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,510,630,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,1165,575,80],"type":"touch"},{"args":["default",5,1200,65,80],"type":"touch"},{"args":[200],"type":"sleep"},{"args":["default",5,125,300,80],"type":"touch"}],"loop":null,"up":null},"note":"换装2","posX":236,"posY":66,"type":"Macro"},{"key":"WheelDown","note":"","pointerId":2,"posX":1189,"posY":422,"range":50,"type":"DirectionalSkill"},{"directional":false,"key":"M4","note":"","pointerId":2,"posX":951,"posY":636,"rangeOrTime":80,"type":"TriggerWhenPressedSkill"},{"type":"Macro","key":"Enter","note":"聊天","posX":1250,"posY":307,"macro":{"down":[{"args":["default",5,1245,280,80],"type":"touch"},{"args":[150],"type":"sleep"},{"args":["default",5,1160,560,80],"type":"touch"},{"args":[],"type":"key-input-mode"}],"loop":null,"up":null}},{"type":"TriggerWhenPressedSkill","key":"WheelUp","note":"装备技能","posX":1157,"posY":276,"pointerId":2,"directional":false,"rangeOrTime":80}],"relativeSize":{"h":720,"w":1280},"title":"AVD-王者荣耀-四技能-导入默认"},
|
||||||
{"list":[{"key":"Backquote","note":"准星键","pointerId":0,"posX":640,"posY":361,"scaleX":1,"scaleY":1,"type":"Sight"},{"key":{"down":"KeyS","left":"KeyA","right":"KeyD","up":"KeyW"},"note":"","offset":150,"pointerId":1,"posX":208,"posY":542,"type":"SteeringWheel"},{"key":"KeyC","note":"","pointerId":3,"posX":1085,"posY":668,"time":80,"type":"Tap"},{"key":"KeyZ","note":"","pointerId":3,"posX":1207,"posY":648,"time":80,"type":"Tap"},{"key":"Space","note":"","pointerId":3,"posX":1230,"posY":503,"time":80,"type":"Tap"},{"key":"M3","note":"","pointerId":4,"posX":992,"posY":229,"scale":0.6,"type":"Observation"},{"key":"Digit1","note":"","pointerId":3,"posX":543,"posY":642,"time":80,"type":"Tap"},{"key":"Digit2","note":"","pointerId":3,"posX":729,"posY":644,"time":80,"type":"Tap"},{"key":"ShiftLeft","note":"","pointerId":3,"posX":1075,"posY":194,"time":80,"type":"Tap"},{"key":"KeyF","note":"","pointerId":3,"posX":861,"posY":310,"time":80,"type":"Tap"},{"key":"KeyG","note":"","pointerId":3,"posX":865,"posY":388,"time":80,"type":"Tap"},{"key":"KeyR","note":"","pointerId":3,"posX":976,"posY":674,"time":80,"type":"Tap"},{"key":"KeyE","note":"","pointerId":3,"posX":872,"posY":495,"time":80,"type":"Tap"},{"key":"KeyB","note":"","pointerId":3,"posX":543,"posY":593,"time":80,"type":"Tap"},{"key":"KeyN","note":"","pointerId":3,"posX":721,"posY":589,"time":80,"type":"Tap"},{"drag":false,"note":"","pointerId":2,"posX":1097,"posY":549,"scaleX":0.5,"scaleY":0.5,"type":"Fire"},{"key":"M2","note":"","pointerId":3,"posX":1227,"posY":376,"time":80,"type":"Tap"},{"key":"Tab","macro":{"down":[{"args":["default",5,100,650,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1250,40,80],"type":"touch"}]},"note":"背包宏","posX":95,"posY":656,"type":"Macro"},{"key":"M1","note":"地图","pointerId":3,"posX":1244,"posY":43,"time":80,"type":"Tap"},{"key":"KeyV","note":"","pointerId":3,"posX":1156,"posY":300,"time":80,"type":"Tap"},{"key":"M4","note":"","pointerId":3,"posX":862,"posY":180,"time":80,"type":"Tap"},{"key":"KeyT","note":"","pointerId":3,"posX":880,"posY":674,"time":80,"type":"Tap"},{"key":"KeyQ","note":"","pointerId":3,"posX":400,"posY":679,"time":80,"type":"Tap"},{"key":"Digit4","note":"","pointerId":3,"posX":766,"posY":251,"time":80,"type":"Tap"},{"key":"Digit5","note":"","pointerId":3,"posX":770,"posY":320,"time":80,"type":"Tap"},{"key":"Digit3","note":"","pointerId":3,"posX":788,"posY":591,"time":80,"type":"Tap"}],"relativeSize":{"h":720,"w":1280},"title":"AVD-和平精英-导入默认"}
|
{"list":[{"key":"Backquote","note":"准星键","pointerId":0,"posX":640,"posY":361,"scaleX":1,"scaleY":1,"type":"Sight"},{"key":{"down":"KeyS","left":"KeyA","right":"KeyD","up":"KeyW"},"note":"","offset":150,"pointerId":1,"posX":208,"posY":542,"type":"SteeringWheel"},{"key":"KeyC","note":"","pointerId":3,"posX":1085,"posY":668,"time":80,"type":"Tap"},{"key":"KeyZ","note":"","pointerId":3,"posX":1207,"posY":648,"time":80,"type":"Tap"},{"key":"Space","note":"","pointerId":3,"posX":1230,"posY":503,"time":80,"type":"Tap"},{"key":"M3","note":"","pointerId":4,"posX":992,"posY":229,"scale":0.6,"type":"Observation"},{"key":"Digit1","note":"","pointerId":3,"posX":543,"posY":642,"time":80,"type":"Tap"},{"key":"Digit2","note":"","pointerId":3,"posX":729,"posY":644,"time":80,"type":"Tap"},{"key":"ShiftLeft","note":"","pointerId":3,"posX":1075,"posY":194,"time":80,"type":"Tap"},{"key":"KeyF","note":"","pointerId":3,"posX":861,"posY":310,"time":80,"type":"Tap"},{"key":"KeyG","note":"","pointerId":3,"posX":865,"posY":388,"time":80,"type":"Tap"},{"key":"KeyR","note":"","pointerId":3,"posX":976,"posY":674,"time":80,"type":"Tap"},{"key":"KeyE","note":"","pointerId":3,"posX":872,"posY":495,"time":80,"type":"Tap"},{"key":"KeyB","note":"","pointerId":3,"posX":543,"posY":593,"time":80,"type":"Tap"},{"key":"KeyN","note":"","pointerId":3,"posX":721,"posY":589,"time":80,"type":"Tap"},{"drag":false,"note":"","pointerId":2,"posX":1097,"posY":549,"scaleX":0.5,"scaleY":0.5,"type":"Fire"},{"key":"M2","note":"","pointerId":3,"posX":1227,"posY":376,"time":80,"type":"Tap"},{"key":"Tab","macro":{"down":[{"args":["default",5,100,650,80],"type":"touch"}],"loop":null,"up":[{"args":["default",5,1250,40,80],"type":"touch"}]},"note":"背包宏","posX":95,"posY":656,"type":"Macro"},{"key":"M1","note":"地图","pointerId":3,"posX":1244,"posY":43,"time":80,"type":"Tap"},{"key":"KeyV","note":"","pointerId":3,"posX":1156,"posY":300,"time":80,"type":"Tap"},{"key":"M4","note":"","pointerId":3,"posX":862,"posY":180,"time":80,"type":"Tap"},{"key":"KeyT","note":"","pointerId":3,"posX":880,"posY":674,"time":80,"type":"Tap"},{"key":"KeyQ","note":"","pointerId":3,"posX":400,"posY":679,"time":80,"type":"Tap"},{"key":"Digit4","note":"","pointerId":3,"posX":766,"posY":251,"time":80,"type":"Tap"},{"key":"Digit5","note":"","pointerId":3,"posX":770,"posY":320,"time":80,"type":"Tap"},{"key":"Digit3","note":"","pointerId":3,"posX":788,"posY":591,"time":80,"type":"Tap"}],"relativeSize":{"h":720,"w":1280},"title":"AVD-和平精英-导入默认"},
|
||||||
|
{"list":[{"key":{"down":"KeyS","left":"KeyA","right":"KeyD","up":"KeyW"},"note":"","offset":150,"pointerId":1,"posX":204,"posY":531,"type":"SteeringWheel"},{"key":"KeyE","note":"","pointerId":3,"posX":1036,"posY":660,"time":80,"type":"Tap"},{"key":"KeyL","note":"","pointerId":2,"posX":1166,"posY":328,"type":"DirectionlessSkill"},{"key":"KeyI","note":"","pointerId":3,"posX":947,"posY":657,"time":80,"type":"Tap"},{"key":"KeyU","note":"","pointerId":3,"posX":970,"posY":542,"time":80,"type":"Tap"},{"key":"KeyF","note":"","pointerId":3,"posX":1056,"posY":458,"time":80,"type":"Tap"},{"key":"Digit1","note":"","pointerId":3,"posX":560,"posY":666,"time":80,"type":"Tap"},{"key":"Digit2","note":"","pointerId":3,"posX":639,"posY":666,"time":80,"type":"Tap"},{"key":"KeyZ","note":"","pointerId":3,"posX":1163,"posY":433,"time":80,"type":"Tap"},{"key":"Escape","note":"","pointerId":3,"posX":1198,"posY":43,"time":80,"type":"Tap"},{"key":"Enter","macro":{"down":[{"args":[],"type":"key-input-mode"}],"loop":null,"up":null},"note":"","posX":1086,"posY":85,"type":"Macro"},{"key":"KeyK","note":"","pointerId":3,"posX":1188,"posY":528,"time":80,"type":"Tap"},{"key":"Space","note":"","pointerId":3,"posX":732,"posY":653,"time":80,"type":"Tap"},{"key":"Semicolon","note":"","pointerId":3,"posX":1200,"posY":234,"time":80,"type":"Tap"},{"key":"KeyN","note":"","pointerId":3,"posX":1054,"posY":232,"time":80,"type":"Tap"},{"key":"KeyO","note":"","pointerId":3,"posX":1133,"posY":232,"time":80,"type":"Tap"},{"key":"ShiftLeft","note":"","pointerId":2,"posX":991,"posY":233,"type":"DirectionlessSkill"},{"key":"KeyC","note":"","pointerId":2,"posX":1131,"posY":628,"type":"DirectionlessSkill"},{"key":"KeyQ","note":"","pointerId":2,"posX":838,"posY":656,"type":"DirectionlessSkill"},{"key":"KeyJ","note":"","pointerId":3,"posX":1132,"posY":628,"time":80,"type":"Tap"},{"intervalBetweenPos":100,"key":"KeyH","note":"","pointerId":3,"pos":[{"x":1055,"y":357},{"x":1059,"y":430}],"posX":1053,"posY":393,"type":"Swipe"},{"type":"Swipe","key":"BracketLeft","note":"","posX":987,"posY":354,"pointerId":3,"pos":[{"x":1055,"y":356},{"x":942,"y":356}],"intervalBetweenPos":100},{"type":"Swipe","key":"Backslash","note":"","posX":1055,"posY":306,"pointerId":3,"pos":[{"x":1052,"y":356},{"x":1052,"y":288}],"intervalBetweenPos":100},{"type":"Swipe","key":"BracketRight","note":"","posX":1094,"posY":353,"pointerId":3,"pos":[{"x":1050,"y":356},{"x":1117,"y":354}],"intervalBetweenPos":100}],"relativeSize":{"h":720,"w":1280},"title":"AVD-DNF-狂战-导入默认"}
|
||||||
]
|
]
|
||||||
|
@ -4,5 +4,5 @@ pub mod client;
|
|||||||
pub mod control_msg;
|
pub mod control_msg;
|
||||||
pub mod resource;
|
pub mod resource;
|
||||||
pub mod scrcpy_mask_cmd;
|
pub mod scrcpy_mask_cmd;
|
||||||
pub mod socket;
|
|
||||||
pub mod share;
|
pub mod share;
|
||||||
|
pub mod socket;
|
||||||
|
@ -181,6 +181,7 @@ fn set_adb_path(adb_path: String, app: tauri::AppHandle) -> Result<(), String> {
|
|||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
.plugin(tauri_plugin_clipboard_manager::init())
|
||||||
.plugin(tauri_plugin_http::init())
|
.plugin(tauri_plugin_http::init())
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.plugin(tauri_plugin_process::init())
|
.plugin(tauri_plugin_process::init())
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"productName": "scrcpy-mask",
|
"productName": "scrcpy-mask",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"identifier": "com.akichase.mask",
|
"identifier": "com.akichase.mask",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "pnpm dev",
|
"beforeDevCommand": "pnpm dev",
|
||||||
|
@ -58,4 +58,9 @@ onMounted(async () => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.n-message {
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -45,6 +45,7 @@ import { useGlobalStore } from "../store/global";
|
|||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { closeExternalControl, connectExternalControl } from "../websocket";
|
import { closeExternalControl, connectExternalControl } from "../websocket";
|
||||||
import { LogicalSize, getCurrent } from "@tauri-apps/api/window";
|
import { LogicalSize, getCurrent } from "@tauri-apps/api/window";
|
||||||
|
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dialog = useDialog();
|
const dialog = useDialog();
|
||||||
@ -73,15 +74,8 @@ onMounted(async () => {
|
|||||||
case "ClipboardChanged":
|
case "ClipboardChanged":
|
||||||
if (payload.clipboard === lastClipboard) break;
|
if (payload.clipboard === lastClipboard) break;
|
||||||
lastClipboard = payload.clipboard;
|
lastClipboard = payload.clipboard;
|
||||||
navigator.clipboard
|
writeText(payload.clipboard);
|
||||||
.writeText(payload.clipboard)
|
console.log(payload);
|
||||||
.then(() => {
|
|
||||||
message.info(t("pages.Device.clipboard.deviceSync.success"));
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error(e);
|
|
||||||
message.error(t("pages.Device.clipboard.deviceSync.failed"));
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case "ClipboardSetAck":
|
case "ClipboardSetAck":
|
||||||
break;
|
break;
|
||||||
|
@ -50,6 +50,7 @@ async function maximizeOrRestore() {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
border-radius: 0 10px 0 0;
|
border-radius: 0 10px 0 0;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
|
||||||
.n-button-group{
|
.n-button-group{
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
listenToEvent,
|
listenToEvent,
|
||||||
unlistenToEvent,
|
unlistenToEvent,
|
||||||
} from "../hotkey";
|
} from "../hotkey";
|
||||||
import { KeyMappingConfig, KeySteeringWheel } from "../keyMappingConfig";
|
import { KeySteeringWheel } from "../keyMappingConfig";
|
||||||
import ScreenStream from "./ScreenStream.vue";
|
import ScreenStream from "./ScreenStream.vue";
|
||||||
import { getVersion } from "@tauri-apps/api/app";
|
import { getVersion } from "@tauri-apps/api/app";
|
||||||
import { fetch } from "@tauri-apps/plugin-http";
|
import { fetch } from "@tauri-apps/plugin-http";
|
||||||
@ -19,6 +19,7 @@ import { getCurrent, PhysicalSize } from "@tauri-apps/api/window";
|
|||||||
import { Store } from "@tauri-apps/plugin-store";
|
import { Store } from "@tauri-apps/plugin-store";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { checkAdbAvailable } from "../invoke";
|
import { checkAdbAvailable } from "../invoke";
|
||||||
|
import { loadLocalStorage } from "../storeLoader";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const store = useGlobalStore();
|
const store = useGlobalStore();
|
||||||
@ -103,79 +104,7 @@ function genClientId() {
|
|||||||
|
|
||||||
async function loadLocalStore() {
|
async function loadLocalStore() {
|
||||||
const localStore = new Store("store.bin");
|
const localStore = new Store("store.bin");
|
||||||
// loading keyMappingConfigList from local store
|
await loadLocalStorage(localStore, store, t);
|
||||||
let keyMappingConfigList = await localStore.get<KeyMappingConfig[]>(
|
|
||||||
"keyMappingConfigList"
|
|
||||||
);
|
|
||||||
if (keyMappingConfigList === null || keyMappingConfigList.length === 0) {
|
|
||||||
// add empty key mapping config
|
|
||||||
// unable to get mask element when app is not ready
|
|
||||||
// so we use the stored mask area to get relative size
|
|
||||||
const maskArea = await localStore.get<{
|
|
||||||
posX: number;
|
|
||||||
posY: number;
|
|
||||||
sizeW: number;
|
|
||||||
sizeH: number;
|
|
||||||
}>("maskArea");
|
|
||||||
let relativeSize = { w: 800, h: 600 };
|
|
||||||
if (maskArea !== null) {
|
|
||||||
relativeSize = {
|
|
||||||
w: maskArea.sizeW,
|
|
||||||
h: maskArea.sizeH,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
keyMappingConfigList = [
|
|
||||||
{
|
|
||||||
relativeSize,
|
|
||||||
title: t("pages.Mask.blankConfig"),
|
|
||||||
list: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
await localStore.set("keyMappingConfigList", keyMappingConfigList);
|
|
||||||
}
|
|
||||||
store.keyMappingConfigList = keyMappingConfigList;
|
|
||||||
|
|
||||||
// loading curKeyMappingIndex from local store
|
|
||||||
let curKeyMappingIndex = await localStore.get<number>("curKeyMappingIndex");
|
|
||||||
if (
|
|
||||||
curKeyMappingIndex === null ||
|
|
||||||
curKeyMappingIndex >= keyMappingConfigList.length
|
|
||||||
) {
|
|
||||||
curKeyMappingIndex = 0;
|
|
||||||
localStore.set("curKeyMappingIndex", curKeyMappingIndex);
|
|
||||||
}
|
|
||||||
store.curKeyMappingIndex = curKeyMappingIndex;
|
|
||||||
|
|
||||||
// loading maskButton from local store
|
|
||||||
let maskButton = await localStore.get<{
|
|
||||||
show: boolean;
|
|
||||||
transparency: number;
|
|
||||||
}>("maskButton");
|
|
||||||
store.maskButton = maskButton ?? {
|
|
||||||
show: true,
|
|
||||||
transparency: 0.5,
|
|
||||||
};
|
|
||||||
|
|
||||||
// loading checkUpdateAtStart from local store
|
|
||||||
const checkUpdateAtStart = await localStore.get<boolean>(
|
|
||||||
"checkUpdateAtStart"
|
|
||||||
);
|
|
||||||
store.checkUpdateAtStart = checkUpdateAtStart ?? true;
|
|
||||||
|
|
||||||
// loading rotation from local store
|
|
||||||
const rotation = await localStore.get<{
|
|
||||||
enable: boolean;
|
|
||||||
verticalLength: number;
|
|
||||||
horizontalLength: number;
|
|
||||||
}>("rotation");
|
|
||||||
if (rotation) store.rotation = rotation;
|
|
||||||
|
|
||||||
// loading screenStream from local store
|
|
||||||
const screenStream = await localStore.get<{
|
|
||||||
enable: boolean;
|
|
||||||
address: string;
|
|
||||||
}>("screenStream");
|
|
||||||
if (screenStream) store.screenStream = screenStream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function cleanAfterimage() {
|
async function cleanAfterimage() {
|
||||||
|
@ -66,10 +66,12 @@ onBeforeUnmount(() => {
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -8,6 +8,7 @@ import KeySkill from "./KeySkill.vue";
|
|||||||
import KeyObservation from "./KeyObservation.vue";
|
import KeyObservation from "./KeyObservation.vue";
|
||||||
import KeySight from "./KeySight.vue";
|
import KeySight from "./KeySight.vue";
|
||||||
import KeyFire from "./KeyFire.vue";
|
import KeyFire from "./KeyFire.vue";
|
||||||
|
import KeySwipe from "./KeySwipe.vue";
|
||||||
import ScreenStream from "../ScreenStream.vue";
|
import ScreenStream from "../ScreenStream.vue";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -17,6 +18,7 @@ import {
|
|||||||
KeyTap,
|
KeyTap,
|
||||||
KeyMacro,
|
KeyMacro,
|
||||||
KeyMapping,
|
KeyMapping,
|
||||||
|
KeySwipe as KeyMappingKeySwipe,
|
||||||
KeySight as KeyMappingKeySight,
|
KeySight as KeyMappingKeySight,
|
||||||
KeyFire as KeyMappingKeyFire,
|
KeyFire as KeyMappingKeyFire,
|
||||||
} from "../../keyMappingConfig";
|
} from "../../keyMappingConfig";
|
||||||
@ -43,6 +45,10 @@ const addButtonOptions: DropdownOption[] = [
|
|||||||
label: () => t("pages.KeyBoard.addButton.SteeringWheel"),
|
label: () => t("pages.KeyBoard.addButton.SteeringWheel"),
|
||||||
key: "SteeringWheel",
|
key: "SteeringWheel",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: () => t("pages.KeyBoard.addButton.Swipe"),
|
||||||
|
key: "Swipe",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: () => t("pages.KeyBoard.addButton.Skill"),
|
label: () => t("pages.KeyBoard.addButton.Skill"),
|
||||||
key: "DirectionalSkill",
|
key: "DirectionalSkill",
|
||||||
@ -72,6 +78,7 @@ const addButtonOptions: DropdownOption[] = [
|
|||||||
function onAddButtonSelect(
|
function onAddButtonSelect(
|
||||||
type:
|
type:
|
||||||
| "Tap"
|
| "Tap"
|
||||||
|
| "Swipe"
|
||||||
| "SteeringWheel"
|
| "SteeringWheel"
|
||||||
| "DirectionalSkill"
|
| "DirectionalSkill"
|
||||||
| "CancelSkill"
|
| "CancelSkill"
|
||||||
@ -92,6 +99,12 @@ function onAddButtonSelect(
|
|||||||
if (type === "Tap") {
|
if (type === "Tap") {
|
||||||
keyMapping.pointerId = 3;
|
keyMapping.pointerId = 3;
|
||||||
(keyMapping as KeyTap).time = 80;
|
(keyMapping as KeyTap).time = 80;
|
||||||
|
} else if (type === "Swipe") {
|
||||||
|
keyMapping.pointerId = 3;
|
||||||
|
(keyMapping as KeyMappingKeySwipe).pos = [
|
||||||
|
{ x: keyMapping.posX, y: keyMapping.posY },
|
||||||
|
];
|
||||||
|
(keyMapping as KeyMappingKeySwipe).intervalBetweenPos = 100;
|
||||||
} else if (type === "SteeringWheel") {
|
} else if (type === "SteeringWheel") {
|
||||||
keyMapping.pointerId = 1;
|
keyMapping.pointerId = 1;
|
||||||
(keyMapping as unknown as KeyMappingSteeringWheel).key = {
|
(keyMapping as unknown as KeyMappingSteeringWheel).key = {
|
||||||
@ -139,6 +152,7 @@ function onAddButtonSelect(
|
|||||||
} else return;
|
} else return;
|
||||||
keyboardStore.edited = true;
|
keyboardStore.edited = true;
|
||||||
store.editKeyMappingList.push(keyMapping as KeyMapping);
|
store.editKeyMappingList.push(keyMapping as KeyMapping);
|
||||||
|
keyboardStore.activeButtonIndex = store.editKeyMappingList.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isKeyUnique(curKey: string): boolean {
|
function isKeyUnique(curKey: string): boolean {
|
||||||
@ -172,6 +186,7 @@ function setCurButtonKey(curKey: string) {
|
|||||||
keyboardStore.showButtonSettingFlag ||
|
keyboardStore.showButtonSettingFlag ||
|
||||||
keyboardStore.activeButtonIndex >= store.editKeyMappingList.length ||
|
keyboardStore.activeButtonIndex >= store.editKeyMappingList.length ||
|
||||||
keyboardStore.showButtonSettingFlag ||
|
keyboardStore.showButtonSettingFlag ||
|
||||||
|
keyboardStore.editSwipePointsFlag ||
|
||||||
keyboardStore.showButtonAddFlag
|
keyboardStore.showButtonAddFlag
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
@ -362,6 +377,10 @@ onBeforeRouteLeave(() => {
|
|||||||
v-else-if="store.editKeyMappingList[index].type === 'Observation'"
|
v-else-if="store.editKeyMappingList[index].type === 'Observation'"
|
||||||
:index="index"
|
:index="index"
|
||||||
/>
|
/>
|
||||||
|
<KeySwipe
|
||||||
|
v-else-if="store.editKeyMappingList[index].type === 'Swipe'"
|
||||||
|
:index="index"
|
||||||
|
/>
|
||||||
<KeySight
|
<KeySight
|
||||||
v-else-if="store.editKeyMappingList[index].type === 'Sight'"
|
v-else-if="store.editKeyMappingList[index].type === 'Sight'"
|
||||||
:index="index"
|
:index="index"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Settings, CloseCircle } from "@vicons/ionicons5";
|
import { Settings, CloseCircle, ReturnUpBack } from "@vicons/ionicons5";
|
||||||
import {
|
import {
|
||||||
NButton,
|
NButton,
|
||||||
NIcon,
|
NIcon,
|
||||||
@ -19,6 +19,7 @@ import { loadDefaultKeyconfig } from "../../invoke";
|
|||||||
import { KeyMappingConfig } from "../../keyMappingConfig";
|
import { KeyMappingConfig } from "../../keyMappingConfig";
|
||||||
import { useKeyboardStore } from "../../store/keyboard";
|
import { useKeyboardStore } from "../../store/keyboard";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const store = useGlobalStore();
|
const store = useGlobalStore();
|
||||||
@ -121,6 +122,9 @@ function dragHandler(downEvent: MouseEvent) {
|
|||||||
localStore.set("keySettingPos", keySettingPos.value);
|
localStore.set("keySettingPos", keySettingPos.value);
|
||||||
} else {
|
} else {
|
||||||
// click up
|
// click up
|
||||||
|
if (keyboardStore.editSwipePointsFlag) {
|
||||||
|
keyboardStore.editSwipePointsFlag = false;
|
||||||
|
} else {
|
||||||
keyboardStore.activeButtonIndex = -1;
|
keyboardStore.activeButtonIndex = -1;
|
||||||
keyboardStore.activeSteeringWheelButtonKeyIndex = -1;
|
keyboardStore.activeSteeringWheelButtonKeyIndex = -1;
|
||||||
keyboardStore.showSettingFlag = !keyboardStore.showSettingFlag;
|
keyboardStore.showSettingFlag = !keyboardStore.showSettingFlag;
|
||||||
@ -131,6 +135,7 @@ function dragHandler(downEvent: MouseEvent) {
|
|||||||
message.info(t("pages.KeyBoard.KeySetting.onlyOneConfig"));
|
message.info(t("pages.KeyBoard.KeySetting.onlyOneConfig"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener("mouseup", upHandler);
|
window.addEventListener("mouseup", upHandler);
|
||||||
}
|
}
|
||||||
@ -251,8 +256,7 @@ function renameKeyMappingConfig() {
|
|||||||
function exportKeyMappingConfig() {
|
function exportKeyMappingConfig() {
|
||||||
const config = store.keyMappingConfigList[store.curKeyMappingIndex];
|
const config = store.keyMappingConfigList[store.curKeyMappingIndex];
|
||||||
const data = JSON.stringify(config, null, 2);
|
const data = JSON.stringify(config, null, 2);
|
||||||
navigator.clipboard
|
writeText(data)
|
||||||
.writeText(data)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
message.success(t("pages.KeyBoard.KeySetting.exportSuccess"));
|
message.success(t("pages.KeyBoard.KeySetting.exportSuccess"));
|
||||||
})
|
})
|
||||||
@ -374,7 +378,10 @@ function resetKeyMappingConfig() {
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<NIcon><Settings /></NIcon>
|
<NIcon>
|
||||||
|
<ReturnUpBack v-if="keyboardStore.editSwipePointsFlag" />
|
||||||
|
<Settings v-else />
|
||||||
|
</NIcon>
|
||||||
</template>
|
</template>
|
||||||
</NButton>
|
</NButton>
|
||||||
<div
|
<div
|
||||||
|
355
src/components/keyboard/KeySwipe.vue
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import { useGlobalStore } from "../../store/global";
|
||||||
|
import {
|
||||||
|
NIcon,
|
||||||
|
NButton,
|
||||||
|
NFormItem,
|
||||||
|
NInput,
|
||||||
|
NH4,
|
||||||
|
NInputNumber,
|
||||||
|
useMessage,
|
||||||
|
} from "naive-ui";
|
||||||
|
import { Analytics, CloseCircle, Settings } from "@vicons/ionicons5";
|
||||||
|
import { useKeyboardStore } from "../../store/keyboard";
|
||||||
|
import { KeySwipe } from "../../keyMappingConfig";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
index: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const keyboardStore = useKeyboardStore();
|
||||||
|
const message = useMessage();
|
||||||
|
const store = useGlobalStore();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const elementRef = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
const isActive = computed(
|
||||||
|
() => props.index === keyboardStore.activeButtonIndex
|
||||||
|
);
|
||||||
|
const keyMapping = computed(
|
||||||
|
() => store.editKeyMappingList[props.index] as KeySwipe
|
||||||
|
);
|
||||||
|
|
||||||
|
const trackPoints = computed(() => {
|
||||||
|
let s = "";
|
||||||
|
if (isActive.value) {
|
||||||
|
for (const point of keyMapping.value.pos) {
|
||||||
|
s += `${point.x},${point.y} `;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
|
||||||
|
function dragHandler(downEvent: MouseEvent) {
|
||||||
|
keyboardStore.activeButtonIndex = props.index;
|
||||||
|
keyboardStore.showButtonSettingFlag = false;
|
||||||
|
const oldX = keyMapping.value.posX;
|
||||||
|
const oldY = keyMapping.value.posY;
|
||||||
|
const element = elementRef.value;
|
||||||
|
if (element) {
|
||||||
|
const keyboardElement = document.getElementById(
|
||||||
|
"keyboardElement"
|
||||||
|
) as HTMLElement;
|
||||||
|
const maxX = keyboardElement.clientWidth - 30;
|
||||||
|
const maxY = keyboardElement.clientHeight - 30;
|
||||||
|
|
||||||
|
const x = downEvent.clientX;
|
||||||
|
const y = downEvent.clientY;
|
||||||
|
const moveHandler = (moveEvent: MouseEvent) => {
|
||||||
|
let newX = oldX + moveEvent.clientX - x;
|
||||||
|
let newY = oldY + moveEvent.clientY - y;
|
||||||
|
newX = Math.max(30, Math.min(newX, maxX));
|
||||||
|
newY = Math.max(30, Math.min(newY, maxY));
|
||||||
|
keyMapping.value.posX = newX;
|
||||||
|
keyMapping.value.posY = newY;
|
||||||
|
};
|
||||||
|
window.addEventListener("mousemove", moveHandler);
|
||||||
|
const upHandler = () => {
|
||||||
|
window.removeEventListener("mousemove", moveHandler);
|
||||||
|
window.removeEventListener("mouseup", upHandler);
|
||||||
|
if (oldX !== keyMapping.value.posX || oldY !== keyMapping.value.posY) {
|
||||||
|
keyboardStore.edited = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("mouseup", upHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function delCurKeyMapping() {
|
||||||
|
keyboardStore.edited = true;
|
||||||
|
keyboardStore.activeButtonIndex = -1;
|
||||||
|
store.editKeyMappingList.splice(props.index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const settingPosX = ref(0);
|
||||||
|
const settingPosY = ref(0);
|
||||||
|
function showSetting() {
|
||||||
|
const keyboardElement = document.getElementById(
|
||||||
|
"keyboardElement"
|
||||||
|
) as HTMLElement;
|
||||||
|
const maxWidth = keyboardElement.clientWidth - 150;
|
||||||
|
const maxHeight = keyboardElement.clientHeight - 380;
|
||||||
|
|
||||||
|
settingPosX.value = Math.min(keyMapping.value.posX + 40, maxWidth);
|
||||||
|
settingPosY.value = Math.min(keyMapping.value.posY - 40, maxHeight);
|
||||||
|
keyboardStore.showButtonSettingFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function editSwipePoints() {
|
||||||
|
message.info(t("pages.KeyBoard.Swipe.editTips"));
|
||||||
|
keyboardStore.showButtonSettingFlag = false;
|
||||||
|
keyboardStore.editSwipePointsFlag = true;
|
||||||
|
keyboardStore.edited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function swipePointDragHandlue(downEvent: MouseEvent, index: number) {
|
||||||
|
if (downEvent.button === 2) {
|
||||||
|
// del point
|
||||||
|
keyMapping.value.pos.splice(index, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (downEvent.button !== 0) return;
|
||||||
|
|
||||||
|
const oldX = keyMapping.value.pos[index].x;
|
||||||
|
const oldY = keyMapping.value.pos[index].y;
|
||||||
|
const keyboardElement = document.getElementById(
|
||||||
|
"keyboardElement"
|
||||||
|
) as HTMLElement;
|
||||||
|
const maxX = keyboardElement.clientWidth;
|
||||||
|
const maxY = keyboardElement.clientHeight;
|
||||||
|
|
||||||
|
const x = downEvent.clientX;
|
||||||
|
const y = downEvent.clientY;
|
||||||
|
const moveHandler = (moveEvent: MouseEvent) => {
|
||||||
|
let newX = oldX + moveEvent.clientX - x;
|
||||||
|
let newY = oldY + moveEvent.clientY - y;
|
||||||
|
newX = Math.max(0, Math.min(newX, maxX));
|
||||||
|
newY = Math.max(0, Math.min(newY, maxY));
|
||||||
|
keyMapping.value.pos[index].x = newX;
|
||||||
|
keyMapping.value.pos[index].y = newY;
|
||||||
|
};
|
||||||
|
const upHandler = () => {
|
||||||
|
window.removeEventListener("mousemove", moveHandler);
|
||||||
|
window.removeEventListener("mouseup", upHandler);
|
||||||
|
};
|
||||||
|
window.addEventListener("mousemove", moveHandler);
|
||||||
|
window.addEventListener("mouseup", upHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
function swipeTrackClickHandler(event: MouseEvent) {
|
||||||
|
if (event.button !== 0) return;
|
||||||
|
console.log(event.target, event.currentTarget);
|
||||||
|
if (event.target !== event.currentTarget) return;
|
||||||
|
keyMapping.value.pos.push({ x: event.clientX - 70, y: event.clientY - 30 });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="{ active: isActive }"
|
||||||
|
:style="{
|
||||||
|
left: `${keyMapping.posX - 30}px`,
|
||||||
|
top: `${keyMapping.posY - 30}px`,
|
||||||
|
}"
|
||||||
|
@mousedown="dragHandler"
|
||||||
|
class="key-swipe"
|
||||||
|
ref="elementRef"
|
||||||
|
>
|
||||||
|
<NIcon size="30"><Analytics /></NIcon>
|
||||||
|
<span>{{ keyMapping.key }}</span>
|
||||||
|
<NButton
|
||||||
|
class="key-close-btn"
|
||||||
|
text
|
||||||
|
@click="delCurKeyMapping"
|
||||||
|
:type="isActive ? 'primary' : 'info'"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<NIcon size="15">
|
||||||
|
<CloseCircle />
|
||||||
|
</NIcon>
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
<NButton
|
||||||
|
class="key-setting-btn"
|
||||||
|
text
|
||||||
|
@click="showSetting"
|
||||||
|
:type="isActive ? 'primary' : 'info'"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<NIcon size="15">
|
||||||
|
<Settings />
|
||||||
|
</NIcon>
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="key-setting"
|
||||||
|
v-if="isActive && keyboardStore.showButtonSettingFlag"
|
||||||
|
:style="{
|
||||||
|
left: `${settingPosX}px`,
|
||||||
|
top: `${settingPosY}px`,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<NH4 prefix="bar">{{ $t("pages.KeyBoard.Swipe.swipe") }}</NH4>
|
||||||
|
<NFormItem :label="$t('pages.KeyBoard.Swipe.pos')">
|
||||||
|
<NButton type="success" @click="editSwipePoints">{{
|
||||||
|
$t("pages.KeyBoard.Swipe.editPos")
|
||||||
|
}}</NButton>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem :label="$t('pages.KeyBoard.Swipe.interval')">
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value="keyMapping.intervalBetweenPos"
|
||||||
|
:placeholder="$t('pages.KeyBoard.Swipe.intervalPlaceholder')"
|
||||||
|
@update:value="keyboardStore.edited = true"
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem :label="$t('pages.KeyBoard.setting.pointerID')">
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value="keyMapping.pointerId"
|
||||||
|
:min="0"
|
||||||
|
:placeholder="$t('pages.KeyBoard.setting.pointerIDPlaceholder')"
|
||||||
|
@update:value="keyboardStore.edited = true"
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem :label="$t('pages.KeyBoard.setting.note')">
|
||||||
|
<NInput
|
||||||
|
v-model:value="keyMapping.note"
|
||||||
|
:placeholder="$t('pages.KeyBoard.setting.notePlaceholder')"
|
||||||
|
@update:value="keyboardStore.edited = true"
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-if="isActive">
|
||||||
|
<div
|
||||||
|
v-if="isActive"
|
||||||
|
class="track"
|
||||||
|
:class="{ 'edit-track': keyboardStore.editSwipePointsFlag }"
|
||||||
|
>
|
||||||
|
<svg @click="swipeTrackClickHandler">
|
||||||
|
<polyline :points="trackPoints" />
|
||||||
|
<circle
|
||||||
|
v-for="(pos, i) in keyMapping.pos"
|
||||||
|
:cx="pos.x"
|
||||||
|
:cy="pos.y"
|
||||||
|
r="5"
|
||||||
|
@mousedown="(e) => swipePointDragHandlue(e, i)"
|
||||||
|
/>
|
||||||
|
<text v-for="(pos, i) in keyMapping.pos" :x="pos.x + 5" :y="pos.y - 5">
|
||||||
|
{{ i }}
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.track {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: -1;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
polyline {
|
||||||
|
fill: none;
|
||||||
|
stroke: var(--primary-hover-color);
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
circle {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: var(--primary-color);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
fill: var(--primary-pressed-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
cursor: default;
|
||||||
|
fill: var(--primary-pressed-color);
|
||||||
|
font-size: 15px;
|
||||||
|
text-anchor: end-alignment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-track {
|
||||||
|
z-index: 4;
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-setting {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 150px;
|
||||||
|
height: 380px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 2px solid var(--light-color);
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-swipe {
|
||||||
|
position: absolute;
|
||||||
|
height: 60px;
|
||||||
|
width: 60px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid var(--blue-color);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.n-icon {
|
||||||
|
color: var(--blue-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.active):hover {
|
||||||
|
border: 2px solid var(--light-color);
|
||||||
|
color: var(--light-color);
|
||||||
|
|
||||||
|
.n-icon {
|
||||||
|
color: var(--light-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-close-btn {
|
||||||
|
position: absolute;
|
||||||
|
left: 65px;
|
||||||
|
bottom: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-setting-btn {
|
||||||
|
position: absolute;
|
||||||
|
left: 65px;
|
||||||
|
top: 45px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
border: 2px solid var(--primary-color);
|
||||||
|
color: var(--primary-color);
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.n-icon {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,23 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Store } from "@tauri-apps/plugin-store";
|
import { Store } from "@tauri-apps/plugin-store";
|
||||||
import { Refresh, TrashBinOutline } from "@vicons/ionicons5";
|
|
||||||
import {
|
import {
|
||||||
NH4,
|
NH4,
|
||||||
NP,
|
|
||||||
NButton,
|
NButton,
|
||||||
NFlex,
|
|
||||||
NList,
|
|
||||||
NListItem,
|
|
||||||
NModal,
|
|
||||||
NInput,
|
NInput,
|
||||||
useDialog,
|
|
||||||
NCard,
|
|
||||||
NIcon,
|
|
||||||
NSelect,
|
NSelect,
|
||||||
NInputGroup,
|
NInputGroup,
|
||||||
useMessage,
|
useMessage,
|
||||||
|
NFlex,
|
||||||
|
NCheckbox,
|
||||||
|
NTooltip,
|
||||||
} from "naive-ui";
|
} from "naive-ui";
|
||||||
import { relaunch } from "@tauri-apps/plugin-process";
|
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import i18n from "../../i18n";
|
import i18n from "../../i18n";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
@ -28,12 +21,6 @@ const { t } = useI18n();
|
|||||||
const localStore = new Store("store.bin");
|
const localStore = new Store("store.bin");
|
||||||
const store = useGlobalStore();
|
const store = useGlobalStore();
|
||||||
const message = useMessage();
|
const message = useMessage();
|
||||||
const dialog = useDialog();
|
|
||||||
|
|
||||||
const localStoreEntries = ref<[string, unknown][]>([]);
|
|
||||||
const showDataModal = ref(false);
|
|
||||||
const dataModalInputVal = ref("");
|
|
||||||
let curDataIndex = -1;
|
|
||||||
|
|
||||||
const languageOptions = [
|
const languageOptions = [
|
||||||
{ label: "简体中文", value: "zh-CN" },
|
{ label: "简体中文", value: "zh-CN" },
|
||||||
@ -45,52 +32,10 @@ const curLanguage = ref("en-US");
|
|||||||
const adbPath = ref("");
|
const adbPath = ref("");
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
refreshLocalData();
|
|
||||||
curLanguage.value = (await localStore.get<string>("language")) ?? "en-US";
|
curLanguage.value = (await localStore.get<string>("language")) ?? "en-US";
|
||||||
adbPath.value = (await localStore.get<string>("adbPath")) ?? "";
|
adbPath.value = (await localStore.get<string>("adbPath")) ?? "";
|
||||||
});
|
});
|
||||||
|
|
||||||
async function refreshLocalData() {
|
|
||||||
localStoreEntries.value = await localStore.entries();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showLocalStore(index: number) {
|
|
||||||
curDataIndex = index;
|
|
||||||
dataModalInputVal.value = JSON.stringify(
|
|
||||||
localStoreEntries.value[index][1],
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
);
|
|
||||||
showDataModal.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function delLocalStore(key?: string) {
|
|
||||||
if (key) {
|
|
||||||
dialog.warning({
|
|
||||||
title: t("pages.Setting.Basic.delLocalStore.dialog.title"),
|
|
||||||
content: t("pages.Setting.Basic.delLocalStore.dialog.delKey", [key]),
|
|
||||||
positiveText: t("pages.Setting.Basic.delLocalStore.dialog.positiveText"),
|
|
||||||
negativeText: t("pages.Setting.Basic.delLocalStore.dialog.negativeText"),
|
|
||||||
onPositiveClick: () => {
|
|
||||||
localStore.delete(key);
|
|
||||||
localStoreEntries.value.splice(curDataIndex, 1);
|
|
||||||
showDataModal.value = false;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dialog.warning({
|
|
||||||
title: t("pages.Setting.Basic.delLocalStore.dialog.title"),
|
|
||||||
content: t("pages.Setting.Basic.delLocalStore.dialog.delAll"),
|
|
||||||
positiveText: t("pages.Setting.Basic.delLocalStore.dialog.positiveText"),
|
|
||||||
negativeText: t("pages.Setting.Basic.delLocalStore.dialog.negativeText"),
|
|
||||||
onPositiveClick: () => {
|
|
||||||
localStore.clear();
|
|
||||||
relaunch();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeLanguage(language: "zh-CN" | "en-US") {
|
function changeLanguage(language: "zh-CN" | "en-US") {
|
||||||
if (language === curLanguage.value) return;
|
if (language === curLanguage.value) return;
|
||||||
curLanguage.value = language;
|
curLanguage.value = language;
|
||||||
@ -106,6 +51,10 @@ async function adjustAdbPath() {
|
|||||||
adbPath.value = (await localStore.get<string>("adbPath")) ?? "";
|
adbPath.value = (await localStore.get<string>("adbPath")) ?? "";
|
||||||
store.hideLoading();
|
store.hideLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeClipboardSync() {
|
||||||
|
localStore.set("clipboardSync", store.clipboardSync);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -128,72 +77,32 @@ async function adjustAdbPath() {
|
|||||||
$t("pages.Setting.Basic.adbPath.set")
|
$t("pages.Setting.Basic.adbPath.set")
|
||||||
}}</NButton>
|
}}</NButton>
|
||||||
</NInputGroup>
|
</NInputGroup>
|
||||||
<NFlex justify="space-between">
|
<NH4 prefix="bar">剪切板同步</NH4>
|
||||||
<NH4 prefix="bar">{{ $t("pages.Setting.Basic.localStore") }}</NH4>
|
<NFlex vertical>
|
||||||
<NFlex>
|
<NCheckbox
|
||||||
<NButton
|
v-model:checked="store.clipboardSync.syncFromDevice"
|
||||||
tertiary
|
@update:checked="changeClipboardSync"
|
||||||
circle
|
|
||||||
type="primary"
|
|
||||||
@click="delLocalStore()"
|
|
||||||
style="margin-right: 20px"
|
|
||||||
>
|
>
|
||||||
<template #icon>
|
<NTooltip trigger="hover">
|
||||||
<NIcon><TrashBinOutline /></NIcon>
|
<template #trigger>从设备同步</template>
|
||||||
</template>
|
设备剪切板发生变化时自动同步更新电脑剪切板
|
||||||
</NButton>
|
</NTooltip>
|
||||||
<NButton
|
</NCheckbox>
|
||||||
tertiary
|
<NCheckbox
|
||||||
circle
|
v-model:checked="store.clipboardSync.pasteFromPC"
|
||||||
type="primary"
|
@update:checked="changeClipboardSync"
|
||||||
@click="refreshLocalData()"
|
|
||||||
style="margin-right: 20px"
|
|
||||||
>
|
>
|
||||||
<template #icon>
|
<NTooltip trigger="hover">
|
||||||
<NIcon><Refresh /></NIcon>
|
<template #trigger>粘贴时同步</template>
|
||||||
</template>
|
在按键输入模式下,按下 Ctrl + V 可将电脑剪切板内容同步粘贴到设备
|
||||||
</NButton>
|
</NTooltip>
|
||||||
|
</NCheckbox>
|
||||||
</NFlex>
|
</NFlex>
|
||||||
</NFlex>
|
|
||||||
<NP>{{ $t("pages.Setting.Basic.delLocalStore.warning") }}</NP>
|
|
||||||
<NList class="data-list" hoverable clickable>
|
|
||||||
<NListItem v-for="(entrie, index) in localStoreEntries">
|
|
||||||
<div @click="showLocalStore(index)">
|
|
||||||
{{ entrie[0] }}
|
|
||||||
</div>
|
</div>
|
||||||
</NListItem>
|
|
||||||
</NList>
|
|
||||||
</div>
|
|
||||||
<NModal v-model:show="showDataModal">
|
|
||||||
<NCard
|
|
||||||
style="width: 50%; height: 80%"
|
|
||||||
:title="localStoreEntries[curDataIndex][0]"
|
|
||||||
>
|
|
||||||
<NFlex vertical style="height: 100%">
|
|
||||||
<NInput
|
|
||||||
type="textarea"
|
|
||||||
style="flex-grow: 1"
|
|
||||||
:value="dataModalInputVal"
|
|
||||||
round
|
|
||||||
readonly
|
|
||||||
/>
|
|
||||||
<NButton
|
|
||||||
type="success"
|
|
||||||
round
|
|
||||||
@click="delLocalStore(localStoreEntries[curDataIndex][0])"
|
|
||||||
>{{ $t("pages.Setting.Basic.delCurData") }}</NButton
|
|
||||||
>
|
|
||||||
</NFlex>
|
|
||||||
</NCard>
|
|
||||||
</NModal>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.setting-page {
|
.setting-page {
|
||||||
padding: 10px 25px;
|
padding: 10px 25px;
|
||||||
|
|
||||||
.data-list {
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
149
src/components/setting/Data.vue
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Store } from "@tauri-apps/plugin-store";
|
||||||
|
import { Refresh, TrashBinOutline } from "@vicons/ionicons5";
|
||||||
|
import {
|
||||||
|
NH4,
|
||||||
|
NP,
|
||||||
|
NButton,
|
||||||
|
NFlex,
|
||||||
|
NList,
|
||||||
|
NListItem,
|
||||||
|
NModal,
|
||||||
|
NInput,
|
||||||
|
useDialog,
|
||||||
|
NCard,
|
||||||
|
NIcon,
|
||||||
|
} from "naive-ui";
|
||||||
|
import { relaunch } from "@tauri-apps/plugin-process";
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const localStore = new Store("store.bin");
|
||||||
|
const dialog = useDialog();
|
||||||
|
|
||||||
|
const localStoreEntries = ref<[string, unknown][]>([]);
|
||||||
|
const showDataModal = ref(false);
|
||||||
|
const dataModalInputVal = ref("");
|
||||||
|
let curDataIndex = -1;
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
refreshLocalData();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function refreshLocalData() {
|
||||||
|
localStoreEntries.value = await localStore.entries();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showLocalStore(index: number) {
|
||||||
|
curDataIndex = index;
|
||||||
|
dataModalInputVal.value = JSON.stringify(
|
||||||
|
localStoreEntries.value[index][1],
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
showDataModal.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delLocalStore(key?: string) {
|
||||||
|
if (key) {
|
||||||
|
dialog.warning({
|
||||||
|
title: t("pages.Setting.Data.delLocalStore.dialog.title"),
|
||||||
|
content: t("pages.Setting.Data.delLocalStore.dialog.delKey", [key]),
|
||||||
|
positiveText: t("pages.Setting.Data.delLocalStore.dialog.positiveText"),
|
||||||
|
negativeText: t("pages.Setting.Data.delLocalStore.dialog.negativeText"),
|
||||||
|
onPositiveClick: () => {
|
||||||
|
localStore.delete(key);
|
||||||
|
localStoreEntries.value.splice(curDataIndex, 1);
|
||||||
|
showDataModal.value = false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dialog.warning({
|
||||||
|
title: t("pages.Setting.Data.delLocalStore.dialog.title"),
|
||||||
|
content: t("pages.Setting.Data.delLocalStore.dialog.delAll"),
|
||||||
|
positiveText: t("pages.Setting.Data.delLocalStore.dialog.positiveText"),
|
||||||
|
negativeText: t("pages.Setting.Data.delLocalStore.dialog.negativeText"),
|
||||||
|
onPositiveClick: () => {
|
||||||
|
localStore.clear();
|
||||||
|
relaunch();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="setting-page">
|
||||||
|
<NFlex justify="space-between">
|
||||||
|
<NH4 prefix="bar">{{ $t("pages.Setting.Data.localStore") }}</NH4>
|
||||||
|
<NFlex>
|
||||||
|
<NButton
|
||||||
|
tertiary
|
||||||
|
circle
|
||||||
|
type="primary"
|
||||||
|
@click="delLocalStore()"
|
||||||
|
style="margin-right: 20px"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<NIcon><TrashBinOutline /></NIcon>
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
<NButton
|
||||||
|
tertiary
|
||||||
|
circle
|
||||||
|
type="primary"
|
||||||
|
@click="refreshLocalData()"
|
||||||
|
style="margin-right: 20px"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<NIcon><Refresh /></NIcon>
|
||||||
|
</template>
|
||||||
|
</NButton>
|
||||||
|
</NFlex>
|
||||||
|
</NFlex>
|
||||||
|
<NP>{{ $t("pages.Setting.Data.delLocalStore.warning") }}</NP>
|
||||||
|
<NList class="data-list" hoverable clickable>
|
||||||
|
<NListItem
|
||||||
|
v-for="(entrie, index) in localStoreEntries"
|
||||||
|
@click="showLocalStore(index)"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{{ entrie[0] }}
|
||||||
|
</div>
|
||||||
|
</NListItem>
|
||||||
|
</NList>
|
||||||
|
</div>
|
||||||
|
<NModal v-model:show="showDataModal">
|
||||||
|
<NCard
|
||||||
|
style="width: 50%; height: 80%"
|
||||||
|
:title="localStoreEntries[curDataIndex][0]"
|
||||||
|
>
|
||||||
|
<NFlex vertical style="height: 100%">
|
||||||
|
<NInput
|
||||||
|
type="textarea"
|
||||||
|
style="flex-grow: 1"
|
||||||
|
:value="dataModalInputVal"
|
||||||
|
round
|
||||||
|
readonly
|
||||||
|
/>
|
||||||
|
<NButton
|
||||||
|
type="success"
|
||||||
|
round
|
||||||
|
@click="delLocalStore(localStoreEntries[curDataIndex][0])"
|
||||||
|
>{{ $t("pages.Setting.Data.delCurData") }}</NButton
|
||||||
|
>
|
||||||
|
</NFlex>
|
||||||
|
</NCard>
|
||||||
|
</NModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.setting-page {
|
||||||
|
padding: 10px 25px;
|
||||||
|
|
||||||
|
.data-list {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Basic from "./Basic.vue";
|
import Basic from "./Basic.vue";
|
||||||
import Mask from "./Mask.vue";
|
import Mask from "./Mask.vue";
|
||||||
|
import Data from "./Data.vue";
|
||||||
import About from "./About.vue";
|
import About from "./About.vue";
|
||||||
import { NTabs, NTabPane, NScrollbar, NSpin } from "naive-ui";
|
import { NTabs, NTabPane, NScrollbar, NSpin } from "naive-ui";
|
||||||
import { useGlobalStore } from "../../store/global";
|
import { useGlobalStore } from "../../store/global";
|
||||||
@ -22,6 +23,11 @@ const store = useGlobalStore();
|
|||||||
<Mask />
|
<Mask />
|
||||||
</NScrollbar>
|
</NScrollbar>
|
||||||
</NTabPane>
|
</NTabPane>
|
||||||
|
<NTabPane :tab="$t('pages.Setting.tabs.data')" name="data">
|
||||||
|
<NScrollbar>
|
||||||
|
<Data />
|
||||||
|
</NScrollbar>
|
||||||
|
</NTabPane>
|
||||||
<NTabPane :tab="$t('pages.Setting.tabs.about')" name="about">
|
<NTabPane :tab="$t('pages.Setting.tabs.about')" name="about">
|
||||||
<NScrollbar>
|
<NScrollbar>
|
||||||
<About />
|
<About />
|
||||||
|
@ -163,13 +163,13 @@ interface InjectKeycode {
|
|||||||
metastate: AndroidMetastate;
|
metastate: AndroidMetastate;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ScCopyKey {
|
export enum ScCopyKey {
|
||||||
SC_COPY_KEY_NONE,
|
SC_COPY_KEY_NONE,
|
||||||
SC_COPY_KEY_COPY,
|
SC_COPY_KEY_COPY,
|
||||||
SC_COPY_KEY_CUT,
|
SC_COPY_KEY_CUT,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ScScreenPowerMode {
|
export enum ScScreenPowerMode {
|
||||||
// see <https://android.googlesource.com/platform/frameworks/base.git/+/pie-release-2/core/java/android/view/SurfaceControl.java#305>
|
// see <https://android.googlesource.com/platform/frameworks/base.git/+/pie-release-2/core/java/android/view/SurfaceControl.java#305>
|
||||||
SC_SCREEN_POWER_MODE_OFF = 0,
|
SC_SCREEN_POWER_MODE_OFF = 0,
|
||||||
SC_SCREEN_POWER_MODE_NORMAL = 2,
|
SC_SCREEN_POWER_MODE_NORMAL = 2,
|
||||||
|
@ -17,12 +17,14 @@ import {
|
|||||||
KeyObservation,
|
KeyObservation,
|
||||||
KeySight,
|
KeySight,
|
||||||
KeySteeringWheel,
|
KeySteeringWheel,
|
||||||
|
KeySwipe,
|
||||||
KeyTap,
|
KeyTap,
|
||||||
KeyTriggerWhenDoublePressedSkill,
|
KeyTriggerWhenDoublePressedSkill,
|
||||||
KeyTriggerWhenPressedSkill,
|
KeyTriggerWhenPressedSkill,
|
||||||
} from "./keyMappingConfig";
|
} from "./keyMappingConfig";
|
||||||
import { useGlobalStore } from "./store/global";
|
import { useGlobalStore } from "./store/global";
|
||||||
import { LogicalPosition, getCurrent } from "@tauri-apps/api/window";
|
import { LogicalPosition, getCurrent } from "@tauri-apps/api/window";
|
||||||
|
import { readText } from "@tauri-apps/plugin-clipboard-manager";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { KeyToCodeMap } from "./frontcommand/KeyToCodeMap";
|
import { KeyToCodeMap } from "./frontcommand/KeyToCodeMap";
|
||||||
import {
|
import {
|
||||||
@ -30,7 +32,7 @@ import {
|
|||||||
AndroidMetastate,
|
AndroidMetastate,
|
||||||
} from "./frontcommand/android";
|
} from "./frontcommand/android";
|
||||||
import { UIEventsCode } from "./frontcommand/UIEventsCode";
|
import { UIEventsCode } from "./frontcommand/UIEventsCode";
|
||||||
import { sendInjectKeycode } from "./frontcommand/controlMsg";
|
import { sendInjectKeycode, sendSetClipboard } from "./frontcommand/controlMsg";
|
||||||
|
|
||||||
function clientxToPosx(clientx: number) {
|
function clientxToPosx(clientx: number) {
|
||||||
return clientx < 70
|
return clientx < 70
|
||||||
@ -947,6 +949,40 @@ function addSightShortcuts(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addSwipeShortcuts(
|
||||||
|
key: string,
|
||||||
|
relativeSize: { w: number; h: number },
|
||||||
|
// pos relative to the mask
|
||||||
|
pos: { x: number; y: number }[],
|
||||||
|
pointerId: number,
|
||||||
|
intervalBetweenPos: number
|
||||||
|
) {
|
||||||
|
const newPosList = pos.map((posObj) => {
|
||||||
|
return {
|
||||||
|
x: Math.round((posObj.x / relativeSize.w) * store.screenSizeW),
|
||||||
|
y: Math.round((posObj.y / relativeSize.h) * store.screenSizeH),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
addShortcut(
|
||||||
|
key,
|
||||||
|
async () => {
|
||||||
|
await swipe({
|
||||||
|
action: SwipeAction.Default,
|
||||||
|
pointerId,
|
||||||
|
screen: {
|
||||||
|
w: store.screenSizeW,
|
||||||
|
h: store.screenSizeH,
|
||||||
|
},
|
||||||
|
pos: newPosList,
|
||||||
|
intervalBetweenPos,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function createMouseRangeBox(): HTMLElement {
|
function createMouseRangeBox(): HTMLElement {
|
||||||
const box = document.createElement("div");
|
const box = document.createElement("div");
|
||||||
box.id = "mouseRangeBox";
|
box.id = "mouseRangeBox";
|
||||||
@ -1046,6 +1082,8 @@ export class KeyInputHandler {
|
|||||||
let action: AndroidKeyEventAction;
|
let action: AndroidKeyEventAction;
|
||||||
let repeatCount = 0;
|
let repeatCount = 0;
|
||||||
if (event.type === "keydown") {
|
if (event.type === "keydown") {
|
||||||
|
if (event.getModifierState("Control") && event.code === "KeyV") return;
|
||||||
|
|
||||||
action = AndroidKeyEventAction.AKEY_EVENT_ACTION_DOWN;
|
action = AndroidKeyEventAction.AKEY_EVENT_ACTION_DOWN;
|
||||||
if (event.repeat) {
|
if (event.repeat) {
|
||||||
let count = KeyInputHandler.repeatCounter.get(keycode);
|
let count = KeyInputHandler.repeatCounter.get(keycode);
|
||||||
@ -1058,6 +1096,18 @@ export class KeyInputHandler {
|
|||||||
KeyInputHandler.repeatCounter.set(keycode, count);
|
KeyInputHandler.repeatCounter.set(keycode, count);
|
||||||
}
|
}
|
||||||
} else if (event.type === "keyup") {
|
} else if (event.type === "keyup") {
|
||||||
|
if (event.getModifierState("Control") && event.code === "KeyV") {
|
||||||
|
(async () => {
|
||||||
|
const text = await readText();
|
||||||
|
await sendSetClipboard({
|
||||||
|
sequence: Math.floor(Math.random() * 10000),
|
||||||
|
text,
|
||||||
|
paste: true,
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP;
|
action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP;
|
||||||
KeyInputHandler.repeatCounter.delete(keycode);
|
KeyInputHandler.repeatCounter.delete(keycode);
|
||||||
} else {
|
} else {
|
||||||
@ -1078,12 +1128,6 @@ export class KeyInputHandler {
|
|||||||
? AndroidMetastate.AMETA_NUM_LOCK_ON
|
? AndroidMetastate.AMETA_NUM_LOCK_ON
|
||||||
: 0);
|
: 0);
|
||||||
|
|
||||||
// const controlMessage = new KeyCodeControlMessage(
|
|
||||||
// action,
|
|
||||||
// keyCode,
|
|
||||||
// repeatCount,
|
|
||||||
// metaState
|
|
||||||
// );
|
|
||||||
sendInjectKeycode({
|
sendInjectKeycode({
|
||||||
action,
|
action,
|
||||||
keycode,
|
keycode,
|
||||||
@ -1378,6 +1422,16 @@ function applyKeyMappingConfigShortcuts(
|
|||||||
item.pointerId
|
item.pointerId
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case "Swipe":
|
||||||
|
asType<KeySwipe>(item);
|
||||||
|
addSwipeShortcuts(
|
||||||
|
item.key,
|
||||||
|
relativeSize,
|
||||||
|
item.pos,
|
||||||
|
item.pointerId,
|
||||||
|
item.intervalBetweenPos
|
||||||
|
);
|
||||||
|
break;
|
||||||
case "TriggerWhenPressedSkill":
|
case "TriggerWhenPressedSkill":
|
||||||
asType<KeyTriggerWhenPressedSkill>(item);
|
asType<KeyTriggerWhenPressedSkill>(item);
|
||||||
addTriggerWhenPressedSkillShortcuts(
|
addTriggerWhenPressedSkillShortcuts(
|
||||||
|
@ -36,13 +36,7 @@
|
|||||||
"wsConnect": "Control",
|
"wsConnect": "Control",
|
||||||
"adbDeviceError": "Unable to get available devices",
|
"adbDeviceError": "Unable to get available devices",
|
||||||
"adbConnectError": "Wireless connection failed",
|
"adbConnectError": "Wireless connection failed",
|
||||||
"rotation": "Device rotation {0}°",
|
"rotation": "Device rotation {0}°"
|
||||||
"clipboard": {
|
|
||||||
"deviceSync": {
|
|
||||||
"success": "Device clipboard synced",
|
|
||||||
"failed": "Device clipboard sync failed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"Mask": {
|
"Mask": {
|
||||||
"keyconfigException": "The key mapping config is abnormal, please delete this config",
|
"keyconfigException": "The key mapping config is abnormal, please delete this config",
|
||||||
@ -62,14 +56,15 @@
|
|||||||
"positiveText": "To control"
|
"positiveText": "To control"
|
||||||
},
|
},
|
||||||
"sightMode": "Mouse is locked, press {0} to unlock",
|
"sightMode": "Mouse is locked, press {0} to unlock",
|
||||||
"checkAdb": "adb is not available and the software cannot run normally. Please ensure that adb is installed on the system and added to the Path environment variable correctly: {0}",
|
"checkAdb": "adb is not available and the software cannot run normally. Fill in the path of the adb file in the setup page, or add the folder where it is located to the Path environment variable.: {0}",
|
||||||
"keyInputMode": "Has entered the keystroke input mode, close this message to exit."
|
"keyInputMode": "Has entered the keystroke input mode, close this message to exit."
|
||||||
},
|
},
|
||||||
"Setting": {
|
"Setting": {
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"basic": "Basic settings",
|
"basic": "Basic settings",
|
||||||
"mask": "Mask setting",
|
"mask": "Mask setting",
|
||||||
"about": "About"
|
"about": "About",
|
||||||
|
"data": "Data management"
|
||||||
},
|
},
|
||||||
"Mask": {
|
"Mask": {
|
||||||
"areaFormMissing": {
|
"areaFormMissing": {
|
||||||
@ -105,6 +100,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Basic": {
|
"Basic": {
|
||||||
|
"language": "Language",
|
||||||
|
"adbPath": {
|
||||||
|
"placeholder": "adb path",
|
||||||
|
"set": "Save",
|
||||||
|
"setSuccess": "adb path set successfully",
|
||||||
|
"title": "adb path"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Data": {
|
||||||
"delLocalStore": {
|
"delLocalStore": {
|
||||||
"dialog": {
|
"dialog": {
|
||||||
"title": "Warning",
|
"title": "Warning",
|
||||||
@ -115,15 +119,8 @@
|
|||||||
},
|
},
|
||||||
"warning": "Deleting data may lead to unpredictable consequences, so please operate with caution. \nIf an exception occurs, please try clearing the data and restarting the software."
|
"warning": "Deleting data may lead to unpredictable consequences, so please operate with caution. \nIf an exception occurs, please try clearing the data and restarting the software."
|
||||||
},
|
},
|
||||||
"language": "Language",
|
|
||||||
"localStore": "Local data",
|
"localStore": "Local data",
|
||||||
"delCurData": "Delete current data",
|
"delCurData": "Delete current data"
|
||||||
"adbPath": {
|
|
||||||
"placeholder": "adb path",
|
|
||||||
"set": "Save",
|
|
||||||
"setSuccess": "adb path set successfully",
|
|
||||||
"title": "adb path"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"About": {
|
"About": {
|
||||||
"introduction": "A Scrcpy client in Rust & Tarui aimed at providing mouse and key mapping to control Android device.",
|
"introduction": "A Scrcpy client in Rust & Tarui aimed at providing mouse and key mapping to control Android device.",
|
||||||
@ -154,7 +151,8 @@
|
|||||||
"Sight": "Front sight",
|
"Sight": "Front sight",
|
||||||
"Fire": "Fire",
|
"Fire": "Fire",
|
||||||
"existFire": "Fire button already exists",
|
"existFire": "Fire button already exists",
|
||||||
"existSight": "Front sight button already exists"
|
"existSight": "Front sight button already exists",
|
||||||
|
"Swipe": "Swipe"
|
||||||
},
|
},
|
||||||
"buttonKeyRepeat": "Key repeat: {0}",
|
"buttonKeyRepeat": "Key repeat: {0}",
|
||||||
"KeyCommon": {
|
"KeyCommon": {
|
||||||
@ -256,6 +254,14 @@
|
|||||||
"scaleX": "Horizontal sensitivity",
|
"scaleX": "Horizontal sensitivity",
|
||||||
"scalePlaceholder": "Please enter sensitivity",
|
"scalePlaceholder": "Please enter sensitivity",
|
||||||
"scaleY": "Vertical sensitivity"
|
"scaleY": "Vertical sensitivity"
|
||||||
|
},
|
||||||
|
"Swipe": {
|
||||||
|
"swipe": "Swipe",
|
||||||
|
"interval": "Swipe time interval",
|
||||||
|
"intervalPlaceholder": "Enter the time interval between points",
|
||||||
|
"pos": "Points",
|
||||||
|
"editPos": "Edit",
|
||||||
|
"editTips": "Left-click on a blank area to add a new coordinate point. \nLeft-click and drag to move a specific point, and right-click to delete the point."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -36,13 +36,7 @@
|
|||||||
"wsConnect": "控制",
|
"wsConnect": "控制",
|
||||||
"adbDeviceError": "无法获取可用设备",
|
"adbDeviceError": "无法获取可用设备",
|
||||||
"adbConnectError": "无线连接失败",
|
"adbConnectError": "无线连接失败",
|
||||||
"rotation": "设备旋转 {0}°",
|
"rotation": "设备旋转 {0}°"
|
||||||
"clipboard": {
|
|
||||||
"deviceSync": {
|
|
||||||
"success": "已从设备同步剪切板",
|
|
||||||
"failed": "从设备同步剪切板失败"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"Mask": {
|
"Mask": {
|
||||||
"keyconfigException": "按键方案异常,请删除此方案",
|
"keyconfigException": "按键方案异常,请删除此方案",
|
||||||
@ -62,14 +56,15 @@
|
|||||||
"positiveText": "去控制"
|
"positiveText": "去控制"
|
||||||
},
|
},
|
||||||
"sightMode": "鼠标已锁定, 按 {0} 键解锁",
|
"sightMode": "鼠标已锁定, 按 {0} 键解锁",
|
||||||
"checkAdb": "adb不可用,软件无法正常运行,请确保系统已安装adb,并正确添加到了Path环境变量中: {0}",
|
"checkAdb": "adb不可用,软件无法正常运行,请确保系统已安装adb。请将adb文件路径填入软件设置界面,或者将其所在文件夹添加到Path环境变量中: {0}",
|
||||||
"keyInputMode": "已进入按键输入模式,关闭本消息可退出"
|
"keyInputMode": "已进入按键输入模式,关闭本消息可退出"
|
||||||
},
|
},
|
||||||
"Setting": {
|
"Setting": {
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"basic": "基本设置",
|
"basic": "基本设置",
|
||||||
"mask": "蒙版设置",
|
"mask": "蒙版设置",
|
||||||
"about": "关于"
|
"about": "关于",
|
||||||
|
"data": "数据管理"
|
||||||
},
|
},
|
||||||
"Mask": {
|
"Mask": {
|
||||||
"incorrectArea": "请正确输入蒙版的坐标和尺寸",
|
"incorrectArea": "请正确输入蒙版的坐标和尺寸",
|
||||||
@ -105,6 +100,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Basic": {
|
"Basic": {
|
||||||
|
"language": "语言",
|
||||||
|
"adbPath": {
|
||||||
|
"setSuccess": "adb 路径设置成功",
|
||||||
|
"title": "adb 路径",
|
||||||
|
"placeholder": "adb 路径",
|
||||||
|
"set": "设置"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Data": {
|
||||||
"delLocalStore": {
|
"delLocalStore": {
|
||||||
"dialog": {
|
"dialog": {
|
||||||
"title": "警告",
|
"title": "警告",
|
||||||
@ -115,15 +119,8 @@
|
|||||||
},
|
},
|
||||||
"warning": "删除数据可能导致无法预料的后果,请慎重操作。若出现异常请尝试清空数据并重启软件。"
|
"warning": "删除数据可能导致无法预料的后果,请慎重操作。若出现异常请尝试清空数据并重启软件。"
|
||||||
},
|
},
|
||||||
"language": "语言",
|
|
||||||
"localStore": "本地数据",
|
"localStore": "本地数据",
|
||||||
"delCurData": "删除当前数据",
|
"delCurData": "删除当前数据"
|
||||||
"adbPath": {
|
|
||||||
"setSuccess": "adb 路径设置成功",
|
|
||||||
"title": "adb 路径",
|
|
||||||
"placeholder": "adb 路径",
|
|
||||||
"set": "设置"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"About": {
|
"About": {
|
||||||
"about": "关于",
|
"about": "关于",
|
||||||
@ -147,7 +144,8 @@
|
|||||||
"Sight": "准星",
|
"Sight": "准星",
|
||||||
"Fire": "开火",
|
"Fire": "开火",
|
||||||
"existSight": "已存在准星按钮",
|
"existSight": "已存在准星按钮",
|
||||||
"existFire": "已存在开火按钮"
|
"existFire": "已存在开火按钮",
|
||||||
|
"Swipe": "滑动"
|
||||||
},
|
},
|
||||||
"buttonKeyRepeat": "按键重复: {0}",
|
"buttonKeyRepeat": "按键重复: {0}",
|
||||||
"noSaveDialog": {
|
"noSaveDialog": {
|
||||||
@ -256,6 +254,14 @@
|
|||||||
"scaleX": "水平灵敏度",
|
"scaleX": "水平灵敏度",
|
||||||
"scaleY": "垂直灵敏度",
|
"scaleY": "垂直灵敏度",
|
||||||
"scalePlaceholder": "请输入灵敏度"
|
"scalePlaceholder": "请输入灵敏度"
|
||||||
|
},
|
||||||
|
"Swipe": {
|
||||||
|
"swipe": "滑动",
|
||||||
|
"interval": "滑动时间间隔",
|
||||||
|
"intervalPlaceholder": "输入坐标点之间的时间间隔",
|
||||||
|
"pos": "坐标点",
|
||||||
|
"editPos": "编辑",
|
||||||
|
"editTips": "左键点击空白区域添加新坐标点。左键拖拽移动特定坐标点,右键删除特定坐标点"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -65,6 +65,14 @@ export interface KeyTap extends KeyBase {
|
|||||||
time: number;
|
time: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface KeySwipe extends KeyBase {
|
||||||
|
type: "Swipe";
|
||||||
|
pointerId: number;
|
||||||
|
key: string;
|
||||||
|
pos: { x: number; y: number }[];
|
||||||
|
intervalBetweenPos: number;
|
||||||
|
}
|
||||||
|
|
||||||
export type KeyMacroList = Array<{
|
export type KeyMacroList = Array<{
|
||||||
type: "touch" | "sleep" | "swipe" | "key-input-mode";
|
type: "touch" | "sleep" | "swipe" | "key-input-mode";
|
||||||
args: any[];
|
args: any[];
|
||||||
@ -106,6 +114,7 @@ export type KeyMapping =
|
|||||||
| KeyMacro
|
| KeyMacro
|
||||||
| KeyCancelSkill
|
| KeyCancelSkill
|
||||||
| KeyTap
|
| KeyTap
|
||||||
|
| KeySwipe
|
||||||
| KeySight
|
| KeySight
|
||||||
| KeyFire;
|
| KeyFire;
|
||||||
|
|
||||||
|
@ -100,6 +100,11 @@ export const useGlobalStore = defineStore("global", () => {
|
|||||||
horizontalLength: 800,
|
horizontalLength: 800,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const clipboardSync = ref({
|
||||||
|
syncFromDevice: true,
|
||||||
|
pasteFromPC: true,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// persistent storage
|
// persistent storage
|
||||||
keyMappingConfigList,
|
keyMappingConfigList,
|
||||||
@ -109,6 +114,7 @@ export const useGlobalStore = defineStore("global", () => {
|
|||||||
externalControlled,
|
externalControlled,
|
||||||
screenStream,
|
screenStream,
|
||||||
rotation,
|
rotation,
|
||||||
|
clipboardSync,
|
||||||
// in-memory storage
|
// in-memory storage
|
||||||
screenStreamClientId,
|
screenStreamClientId,
|
||||||
maskSizeW,
|
maskSizeW,
|
||||||
|
@ -6,6 +6,7 @@ export const useKeyboardStore = defineStore("keyboard", () => {
|
|||||||
const showSettingFlag = ref(false);
|
const showSettingFlag = ref(false);
|
||||||
const showButtonSettingFlag = ref(false);
|
const showButtonSettingFlag = ref(false);
|
||||||
const showButtonAddFlag = ref(false);
|
const showButtonAddFlag = ref(false);
|
||||||
|
const editSwipePointsFlag = ref(false);
|
||||||
const activeButtonIndex = ref(-1);
|
const activeButtonIndex = ref(-1);
|
||||||
const activeSteeringWheelButtonKeyIndex = ref(-1);
|
const activeSteeringWheelButtonKeyIndex = ref(-1);
|
||||||
const edited = ref(false);
|
const edited = ref(false);
|
||||||
@ -15,6 +16,7 @@ export const useKeyboardStore = defineStore("keyboard", () => {
|
|||||||
showSettingFlag,
|
showSettingFlag,
|
||||||
showButtonSettingFlag,
|
showButtonSettingFlag,
|
||||||
showButtonAddFlag,
|
showButtonAddFlag,
|
||||||
|
editSwipePointsFlag,
|
||||||
activeButtonIndex,
|
activeButtonIndex,
|
||||||
activeSteeringWheelButtonKeyIndex,
|
activeSteeringWheelButtonKeyIndex,
|
||||||
edited,
|
edited,
|
||||||
|
122
src/storeLoader.ts
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import { Store } from "@tauri-apps/plugin-store";
|
||||||
|
import { KeyMappingConfig } from "./keyMappingConfig";
|
||||||
|
import { useGlobalStore } from "./store/global";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
let localStore: Store;
|
||||||
|
let store: ReturnType<typeof useGlobalStore>;
|
||||||
|
let t: ReturnType<typeof useI18n>["t"];
|
||||||
|
|
||||||
|
async function loadKeyMappingConfigList() {
|
||||||
|
// loading keyMappingConfigList from local store
|
||||||
|
let keyMappingConfigList = await localStore.get<KeyMappingConfig[]>(
|
||||||
|
"keyMappingConfigList"
|
||||||
|
);
|
||||||
|
if (keyMappingConfigList === null || keyMappingConfigList.length === 0) {
|
||||||
|
// add empty key mapping config
|
||||||
|
// unable to get mask element when app is not ready
|
||||||
|
// so we use the stored mask area to get relative size
|
||||||
|
const maskArea = await localStore.get<{
|
||||||
|
posX: number;
|
||||||
|
posY: number;
|
||||||
|
sizeW: number;
|
||||||
|
sizeH: number;
|
||||||
|
}>("maskArea");
|
||||||
|
let relativeSize = { w: 800, h: 600 };
|
||||||
|
if (maskArea !== null) {
|
||||||
|
relativeSize = {
|
||||||
|
w: maskArea.sizeW,
|
||||||
|
h: maskArea.sizeH,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
keyMappingConfigList = [
|
||||||
|
{
|
||||||
|
relativeSize,
|
||||||
|
title: t("pages.Mask.blankConfig"),
|
||||||
|
list: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await localStore.set("keyMappingConfigList", keyMappingConfigList);
|
||||||
|
}
|
||||||
|
store.keyMappingConfigList = keyMappingConfigList;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadCurKeyMappingIndex() {
|
||||||
|
// loading curKeyMappingIndex from local store
|
||||||
|
let curKeyMappingIndex = await localStore.get<number>("curKeyMappingIndex");
|
||||||
|
if (
|
||||||
|
curKeyMappingIndex === null ||
|
||||||
|
curKeyMappingIndex >= store.keyMappingConfigList.length
|
||||||
|
) {
|
||||||
|
curKeyMappingIndex = 0;
|
||||||
|
localStore.set("curKeyMappingIndex", curKeyMappingIndex);
|
||||||
|
}
|
||||||
|
store.curKeyMappingIndex = curKeyMappingIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadMaskButton() {
|
||||||
|
// loading maskButton from local store
|
||||||
|
let maskButton = await localStore.get<{
|
||||||
|
show: boolean;
|
||||||
|
transparency: number;
|
||||||
|
}>("maskButton");
|
||||||
|
store.maskButton = maskButton ?? {
|
||||||
|
show: true,
|
||||||
|
transparency: 0.5,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadCheckUpdateAtStart() {
|
||||||
|
// loading checkUpdateAtStart from local store
|
||||||
|
const checkUpdateAtStart = await localStore.get<boolean>(
|
||||||
|
"checkUpdateAtStart"
|
||||||
|
);
|
||||||
|
store.checkUpdateAtStart = checkUpdateAtStart ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadRotation() {
|
||||||
|
// loading rotation from local store
|
||||||
|
const rotation = await localStore.get<{
|
||||||
|
enable: boolean;
|
||||||
|
verticalLength: number;
|
||||||
|
horizontalLength: number;
|
||||||
|
}>("rotation");
|
||||||
|
if (rotation) store.rotation = rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadScreenStream() {
|
||||||
|
// loading screenStream from local store
|
||||||
|
const screenStream = await localStore.get<{
|
||||||
|
enable: boolean;
|
||||||
|
address: string;
|
||||||
|
}>("screenStream");
|
||||||
|
if (screenStream) store.screenStream = screenStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadClipboardSync() {
|
||||||
|
// loading clipboardSync from local store
|
||||||
|
const clipboardSync = await localStore.get<{
|
||||||
|
syncFromDevice: boolean;
|
||||||
|
pasteFromPC: boolean;
|
||||||
|
}>("clipboardSync");
|
||||||
|
if (clipboardSync) store.clipboardSync = clipboardSync;
|
||||||
|
console.log(store.clipboardSync);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function loadLocalStorage(
|
||||||
|
theLocalStore: Store,
|
||||||
|
theStore: ReturnType<typeof useGlobalStore>,
|
||||||
|
theT: ReturnType<typeof useI18n>["t"]
|
||||||
|
) {
|
||||||
|
localStore = theLocalStore;
|
||||||
|
store = theStore;
|
||||||
|
t = theT;
|
||||||
|
|
||||||
|
await loadKeyMappingConfigList();
|
||||||
|
await loadCurKeyMappingIndex();
|
||||||
|
await loadMaskButton();
|
||||||
|
await loadCheckUpdateAtStart();
|
||||||
|
await loadRotation();
|
||||||
|
await loadScreenStream();
|
||||||
|
await loadClipboardSync();
|
||||||
|
}
|