From 880fa32793b85051d9fb5df53367ac7c4053ae46 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Mon, 29 Jun 2026 09:49:09 +0800 Subject: [PATCH] =?UTF-8?q?fix(devices):=20=E6=9C=AC=E6=9C=BA=E4=B9=9F?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=20=E2=8B=AF=20=E8=8F=9C=E5=8D=95(=E5=8F=AA?= =?UTF-8?q?=E3=80=8C=E9=87=8D=E5=91=BD=E5=90=8D=E3=80=8D)=E2=80=94?= =?UTF-8?q?=E2=80=94=20=E4=BF=AE=E5=8D=95=E8=AE=BE=E5=A4=87=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=94=B9=E5=90=8D(1.0.14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前 ⋯ 菜单对本机隐藏,而用户唯一设备就是本机 → 根本点不到、改不了名。 改:本机显示 ⋯ 菜单但只含「重命名」(自我强制退出/清除无意义,仍只对他设备)。 测试:本机菜单只有重命名断言;全量 flutter 绿。 Co-Authored-By: Claude Opus 4.8 --- client/lib/widgets/account_screens.dart | 23 ++++++++++++--------- client/pubspec.yaml | 2 +- client/test/widget/devices_screen_test.dart | 21 +++++++++++++------ client/windows/installer/pangolin.iss | 2 +- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/client/lib/widgets/account_screens.dart b/client/lib/widgets/account_screens.dart index ae9ca66..db444f7 100644 --- a/client/lib/widgets/account_screens.dart +++ b/client/lib/widgets/account_screens.dart @@ -188,7 +188,7 @@ class DevicesScreen extends ConsumerWidget { ), const SizedBox(width: 8), _statusDot(c, d.online), - if (!isLocal) _menu(context, ref, c, d) else const SizedBox(width: 8), + _menu(context, ref, c, d, isLocal), ]), ); } @@ -214,7 +214,8 @@ class DevicesScreen extends ConsumerWidget { ]); } - Widget _menu(BuildContext context, WidgetRef ref, PangolinScheme c, Device d) => PopupMenuButton( + // 本机:只给「重命名」(自我踢下线/清除没意义);其他设备:重命名+强制退出+清除。 + Widget _menu(BuildContext context, WidgetRef ref, PangolinScheme c, Device d, bool isLocal) => PopupMenuButton( icon: Icon(PangolinIcons.moreVertical, size: 18, color: c.fg3), color: c.surface, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(PangolinRadius.md), side: BorderSide(color: c.border)), @@ -223,14 +224,16 @@ class DevicesScreen extends ConsumerWidget { Icon(PangolinIcons.edit, size: 16, color: c.fg2), const SizedBox(width: 10), Text(t.devRename, style: PangolinText.sm.copyWith(color: c.fg1)), ])), - PopupMenuItem(value: 'logout', child: Row(children: [ - Icon(PangolinIcons.logOut, size: 16, color: c.fg2), const SizedBox(width: 10), - Text(t.devForceLogout, style: PangolinText.sm.copyWith(color: c.fg1)), - ])), - PopupMenuItem(value: 'clear', child: Row(children: [ - Icon(PangolinIcons.trash, size: 16, color: c.danger), const SizedBox(width: 10), - Text(t.devClearLogin, style: PangolinText.sm.copyWith(color: c.danger)), - ])), + if (!isLocal) ...[ + PopupMenuItem(value: 'logout', child: Row(children: [ + Icon(PangolinIcons.logOut, size: 16, color: c.fg2), const SizedBox(width: 10), + Text(t.devForceLogout, style: PangolinText.sm.copyWith(color: c.fg1)), + ])), + PopupMenuItem(value: 'clear', child: Row(children: [ + Icon(PangolinIcons.trash, size: 16, color: c.danger), const SizedBox(width: 10), + Text(t.devClearLogin, style: PangolinText.sm.copyWith(color: c.danger)), + ])), + ], ], onSelected: (v) async { if (v == 'rename') { diff --git a/client/pubspec.yaml b/client/pubspec.yaml index d32ad8e..7be200f 100644 --- a/client/pubspec.yaml +++ b/client/pubspec.yaml @@ -1,7 +1,7 @@ name: pangolin_vpn description: 穿山甲 · Pangolin — 极简、稳定、跨平台网络加速客户端。 publish_to: "none" -version: 1.0.13+14 +version: 1.0.14+15 environment: sdk: ^3.5.0 diff --git a/client/test/widget/devices_screen_test.dart b/client/test/widget/devices_screen_test.dart index 1b3b442..97541de 100644 --- a/client/test/widget/devices_screen_test.dart +++ b/client/test/widget/devices_screen_test.dart @@ -92,12 +92,21 @@ void main() { expect(find.text('iPhone 15'), findsOneWidget); }); + testWidgets('本机 ⋯ 菜单只有「重命名」,无强制退出/清除', (tester) async { + await pump(tester); + // 第一个菜单 = 本机(MacBook Pro)。 + await tester.tap(find.byType(PopupMenuButton).first); + await tester.pumpAndSettle(); + expect(find.text(t.devRename), findsOneWidget); + expect(find.text(t.devForceLogout), findsNothing); + expect(find.text(t.devClearLogin), findsNothing); + }); + testWidgets('非本机行 ⋯ 菜单 → 强制退出 → 确认 → 调 logout 接口', (tester) async { await pump(tester); - // 仅非本机(iPhone)有 ⋯ 菜单。 - final menu = find.byType(PopupMenuButton); - expect(menu, findsOneWidget); - await tester.tap(menu); + // 本机+手机各一个菜单;手机(最后一个)才有强制退出/清除。 + expect(find.byType(PopupMenuButton), findsNWidgets(2)); + await tester.tap(find.byType(PopupMenuButton).last); await tester.pumpAndSettle(); expect(find.text(t.devForceLogout), findsOneWidget); expect(find.text(t.devClearLogin), findsOneWidget); @@ -115,7 +124,7 @@ void main() { testWidgets('清除登录信息 → 确认 → 调 DELETE 接口', (tester) async { await pump(tester); - await tester.tap(find.byType(PopupMenuButton)); + await tester.tap(find.byType(PopupMenuButton).last); await tester.pumpAndSettle(); await tester.tap(find.text(t.devClearLogin)); await tester.pumpAndSettle(); @@ -127,7 +136,7 @@ void main() { testWidgets('重命名 → 输入新名 → 保存 → 调 rename 接口', (tester) async { await pump(tester); - await tester.tap(find.byType(PopupMenuButton)); + await tester.tap(find.byType(PopupMenuButton).last); await tester.pumpAndSettle(); await tester.tap(find.text(t.devRename)); await tester.pumpAndSettle(); diff --git a/client/windows/installer/pangolin.iss b/client/windows/installer/pangolin.iss index f5d66f6..797df55 100644 --- a/client/windows/installer/pangolin.iss +++ b/client/windows/installer/pangolin.iss @@ -3,7 +3,7 @@ ; 前置: 先在 client/ 跑 `flutter build windows`(Release),产物在 ; ..\..\build\windows\x64\runner\Release #define MyAppName "穿山甲 Pangolin" -#define MyAppVersion "1.0.13" +#define MyAppVersion "1.0.14" #define MyAppPublisher "Pangolin" #define MyAppExeName "pangolin_vpn.exe" #define BuildDir "..\..\build\windows\x64\runner\Release"