Skip to content

Commit 519bc97

Browse files
committed
feat: add screen power toggle functionality to device control
feat: update changelog with new screen power button feature optimize: update .gitignore to exclude TypeScript build info files
1 parent 471c57f commit 519bc97

5 files changed

Lines changed: 29 additions & 51 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ database.db
4848
/.agents
4949
dist-cli/
5050
/cli/linkandroid-cli
51+
*.tsbuildinfo
5152
test-results/
5253
/_temp/
5354
/DEV_QUEUE.md

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- 新增:scrcpy升级到4.1版本
44
- 新增:测试项目根目录统一解析工具 projectRoot()
5+
- 新增:投屏右侧新增息屏/亮屏按钮,方便在投屏时快速控制设备屏幕状态
56
- 优化:测试文件统一使用 projectRoot() 替代各自独立计算根目录
67
- 优化:.gitignore 增加 OpenCode 临时文件忽略规则
78
- 优化:更新应用图标资源(appx、tray、logo 等)

electron/mapi/serve/main.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const deviceStates: Map<string, any> = new Map()
1212
const deviceFollowMode: Map<string, boolean> = new Map()
1313
// 每个设备的置顶状态
1414
const deviceTopMode: Map<string, boolean> = new Map()
15+
// 每个设备的屏幕开关状态(true=亮屏,false=息屏)
16+
const deviceScreenOn: Map<string, boolean> = new Map()
1517

1618
const start = async (): Promise<number> => {
1719
if (wss) {
@@ -32,6 +34,9 @@ const start = async (): Promise<number> => {
3234
const getPanelConfig = (deviceId: string) => {
3335
const isFollowMode = deviceFollowMode.get(deviceId) || false
3436
const isTopMode = deviceTopMode.get(deviceId) || false
37+
const isScreenOn = deviceScreenOn.get(deviceId)
38+
// 默认 true(亮屏),除非显式设为 false
39+
const screenState = isScreenOn !== undefined ? isScreenOn : true
3540
return {
3641
type: 'panel',
3742
data: {
@@ -42,6 +47,7 @@ const start = async (): Promise<number> => {
4247
{id: 'volume_up', icon: 'v-plus'},
4348
{id: 'volume_down', icon: 'v-minus'},
4449
{id: 'screenshot', icon: 'screenshot'},
50+
{id: 'screen_power', icon: screenState ? 'screen-on' : 'screen-off'},
4551
{id: 'follow', icon: isFollowMode ? 'follow_active' : 'follow'},
4652
{id: 'toggle_top', icon: isTopMode ? 'top_active' : 'top'},
4753
{id: 'close', icon: 'quit'},
@@ -125,6 +131,19 @@ const start = async (): Promise<number> => {
125131
}),
126132
)
127133
ws.send(JSON.stringify(getPanelConfig(deviceId)))
134+
} else if (buttonId === 'screen_power') {
135+
const currentState = deviceScreenOn.get(deviceId)
136+
const newState = currentState !== undefined ? !currentState : false
137+
deviceScreenOn.set(deviceId, newState)
138+
Log.info(`Screen power toggled for ${deviceId}: ${newState ? 'on' : 'off'}`)
139+
data.deviceId = deviceId
140+
data.type = 'DevicePanelButtonClick'
141+
broadcast('Render', data)
142+
ws.send(JSON.stringify(getPanelConfig(deviceId)))
143+
const isFollowMode = deviceFollowMode.get(deviceId) || false
144+
if (isFollowMode) {
145+
handlePanelButtonFollowMode(deviceId, buttonId)
146+
}
128147
} else if (buttonId === 'close') {
129148
ws.send(
130149
JSON.stringify({
@@ -164,10 +183,11 @@ const start = async (): Promise<number> => {
164183
id: deviceId,
165184
})
166185
}
167-
// 清理设备的随动状态和置顶状态
186+
// 清理设备的随动状态、置顶状态和屏幕开关状态
168187
if (clientType === 'DeviceMirror' && deviceId) {
169188
deviceFollowMode.delete(deviceId)
170189
deviceTopMode.delete(deviceId)
190+
deviceScreenOn.delete(deviceId)
171191
}
172192
})
173193

@@ -231,7 +251,7 @@ const isDeviceEvent = (eventType: string): boolean => {
231251

232252
// 判断面板按钮是否支持随动
233253
const isPanelButtonFollowable = (buttonId: string): boolean => {
234-
const followableButtons = ['home', 'back', 'recent', 'volume_up', 'volume_down', 'screenshot']
254+
const followableButtons = ['home', 'back', 'recent', 'volume_up', 'volume_down', 'screenshot', 'screen_power']
235255
return followableButtons.includes(buttonId)
236256
}
237257

@@ -244,6 +264,7 @@ const panelButtonToKeyCode = (buttonId: string): number | null => {
244264
volume_up: 24, // KEYCODE_VOLUME_UP
245265
volume_down: 25, // KEYCODE_VOLUME_DOWN
246266
screenshot: 120, // KEYCODE_SYSRQ
267+
screen_power: 26, // KEYCODE_POWER
247268
}
248269
return keyCodeMap[buttonId] || null
249270
}

src/components.d.ts

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -23,79 +23,30 @@ declare module 'vue' {
2323
FileLogViewer: typeof import('./components/common/FileLogViewer.vue')['default']
2424
FilesSelector: typeof import('./components/common/FilesSelector.vue')['default']
2525
HtmlViewer: typeof import('./components/common/HtmlViewer.vue')['default']
26-
ILucideBookOpen: typeof import('~icons/lucide/book-open')['default']
2726
ILucideBot: typeof import('~icons/lucide/bot')['default']
28-
ILucideCheck: typeof import('~icons/lucide/check')['default']
29-
ILucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
3027
ILucideCheckSquare: typeof import('~icons/lucide/check-square')['default']
3128
ILucideChevronDown: typeof import('~icons/lucide/chevron-down')['default']
32-
ILucideChevronLeft: typeof import('~icons/lucide/chevron-left')['default']
33-
ILucideChevronUp: typeof import('~icons/lucide/chevron-up')['default']
34-
ILucideCircle: typeof import('~icons/lucide/circle')['default']
35-
ILucideCircleAlert: typeof import('~icons/lucide/circle-alert')['default']
36-
ILucideCircleCheck: typeof import('~icons/lucide/circle-check')['default']
37-
ILucideCirclePause: typeof import('~icons/lucide/circle-pause')['default']
38-
ILucideCircleX: typeof import('~icons/lucide/circle-x')['default']
3929
ILucideClock: typeof import('~icons/lucide/clock')['default']
4030
ILucideCode: typeof import('~icons/lucide/code')['default']
4131
ILucideCopy: typeof import('~icons/lucide/copy')['default']
42-
ILucideDownload: typeof import('~icons/lucide/download')['default']
43-
ILucideEdit3: typeof import('~icons/lucide/edit3')['default']
4432
ILucideEllipsis: typeof import('~icons/lucide/ellipsis')['default']
45-
ILucideEllipsisVertical: typeof import('~icons/lucide/ellipsis-vertical')['default']
46-
ILucideEye: typeof import('~icons/lucide/eye')['default']
47-
ILucideFile: typeof import('~icons/lucide/file')['default']
48-
ILucideFileText: typeof import('~icons/lucide/file-text')['default']
49-
ILucideFolder: typeof import('~icons/lucide/folder')['default']
5033
ILucideHistory: typeof import('~icons/lucide/history')['default']
51-
ILucideHouse: typeof import('~icons/lucide/house')['default']
52-
ILucideImage: typeof import('~icons/lucide/image')['default']
53-
ILucideImport: typeof import('~icons/lucide/import')['default']
54-
ILucideInfo: typeof import('~icons/lucide/info')['default']
5534
ILucideLayers: typeof import('~icons/lucide/layers')['default']
56-
ILucideLayoutGrid: typeof import('~icons/lucide/layout-grid')['default']
5735
ILucideLink: typeof import('~icons/lucide/link')['default']
58-
ILucideList: typeof import('~icons/lucide/list')['default']
59-
ILucideLoader: typeof import('~icons/lucide/loader')['default']
60-
ILucideLock: typeof import('~icons/lucide/lock')['default']
61-
ILucideMessageSquare: typeof import('~icons/lucide/message-square')['default']
6236
ILucideMonitor: typeof import('~icons/lucide/monitor')['default']
63-
ILucideMousePointerClick: typeof import('~icons/lucide/mouse-pointer-click')['default']
64-
ILucideNavigation: typeof import('~icons/lucide/navigation')['default']
6537
ILucidePackage: typeof import('~icons/lucide/package')['default']
6638
ILucidePencil: typeof import('~icons/lucide/pencil')['default']
6739
ILucidePlay: typeof import('~icons/lucide/play')['default']
6840
ILucidePlus: typeof import('~icons/lucide/plus')['default']
6941
ILucideQrCode: typeof import('~icons/lucide/qr-code')['default']
70-
ILucideRefreshCw: typeof import('~icons/lucide/refresh-cw')['default']
7142
ILucideSearch: typeof import('~icons/lucide/search')['default']
7243
ILucideSettings: typeof import('~icons/lucide/settings')['default']
7344
ILucideShield: typeof import('~icons/lucide/shield')['default']
7445
ILucideSmartphone: typeof import('~icons/lucide/smartphone')['default']
7546
ILucideSquare: typeof import('~icons/lucide/square')['default']
76-
ILucideSquareArrowOutUpRight: typeof import('~icons/lucide/square-arrow-out-up-right')['default']
77-
ILucideTag: typeof import('~icons/lucide/tag')['default']
7847
ILucideTrash2: typeof import('~icons/lucide/trash2')['default']
79-
ILucideUpload: typeof import('~icons/lucide/upload')['default']
8048
ILucideUser: typeof import('~icons/lucide/user')['default']
81-
ILucideWifi: typeof import('~icons/lucide/wifi')['default']
8249
ILucideWorkflow: typeof import('~icons/lucide/workflow')['default']
83-
ILucideWrench: typeof import('~icons/lucide/wrench')['default']
84-
ILucideX: typeof import('~icons/lucide/x')['default']
85-
IMdiAndroid: typeof import('~icons/mdi/android')['default']
86-
IMdiCamera: typeof import('~icons/mdi/camera')['default']
87-
IMdiCameraFront: typeof import('~icons/mdi/camera-front')['default']
88-
IMdiCameraRear: typeof import('~icons/mdi/camera-rear')['default']
89-
IMdiCast: typeof import('~icons/mdi/cast')['default']
90-
IMdiFolderOutline: typeof import('~icons/mdi/folder-outline')['default']
91-
IMdiInbox: typeof import('~icons/mdi/inbox')['default']
92-
IMdiIpNetwork: typeof import('~icons/mdi/ip-network')['default']
93-
IMdiMagnifyMinus: typeof import('~icons/mdi/magnify-minus')['default']
94-
IMdiMagnifyPlus: typeof import('~icons/mdi/magnify-plus')['default']
95-
IMdiStopCircle: typeof import('~icons/mdi/stop-circle')['default']
96-
IMdiUsb: typeof import('~icons/mdi/usb')['default']
97-
IMdiVideo: typeof import('~icons/mdi/video')['default']
98-
IMdiWifi: typeof import('~icons/mdi/wifi')['default']
9950
InputInlineEditor: typeof import('./components/common/InputInlineEditor.vue')['default']
10051
ListerTop: typeof import('./components/common/ListerTop.vue')['default']
10152
LLMRechargeDialog: typeof import('./components/common/LLMRechargeDialog.vue')['default']

src/store/modules/device.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ const handlePanelButtonClick = async (deviceId: string, buttonId: string) => {
233233
args = ['shell', 'input', 'keyevent', 'KEYCODE_SYSRQ']
234234
await $mapi.adb.spawnShell(args, {}, deviceId)
235235
break
236+
case 'screen_power':
237+
args = ['shell', 'input', 'keyevent', 'KEYCODE_POWER']
238+
await $mapi.adb.spawnShell(args, {}, deviceId)
239+
break
236240
case 'close':
237241
await stopDeviceManage(deviceId)
238242
break

0 commit comments

Comments
 (0)