mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 18:20:43 +00:00
阶段1+2:恢复 HTTP/2 加速 + 重做官网
阶段1 网络加速 - 发现隧道在跑 QUIC(ExecStart 丢了 --protocol http2), 实测 QUIC 可用率 48% vs HTTP/2 80%+,是重大性能回退。 恢复后公网延迟从 4141ms 降到 690ms(快 6 倍),可用率 92%。 - 优选 IP 结论:无效。hosts 覆盖确实生效了(日志里连的就是指定 IP), 但落点仍是 lax —— 运营商把所有 Cloudflare anycast 都路由到美西。 已清掉这段无效配置。 - BBR 不可用:设备是自定义内核 6.4.0-rc4-jsbsbxjxh66, 没编 tcp_bbr 模块也没配置项。改用 cubic + 调优: TCP 缓冲 4MB、tcp_fastopen=3、tcp_slow_start_after_idle=0 (长轮询场景关键)、tcp_tw_reuse=1。 阶段2 官网重做 - 拆出独立模块 relay/landing.py(relay.py 已两千多行, 再塞 HTML 没法看) - 信息结构参考成熟产品站:吸顶导航 / Hero / 九宫格功能 / 三步上手 / 下载 / FAQ / 页脚 - 保持白色简洁:底白、浅灰面板、细边框、大量留白 - logo 用内联 SVG(ICO 放 img 里实测是破图) - 管理入口从官网移除(管理不对外开放) 过程中被自己的测试抓到两个 bug: - 模块叫 site.py 会和 Python 标准库重名,import site 拿到的是标准库 - _logo() 里把 % 格式化和字符串拼接混用,直接抛 TypeError
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''防回归:抓"定义了但从没被调用"的方法。
|
||||
|
||||
为什么值得单独一个测试:
|
||||
1.7.0 交付后用户装上发现**一片白屏**。根因是
|
||||
private void initTabs() { ... } // 定义在第 937 行
|
||||
而 onCreate 里只调了 buildControlPanel(),**从头到尾没人调 initTabs()**。
|
||||
结果 tabDefs 为 null -> selectTab() 直接 return -> 内容区空白。
|
||||
|
||||
这种错误编译能过、别的测试也能过,只有真机跑起来才看得见,
|
||||
所以必须静态查出来。
|
||||
|
||||
判定方法:
|
||||
统计方法名在文件里出现的次数(定义那一处也算)。
|
||||
只出现 1 次 = 只有定义没调用。
|
||||
|
||||
分两档:
|
||||
* **硬性失败**:关键路径上的方法(initTabs / 三个面板 / selectTab)。
|
||||
这些漏了就是白屏或功能全无,必须拦住。
|
||||
* **仅报告**:其它可疑方法。有些确实是历史遗留的死代码
|
||||
(下面的 KNOWN_DEAD 记录了已确认的),有些是接口回调
|
||||
(由框架调用,本文件里当然只有定义)。
|
||||
报告出来供清理,但不拦构建 —— 免得噪音太大没人看。
|
||||
'''
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
MAIN = (ROOT / "android" / "src" / "com" / "lanremote" / "watch"
|
||||
/ "MainActivity.java")
|
||||
|
||||
# 框架/接口回调:由 Android 或 RemoteClient 调用,本文件里只有定义是正常的
|
||||
WHITELIST = {
|
||||
"onCreate", "onDestroy", "onResume", "onPause", "onStart", "onStop",
|
||||
"onRestart", "onNewIntent", "onSaveInstanceState", "onRestoreInstanceState",
|
||||
"onBackPressed", "onKeyDown", "onKeyUp", "onWindowFocusChanged",
|
||||
"onRequestPermissionsResult", "onActivityResult", "onOptionsItemSelected",
|
||||
"onCreateOptionsMenu", "onPrepareOptionsMenu", "onConfigurationChanged",
|
||||
"onTouchEvent", "onClick", "onLongClick", "onTouch", "onAnimationUpdate",
|
||||
"onAnimationStart", "onAnimationEnd", "onAnimationCancel", "onAnimationRepeat",
|
||||
"onPreDraw", "onGlobalLayout", "onScrollChanged", "onItemClick",
|
||||
"onItemSelected", "onNothingSelected", "onFocusChange", "onEditorAction",
|
||||
"run", "call", "get", "set", "equals", "hashCode", "toString",
|
||||
"uncaughtException", "afterTextChanged", "beforeTextChanged",
|
||||
"onTextChanged", "onProgressChanged", "onStartTrackingTouch",
|
||||
"onStopTrackingTouch", "onDateSet", "onTimeSet", "onDismiss",
|
||||
"onCancel", "onShow", "onKey", "onCreateDialog", "onPrepareDialog",
|
||||
"onReceive", "onServiceConnected", "onServiceDisconnected",
|
||||
"onBind", "onCreateView", "onViewCreated", "onDestroyView",
|
||||
"onAttach", "onDetach", "onActivityCreated", "onOptionsMenuClosed",
|
||||
"onContextItemSelected", "onCreateContextMenu", "handleMessage",
|
||||
"onChildViewAdded", "onChildViewRemoved", "onGlobalFocusChanged",
|
||||
"onLayoutChange", "onScrollStateChanged", "onScrolled",
|
||||
"onPageStarted", "onPageFinished", "shouldOverrideUrlLoading",
|
||||
"onReceivedError", "onDownloadStart", "onChildDraw",
|
||||
# RemoteClient.Listener 的实现
|
||||
"onDisconnected", "onEvent", "onFrame", "onProgress", "onLog",
|
||||
}
|
||||
|
||||
# 已确认的历史遗留死代码:早期版本的实现,后来换成了别的写法,
|
||||
# 函数留着但没人调。不影响功能,列出来是为了有朝一日清掉。
|
||||
KNOWN_DEAD = {
|
||||
"buildFeatureTab": "旧的分页构建方式,已被 renderGroups() 取代",
|
||||
"pickFolder": "已被 pickFile() 取代",
|
||||
"pickClipHistory": "功能已移到服务端注册表",
|
||||
"confirmWallpaper": "功能已移到服务端注册表",
|
||||
"confirmMonitor": "功能已移到服务端注册表",
|
||||
"sendMedia": "已被 media() 取代",
|
||||
"promptRun": "已被 runFeature() 取代",
|
||||
"showInfo": "已被 feature_run 的 info 取代",
|
||||
"findSavedToken": "旧的重连逻辑,已被 RelayTransport 取代",
|
||||
"glassBackground": "旧的美化辅助函数,样式改成 glass() 后没人用了",
|
||||
"sp": "旧的字号辅助,已被 dp() 取代",
|
||||
}
|
||||
|
||||
# 关键路径:这些漏了就是白屏 / 功能全无,必须硬性拦住
|
||||
CRITICAL = ("buildConnectPanel", "buildControlPanel", "initTabs",
|
||||
"buildMirrorPanel", "buildLanPanel")
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
|
||||
def check(name, ok, detail=""):
|
||||
global passed, failed
|
||||
if ok:
|
||||
passed += 1
|
||||
print(" [PASS] " + name)
|
||||
else:
|
||||
failed += 1
|
||||
print(" [FAIL] " + name + " " + str(detail))
|
||||
|
||||
|
||||
def defined_methods(text: str) -> list[str]:
|
||||
pattern = re.compile(
|
||||
r"(?:private|public|protected|static|final|\s)+"
|
||||
r"[\w<>\[\],.\s]+\s+(\w+)\s*\([^)]*\)\s*(?:throws [\w.,\s]+)?\{")
|
||||
names = []
|
||||
for match in pattern.finditer(text):
|
||||
name = match.group(1)
|
||||
if name in ("if", "for", "while", "switch", "catch", "synchronized",
|
||||
"try", "return", "new"):
|
||||
continue
|
||||
names.append(name)
|
||||
return names
|
||||
|
||||
|
||||
def main() -> int:
|
||||
check("MainActivity.java 在", MAIN.is_file())
|
||||
if not MAIN.is_file():
|
||||
return 1
|
||||
text = MAIN.read_text(encoding="utf-8")
|
||||
|
||||
print()
|
||||
print("一、关键路径必须被调用(漏了就是白屏)")
|
||||
# initTabs 专项:白屏的根因就是它
|
||||
init_def = len(re.findall(r"private void initTabs\s*\(", text))
|
||||
init_use = len(re.findall(r"\binitTabs\s*\(\s*\)", text))
|
||||
check("initTabs() 有定义", init_def >= 1, f"定义 {init_def} 处")
|
||||
check("initTabs() 被调用(否则连上后一片白屏)",
|
||||
init_use >= 2, f"出现 {init_use} 次(1 次是定义,>1 才算被调用)")
|
||||
check("initTabs() 紧跟 buildControlPanel()",
|
||||
re.search(r"buildControlPanel\(\);\s*(?://[^\n]*\n\s*)*initTabs\(\);",
|
||||
text) is not None,
|
||||
"必须在 buildControlPanel() 之后立刻调用")
|
||||
|
||||
for method in CRITICAL:
|
||||
n = len(re.findall(r"\b" + method + r"\s*\(", text))
|
||||
check(f"{method}() 被调用", n > 1, f"出现 {n} 次")
|
||||
|
||||
print()
|
||||
print("二、分页定义完整性")
|
||||
tab_names = re.findall(r'new TabDef\("([^"]+)"', text)
|
||||
check("定义了 10 个分页", len(tab_names) == 10, f"实际 {len(tab_names)} 个")
|
||||
print(f" 分页: {' '.join(tab_names)}")
|
||||
check("selectTab 有定义", "private void selectTab(" in text)
|
||||
check("selectTab 被调用", len(re.findall(r"\bselectTab\s*\(", text)) > 1)
|
||||
|
||||
print()
|
||||
print("三、未调用方法扫描")
|
||||
names = defined_methods(text)
|
||||
orphans = []
|
||||
for name in sorted(set(names)):
|
||||
if name in WHITELIST or name in KNOWN_DEAD:
|
||||
continue
|
||||
n = len(re.findall(r"\b" + re.escape(name) + r"\s*\(", text))
|
||||
if n <= 1:
|
||||
orphans.append((name, n))
|
||||
|
||||
check("没有**未知**的未调用方法", not orphans,
|
||||
"\n ".join(f"{n}({c} 次)" for n, c in orphans)
|
||||
if orphans else "")
|
||||
if orphans:
|
||||
print()
|
||||
print(" 未知的未调用方法(可能是漏接的事件处理,也可能是新的死代码):")
|
||||
for name, cnt in orphans:
|
||||
print(f" {name} (出现 {cnt} 次)")
|
||||
|
||||
if KNOWN_DEAD:
|
||||
print()
|
||||
print(f" 已知死代码 {len(KNOWN_DEAD)} 个(不影响功能,待清理):")
|
||||
for name, why in sorted(KNOWN_DEAD.items()):
|
||||
still = len(re.findall(r"\b" + re.escape(name) + r"\s*\(", text))
|
||||
mark = "" if still else " [已删除]"
|
||||
print(f" {name}: {why}{mark}")
|
||||
|
||||
print()
|
||||
print("=" * 58)
|
||||
print(f"通过 {passed} 项,失败 {failed} 项")
|
||||
return 0 if failed == 0 else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user