diff --git a/src/frontend/lib/providers/note_editor_provider.dart b/src/frontend/lib/providers/note_editor_provider.dart index 7fb45666..16ff3e84 100644 --- a/src/frontend/lib/providers/note_editor_provider.dart +++ b/src/frontend/lib/providers/note_editor_provider.dart @@ -1333,6 +1333,16 @@ class NoteEditorProvider with ChangeNotifier implements NoteEditorViewModel { return blockId; } + @override + void redo() { + _documentBuilder.redo(); + } + + @override + void undo() { + _documentBuilder.undo(); + } + @override void resetState() { _logger.info('Resetting NoteEditorProvider state'); diff --git a/src/frontend/lib/screens/note_editor_screen.dart b/src/frontend/lib/screens/note_editor_screen.dart index ac849943..52d05d8f 100644 --- a/src/frontend/lib/screens/note_editor_screen.dart +++ b/src/frontend/lib/screens/note_editor_screen.dart @@ -212,11 +212,20 @@ class _NoteEditorScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - // Add AppBarCommon with ONLY theme switching functionality appBar: AppBarCommon( - title: '', // Empty title as we have our own title field - showBackButton: false, // No back button in app bar + title: '', + showBackButton: true, actions: [ + IconButton( + icon: const Icon(Icons.undo_outlined), + tooltip: 'Undo last edit', + onPressed: () => _noteEditorViewModel.undo(), + ), + IconButton( + icon: const Icon(Icons.redo_outlined), + tooltip: 'Redo last edit', + onPressed: () => _noteEditorViewModel.redo(), + ), IconButton( icon: const Icon(Icons.refresh_outlined), tooltip: 'Refresh note content', diff --git a/src/frontend/lib/screens/user_profile_screen.dart b/src/frontend/lib/screens/user_profile_screen.dart index 10944a80..58a4a53d 100644 --- a/src/frontend/lib/screens/user_profile_screen.dart +++ b/src/frontend/lib/screens/user_profile_screen.dart @@ -16,7 +16,6 @@ class UserProfileScreen extends StatefulWidget { class _UserProfileScreenState extends State { final Logger _logger = Logger('UserProfileScreen'); - final GlobalKey _scaffoldKey = GlobalKey(); final _formKey = GlobalKey(); final _passwordFormKey = GlobalKey(); @@ -176,12 +175,10 @@ class _UserProfileScreenState extends State { final theme = Theme.of(context); return Scaffold( - key: _scaffoldKey, appBar: AppBarCommon( title: 'Profile', onBackPressed: () => context.go('/'), showBackButton: true, - onMenuPressed: () => _scaffoldKey.currentState?.openDrawer(), actions: const [ThemeSwitcher()], ), drawer: const SidebarDrawer(), diff --git a/src/frontend/lib/utils/document_builder.dart b/src/frontend/lib/utils/document_builder.dart index ea55b63a..63b1c2c4 100644 --- a/src/frontend/lib/utils/document_builder.dart +++ b/src/frontend/lib/utils/document_builder.dart @@ -96,8 +96,11 @@ class DocumentBuilder { _composer.selectionNotifier.addListener(_updateToolbarDisplay); // Create editor with our document and composer - _editor = - createDefaultDocumentEditor(document: _document, composer: _composer); + _editor = createDefaultDocumentEditor( + document: _document, + composer: _composer, + isHistoryEnabled: true, + ); // Add action tags listener for inline commands _inlineCommandsPlugin = ActionTagsPlugin(); @@ -1318,6 +1321,14 @@ class DocumentBuilder { return document; } + void redo() { + _editor.redo(); + } + + void undo() { + _editor.undo(); + } + // Create Super Editor with configured components for SuperEditor 0.3.0 Widget createSuperEditor({ required bool readOnly, diff --git a/src/frontend/lib/viewmodel/note_editor_viewmodel.dart b/src/frontend/lib/viewmodel/note_editor_viewmodel.dart index f2721320..2c7d808f 100644 --- a/src/frontend/lib/viewmodel/note_editor_viewmodel.dart +++ b/src/frontend/lib/viewmodel/note_editor_viewmodel.dart @@ -67,6 +67,9 @@ abstract class NoteEditorViewModel extends BaseViewModel { void setFocusToBlock(String blockId); String? consumeFocusRequest(); + void redo() {} + void undo() {} + // User modified blocks tracking Set get userModifiedBlockIds; diff --git a/src/frontend/lib/widgets/app_bar_common.dart b/src/frontend/lib/widgets/app_bar_common.dart index 157772d8..cb67313d 100644 --- a/src/frontend/lib/widgets/app_bar_common.dart +++ b/src/frontend/lib/widgets/app_bar_common.dart @@ -4,7 +4,6 @@ import 'package:go_router/go_router.dart'; class AppBarCommon extends StatelessWidget implements PreferredSizeWidget { final String? title; final List? actions; - final Widget? leading; final bool showBackButton; final VoidCallback? onBackPressed; final VoidCallback? onMenuPressed; @@ -13,12 +12,12 @@ class AppBarCommon extends StatelessWidget implements PreferredSizeWidget { final Color? backgroundColor; final Color? foregroundColor; final bool showProfileButton; - + final bool showUndoRedoButtons; + const AppBarCommon({ Key? key, this.title, this.actions, - this.leading, this.showBackButton = true, this.onBackPressed, this.onMenuPressed, @@ -27,31 +26,31 @@ class AppBarCommon extends StatelessWidget implements PreferredSizeWidget { this.backgroundColor, this.foregroundColor, this.showProfileButton = true, + this.showUndoRedoButtons = false, }) : super(key: key); @override Widget build(BuildContext context) { - Widget? leadingWidget = leading; + List? leadingWidgets = []; - // If leading is not provided and showBackButton is true, show back button - if (leading == null) { - if (showBackButton) { - leadingWidget = IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: onBackPressed ?? () => Navigator.of(context).pop(), - ); - } else if (onMenuPressed != null) { - // Show menu button if onMenuPressed callback is provided - leadingWidget = IconButton( - icon: const Icon(Icons.menu), - onPressed: onMenuPressed, - ); - } + if (onMenuPressed != null) { + // Show menu button if onMenuPressed callback is provided + leadingWidgets.add(IconButton( + icon: const Icon(Icons.menu), + onPressed: onMenuPressed, + )); } + if (showBackButton) { + leadingWidgets.add(IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: onBackPressed ?? () => Navigator.of(context).pop(), + )); + } + // Create a copy of the actions list to modify if needed List? actionWidgets = actions != null ? List.from(actions!) : []; - + // Add profile button to actions if showProfileButton is true if (showProfileButton) { actionWidgets.add( @@ -67,13 +66,18 @@ class AppBarCommon extends StatelessWidget implements PreferredSizeWidget { } return AppBar( + leading: Builder(builder: (context) => Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: leadingWidgets, + ), + ), + actions: actionWidgets, title: title != null ? Text(title!) : null, centerTitle: centerTitle, elevation: elevation, backgroundColor: backgroundColor, foregroundColor: foregroundColor, - leading: leadingWidget, - actions: actionWidgets, ); }