mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 21:50:44 +00:00
被控端 - 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%) - 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败) - 每分钟回头找局域网,自动切回快 400 倍的路径 - 画面心跳帧:静止时省流量,客户端仍知道流是活的 - 锁屏时给出可操作的提示 手表端 - 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException - 连接错误翻译成人话(证书/时间/解析/超时分别提示) - 经中转连上后用服务器报的地址刷新已配对记录 - 新增局域网连接页面、服务器延迟检测 服务器端 - 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502) - 网络调优脚本 net-tune.sh(开机自动应用) - 管理页:批量删除、网络体检、下载区 - 隧道改 HTTP/2 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
420 lines
18 KiB
Python
420 lines
18 KiB
Python
# -*- 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<String, Object> reply =
|
|
client.call(Json.obj("cmd", "feature_list"), 25000);
|
|
final List<Map<String, Object>> items = mapList(reply, "features");
|
|
ui.post(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
featureCache = items;
|
|
featureGroups = new ArrayList<String>();
|
|
for (Map<String, Object> 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<Map<String, Object>> items =
|
|
new ArrayList<Map<String, Object>>();
|
|
for (Map<String, Object> 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<String, Object> 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())
|