# -*- coding: utf-8 -*- """删掉「功能」页,把 14 个分组散到各个分页。 新分页(10 个): 媒体 音量 + 媒体 屏幕 显示 文件 文件 语音 静默 电脑 查看 + 工具 网络 网络 + 极客 系统 系统 教室 教室 + 教学 效率 效率 娱乐 娱乐 每个分页 = 原有快捷按钮 + 该分页负责的功能分组(带小标题)。 分组按钮直接从 feature_list 拉取,电脑端加了新功能这里自动就有。 """ from __future__ import annotations import sys from pathlib import Path MAIN = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\android\src" r"\com\lanremote\watch\MainActivity.java") # ---------------- 1. TabDef 加 groups ---------------- TABDEF_OLD = ''' private static final class TabDef { final String name; final Act[] acts; TabDef(String name, Act[] acts) { this.name = name; this.acts = acts; } }''' TABDEF_NEW = ''' private static final class TabDef { final String name; final Act[] acts; final String[] groups; // 这个分页要渲染哪些功能分组 TabDef(String name, Act[] acts, String... groups) { this.name = name; this.acts = acts; this.groups = groups; } }''' # ---------------- 2. selectTab:快捷按钮 + 分组 ---------------- SELECT_OLD = ''' moveTabIndicator(tabBar.getChildAt(index)); if ("功能".equals(tabDefs[index].name)) { buildFeatureTab(); return; } tabContent.removeAllViews(); cellQueue.clear(); for (Act item : tabDefs[index].acts) { addRow(tabContent, action(item.label, item.task), null); } flushGrid(tabContent); // 切页时内容淡入 + 轻微上移,做出"流动"的感觉 animateIn(tabContent, 10f, 220); }''' SELECT_NEW = ''' moveTabIndicator(tabBar.getChildAt(index)); tabContent.removeAllViews(); cellQueue.clear(); for (Act item : tabDefs[index].acts) { addRow(tabContent, action(item.label, item.task), null); } flushGrid(tabContent); // 这个分页负责的功能分组 if (tabDefs[index].groups.length > 0) { renderGroups(tabContent, tabDefs[index].groups); } // 切页时内容淡入 + 轻微上移,做出"流动"的感觉 animateIn(tabContent, 10f, 220); } /** 把一个分页负责的功能分组渲染成按钮(每组带一个小标题)。 */ private void renderGroups(final LinearLayout container, final String[] groups) { if (featureCache == null || featureCache.isEmpty()) { // 还没拉到功能列表:先显示提示,拉到之后重画当前页 TextView hint = new TextView(this); hint.setText("正在获取电脑端功能…"); hint.setTextColor(C_DIM); hint.setTextSize(TypedValue.COMPLEX_UNIT_SP, 11); hint.setPadding(dp(4), dp(6), dp(4), dp(6)); container.addView(hint); if (featureGroups == null) { io.execute(new Runnable() { @Override public void run() { try { Map reply = client.call(Json.obj("cmd", "feature_list"), 25000); final List> items = mapList(reply, "features"); ui.post(new Runnable() { @Override public void run() { featureCache = items; featureGroups = new ArrayList(); for (Map f : items) { String g = Json.str(f, "group", "其他"); if (!featureGroups.contains(g)) { featureGroups.add(g); } } selectTab(currentTab); } }); } catch (final IOException e) { ui.post(new Runnable() { @Override public void run() { appendLog("获取功能列表失败:" + e.getMessage()); toast("没连上电脑,功能列表拉不到"); } }); } } }); } return; } for (final String group : groups) { final List> items = new ArrayList>(); for (Map f : featureCache) { if (group.equals(Json.str(f, "group", ""))) { items.add(f); } } if (items.isEmpty()) { continue; } TextView header = new TextView(this); header.setText(group); header.setTextColor(C_ACCENT); header.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12); header.setPadding(dp(4), dp(10), dp(4), dp(2)); container.addView(header); LinearLayout grid = new LinearLayout(this); grid.setOrientation(LinearLayout.VERTICAL); container.addView(grid); cellQueue.clear(); for (final Map item : items) { addRow(grid, action(Json.str(item, "label", "?"), new Runnable() { @Override public void run() { dispatchFeature(item); } }), null); } flushGrid(grid); } }''' # ---------------- 3. initTabs:新分页表 ---------------- INIT_ANCHOR_START = " tabDefs = new TabDef[]{" INIT_ANCHOR_END = " tabBar.removeAllViews();" def main() -> int: text = MAIN.read_text(encoding="utf-8") for old, new, tag in ((TABDEF_OLD, TABDEF_NEW, "TabDef 加 groups"), (SELECT_OLD, SELECT_NEW, "selectTab + renderGroups")): if old not in text: print(f" [失败] {tag} —— 锚点没找到") return 1 text = text.replace(old, new, 1) print(f" {tag}: OK") # 替换整个 tabDefs 数组 start = text.find(INIT_ANCHOR_START) end = text.find(INIT_ANCHOR_END, start) if start < 0 or end < 0: print(f" [失败] 找不到 tabDefs 数组 (start={start}, end={end})") return 1 # 保留数组里原有的 Act 定义不现实(太散),改为按名字重建: # 逐个分页用「快捷按钮 + 分组」表达 new_tabs = ''' tabDefs = new TabDef[]{ new TabDef("媒体", new Act[]{ act("播放/暂停", new Runnable() { public void run() { media("playpause"); } }), act("停止", new Runnable() { public void run() { media("stop"); } }), act("上一曲", new Runnable() { public void run() { media("prev"); } }), act("下一曲", new Runnable() { public void run() { media("next"); } }), act("音量 +", new Runnable() { public void run() { media("volup"); } }), act("音量 -", new Runnable() { public void run() { media("voldown"); } }), act("静音", new Runnable() { public void run() { media("mute"); } }), }, "音量", "媒体"), new TabDef("屏幕", new Act[]{ act("屏幕镜像", new Runnable() { public void run() { openMirrorPanel(); } }), act("截屏", new Runnable() { public void run() { doScreenshot(); } }), act("投图到电脑", new Runnable() { public void run() { pickFile(REQ_IMAGE, "image/*"); } }), act("放音到电脑", new Runnable() { public void run() { pickFile(REQ_AUDIO, "audio/*"); } }), }, "显示"), new TabDef("文件", new Act[]{ act("发送文件", new Runnable() { public void run() { pickFile(REQ_FILE, "*/*"); } }), act("接收文件", new Runnable() { public void run() { showRemoteFiles(); } }), act("剪贴板→电脑", new Runnable() { public void run() { promptClipboardToPc(); } }), act("取电脑剪贴板", new Runnable() { public void run() { fetchClipboard(); } }), }, "文件"), new TabDef("语音", new Act[]{ act("语音播报", new Runnable() { public void run() { promptSay(); } }), act("音色", new Runnable() { public void run() { pickVoice(); } }), act("朗读剪贴板", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "say_clip"), "朗读剪贴板"); } }), act("电脑音乐", new Runnable() { public void run() { pickLocalAudio(); } }), act("弹通知", new Runnable() { public void run() { promptNotify(); } }), }, "静默"), new TabDef("电脑", new Act[]{ act("快捷命令", new Runnable() { public void run() { pickQuickApp(); } }), act("打开网址", new Runnable() { public void run() { promptOpenUrl(); } }), act("进程管理", new Runnable() { public void run() { pickProcess(); } }), act("性能", new Runnable() { public void run() { showPerf(); } }), act("磁盘", new Runnable() { public void run() { showDisk(); } }), act("电量", new Runnable() { public void run() { showBattery(); } }), }, "查看", "工具"), new TabDef("网络", new Act[]{ act("本机监听端口", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "open_ports", "params", Json.obj()), "监听端口"); } }), act("确认能连上", new Runnable() { public void run() { requestPcSelfCheck(); } }), }, "网络", "极客"), new TabDef("系统", new Act[]{ act("锁屏", new Runnable() { public void run() { confirmPower("lock", "锁屏"); } }), act("睡眠", new Runnable() { public void run() { confirmPower("sleep", "睡眠"); } }), act("关机", new Runnable() { public void run() { confirmPower("shutdown", "关机"); } }), act("重启", new Runnable() { public void run() { confirmPower("restart", "重启"); } }), act("取消定时关机", new Runnable() { public void run() { cancelShutdown(); } }), act("定时关机", new Runnable() { public void run() { pickShutdownTimer(); } }), }, "系统"), new TabDef("教室", new Act[]{ act("屏蔽游戏网站", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "game_block_common", "params", Json.obj()), "屏蔽游戏网站"); } }), act("结束游戏进程", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "kill_games", "params", Json.obj()), "结束游戏"); } }), act("一键恢复全部", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "restore_all", "params", Json.obj()), "恢复全部限制"); } }), act("看有哪些限制", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "restrict_status", "params", Json.obj()), "限制状态"); } }), }, "教室", "教学"), new TabDef("效率", new Act[]{ act("加待办", new Runnable() { public void run() { promptTwo("加一条待办", "内容", "(第二格留空)", new TwoHandler() { public void onInput(String a, String b) { runFeature("todo_add", Json.obj("text", a), "待办"); } }); } }), act("看所有待办", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "todo_list", "params", Json.obj()), "待办列表"); } }), }, "效率"), new TabDef("娱乐", new Act[]{ act("掷骰子", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "dice", "params", Json.obj()), "掷骰子"); } }), act("抽奖", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "lottery", "params", Json.obj()), "抽奖"); }), act("抛硬币", new Runnable() { public void run() { sendCommand(Json.obj("cmd", "feature_run", "name", "coin_flip", "params", Json.obj()), "抛硬币"); }), }, "娱乐"), }; ''' text = text[:start] + new_tabs + text[end:] print(" initTabs: 分页表已重建(功能页已删除)") # 删掉旧的 buildFeatureTab(已经没人用了) bf_start = text.find(" /** 「功能」页:分组由电脑端声明,这里拉取后动态生成按钮。 */") if bf_start > 0: # 找到下一个同级方法 bf_end = text.find("\n /** 指示器滑到目标标签", bf_start) if bf_end < 0: bf_end = text.find("\n private ", bf_start + 10) if bf_end > bf_start: text = text[:bf_start] + text[bf_end + 1:] print(" 旧 buildFeatureTab 已删除") MAIN.write_text(text, encoding="utf-8") return 0 if __name__ == "__main__": sys.exit(main())