wangjia
bf84492eef
feat(client/native): stats-overhaul Phase1 — 四端实时统计采集端
...
各原生侧把 libbox/Clash 的实时上下行/延迟经冻结的 pangolin/vpn/stats channel
生产真实帧:
- iOS/macOS 新增 StatsClient.swift(LibboxNewCommandClient,statusInterval 1s,
uplink/downlink/总量 + urltest 延迟映射契约字段),VpnManager/VpnChannel 状态
观察驱动 start/stop,pbxproj 登记。
- Android PangolinVpnService.kt 延迟修复。
契约字段 uploadBytes/downloadBytes/uploadSpeed/downloadSpeed/urltestResults 不改。
真机验证(连接后实时跳动)为运行时步骤,见计划 Phase1 待办。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 18:13:48 +08:00
wangjia
4f9d2d2cf3
fix(client): 补提交 stats-overhaul 漏掉的 account_api/kernel_process WIP
...
同 device_usage:account_api.dart(deviceUsage/usage 方法)、kernel_process.dart
及对应测试一直未提交,本地有→analyze/test 过,但不在 git→Windows 构建报
「deviceUsage isn't defined」。补齐使提交树自洽可构建。
孤儿组件 device_stat_row/metric_card 已无人引用,不提交。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 17:53:56 +08:00
wangjia
a7c3795e5a
fix(client): 补提交漏掉的 device_usage 模型 + 测试(Windows 构建缺文件)
...
device_usage.dart 一直是 untracked(stats-overhaul WIP 漏提交),本地有所以
analyze/test 过,但不在 git → bundle → Windows 构建报「找不到 device_usage.dart /
DeviceUsage isn't a type」。account_providers/account_api/golden 测试都引用它,补提交。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 17:51:25 +08:00
wangjia
6f480acad5
build(client/windows): installer 版本 bump 1.0.4 → 1.0.5(含统计页重设计)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 17:47:46 +08:00
wangjia
01ebafc05e
feat(client/stats): 统计页重设计 — 月/周/日周期卡 + 设备下拉 + 两周折线 + 修刷新
...
布局重做(对照确认稿):
- 3 张周期卡(本月/本周/今日),每张 = ↓下行 · ↑上行 · 使用时长(PeriodCard)
- 右上设备下拉(_DeviceDropdown,先只挂「全部」;每设备归因打通后填设备名,见 TODO #9/#10)
- 柱状图 → 折线图:最近两周(14 天)按天流量(UsageLineChart,CustomPainter 零依赖)
数据源统一 + 修刷新(根治「本月流量冻住」):
- 月/周/日 + 折线全从单一源 usageProvider(30) 聚合(取最后 N 天点求和,末点即今日,
避开 UTC/本地日期坑);不再 me.weekly + usage 两条管线
- usageProvider/deviceUsageProvider 改 autoDispose(进页重取)+ 下拉刷新(invalidate)
+ 刷新连带 meProvider.refresh。后端每 60s 更新,无需更勤
UI 全走 PangolinColors/Text/Spacing token 单源、零硬编码;中英 l10n key 补齐。
widget 数值断言测试(刀1)按新结构重写并通过;统计/连接页 golden 重生成
(非 CI 闸;components/auth 基线未动)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 17:43:14 +08:00
wangjia
47147a1041
build(client/windows): installer 版本 bump 1.0.3 → 1.0.4(含节点国旗)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 16:32:57 +08:00
wangjia
855d9e0e30
feat(client): 连接页桌面节点胶囊(_NodePill)加地域国旗
...
桌面连接页「已连接」下的节点框是 _NodePill,此前只有文字「节点名·延时」+
智能选择 zap,无国旗。在地域前加 CountryCode(size 20)国旗(无效码回退码块),
智能选择时国旗 + zap 并存。手机/平板的 _CurrentNodeCard 本已有旗。
桌面连接页非 golden 覆盖(含旋转动画),无 golden 变更。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 16:32:24 +08:00
wangjia
8eb7d04fe1
feat(client): 节点地区图标改国旗(SVG 填满裁切),未知码回退码块
...
CountryCode 由 2 字母码块改为渲染真国旗:country_flags 包按 region 码出 SVG
旗(BoxFit.cover 填满裁切),全平台含 Windows 都显示(emoji 国旗在 Windows
不渲染,故走 SVG)。FlagCode 判定无效码(AUTO/占位/非地区码)时回退原码块;
选中态由 accent 底色改为 accent 边框环。
CountryCode 共享于节点列表/连接页/统计页,故三处节点图标统一变国旗,
对应 tablet_servers/connect/stats + desktop_stats golden 已 Mac 重生成
(这些页非 CI golden 闸;CI 闸的 components/auth 基线未动)。
依赖:country_flags ^3.1.0(解析 3.3.0)。analyze 干净,非 golden 测试全过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-28 16:25:48 +08:00
wangjia
b12519be0a
fix(client/windows): runner 加 /utf-8 编译选项,根治 C4819 中文注释编译失败
...
win32_window.cpp 含中文注释(UTF-8 无 BOM),在 zh-CN 机器(代码页 936)+ 新版
MSVC 上报 C4819「字符无法用当前代码页表示」,叠加 runner 的 /WX 直接 error
C2220 编译失败。APPLY_STANDARD_SETTINGS 加 /utf-8,让 MSVC 按 UTF-8 解析
所有 runner 源码,永久根治。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-27 20:49:36 +08:00
wangjia
8d3c5da7ee
fix(client/windows): installer 覆盖修复 — 装新版前静默卸载遗留 AppId 的 1.0.0
...
1.0.0 的 AppId 是非法 GUID(...PANGOLIN0001),1.0.1 起改成合法 GUID。
AppId 不同 → Inno 视为两个独立产品 → 控制面板里 1.00/1.01 并排不覆盖。
当前 AppId 已稳定会原地升级;再在 ssInstall 前把遗留 AppId 的残留装
静默卸掉(/VERYSILENT),清掉已并存的 1.0.0 幽灵。版本 bump 1.0.2→1.0.3。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-27 20:42:54 +08:00
wangjia
60daa6b399
test(client): 刀1 — 统计页「上屏数值对不对」widget 断言(缺口①)
...
闭合最初诉求「统计准不准」的前端那一半:后端记账已 L4 e2e,前端此前只到
解析单测(解析对 ≠ 渲染对)。新测试把真实形态的后端响应(/v1/me·/v1/usage·
/v1/usage/devices)经真 ApiClient→AccountApi→provider 链(连带测 JSON 解析)
喂给 StatsPage,断言:
- 指标卡:本月流量 ΣgbTotal=3.0、本月时长 Σmin/60=2.0、未连接延迟=节点 ping 42
- 周柱:7 根来自 me.weekly_gb(取唯一值核对)
- 分设备:2 行,每行流量/时长正确
注入 MockClient 不打真网络;用 find.byWidgetPredicate 匹配 MetricCard/DeviceStatRow
公共字段,无需改生产代码。改坏期望值已验证转红(非永真)。自动并入 flutter-client job。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 22:59:05 +08:00
wangjia
eb1bd11439
fix(test): 契约测试解耦 stats-overhaul WIP(CI 抓到的真问题)
...
ci-pangolin / Lint — shellcheck (pull_request) Failing after 9s
ci-pangolin / OpenAPI Sync Check (pull_request) Successful in 18s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (pull_request) Successful in 6s
ci-pangolin / Flutter — analyze + test (pull_request) Successful in 39s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (pull_request) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (pull_request) Successful in 4s
ci-pangolin / Go — build + test (pull_request) Successful in 2m2s
ci-pangolin / E2E Smoke — L4 进程级端到端 (pull_request) Failing after 2m14s
ci-pangolin / Golden — 视觉回归 (components + auth) (pull_request) Successful in 31s
CI 暴露:我的契约测试引用了未提交的 stats-overhaul 文件,本地能过(文件在工作区)、
CI checkout 已提交代码就崩:
- api_contract_test.dart import device_usage.dart(?? 未提交)→ flutter analyze 报
'Target of URI doesn't exist'
- usage/contract_test.go 引用 DeviceUsagePoint/deviceUsageResponse(HEAD service.go/
handler.go 均无)→ go-server 编译失败
摘掉 /v1/usage/devices(DeviceUsage)契约,保留 /v1/me + /v1/usage(已提交)。
待 stats-overhaul 合并后再补 DeviceUsage 契约。
验证:flutter analyze test/contract 'No issues';go vet usage 无错。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 18:13:27 +08:00
wangjia
945c2e2f8d
test(ci): 闸2 Dart 支柱4 lint 升 error 级(真守门)
...
analyze 闸修好后(exit 0),把支柱4 两条规则提升为 error 级:
- only_throw_errors / avoid_catching_errors → analyzer.errors: error
- 即使 CI --no-fatal-infos,这俩违规仍致命(挡 merge);当前零违规
- 将来 throw 字符串 / catch Error → CI 红(支柱4:错误是有类型的值)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 13:45:31 +08:00
wangjia
bb2688cede
test(ci): L3 golden 进 CI(components+auth 子集,Linux 权威基线)
...
L3 视觉回归真进 CI(此前卡 docker daemon 未起 + dirty 纠缠;现启 Docker 落地干净子集):
- 在 ghcr.io/cirruslabs/flutter 容器重生成 components+auth 的 14 张 Linux 权威基线
(auth_login/connect 三态/quota/smart_card;mac 渲染与 CI Linux 不一致,故钉死 Linux),
容器内 --update-goldens 后无 flag 复跑幂等通过
- ci.yml 新增 golden job(第9个):flutter test components_golden_test + auth_redesign_golden_test
- 解耦干净:这俩只 import clean widget;stats-overhaul 的 l10n 改动纯新增(现有键未动)
→ 渲染不受影响、不裹挟 dirty;tablet/desktop-stats golden 仍耦合 stats-overhaul,待合并后并入
- docs/test-architecture.html:L3 状态更新为「已进 CI(子集)」
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 13:20:55 +08:00
wangjia
76dbdcfa83
test(client): L2 点连接能连上 流程 + ConnectApi 注入(支柱1)
...
- connection_provider:加 connectApiFactoryProvider(原内部 new ConnectApi 改成
可注入工厂,支柱1 接缝即接口)——默认行为不变
- test/unit/flow_connect_test.dart:真 toggle → fetchConfig(注入 MockClient 回占位
config)→ bridge.start → statusStream 确认 → on → 再 toggle → off;
验证「非乐观翻转」红线(on 必由 bridge 确认)
- 全量 unit/widget 47 全过(重构不破坏)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 12:13:40 +08:00
wangjia
95fad37989
test(client): L2 登陆/重启续登/登出 流程(真 AuthNotifier)
...
驱动真实 AuthNotifier(非桩),仅在可注入接缝 TokenStore 处换内存实现,覆盖最初诉求:
- 登陆:saveTokens → isLoggedIn + 令牌持久化
- 重启续登:新 AuthNotifier 从同一 store 恢复登录态(无需重输密码)
- 登出:logout → 未登录 + store 清空,再重启仍未登录
- 3 用例全过
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 12:10:52 +08:00
wangjia
cb6fc25bc9
test(client): L1 数值格式化纯函数单测 + 从 widget 抽出(支柱3)
...
- lib/util/format.dart:抽出 formatSpeed/formatDuration(原私有于 connect_page
_speed / connect_button _fmt,混在 widget 里没法单测)
- connect_page/connect_button 改用公共纯函数(渲染输出不变)
- test/unit/format_test.dart:10 用例覆盖速率 B/s→GB/s 各单位边界 +
时长 HH:MM:SS 补零/小时不封顶/取模 60
- 验证:format 10 + widget 8 全过、analyze 无 error/warning
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 12:06:34 +08:00
wangjia
64f96fe018
refactor(api): /v1/me 收敛 expire_at → 只发 expires_at(无 web 用户中心)
...
之前后端同时发 expire_at + expires_at(分别给 app + web 用户中心)。现已无 web 端,
双发是纯冗余,统一只用 expires_at:
- account.go:meResponse 删 ExpireAt 字段 + GetMe handler 不再赋值
- client me.dart:fromJson 删 (expires_at ?? expire_at) 别名回退
- 两端契约快照同步:Go meResponse 冻结集去 expire_at(12→11 key)、删 Dart 别名测试
- 验证:go test httpapi 绿、flutter test contract(14)绿、analyze EXIT 0、e2e 全链路绿
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 10:08:50 +08:00
wangjia
dbd183ee00
fix(ci): 修 flutter analyze 闸长期 exit 1(形同虚设)
...
发现:CI flutter analyze 退出码 1(1204 个 info,0 error/warning),其中 1191 来自
第三方 vendored 包 lucide_icons_patched —— 这道闸一直红/无效。
- analysis_options.yaml:exclude packages/lucide_icons_patched/**(去 1191 噪音)
- ci.yml:flutter analyze --no-fatal-infos(info 是建议级不该硬挡 merge;
error/warning 仍致命)→ analyze EXIT 0、闸真正可用
- 顺手清 11 个 clean 文件 info:auth_api 删 >>>AUTHLOG 调试 print 残留(+unused sw)、
account_page/plan_card withOpacity→withValues、vpn_bridge where(is Map)→whereType、
测试文件删多余 import + final→const
- 剩 2 个 info 在 stats-overhaul dirty 文件(stats_page/device_stat_row),留其合并清
- 验证:flutter analyze --no-fatal-infos EXIT 0(1204→2)、flutter test 48 全过
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-25 07:39:14 +08:00
wangjia
149aa90cfa
test(contract): 第2刀b Dart 契约快照(stats + /v1 API 字段面冻结)
...
支柱 2(契约单源)守门 — 堵 mac-stats-0 一类跨进程契约悄悄分叉:
- test/contract/stats_contract_test.dart:冻结 pangolin/vpn/stats payload
字段面 + status 四值,改契约即测试红、逼同步原生产出端 + 文档
- test/contract/api_contract_test.dart:冻结 /v1/me、/v1/usage、
/v1/usage/devices 的 snake_case 字段面
- ci.yml:flutter job 测试纳入 test/contract;本地 15 用例全过
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-24 23:32:00 +08:00
wangjia
62925a6886
Merge worktree-windows-icon-tray-fix: Windows 桌面/托盘/任务栏图标 + 关窗不断连接
...
- 关窗(X/Alt+F4)隐藏到托盘并保持隧道,真退出只走托盘菜单(Platform.isWindows 隔离)
- 窗口标题设「穿山甲」(无 VPN 字眼)
- Windows 托盘改用 .ico(Win32 只认 ico,PNG 空白),mac/Linux 仍 PNG
- 更新 app_icon.ico / tray_icon.ico / Runner.rc / installer
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 10:54:23 +08:00
wangjia
e4db3beba6
Merge branch 'main' into feature/pangolin-ios
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
# Conflicts:
# client/lib/bridge/vpn_bridge_provider.dart
# docs/index.html
2026-06-23 10:05:20 +08:00
wangjia
e25649cd27
feat(client/ios): iPad tablet 正式适配——断点≥900 对齐设计源 + tablet golden 回归闸
...
- form_factor 触屏 tablet 阈值 600→900,对齐 design/ui_kits/tablet(1180×820 横屏
侧栏):iPad 横屏/12.9″竖屏走侧栏,标准/11″竖屏回落 mobile 底 Tab,避免双栏挤压
- form_factor_test 补全断点边界(900/899)与各 iPad 尺寸用例
- 新增 tablet_pages_golden_test:四视图×明暗×中英 12 张 golden,注入演示数据
(6 节点/周流量/30 天用量)让 2 列网格与周柱满渲染,作回归闸
- design/CONTRACT.md:tablet 像素契约(取自 tabapp.jsx)+ 逐屏验收清单
- 真机 iPad mini 6 视觉签核通过;141 测试全绿
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 10:00:14 +08:00
wangjia
11ee3342bf
feat(client/ios): 补齐 App 图标(iPhone+iPad 全尺寸,去 alpha)
...
iOS AppIcon.appiconset 只有 Contents.json、无任何 PNG → 桌面图标空白。
以 design 单源 assets/app-icon.svg(去圆角 rx=0 全幅方形)经 qlmanage 渲染 1024,
flutter_launcher_icons 铺开 21 张全尺寸(含 iPad 76/83.5)并去 alpha(App Store 合规)。
新增 dev_dep flutter_launcher_icons + 配置块,改图标重渲源图后 dart run 即可。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 00:39:37 +08:00
wangjia
bd984feff9
fix(client/ios): iOS 接通原生隧道——切真桥 + save-before-start + DNS matchDomains
...
根因:iOS 端 vpn_bridge_provider 把 iOS 归入'其他平台 → VpnBridgeMock',
整个 App 用假桥,伪造已连接状态与写死的 URLTest 延迟(18/32/54ms),从不调用
B1/C1 打通的原生 NEPacketTunnelProvider。表现为 UI 显示已连接但流量全直连
(apple 通/google 被墙、RTT 20ms),设备日志无任何隧道/sing-box/节点痕迹。
三处修复:
1. vpn_bridge_provider.dart: iOS → VpnNativeBridge(真原生 MethodChannel)。
2. VpnManager.start(): 先 saveToPreferences+重载(首启触发系统授权、持久化配置)
再 startVPNTunnel,否则对未持久化 manager 调用抛 NEVPNError。对齐 macOS。
3. PacketTunnelProvider.openTun: DNS 补 matchDomains=[""],强制所有 DNS 走隧道,
iOS 不设会把隧道 DNS 当补充解析器、查询仍走系统直连 DNS 致污染打不开站点。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 00:28:53 +08:00
wangjia
9b365c7e1c
fix(client/ios): PacketTunnel 引入 Generated.xcconfig 注入版本号
...
扩展 Info.plist 的 CFBundleVersion=$(FLUTTER_BUILD_NUMBER) 因 target 未引
Flutter 的 Generated.xcconfig 而展开为空串,iOS 装机校验 MissingBundleVersion
(code 33) 拒绝安装。给 PacketTunnel 三个 build config 加 baseConfiguration
Reference 指向 Generated.xcconfig(纯 Flutter 变量,无 Pods,不破坏 OTHER_LDFLAGS=""),
使扩展版本号 = 主 App = 1.0.0(1),满足 App Extension 版本须与 host app 一致的上架要求。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 23:59:05 +08:00
wangjia
f3f91cc0ff
feat(android): 启动图标改用官方穿山甲(自适应图标)
...
前景 path 取自官方 client/assets/logo-mark-white.svg(原样,非重绘),仅加 Android 安全区居中;
背景为 app-icon.svg 的橙色渐变(#C8794A→#9E5630);删除占位三角 drawable/ic_launcher.xml。
Vivo X200/华为 DCO-AL00 真机验证图标显示正常。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 23:42:18 +08:00
wangjia
76d8e57a44
build(client/ios): B1 完成——PacketTunnel 链接 libbox+系统框架,iOS 构建打通
...
- PacketTunnel 链 Libbox.xcframework(静态,只Link不Embed)+ NetworkExtension
+ SystemConfiguration + libresolv.tbd + UIKit(libbox iOS 引用 UIApplication);
OTHER_LDFLAGS="" 切 CocoaPods 继承,FRAMEWORK_SEARCH_PATHS 指 Frameworks/
- 桥接头手动声明 sockaddr_ctl/ctl_info(iOS SDK 无 kern_control.h,稳定内核 ABI)
- 部署目标 iOS 12→14(os.Logger 需 14;低版老机不再兼容,用户拍板)
- 修预存脚手架坑: Podfile 删悬空 RunnerTests; Info.plist 移出 Resources(双产出);
Runner 构建阶段重排(Embed App Extensions 前置, Thin Binary 殿后) 解依赖环
- 验证: flutter build ios 通过, C1 Provider 编译通过, otool -L 扩展零外部 @rpath
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 22:20:49 +08:00
wangjia
381a621d77
feat(client/ios): Provider 对齐 macOS libbox 集成(CommandServer+utun fd)+ 内存监控
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-22 20:58:03 +08:00
wangjia
33a3508489
build(client/ios): 引入 iOS libbox 框架 + gitignore 排除产物
2026-06-22 20:52:28 +08:00
wangjia
99695e8861
test(client): 锁定 form_factor 断点(iPad→tablet, iPhone→mobile)
2026-06-22 20:51:34 +08:00
wangjia
d0919943f5
fix(android): 真机连通修复——补 ACCESS_NETWORK_STATE + 砍 IPv6 zone(Task 7)
...
Vivo X200(Android 16)真机实测两处运行期崩溃并修复:
- DefaultNetworkMonitor 用 ConnectivityManager 需 ACCESS_NETWORK_STATE 权限(缺则 SecurityException)
- getInterfaces 返回的 IPv6 link-local 含 zone(%rmnet_data0),sing-box netip.ParsePrefix panic;substringBefore('%') 砍掉
真机端到端连通已由用户验证通过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 20:43:49 +08:00
wangjia
126c06833d
feat(android): libbox 隧道重写对接真实 1.13.12 API,APK 编译通过(Task 5)
...
原生层照 PoC 旧/想象 API 写,与真实 sing-box 1.13.12 libbox 差距是架构级:
- 包名 libbox(非 go.libbox);无 BoxService,改 Libbox.setup + CommandServer 模型
- PangolinVpnService 重写:实现完整 PlatformInterface(15法)+CommandServerHandler
- 新增 DefaultNetworkMonitor(上报默认接口,缺则报 no available network)
- openTun 适配真实 TunOptions(RoutePrefixIterator/getMTU/StringBox DNS)
- 统计/切节点经 CommandClient(uplinkTotal/selectOutbound);MainActivity 接线
构建环境矩阵打通:Gradle 8.7(Java21)+声明式插件迁移+AGP 8.6+Kotlin 2.2.0+占位图标
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 19:28:24 +08:00
wangjia
82741ce0c4
feat(android): Dart provider 接 Android→VpnNativeBridge(Task 4)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 18:48:58 +08:00
wangjia
5ea4e1ae03
fix(client/windows): 任务栏图标 + 关闭窗口不再断连接
...
- 关闭窗口断连接:onExitRequested 原先无条件 _teardownVpn 再退出;Windows 点 X
会触发该回调拆隧道,而 window_manager 的 preventClose 又把窗口仅隐藏到托盘
→ 出现「一关就断网、进程还在」。改为 Windows 下点 X/Alt+F4 取消退出+隐藏,
保持隧道;真正退出只走托盘「退出」(onBeforeQuit 标记 _isQuitting 再拆隧道)。
macOS Cmd+Q 仍正常拆隧道退出。
- 任务栏图标没换:仅靠 WNDCLASS.hIcon(LoadIcon 单尺寸)任务栏可能拿不到正确
尺寸。窗口创建后用 LoadImage 按系统 SM_CXICON/SM_CXSMICON 各取一份,
WM_SETICON 显式设 ICON_BIG(任务栏/Alt-Tab)+ ICON_SMALL(标题栏)。
- 版本 1.0.1 → 1.0.2。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 17:53:34 +08:00
wangjia
94993b21b4
fix(client/windows): 修桌面/标题栏图标 + 标题文案 + 系统托盘空白
...
- app_icon.ico 重新由 assets/app-icon.svg 生成(穿山甲品牌图标,多尺寸),
替换残留的默认 Flutter logo —— 同时修好桌面图标与标题栏小图标。
- 窗口标题去掉 "VPN" 字眼:main.cpp 原生标题 pangolin_vpn → Pangolin;
main.dart 用 windowManager.setTitle('穿山甲') 显示中文品牌名;
Runner.rc 的 FileDescription/InternalName/ProductName → Pangolin。
- 系统托盘空白:Windows 走 Win32 Shell_NotifyIcon 只认 .ico(传 PNG 显示空白),
新增 BMP 编码的 assets/tray_icon.ico,system_tray.dart 按平台选 ico/png。
- 安装包版本 1.0.0 → 1.0.1(pubspec 1.0.1+2)便于区分测试构建。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 17:06:05 +08:00
wangjia
eea851737f
docs(client/windows): 合并后校正 README API 默认值说明(已随 main 改为测试节点)
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 14:17:48 +08:00
wangjia
ac0fc774cb
Merge branch 'main' into feature/windows
2026-06-22 14:17:19 +08:00
wangjia
322d806876
fix+build(client/windows): 复查修缮——一键构建脚本 + 修 README dart-define 漏项 + 清 lint
...
- 新增 client/windows/build.ps1:拉内核→带 --dart-define 构建→出安装包一键串联,
规避 Release 漏 --dart-define 导致默认连 localhost、登录「网络请求失败」的坑。
- README:Release 命令补回 --dart-define 并加显式警告,指向一键脚本。
- 清 4 个 lint warning:desktop_vpn_bridge 多余 cast→pattern match、去多余非空断言;
nav_sidebar 删未用 import;vpn_bridge_mock 加 killSwitchEnabled getter。
- 同步 window_manager/tray_manager/screen_retriever 插件注册生成文件(win+macos)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 14:17:13 +08:00
wangjia
4025ce341c
build(client/windows): installer AppId 改为合法 GUID
...
原 AppId 段含非 hex 占位(PANGOLIN0001);Inno 虽接受任意串,改为规范 GUID 更清晰。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 09:17:31 +08:00
wangjia
ec0e3d1498
docs(client/windows): 更新 README — 真机构建验证 + 字体打包 + 安装包 + 踩坑
...
记录:已真机 build 通过;ATL 前置;LNK1327/mt.exe(MANIFESTUAC)与 fetch SHA pin 排错;
flutter build + ISCC 出安装包步骤;待人工验证清单(运行期连通/托盘/卸载)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 09:08:19 +08:00
wangjia
18a8c9024c
build(client/windows): Inno Setup 安装包脚本 + 简中语言包
...
- pangolin.iss:打包 Release 全量(exe + flutter 运行时 + sing-box.exe + wintun.dll
+ data/字体),装到 Program Files\Pangolin,开始菜单/桌面快捷方式,卸载清理
%LOCALAPPDATA%\Pangolin。
- 随仓库附带 ChineseSimplified.isl(本机 Inno Setup 未含官方简中包),.iss 相对引用,
安装包自带中文向导。
- 已在 Windows 真机 ISCC 编译通过 → Output\pangolin-setup-1.0.0.exe(24MB)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 09:06:44 +08:00
wangjia
3b16e8ff36
fix(client/windows): 关闭链接器 UAC 清单注入(/MANIFESTUAC:NO)
...
runner.exe.manifest 已声明 requireAdministrator;链接器默认还会注入 asInvoker 的
UAC 清单,两者 level 冲突 → mt.exe c1010001 → LINK LNK1327,Release 链接失败。
对 runner target 加 /MANIFESTUAC:NO,仅用 manifest 文件的 level。真机 build 通过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 09:03:16 +08:00
wangjia
cebc9a1c4f
fix(client/macos+server): 隧道运行时打通——DNS 劫持 + 死锁/空指针修复
...
接续 447f3f4(系统扩展可加载),修复"扩展能起但连上无法上网"的运行时问题,
现已在 macOS 15(cara)端到端连通:出口=节点 IP、国外站可达、DNS 经隧道解析。
服务端(clientconfig.go):
- route.rules 首条加 {"action":"hijack-dns","port":[53]}(排在 LAN 直连规则前)。
否则发往隧道 DNS(172.19.0.2:53)的查询被 172.16.0.0/12 吞去直连,域名解析失败。
sing-box 1.13 按端口劫持(protocol:dns 需先 sniff,不稳)。
客户端——保留三个真 bug 修复:
- startTunnel 的 libbox 启动移到后台队列:避免在 provider 队列同步阻塞,与
openTun→setTunnelNetworkSettings 回调三方死锁(隧道永远卡 connecting)。
- startOrReloadService(options:) 传非空 LibboxOverrideOptions():传 nil 致空指针 SIGSEGV。
- startDefaultInterfaceMonitor 阻塞到首个 path 更新再返回:修 "no available network interface"。
- 清除排障期临时诊断代码;CFBundleVersion 递增(sysextd 按版本去重)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-22 08:57:55 +08:00
wangjia
7e7854427c
docs(client): 修订 pangolin_theme 字体注释(改本地打包后过时描述)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 07:51:58 +08:00
wangjia
6fc032bac8
feat(client): 字体改本地打包(拉丁全量 + Noto Sans SC GB2312 子集)
...
生产 PangolinFonts.useBundled=true,离线可用,不再运行时拉 google_fonts;
中文经 fontFamilyFallback=[Noto Sans SC] 兜底,子集外字符再兜系统 CJK 字体。
- 拉丁:Sora/Manrope/JetBrains Mono 静态权重(复用 test/fonts)。
- 中文:Noto Sans SC 变量字体 instance 到 Regular + subset 到 GB2312 6763 字
(单权重,粗体引擎合成),client/fonts 合计约 3.4MB。
- tools/fonts/make-cjk-subset.sh 可复现生成(GB2312 字表无需联网)。
- 新增 test/unit/fonts_test.dart 锁定接线;golden 因 notdef 占位字形微调已更新。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 07:48:21 +08:00
wangjia
14498a3ccd
feat(client/desktop): 设定窗口默认 920x640 / 最小宽 720
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-21 23:02:43 +08:00
wangjia
447f3f494e
feat(client/macos): P1 原生隧道——PacketTunnel 系统扩展可加载 + libbox 运行
...
经长链路排查(同机对照可工作的 Tailscale),修复 macOS 系统扩展 realize
失败(OSSystemExtensionErrorDomain code=4)与 libbox 运行时崩溃,使内嵌
sing-box 的系统扩展能在 macOS 15 上激活并启动隧道。
系统扩展 realize(三个叠加根因):
- 扩展自包含:PacketTunnel 加 OTHER_LDFLAGS="" 切断对项目级 CocoaPods 链接
标志的继承(原会把 flutter_secure_storage 链进扩展);Libbox.xcframework
改纯 Link(静态),从 Embed Frameworks 移除冗余内嵌
- bundle 名 = 标识符:PRODUCT_NAME 设为 com.pangolin.pangolin.PacketTunnel
- 扩展 Info.plist 补 NSSystemExtensionUsageDescription(网络扩展类别强制要求)
- App Group 改 macOS 原生格式 BYL4KQHMTN.com.pangolin.pangolin;NEMachServiceName
以其为前缀;扩展补 network.client/server;get-task-allow=false + 签名加 --timestamp
- CFBundleVersion 随构建递增(否则 sysextd 视为同版本不更新)
libbox 运行时:
- startOrReloadService(options:) 传 nil 致空指针 SIGSEGV → 传 LibboxOverrideOptions()
- 默认接口监控阻塞到首个 path 更新再返回,修 "no available network interface"
配套:
- scripts/local_test.sh:build/sign/notarize/copy/run 一条龙(Developer ID + 公证)
- client/macos/sign_libbox.sh:构建期以 Developer ID 重签内嵌 Libbox
- VpnChannel:401 自动刷新 token、详尽 os_log;auth/api 统一走 kApiBaseUrl
- docs/macos-sysext-realize-troubleshooting.html:完整踩坑复盘
WIP / 临时(后续清理):
- 隧道运行时仍在排查:剥离远程 rule-set 后 sing-box 启动卡点未定位
- 含临时诊断代码:main.swift stderr 重定向、box.log 输出、rule-set 剥离、debug 日志
- api_config 仍指向联调节点,发版前还原
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-21 21:18:33 +08:00
wangjia
43b25c8aa0
feat: 国内流量直连分流(geoip-cn / geosite-cn)— #5
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
国内 IP/域名直连(不走隧道)→ 省流量 + 国内访问快;非国内走代理。
- clientconfig.go: BuildClientConfig 加 ClientConfigOpts{SplitCN,RulesBaseURL};
开启时 route 加 {rule_set:[geoip-cn,geosite-cn]→direct} + 定义 rule_set
(remote .srs,download_detour:direct 直连下载)
- rules.go: 控制面静态服务 /v1/rules/{name}.srs(白名单防穿越)——自托管避免
GitHub 在国内被墙的鸡生蛋;客户端反正连控制面,可达性有保证
- nodes.go ConnectNode: 读 ?split_cn → opts;NodeAPI 加 rulesBaseURL
(PANGOLIN_PUBLIC_URL);main.go 挂 /v1/rules 路由 + RulesHandler
- 客户端: connect_api splitCN→?split_cn=1;connection_provider 传 smartRoute 偏好
- deploy/single-node: 拉 geoip-cn/geosite-cn.srs 到 $DATA_DIR/rules +
设 PANGOLIN_PUBLIC_URL/PANGOLIN_RULES_DIR
验证:go test(splitCN 开/关渲染 + RulesHandler 白名单/404)+ flutter analyze +
shellcheck;不需要节点。订阅链接暂用默认 opts、DNS 分流为后续增强。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-19 20:34:00 +08:00
wangjia
2a4d6c9648
build(client/macos): Runner 开启 Hardened Runtime(公证前置)
...
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
PacketTunnel 已有 ENABLE_HARDENED_RUNTIME;给 Runner 的 Debug/Release 也补上。
Developer ID 分发 + 公证要求 Hardened Runtime。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-19 16:04:53 +08:00