From dd90c66f3528eec2a3db5167e2c35a2d61d11fb2 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Fri, 10 Apr 2026 11:20:05 +0800 Subject: [PATCH] feat: add settings sidebar back to chat action --- lib/app/app_shell_desktop.dart | 5 + lib/widgets/sidebar_navigation.dart | 4 + .../sidebar_navigation_task_section.dart | 100 +++++++++++++++--- ...debar_navigation_settings_back_to_chat.png | Bin 0 -> 21641 bytes ...ion_settings_back_to_chat_golden_test.dart | 50 +++++++++ test/widgets/sidebar_navigation_suite.dart | 53 ++++++++++ 6 files changed, 196 insertions(+), 16 deletions(-) create mode 100644 test/golden/goldens/sidebar_navigation_settings_back_to_chat.png create mode 100644 test/golden/sidebar_navigation_settings_back_to_chat_golden_test.dart diff --git a/lib/app/app_shell_desktop.dart b/lib/app/app_shell_desktop.dart index 3b4a08ec..57aa0cfc 100644 --- a/lib/app/app_shell_desktop.dart +++ b/lib/app/app_shell_desktop.dart @@ -379,6 +379,11 @@ class _AppShellState extends State { controller, visibleExecutionTargets, ), + onReturnToAssistant: () { + controller.navigateTo( + WorkspaceDestination.assistant, + ); + }, onSelectTask: (sessionKey) async { controller.navigateTo( WorkspaceDestination.assistant, diff --git a/lib/widgets/sidebar_navigation.dart b/lib/widgets/sidebar_navigation.dart index cce3d922..8b8c2fcb 100644 --- a/lib/widgets/sidebar_navigation.dart +++ b/lib/widgets/sidebar_navigation.dart @@ -46,6 +46,7 @@ class SidebarNavigation extends StatelessWidget { this.assistantSkillCount = 0, this.onRefreshTasks, this.onCreateTask, + this.onReturnToAssistant, this.onSelectTask, this.onArchiveTask, this.onRenameTask, @@ -81,6 +82,7 @@ class SidebarNavigation extends StatelessWidget { final int assistantSkillCount; final Future Function()? onRefreshTasks; final Future Function()? onCreateTask; + final VoidCallback? onReturnToAssistant; final Future Function(String sessionKey)? onSelectTask; final Future Function(String sessionKey)? onArchiveTask; final Future Function(String sessionKey, String title)? onRenameTask; @@ -123,6 +125,7 @@ class SidebarNavigation extends StatelessWidget { if (!isCollapsed) Expanded( child: SidebarTaskSection( + currentSection: currentSection, items: taskItems, visibleExecutionTargets: visibleExecutionTargets, skillCount: assistantSkillCount, @@ -130,6 +133,7 @@ class SidebarNavigation extends StatelessWidget { onCycleSidebarState: onCycleSidebarState, onRefreshTasks: onRefreshTasks, onCreateTask: onCreateTask, + onReturnToAssistant: onReturnToAssistant, onSelectTask: onSelectTask, onArchiveTask: onArchiveTask, onRenameTask: onRenameTask, diff --git a/lib/widgets/sidebar_navigation_task_section.dart b/lib/widgets/sidebar_navigation_task_section.dart index 1c9a1c34..9a954c38 100644 --- a/lib/widgets/sidebar_navigation_task_section.dart +++ b/lib/widgets/sidebar_navigation_task_section.dart @@ -25,6 +25,7 @@ class SidebarTaskItem { class SidebarTaskSection extends StatefulWidget { const SidebarTaskSection({ super.key, + required this.currentSection, required this.items, required this.visibleExecutionTargets, required this.skillCount, @@ -32,11 +33,13 @@ class SidebarTaskSection extends StatefulWidget { required this.onCycleSidebarState, this.onRefreshTasks, this.onCreateTask, + this.onReturnToAssistant, this.onSelectTask, this.onArchiveTask, this.onRenameTask, }); + final WorkspaceDestination currentSection; final List items; final List visibleExecutionTargets; final int skillCount; @@ -44,6 +47,7 @@ class SidebarTaskSection extends StatefulWidget { final VoidCallback onCycleSidebarState; final Future Function()? onRefreshTasks; final Future Function()? onCreateTask; + final VoidCallback? onReturnToAssistant; final Future Function(String sessionKey)? onSelectTask; final Future Function(String sessionKey)? onArchiveTask; final Future Function(String sessionKey, String title)? onRenameTask; @@ -157,22 +161,26 @@ class _SidebarTaskSectionState extends State { ), Padding( padding: const EdgeInsets.fromLTRB(4, 0, 4, 8), - child: FilledButton.tonalIcon( - key: const Key('workspace-sidebar-new-task-button'), - onPressed: widget.onCreateTask == null - ? null - : () async { - await widget.onCreateTask!(); - }, - icon: const Icon(Icons.edit_note_rounded), - label: Text(appText('新对话', 'New conversation')), - style: FilledButton.styleFrom( - minimumSize: const Size(0, 40), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - ), + child: widget.currentSection == WorkspaceDestination.settings + ? _SidebarBackToAssistantButton( + onPressed: widget.onReturnToAssistant, + ) + : FilledButton.tonalIcon( + key: const Key('workspace-sidebar-new-task-button'), + onPressed: widget.onCreateTask == null + ? null + : () async { + await widget.onCreateTask!(); + }, + icon: const Icon(Icons.edit_note_rounded), + label: Text(appText('新对话', 'New conversation')), + style: FilledButton.styleFrom( + minimumSize: const Size(0, 40), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + ), ), Padding( padding: const EdgeInsets.fromLTRB(4, 4, 4, 6), @@ -341,6 +349,66 @@ class _SidebarTaskSectionState extends State { } } +class _SidebarBackToAssistantButton extends StatelessWidget { + const _SidebarBackToAssistantButton({required this.onPressed}); + + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + final palette = context.palette; + final theme = Theme.of(context); + return Material( + color: Colors.transparent, + child: InkWell( + key: const Key('workspace-sidebar-back-to-chat-button'), + onTap: onPressed, + borderRadius: BorderRadius.circular(18), + child: Ink( + height: 56, + decoration: BoxDecoration( + color: palette.surfaceSecondary, + borderRadius: BorderRadius.circular(18), + border: Border.all(color: palette.strokeSoft), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + Container( + width: 36, + height: 36, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all(color: palette.textPrimary, width: 1.8), + ), + child: Icon( + Icons.arrow_back_rounded, + size: 24, + color: palette.textPrimary, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + appText('返回聊天', 'Back to chat'), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.w700, + color: palette.textPrimary, + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} + class _SidebarTaskGroup { const _SidebarTaskGroup({required this.executionTarget, required this.items}); diff --git a/test/golden/goldens/sidebar_navigation_settings_back_to_chat.png b/test/golden/goldens/sidebar_navigation_settings_back_to_chat.png new file mode 100644 index 0000000000000000000000000000000000000000..09afa0b4e86c051228d2a5476a788de7702aacbf GIT binary patch literal 21641 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 NSXd0smw)11&Ob$k(O3Wg literal 0 HcmV?d00001 diff --git a/test/golden/sidebar_navigation_settings_back_to_chat_golden_test.dart b/test/golden/sidebar_navigation_settings_back_to_chat_golden_test.dart new file mode 100644 index 00000000..b519f63b --- /dev/null +++ b/test/golden/sidebar_navigation_settings_back_to_chat_golden_test.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:golden_toolkit/golden_toolkit.dart'; +import 'package:xworkmate/i18n/app_language.dart'; +import 'package:xworkmate/models/app_models.dart'; +import 'package:xworkmate/widgets/sidebar_navigation.dart'; + +import '../helpers/golden_test_bootstrap.dart'; + +void main() { + setUpAll(() async { + await loadGoldenFonts(); + }); + + testGoldens('settings sidebar shows back to chat action', (tester) async { + await pumpGoldenApp( + tester, + Align( + alignment: Alignment.topLeft, + child: SizedBox( + width: 344, + height: 920, + child: SidebarNavigation( + currentSection: WorkspaceDestination.settings, + sidebarState: AppSidebarState.expanded, + appLanguage: AppLanguage.zh, + themeMode: ThemeMode.light, + onSectionChanged: (_) {}, + onToggleLanguage: () {}, + onCycleSidebarState: () {}, + onExpandFromCollapsed: () {}, + onOpenHome: () {}, + onOpenAccount: () {}, + onOpenThemeToggle: () {}, + onReturnToAssistant: () {}, + accountName: 'Tester', + accountSubtitle: 'Workspace', + onToggleAccountWorkspaceFollowed: () async {}, + ), + ), + ), + size: const Size(400, 960), + ); + + await screenMatchesGolden( + tester, + 'sidebar_navigation_settings_back_to_chat', + ); + }); +} diff --git a/test/widgets/sidebar_navigation_suite.dart b/test/widgets/sidebar_navigation_suite.dart index 14dbffbe..74c943a8 100644 --- a/test/widgets/sidebar_navigation_suite.dart +++ b/test/widgets/sidebar_navigation_suite.dart @@ -256,6 +256,10 @@ void main() { find.byKey(const Key('workspace-sidebar-new-task-button')), findsOneWidget, ); + expect( + find.byKey(const Key('workspace-sidebar-back-to-chat-button')), + findsNothing, + ); expect(find.text('任务列表'), findsOneWidget); expect(find.text('自动化'), findsNothing); expect(find.text('MCP Hub'), findsNothing); @@ -269,6 +273,55 @@ void main() { }, ); + testWidgets('SidebarNavigation shows back to chat action on settings page', ( + WidgetTester tester, + ) async { + var returnedToAssistant = 0; + + await tester.pumpWidget( + MaterialApp( + theme: AppTheme.light(), + home: Scaffold( + body: SidebarNavigation( + currentSection: WorkspaceDestination.settings, + sidebarState: AppSidebarState.expanded, + appLanguage: AppLanguage.zh, + themeMode: ThemeMode.light, + onSectionChanged: (_) {}, + onToggleLanguage: () {}, + onCycleSidebarState: () {}, + onExpandFromCollapsed: () {}, + onOpenHome: () {}, + onOpenAccount: () {}, + onOpenThemeToggle: () {}, + accountName: 'Tester', + accountSubtitle: 'Workspace', + onToggleAccountWorkspaceFollowed: () async {}, + onReturnToAssistant: () => returnedToAssistant++, + ), + ), + ), + ); + await tester.pumpAndSettle(); + + expect( + find.byKey(const Key('workspace-sidebar-back-to-chat-button')), + findsOneWidget, + ); + expect(find.text('返回聊天'), findsOneWidget); + expect( + find.byKey(const Key('workspace-sidebar-new-task-button')), + findsNothing, + ); + + await tester.tap( + find.byKey(const Key('workspace-sidebar-back-to-chat-button')), + ); + await tester.pumpAndSettle(); + + expect(returnedToAssistant, 1); + }); + testWidgets( 'SidebarNavigation merges local and remote tasks into one gateway group', (WidgetTester tester) async {