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
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
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
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
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
e10f214dee
feat(client): 系统托盘常驻 + 关闭窗口隐藏到托盘(桌面端)
...
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
- system_tray.dart:TrayService 用 tray_manager + window_manager。setPreventClose
拦截关闭 → 隐藏到托盘(常驻保持隧道);托盘图标点击/「显示主界面」重新显示,
「退出」真正退出。
- main() 改 async:桌面端 runApp 前 init 托盘;移动端/web 跳过(isDesktop 守卫)。
- 托盘图标复用 app_icon_32.png → assets/tray_icon.png。
- 新依赖:tray_manager / window_manager。
flutter analyze 0 error;114 tests passed。托盘为运行时/原生功能,需 release .app 验证。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-19 06:31:40 +08:00
wangjia
6ee7114ff8
feat(client): P6 设置项落地真实行为( #6 6F,本地部分)
...
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
- settings_provider:三开关 shared_preferences 持久化 + 副作用落地:
killSwitch→VpnBridge.setKillSwitch(on:);autostart→桌面原生登录项
(launch_at_startup);smartRoute 持久化为偏好(连接时作 split_cn,见 #5 )。
- settings_page → ConsumerWidget,开关接 settingsProvider;协议标签
WireGuard→REALITY/Hysteria2;版本号取 pubspec(package_info_plus)。
- 新依赖:shared_preferences / package_info_plus / launch_at_startup。
flutter analyze 0 error;114 tests passed;settings golden 重生成。
待办:#5 智能分流的 server 端 geoip-cn 下发 + autostart 真机验证(需 release .app)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-19 00:13:41 +08:00
wangjia
4dc4127252
feat(client): 三端布局架构 + macOS 桌面端 + app 图标
...
三端布局(mobile/tablet/desktop):
- core/responsive/form_factor.dart 形态判定 + shell/ 分发器(home_shell→desktop/mobile)
- desktop_shell 对照 ui_kits/desktop/dapp.jsx: 侧栏204·6项 + 套餐卡 + 顶栏(标题/状态/主题切换) + 连接页居中单列
- 新增组件 nav_sidebar / plan_badge_card / content_top_bar / bottom_tab_bar
- 新增一级页 contact_page / settings_page; navigation_provider(NavView)
- 删除旧 widgets/home_shell.dart(逻辑迁入 shell/)
macOS 桌面端:
- 窗口默认 920×600 + 最小 720×560(MainFlutterWindow.swift)
- app 图标替换为穿山甲(AppIcon.appiconset 全套, 由 app-icon.svg 渲染)
其余(本会话):
- Phase2 接线: auth_api/token_store/auth_provider/vpn_bridge_provider + 真实 connection/nodes
- lucide_icons 兼容补丁(packages/lucide_icons_patched) 修复 IconData final 报错
- 测试修复: connect_passthrough(UTF-8) / harness / golden @Skip
- l10n 新增 settingsTitle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-16 09:23:20 +08:00
wangjia
bf1717a369
merge: 控制面联调 M6 [tsk_nuoKSM4Vt-zK]
...
# Conflicts:
# .gitignore
# client/lib/widgets/home_shell.dart
# client/lib/widgets/server_tile.dart
# client/pubspec.yaml
2026-06-13 17:32:26 +08:00
wangjia
f97ae8186b
feat(client): Flutter 逐屏还原 + iPad ≥900 断点 (tsk_gpPXi-icyeOE)
...
对照 design/ui_kits mobile+tablet 原型逐屏补齐 Flutter 客户端:
- l10n 资源层(strings_zh/en,单显)+ Riverpod 状态层(连接状态机/免费额度/
节点选择/语言/主题),UI 与数据解耦,mock 数据接 API 不动 UI。
- 连接键严格三态(off 虚线轨道环 / connecting 旋转弧 / on 满环+计时+光晕),
状态来自 connectionProvider,点击只派发事件——禁止乐观显示。
- 节点页置顶「智能选择」推荐卡(clay 渐变 zap + 推荐胶囊,默认选中);
免费额度卡(剩余分钟+进度条 ≤3 分钟切 warning + 看广告解锁变绿)。
- Tab 左右滑动切换(手势竞技场仲裁,子页滚动不误触发,200ms 方向感知滑入)。
- iPad/宽屏 ≥900 LayoutBuilder 切侧栏分栏(导航行高 ≥48,连接页双栏/节点双列网格),
复用同一批原子组件,不 fork 页面。
- 语义 token 零硬编码;文案全部走 l10n;套餐数字对齐 §7;无支付表单/emoji 国旗。
- CI 红线词扫描扩展到 client/lib;新增 Flutter analyze+test CI 任务。
- 测试:连接状态机/额度/节点单测、连接键三态与卡片组件测试、
golden(连接键三态/推荐卡/额度卡 × 明暗)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 14:32:36 +08:00
wangjia
bd8f974a25
feat(M6): 控制面联调 — mock connect server + 客户端 ConnectApi 透传
...
tsk_nuoKSM4Vt-zK
## 服务端(server/cmd/mockserver)
- `main.go`(79 行):独立 mock HTTP server,实现 POST /v1/nodes/:id/connect
- 路径/请求体/响应体字段名与 §3.1 契约逐字一致
- Bearer token 鉴权(-token 参数,空值跳过,不入库)
- 缺少 device_id → 400;未授权 → 401;非 POST → 405
- 返回完整 sing-box config JSON(tun + REALITY/Hy2 outbound + urltest + route/dns)
- 注:mock 联调;待 #5/#6 真实 connect 接口就绪后替换
- `main_test.go`:6 项单测,覆盖 §3.1 结构校验、auth、method、path
## 客户端(client/)
- `lib/services/connect_api.dart`:ConnectApi 类
- fetchConfig(nodeId, deviceId) → 原始响应体字符串(不做任何修改)
- 错误路径:HTTP 非 200 / 超时 / 非法 JSON → ConnectApiException(含双语 message)
- `lib/services/vpn_bridge.dart`:VpnBridge stub(M6 联调,libbox 绑定待 11C)
- start(configJson) 原样存储,不修改;stop() 清空
- `lib/widgets/home_shell.dart`:_toggle/_pick 替换为真实 API 流程
- ConnectApi.fetchConfig → VpnBridge.start(透传,无中间变换)
- 错误路径:ConnectApiException → SnackBar,status 回 off,无残留半开隧道
- API URL/token/deviceId 由 --dart-define 注入(不入库)
- `lib/widgets/server_tile.dart`:ServerInfo 新增 nodeId 字段
- `pubspec.yaml`:新增 http: ^1.2.1 依赖
- `test/connect_passthrough_test.dart`:4 项透传断言单测
- 核心:fetchConfig 返回字符串 === VpnBridge.start 接收字符串(逐字节相等)
- 空格/格式原样保留(不经 jsonEncode 重序列化)
- HTTP 错误、非法 JSON 错误路径覆盖
## 运行方式(M6 联调)
```
# 启动 mock server(无 auth)
go run ./server/cmd/mockserver -addr :8081
# 启动客户端(指向 mock server)
flutter run \
--dart-define=PANGOLIN_API_URL=http://localhost:8081 \
--dart-define=PANGOLIN_API_TOKEN=dev-mock-token \
--dart-define=PANGOLIN_DEVICE_ID=demo-device-001
```
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-13 14:16:29 +08:00
wangjia
526e7f2f33
feat(tsk_iRa5iBC4v7Tu): Flutter 客户端工程搭建(演示态)
...
基于 design/flutter/ 起步包在 client/ 下建立 Flutter 工程:
- pubspec.yaml:flutter_svg / lucide_icons / google_fonts 依赖;
SVG 资产注册;字体由 google_fonts 运行时加载,无需本地 ttf
- lib/pangolin_theme.dart:完整设计令牌(色阶 / 间距 / 圆角 /
动效 / 文字阶),PangolinText 改用 GoogleFonts getter,
PangolinTheme.light / .dark 开箱即用
- lib/main.dart:runApp + 明暗主题 + 登录 → 引导 → 主框架 RootFlow
- lib/widgets/:全套组件雏形
pangolin_icons Lucide 图标映射
pangolin_button 胶囊按钮四态
country_code 国家码块 + 信号条
status_pill 色点胶囊
connect_button 核心连接键三态(off/connecting/on + 动画)
server_tile 服务器列表行
plan_card 套餐卡(专业版渐变高亮)
auth_screen 登录 / 注册(邮箱验证码 + 设密码)
onboarding_screen 首次引导 PageView(3 屏可滑动 + 进度点)
home_shell 底部 4 Tab(连接/节点/统计/账户 + 状态机)
account_screens 套餐选择 / 设备管理 / 兑换 / 联系我们
pangolin_logo PangolinMark / BrandLockup / AppIcon(SVG)
- assets/:logo-mark / logo-mark-white / logo-wordmark / app-icon(SVG)
- android/:Kotlin 主 Activity + Manifest + Gradle 配置
- ios/:Runner.xcodeproj + xcscheme + Podfile + AppDelegate + storyboard
运行方式(cd client/):
flutter pub get && flutter run
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-13 02:15:42 +08:00