mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 14:50:45 +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 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
262 lines
10 KiB
Python
262 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""液态玻璃 第二步:动态效果
|
||
|
||
* Tab 栏:玻璃容器 + 一个会"滑过去"的指示器(宽高和位置一起动)
|
||
* 切页:内容淡入 + 轻微上移
|
||
* 浮层面板(镜像/诊断):从底部滑入、滑出
|
||
* 顶栏 / 日志 / 连接面板:换成玻璃材质
|
||
|
||
注意:这个脚本**无条件写盘**。之前因为一处锚点失败就整体不写,
|
||
白白丢了一整轮改动 —— 现在失败的只跳过那一处。
|
||
"""
|
||
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. Tab 栏:玻璃 + 滑动指示器 ----------------
|
||
|
||
TABBAR_OLD = ''' // ---- 分页标签 ----
|
||
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)));'''
|
||
|
||
TABBAR_NEW = ''' // ---- 分页标签(玻璃容器 + 滑动指示器)----
|
||
HorizontalScrollView tabScroll = new HorizontalScrollView(this);
|
||
tabScroll.setHorizontalScrollBarEnabled(false);
|
||
|
||
FrameLayout tabWrap = new FrameLayout(this);
|
||
tabWrap.setBackground(glass(18));
|
||
tabWrap.setPadding(dp(4), dp(4), dp(4), dp(4));
|
||
|
||
tabIndicator = new View(this);
|
||
tabIndicator.setBackground(glassButton(C_ACCENT, 14));
|
||
tabIndicator.setLayoutParams(new FrameLayout.LayoutParams(dp(60), dp(34)));
|
||
tabWrap.addView(tabIndicator);
|
||
|
||
tabBar = new LinearLayout(this);
|
||
tabBar.setOrientation(LinearLayout.HORIZONTAL);
|
||
tabWrap.addView(tabBar, new FrameLayout.LayoutParams(
|
||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||
|
||
tabScroll.addView(tabWrap);
|
||
controlPanel.addView(tabScroll, new LinearLayout.LayoutParams(
|
||
ViewGroup.LayoutParams.MATCH_PARENT, dp(48)));'''
|
||
|
||
# ---------------- 2. 标签按钮:透明底 ----------------
|
||
|
||
TABITEM_OLD = ''' tab.setPadding(dp(14), dp(8), dp(14), dp(8));
|
||
tab.setOnClickListener(new View.OnClickListener() {'''
|
||
|
||
TABITEM_NEW = ''' tab.setPadding(dp(14), dp(8), dp(14), dp(8));
|
||
tab.setBackgroundColor(0x00000000);
|
||
tab.setOnClickListener(new View.OnClickListener() {'''
|
||
|
||
TABITEM_MARGIN_OLD = ''' LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||
params.setMargins(0, 0, dp(6), 0);'''
|
||
|
||
TABITEM_MARGIN_NEW = ''' LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||
params.setMargins(0, 0, 0, 0);'''
|
||
|
||
# ---------------- 3. selectTab ----------------
|
||
|
||
SELECT_OLD = ''' 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);
|
||
}
|
||
}'''
|
||
|
||
SELECT_NEW = ''' currentTab = index;
|
||
for (int i = 0; i < tabBar.getChildCount(); i++) {
|
||
View child = tabBar.getChildAt(i);
|
||
boolean on = (i == index);
|
||
child.setBackgroundColor(0x00000000);
|
||
if (child instanceof TextView) {
|
||
((TextView) child).setTextColor(on ? 0xFFFFFFFF : C_FG);
|
||
child.animate().alpha(on ? 1f : 0.72f).setDuration(200).start();
|
||
}
|
||
}
|
||
moveTabIndicator(tabBar.getChildAt(index));'''
|
||
|
||
SELECT_ANIM_OLD = ''' for (Act item : tabDefs[index].acts) {
|
||
addRow(tabContent, action(item.label, item.task), null);
|
||
}
|
||
flushGrid(tabContent);
|
||
}'''
|
||
|
||
SELECT_ANIM_NEW = ''' for (Act item : tabDefs[index].acts) {
|
||
addRow(tabContent, action(item.label, item.task), null);
|
||
}
|
||
flushGrid(tabContent);
|
||
// 切页时内容淡入 + 轻微上移,做出"流动"的感觉
|
||
animateIn(tabContent, 10f, 220);
|
||
}
|
||
|
||
/** 指示器滑到目标标签;宽度和位置一起动。 */
|
||
private void moveTabIndicator(final View target) {
|
||
if (tabIndicator == null || target == null) {
|
||
return;
|
||
}
|
||
if (target.getWidth() == 0) {
|
||
// 布局还没完成,等一帧再试
|
||
tabIndicator.post(new Runnable() {
|
||
@Override
|
||
public void run() {
|
||
moveTabIndicator(target);
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
final int startX = (int) tabIndicator.getTranslationX();
|
||
final int startW = tabIndicator.getLayoutParams().width;
|
||
final int endX = tabBar.getLeft() + target.getLeft();
|
||
final int endW = target.getWidth();
|
||
|
||
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
|
||
animator.setDuration(300);
|
||
animator.setInterpolator(new android.view.animation.DecelerateInterpolator());
|
||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||
@Override
|
||
public void onAnimationUpdate(ValueAnimator animation) {
|
||
float fraction = (Float) animation.getAnimatedValue();
|
||
ViewGroup.LayoutParams params = tabIndicator.getLayoutParams();
|
||
params.width = (int) (startW + (endW - startW) * fraction);
|
||
tabIndicator.setLayoutParams(params);
|
||
tabIndicator.setTranslationX(startX + (endX - startX) * fraction);
|
||
}
|
||
});
|
||
animator.start();
|
||
}'''
|
||
|
||
# ---------------- 4. 字段 ----------------
|
||
|
||
FIELD_OLD = " private List<String> featureGroups = null;"
|
||
FIELD_NEW = (" private List<String> featureGroups = null;\n"
|
||
" private View tabIndicator;")
|
||
|
||
# ---------------- 5. 顶栏 / 日志 / 连接面板 ----------------
|
||
|
||
TOPBAR_OLD = ''' top.addView(disconnect);
|
||
controlPanel.addView(top);'''
|
||
|
||
TOPBAR_NEW = ''' top.addView(disconnect);
|
||
top.setBackground(glass(16));
|
||
top.setPadding(dp(10), dp(8), dp(8), dp(8));
|
||
controlPanel.addView(top);'''
|
||
|
||
LOG_OLD = " logView.setBackground(rounded(C_CARD, 6));"
|
||
LOG_NEW = " logView.setBackground(glass(GLASS_FILL_SOLID, 14, GLASS_EDGE_DIM));"
|
||
|
||
CONNECT_OLD = ''' ScrollView scroll = new ScrollView(this);
|
||
scroll.setBackgroundColor(C_BG);
|
||
|
||
LinearLayout box = new LinearLayout(this);
|
||
box.setOrientation(LinearLayout.VERTICAL);
|
||
box.setBackgroundColor(C_BG);'''
|
||
|
||
CONNECT_NEW = ''' ScrollView scroll = new ScrollView(this);
|
||
scroll.setBackgroundColor(0x00000000);
|
||
|
||
LinearLayout box = new LinearLayout(this);
|
||
box.setOrientation(LinearLayout.VERTICAL);
|
||
box.setBackgroundColor(0x00000000);'''
|
||
|
||
# ---------------- 6. 面板滑入滑出(用唯一锚点)----------------
|
||
|
||
MIRROR_OPEN_OLD = ''' mirrorPanel.setVisibility(View.VISIBLE);
|
||
mirrorPanel.bringToFront();'''
|
||
MIRROR_OPEN_NEW = ''' mirrorPanel.setVisibility(View.VISIBLE);
|
||
mirrorPanel.bringToFront();
|
||
animateIn(mirrorPanel, 24f, 260);'''
|
||
|
||
# 关闭镜像面板:只在 closeMirrorPanel() 里那一处(后面紧跟 mirrorImage 判空)
|
||
MIRROR_CLOSE_OLD = ''' mirrorPanel.setVisibility(View.GONE);
|
||
if (mirrorImage != null) {'''
|
||
MIRROR_CLOSE_NEW = ''' animateOut(mirrorPanel, 24f, 200, new Runnable() {
|
||
@Override
|
||
public void run() {
|
||
mirrorPanel.setVisibility(View.GONE);
|
||
}
|
||
});
|
||
if (mirrorImage != null) {'''
|
||
|
||
DIAG_OPEN_OLD = ''' diagPanel.setVisibility(View.VISIBLE);
|
||
diagPanel.bringToFront();'''
|
||
DIAG_OPEN_NEW = ''' diagPanel.setVisibility(View.VISIBLE);
|
||
diagPanel.bringToFront();
|
||
animateIn(diagPanel, 26f, 280);'''
|
||
|
||
DIAG_CLOSE_OLD = ''' if (diagPanel != null) {
|
||
diagPanel.setVisibility(View.GONE);
|
||
}'''
|
||
DIAG_CLOSE_NEW = ''' if (diagPanel != null) {
|
||
animateOut(diagPanel, 26f, 200, new Runnable() {
|
||
@Override
|
||
public void run() {
|
||
diagPanel.setVisibility(View.GONE);
|
||
}
|
||
});
|
||
}'''
|
||
|
||
PAIRS = [
|
||
(FIELD_OLD, FIELD_NEW, "tabIndicator 字段"),
|
||
(TABBAR_OLD, TABBAR_NEW, "Tab 栏玻璃容器"),
|
||
(TABITEM_OLD, TABITEM_NEW, "标签透明底"),
|
||
(TABITEM_MARGIN_OLD, TABITEM_MARGIN_NEW, "标签间距"),
|
||
(SELECT_OLD, SELECT_NEW, "selectTab 指示器"),
|
||
(SELECT_ANIM_OLD, SELECT_ANIM_NEW, "内容转场 + moveTabIndicator"),
|
||
(TOPBAR_OLD, TOPBAR_NEW, "顶栏玻璃"),
|
||
(LOG_OLD, LOG_NEW, "日志玻璃"),
|
||
(CONNECT_OLD, CONNECT_NEW, "连接面板透明"),
|
||
(MIRROR_OPEN_OLD, MIRROR_OPEN_NEW, "镜像面板滑入"),
|
||
(MIRROR_CLOSE_OLD, MIRROR_CLOSE_NEW, "镜像面板滑出"),
|
||
(DIAG_OPEN_OLD, DIAG_OPEN_NEW, "诊断面板滑入"),
|
||
(DIAG_CLOSE_OLD, DIAG_CLOSE_NEW, "诊断面板滑出"),
|
||
]
|
||
|
||
|
||
def main() -> int:
|
||
text = MAIN.read_text(encoding="utf-8")
|
||
failed = []
|
||
applied = 0
|
||
for old, new, tag in PAIRS:
|
||
if old not in text:
|
||
failed.append(tag)
|
||
print(f" [跳过] {tag} —— 锚点没找到")
|
||
continue
|
||
occurrences = text.count(old)
|
||
if occurrences > 1:
|
||
print(f" [注意] {tag} 匹配 {occurrences} 处,只改第一处")
|
||
text = text.replace(old, new, 1)
|
||
applied += 1
|
||
print(f" {tag}: OK")
|
||
|
||
# 无条件写盘:失败的只跳过那一处,不能整体丢
|
||
MAIN.write_text(text, encoding="utf-8")
|
||
print(f"\n 已写盘(成功 {applied}/{len(PAIRS)})")
|
||
if failed:
|
||
print(f" 未应用: {', '.join(failed)}")
|
||
return 1
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|