Commit Graph

14 Commits

Author SHA1 Message Date
wangjia d0d39c93f6 fix(client): 设备列表离线时间改用 last_seen「最后在线」(原 last_login 不准)
设备列表对离线设备显示「最后登录 X 前」,取的是 last_login(会话创建那一刻)。一直在线
的设备断开后会错显成登录时间(如 13 小时前),与实际「最后活跃」不符。改用 last_seen
(连接/用量上报/~15s 会话轮询都会刷新),标签相应改为「最后在线」/「Last online」。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:30:43 +08:00
wangjia 328d34a320 fix(client): 「我的」页加「设置」入口(我的设备下面)——iPad 竖屏/手机可达设置
iPad 竖屏回落 mobile 底 Tab(无侧栏),设置入口够不着。在账户页「我的设备」下面加一行
「设置」→ 下钻 SettingsScreen(复用桌面 SettingsPage + 移动返回栏)。与「联系我们」一致:
desktop/tablet 侧栏 + 账户页都可进。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 21:48:54 +08:00
wangjia d192d96d95 fix(client): 设备页每 15s 静默刷新列表,其他设备状态变化 ~15s 内可见
原设备列表打开时加载一次就不动(感觉十几分钟才同步)。加透传式轮询包装器
_DevicesAutoRefresh:在设备页期间每 15s 调 DevicesNotifier.refresh()(静默、不闪 loading、
失败保留旧列表)。配合服务端会话轮询刷 last_seen + 90s 窗口,其他设备上/下线 ~15s 内反映。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:05:32 +08:00
wangjia 6249d5b2ea refactor(client): 抽公用 PangolinFieldBox 统一输入框 + 根治填充两色接缝
根因:主题 inputDecorationTheme 设了 filled:true/fillColor:bg,自定义容器里嵌
TextField 时内层自铺 bg 底,与容器底色(搜索框 bgSubtle / 登录 surface)不一致 →
两端一色中间另一色接缝(节点搜索框最明显,登录/兑换框也有隐患)。

- kBareInput 加 filled:false:内层 TextField 不再自铺底,底色统一交给外层容器。
- 新增 widgets/pangolin_field.dart:PangolinFieldBox(圆角容器 + 底色 + 可选描边/
  聚焦光环 + 标签 + 前置图标 + 后置 widget)+ bareInputDecoration() 助手。
- 三处输入框统一改用:节点搜索框、登录/注册字段(_field)、兑换码输入框。
- 重生成 auth_login(dark/light)+ desktop_redeem golden(均人工核对外观正确)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 12:29:53 +08:00
wangjia 6788501e4a feat(client): 通用自适应弹出菜单(按屏幕位置上/下弹,不挡触发器)
新增 AdaptiveMenuButton:GlobalKey 量触发器矩形,据上下剩余空间决定向下/向上
弹出、右对齐裁剪到屏内,Overlay 全屏 barrier + 淡入缩放动画。「我的设备」⋯
菜单由 PopupMenuButton 换成它(重命名 + 强制退出/清除),修正小屏被遮挡问题。
devices_screen_test 同步改用 AdaptiveMenuButton 触发器断言。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 10:11:20 +08:00
wangjia 880fa32793 fix(devices): 本机也显示 ⋯ 菜单(只「重命名」)—— 修单设备无法改名(1.0.14)
ci-pangolin / Lint — shellcheck (push) Successful in 8s
ci-pangolin / OpenAPI Sync Check (push) Successful in 16s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 14s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 4s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 15s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m10s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
之前 ⋯ 菜单对本机隐藏,而用户唯一设备就是本机 → 根本点不到、改不了名。
改:本机显示 ⋯ 菜单但只含「重命名」(自我强制退出/清除无意义,仍只对他设备)。
测试:本机菜单只有重命名断言;全量 flutter 绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 09:49:09 +08:00
wangjia 315c343ed5 feat(devices): 设备默认名「平台简写·主机名」+ 支持重命名(1.0.13)
ci-pangolin / Lint — shellcheck (push) Successful in 7s
ci-pangolin / OpenAPI Sync Check (push) Successful in 17s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 6s
ci-pangolin / Flutter — analyze + test (push) Failing after 14s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 6s
ci-pangolin / Go — build + test (push) Successful in 11s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m3s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
① 默认名:DeviceIdentity 改「平台简写(Win/Mac/Linux/iOS/Andr)·主机名」,主机名截
   到 8、总长≈12(替代裸主机名,更短)。
② 重命名:新端点 POST /v1/me/devices/{uuid}/rename(Service.RenameDevice 校验归属+
   截 64);store.UpdateName;客户端 account_api.renameDevice + provider.rename +
   「我的设备」⋯ 菜单加「重命名」+ 输入弹窗;l10n(zh/en)。
③ 版本 1.0.13。
测试:server RenameDevice(归属/空名/404)+ 客户端 rename widget;全量 go/flutter 绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 09:12:36 +08:00
wangjia 58526b09e6 feat(client): P6 DevicesScreen 重做 + DevicePlatform 枚举
ci-pangolin / Lint — shellcheck (push) Successful in 7s
ci-pangolin / OpenAPI Sync Check (push) Successful in 19s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 7s
ci-pangolin / Flutter — analyze + test (push) Successful in 23s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 5s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 5s
ci-pangolin / Go — build + test (push) Successful in 9s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 14s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Failing after 4m12s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 15s
回应「状态码用枚举更好」:新增 DevicePlatform 枚举(线格式 fromWire 解析,
UI 只碰枚举,穷尽 switch),Device.platformKind getter;platform 图标按枚举 switch。
DevicesScreen 按 §7 视觉稿重做:行内 名称+「本机」标 / 平台·客户端版本·最后登录 /
在线绿点光晕·离线灰点 + 行尾 ⋯ 菜单(强制退出 / 清除登录信息·危险红)+ 危险二次
确认弹窗;本机行不显示 ⋯(不自我踢)。l10n 新增在线/离线/最后登录/从未登录/强制
退出/清除登录信息/取消 + 确认文案(中英);「当前设备」改「本机」。
新图标 moreVertical/trash/alertTriangle。localDeviceIdProvider 供本机判定。
测试:devices_screen widget 3 例(本机标+在线/离线+版本渲染 / ⋯菜单→强制退出→
确认→POST logout / 清除→DELETE);全量 flutter test 58 绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 06:10:37 +08:00
wangjia 25e8330e3b fix(client): 修聚焦时输入框橙边漏出错位/被裁(登录·注册·搜索·兑换码)
ci-pangolin / Lint — shellcheck (push) Successful in 10s
ci-pangolin / OpenAPI Sync Check (push) Successful in 31s
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Successful in 5s
ci-pangolin / Flutter — analyze + test (push) Successful in 24s
ci-pangolin / Portable SQL — 可移植性 (mysql/sqlite) (push) Successful in 6s
ci-pangolin / Codegen Drift — token 生成物未漂移 (push) Successful in 4s
ci-pangolin / Go — build + test (push) Successful in 10s
ci-pangolin / E2E Smoke — L4 进程级端到端 (push) Successful in 18s
ci-pangolin / Go — integration (mysql/redis testcontainers) (push) Successful in 4m13s
ci-pangolin / Golden — 视觉回归 (components + auth) (push) Successful in 14s
主题 inputDecorationTheme 设了 focusedBorder: OutlineInputBorder(accent),
而登录/注册的邮箱·密码·验证码、节点页搜索框、兑换码框这几处的 TextField
只写 border: InputBorder.none、未覆盖 focusedBorder —— 聚焦瞬间主题的橙色
OutlineInputBorder 漏到内层 TextField 上,与外层自定义容器圆角错位/左右被裁。

统一加共享 kBareInput 装饰(pangolin_theme.dart)关掉所有边框状态泄漏,
四处替换。只压边框、不动 filled/fillColor —— 未聚焦态外观与改前一致,
不动 golden;聚焦指示仍由外层容器自己的 Border.all(accent) 负责。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 22:21:50 +08:00
wangjia 93ec421c41 fix(plans): /v1/plans 500 修复 — plans 表无 name_zh/name_en 列
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
ListPlans 历来 SELECT name_zh/name_en,但 plans 表从未有这两列(各迁移/seed
均无)→ 该端点一直 500(无 live 测试故未暴露)。改为不查名称列(套餐名是 UI
文案,客户端 PlansScreen 按 code 取 l10n:free/pro/team)。价格等真实字段保留。

已在节点实测:/v1/plans 200,返回 free ¥0 / pro ¥25 / team ¥99。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 00:32:40 +08:00
wangjia f20eddad55 feat(client): P4 节点实测延迟/设备/套餐价/兑换/统计接真(#6 6D)
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
- latency_probe.dart:并行 TCP 握手实测各节点 per-client RTT(服务端无法代知)。
- nodes_provider:解析 /v1/nodes 的 host/port,后台测延迟回填 Node.ping;智能选择
  按实测最小;去掉 8 个伪造演示节点(空列表用中性占位,不再伪造服务器)。
- Node:+host/port/copyWith/pingLabel(未测显示 —);各端 ping 显示改 pingLabel。
- account_screens:PlansScreen 接 /v1/plans(价格 priceLabel + me 标当前档);
  DevicesScreen 接 /v1/me/devices + 移除 DELETE + last_seen;RedeemScreen 接
  /v1/redeem(成功刷新 me,失败显示后端文案)。
- stats_page:周柱接 me.weekly_gb,本月流量/时长接 usage(30),延迟用生效节点实测。
- 顺带补登记早前 log_time.dart 的删除(log.dart 重构遗漏 stage)。

flutter analyze 0 error;115 tests passed;受影响 4 golden 重生成。
本机设备高亮 + 真实 device id 随 P6(device_info_plus)落地。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 00:04:25 +08:00
wangjia fe16f89bc3 feat(client): 账户子页 desktop 内容区下钻(档1)
- desktop 上套餐选择/兑换购买/设备管理改为内容区下钻(侧栏保留、shell 顶栏带
  返回箭头),不再全屏 push 盖住侧栏;mobile/tablet 仍全屏 push
- _SubScaffold 加 embedded 参数(true 只返回内容),PlansScreen/DevicesScreen/
  RedeemScreen 透传;NavView 加 devices + kAccountSubViews 集合
- desktop_shell 渲染子页(embedded) + 顶栏 onBack→account;account_page 按
  formFactor 选下钻(切 navView)或 push
- desktop 整页 golden 补 套餐/兑换/设备 三子页(共 8 页)

测试: flutter test 84 通过(+3 子页 golden), analyze 0 error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 12:36:14 +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 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