ykxmz 1.5.0锛氫慨澶嶆墜琛ㄧ TLS 璇佷功鏍¢獙 + MTU 淇缃戠粶绋冲畾鎬?

琚帶绔?- 淇 MTU 闂锛氬す MSS + 璺緞 MTU 鎺㈡祴锛堝叕缃戝彲鐢ㄧ巼 48% -> 100%锛?- 澶嶇敤 HTTP 杩炴帴锛堝厤鎺夋瘡娆℃柊寤?TLS 鐨?30% 鎻℃墜澶辫触锛?- 姣忓垎閽熷洖澶存壘灞€鍩熺綉锛岃嚜鍔ㄥ垏鍥炲揩 400 鍊嶇殑璺緞
- 鐢婚潰蹇冭烦甯э細闈欐鏃剁渷娴侀噺锛屽鎴风浠嶇煡閬撴祦鏄椿鐨?- 閿佸睆鏃剁粰鍑哄彲鎿嶄綔鐨勬彁绀?
鎵嬭〃绔?- 鍐呯疆 GTS Root R4 / GlobalSign Root CA锛屼慨 SSLHandshakeException
- 杩炴帴閿欒缈昏瘧鎴愪汉璇濓紙璇佷功/鏃堕棿/瑙f瀽/瓒呮椂鍒嗗埆鎻愮ず锛?- 缁忎腑杞繛涓婂悗鐢ㄦ湇鍔″櫒鎶ョ殑鍦板潃鍒锋柊宸查厤瀵硅褰?- 鏂板灞€鍩熺綉杩炴帴椤甸潰銆佹湇鍔″櫒寤惰繜妫€娴?
鏈嶅姟鍣ㄧ
- 鏀寔 chunked 璇锋眰浣擄紙淇瘡 16 绉掍竴娆$殑杩炴帴閿欎贡涓庡ぇ闈㈢Н 502锛?- 缃戠粶璋冧紭鑴氭湰 net-tune.sh锛堝紑鏈鸿嚜鍔ㄥ簲鐢級
- 绠$悊椤碉細鎵归噺鍒犻櫎銆佺綉缁滀綋妫€銆佷笅杞藉尯
- 闅ч亾鏀?HTTP/2 + 鍙岃繛鎺?
鏂囨。
- 璁稿彲鍗忚 / 瀹夎鍓嶅繀璇?/ 瀹夎鍚庨』鐭ワ紙浣滆€咃細灏忛害瀛愶級
This commit is contained in:
xmz7891
2026-10-06 19:01:05 +08:00
commit b705216e4a
3195 changed files with 203292 additions and 0 deletions
+559
View File
@@ -0,0 +1,559 @@
# -*- coding: utf-8 -*-
"""手表端 UI 彻底重做:分页 + 37 个功能。
原来是一长条 28 个按钮的网格,要滚 274dp。
现在分成 6 页,每页最多 7 个按钮 —— **完全不用滚动**。
媒体 (7) 屏幕 (6) 文件 (6) 语音 (5) 电脑 (6) 系统 (7)
"""
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")
START = " // 按钮网格\n"
END = " flushGrid(grid); // 按当前列数把上面入队的按钮切成行\n"
NEW_PANEL = ''' // ---- 分页标签 ----
HorizontalScrollView tabScroll = new HorizontalScrollView(this);
tabScroll.setHorizontalScrollBarEnabled(false);
tabBar = new LinearLayout(this);
tabBar.setOrientation(LinearLayout.HORIZONTAL);
tabBar.setPadding(0, 0, 0, 0);
tabScroll.addView(tabBar);
controlPanel.addView(tabScroll, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, dp(42)));
// ---- 分页内容 ----
tabContent = new LinearLayout(this);
tabContent.setOrientation(LinearLayout.VERTICAL);
tabContent.setPadding(0, dp(6), 0, dp(6));
ScrollView contentScroll = new ScrollView(this);
contentScroll.addView(tabContent, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
controlPanel.addView(contentScroll, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
'''
# ---------------------------------------------------------------- tabs 机制
TAB_METHODS_ANCHOR = ''' private Button bigButton(String text, int color, float sizeSp) {'''
TAB_METHODS = ''' // ==================================================================
// 分页
// ==================================================================
private static final class Act {
final String label;
final Runnable task;
Act(String label, Runnable task) {
this.label = label;
this.task = task;
}
}
private static final class TabDef {
final String name;
final Act[] acts;
TabDef(String name, Act[] acts) {
this.name = name;
this.acts = acts;
}
}
private TabDef[] tabDefs;
private LinearLayout tabBar;
private LinearLayout tabContent;
private int currentTab = 0;
private Act act(String label, Runnable task) {
return new Act(label, task);
}
/** 定义所有分页。每页最多 7 个按钮,一屏放得下,不用滚。 */
private void initTabs() {
tabDefs = new TabDef[]{
new TabDef("媒体", new Act[]{
act("播放/暂停", new Runnable() {
public void run() { media("play_pause"); }
}),
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("vol_up"); }
}),
act("音量 -", new Runnable() {
public void run() { media("vol_down"); }
}),
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/*"); }
}),
act("关显示器", new Runnable() {
public void run() { confirmMonitor(); }
}),
act("设为壁纸", new Runnable() {
public void run() { confirmWallpaper(); }
}),
}),
new TabDef("文件", new Act[]{
act("发送文件", new Runnable() {
public void run() { pickFile(REQ_FILE, "*/*"); }
}),
act("接收文件", new Runnable() {
public void run() { showReceivedFiles(); }
}),
act("剪贴板→电脑", new Runnable() {
public void run() { promptClipSet(); }
}),
act("取电脑剪贴板", new Runnable() {
public void run() { fetchClip(); }
}),
act("剪贴板历史", new Runnable() {
public void run() { pickClipHistory(); }
}),
act("打开文件夹", new Runnable() {
public void run() { pickFolder(); }
}),
}),
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() { 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("reboot", "重启"); }
}),
act("取消定时关机", new Runnable() {
public void run() { cancelShutdown(); }
}),
act("定时关机", new Runnable() {
public void run() { pickShutdownTimer(); }
}),
act("设备诊断", new Runnable() {
public void run() { openDiagPanel(); }
}),
}),
};
tabBar.removeAllViews();
for (int i = 0; i < tabDefs.length; i++) {
final int index = i;
TextView tab = new TextView(this);
tab.setText(tabDefs[i].name);
tab.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
tab.setGravity(Gravity.CENTER);
tab.setPadding(dp(14), dp(8), dp(14), dp(8));
tab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selectTab(index);
}
});
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT);
params.setMargins(0, 0, dp(6), 0);
tab.setLayoutParams(params);
tabBar.addView(tab);
}
selectTab(0);
}
private void selectTab(int index) {
if (tabDefs == null || index < 0 || index >= tabDefs.length) {
return;
}
currentTab = index;
for (int i = 0; i < tabBar.getChildCount(); i++) {
View child = tabBar.getChildAt(i);
boolean on = (i == index);
child.setBackground(rounded(on ? C_ACCENT : C_CARD, 8));
if (child instanceof TextView) {
((TextView) child).setTextColor(on ? 0xFFFFFFFF : C_FG);
}
}
tabContent.removeAllViews();
cellQueue.clear();
for (Act item : tabDefs[index].acts) {
addRow(tabContent, action(item.label, item.task), null);
}
flushGrid(tabContent);
}
// ==================================================================
// 新功能
// ==================================================================
private void media(String what) {
sendCommand(Json.obj("cmd", "media", "action", what), "媒体");
}
private void confirmMonitor() {
new AlertDialog.Builder(this)
.setTitle("关闭显示器")
.setMessage("要关掉电脑显示器吗?(动一下鼠标或按键就能唤醒)")
.setPositiveButton("关掉", new android.content.DialogInterface.OnClickListener() {
@Override
public void onClick(android.content.DialogInterface d, int w) {
sendCommand(Json.obj("cmd", "monitor", "on", false), "关显示器");
}
})
.setNegativeButton("取消", null)
.show();
}
private void confirmWallpaper() {
new AlertDialog.Builder(this)
.setTitle("设为壁纸")
.setMessage("把电脑上最近收到的那张图片设为桌面壁纸?")
.setPositiveButton("设置", new android.content.DialogInterface.OnClickListener() {
@Override
public void onClick(android.content.DialogInterface d, int w) {
sendCommand(Json.obj("cmd", "set_wallpaper"), "设置壁纸");
}
})
.setNegativeButton("取消", null)
.show();
}
private void pickShutdownTimer() {
final int[] minutes = {15, 30, 60, 120};
final String[] labels = {"15 分钟后", "30 分钟后", "1 小时后", "2 小时后"};
showChooser("定时关机", new ArrayList<String>(java.util.Arrays.asList(labels)),
new Chooser() {
@Override
public void onPick(int index) {
sendCommand(Json.obj("cmd", "shutdown_timer",
"minutes", minutes[index]), "定时关机");
}
});
}
private void cancelShutdown() {
sendCommand(Json.obj("cmd", "shutdown_timer", "cancel", true), "取消定时关机");
}
private void promptOpenUrl() {
promptInput("在电脑上打开网址", "如 baidu.com", "https://", new InputHandler() {
@Override
public void onInput(String text) {
if (!text.isEmpty()) {
sendCommand(Json.obj("cmd", "open_url", "url", text), "打开网址");
}
}
});
}
private void pickQuickApp() {
final String[][] apps = {
{"任务管理器", "taskmgr"},
{"资源管理器", "explorer"},
{"命令提示符", "cmd"},
{"计算器", "calc"},
{"记事本", "notepad"},
{"画图", "mspaint"},
{"控制面板", "control"},
{"设备管理器", "devmgmt"},
};
List<String> labels = new ArrayList<String>();
for (String[] item : apps) {
labels.add(item[0]);
}
showChooser("在电脑上打开", labels, new Chooser() {
@Override
public void onPick(int index) {
sendCommand(Json.obj("cmd", "quick", "app", apps[index][1]),
"打开" + apps[index][0]);
}
});
}
private void pickFolder() {
final String[][] folders = {
{"下载", "downloads"},
{"文档", "documents"},
{"桌面", "desktop"},
{"图片", "pictures"},
{"音乐", "music"},
{"接收目录", "received"},
{"程序目录", "app"},
};
List<String> labels = new ArrayList<String>();
for (String[] item : folders) {
labels.add(item[0]);
}
showChooser("打开电脑文件夹", labels, new Chooser() {
@Override
public void onPick(int index) {
sendCommand(Json.obj("cmd", "open_folder", "folder", folders[index][1]),
"打开" + folders[index][0]);
}
});
}
private void pickProcess() {
appendLog("正在获取电脑进程…");
io.execute(new Runnable() {
@Override
public void run() {
try {
final Map<String, Object> reply =
client.call(Json.obj("cmd", "proc_list"), 20000);
final List<String> names = stringList(reply, "names");
final List<String> pids = stringList(reply, "pids");
ui.post(new Runnable() {
@Override
public void run() {
if (names.isEmpty()) {
toast("没读到进程,或没连上");
return;
}
showChooser("占内存最多的进程", names, new Chooser() {
@Override
public void onPick(int index) {
confirmKill(names.get(index), pids.get(index));
}
});
}
});
} catch (final IOException e) {
postError("获取进程", e);
}
}
});
}
private void confirmKill(String label, String pid) {
final int target;
try {
target = Integer.parseInt(pid);
} catch (NumberFormatException e) {
toast("进程号不对");
return;
}
new AlertDialog.Builder(this)
.setTitle("结束进程")
.setMessage("确定要结束这个进程吗?\n\n" + label)
.setPositiveButton("结束", new android.content.DialogInterface.OnClickListener() {
@Override
public void onClick(android.content.DialogInterface d, int w) {
sendCommand(Json.obj("cmd", "proc_kill", "pid", target), "结束进程");
}
})
.setNegativeButton("取消", null)
.show();
}
private void showPerf() {
fetchAndShow("性能", Json.obj("cmd", "perf"), "note");
}
private void showDisk() {
fetchAndShow("磁盘占用", Json.obj("cmd", "disk"), "note");
}
private void showBattery() {
fetchAndShow("电脑电量", Json.obj("cmd", "battery"), "note");
}
/** 拉一条命令,把 note 用对话框显示出来。 */
private void fetchAndShow(final String title, final Map<String, Object> request,
final String field) {
appendLog("正在获取" + title + "…");
io.execute(new Runnable() {
@Override
public void run() {
try {
final Map<String, Object> reply = client.call(request, 15000);
final boolean ok = Json.bool(reply, "ok", false);
final String note = ok
? Json.str(reply, field, "(无内容)")
: Json.str(reply, "error", "读取失败");
ui.post(new Runnable() {
@Override
public void run() {
appendLog(title + ":" + note);
new AlertDialog.Builder(MainActivity.this)
.setTitle(title)
.setMessage(note)
.setPositiveButton("知道了", null)
.show();
}
});
} catch (final IOException e) {
postError(title, e);
}
}
});
}
private void pickClipHistory() {
appendLog("正在获取剪贴板历史…");
io.execute(new Runnable() {
@Override
public void run() {
try {
final Map<String, Object> reply =
client.call(Json.obj("cmd", "clip_history"), 12000);
final List<String> texts = stringList(reply, "texts");
final List<String> times = stringList(reply, "times");
ui.post(new Runnable() {
@Override
public void run() {
if (texts.isEmpty()) {
toast("电脑剪贴板还没有历史");
return;
}
List<String> labels = new ArrayList<String>();
for (int i = 0; i < texts.size(); i++) {
String preview = texts.get(i).replace("\\n", " ");
if (preview.length() > 22) {
preview = preview.substring(0, 22) + "…";
}
String when = i < times.size() ? times.get(i) + " " : "";
labels.add(when + preview);
}
showChooser("剪贴板历史(点一条取到手表)", labels, new Chooser() {
@Override
public void onPick(int index) {
copyToWatchClipboard(texts.get(index));
toast("已复制到手表剪贴板");
appendLog("取回一条剪贴板历史");
}
});
}
});
} catch (final IOException e) {
postError("剪贴板历史", e);
}
}
});
}
'''
def main() -> int:
text = MAIN.read_text(encoding="utf-8")
start = text.find(START)
end = text.find(END)
if start < 0 or end < 0:
print(f" [失败] 找不到网格区块 (start={start}, end={end})")
return 1
end += len(END)
text = text[:start] + NEW_PANEL + text[end:]
print(" 分页面板: OK")
if TAB_METHODS_ANCHOR not in text:
print(" [失败] bigButton 锚点未匹配")
return 1
text = text.replace(TAB_METHODS_ANCHOR, TAB_METHODS + TAB_METHODS_ANCHOR, 1)
print(" 分页机制 + 新功能: OK")
# addRow 要能接受 null(一页里按钮数可能是奇数)
old_add = ''' private void addRow(LinearLayout parent, View left, View right) {
// 只入队,真正的行切分在 flushGrid() 里按 gridColumns 统一做。
// 这样上层那串 addRow(a, b) 不用改,列数就能自适应。
cellQueue.add(left);
cellQueue.add(right);
}'''
new_add = ''' private void addRow(LinearLayout parent, View left, View right) {
// 只入队,真正的行切分在 flushGrid() 里按 gridColumns 统一做。
// 允许传 null:分页里某一页的按钮数可能是奇数。
if (left != null) {
cellQueue.add(left);
}
if (right != null) {
cellQueue.add(right);
}
}'''
if old_add in text:
text = text.replace(old_add, new_add, 1)
print(" addRow 支持 null: OK")
else:
print(" [警告] addRow 未替换")
# 初始化分页
old_init = " showConnectPanel();"
new_init = " initTabs();\n showConnectPanel();"
if old_init in text:
text = text.replace(old_init, new_init, 1)
print(" initTabs 调用: OK")
MAIN.write_text(text, encoding="utf-8")
return 0
if __name__ == "__main__":
sys.exit(main())