import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../viewmodels/note_view_model.dart'; import 'note_editor_screen.dart'; import 'settings_screen.dart'; class NoteListScreen extends StatelessWidget { const NoteListScreen({super.key}); @override Widget build(BuildContext context) { final vm = context.watch(); return Scaffold( appBar: AppBar( title: const Text('Notes'), actions: [ IconButton( icon: const Icon(Icons.more_vert), onPressed: () => _showMenu(context, vm), ), ], ), body: _buildBody(context, vm), floatingActionButton: FloatingActionButton( onPressed: () => _createNote(context, vm), child: const Icon(Icons.add), ), ); } Widget _buildBody(BuildContext context, NoteViewModel vm) { if (vm.isLoading) { return const Center(child: CircularProgressIndicator()); } if (vm.error != null) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text(vm.error!, style: const TextStyle(color: Colors.red)), const SizedBox(height: 12), ElevatedButton( onPressed: vm.loadNotes, child: const Text('Retry'), ), ], ), ); } if (vm.notes.isEmpty) { return const Center( child: Text( 'No notes yet.\nTap + to create one.', textAlign: TextAlign.center, style: TextStyle(color: Colors.grey), ), ); } return ListView.separated( padding: const EdgeInsets.symmetric(vertical: 8), itemCount: vm.notes.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (context, index) { final note = vm.notes[index]; return ListTile( title: Text( note.title.isEmpty ? 'Untitled' : note.title, maxLines: 1, overflow: TextOverflow.ellipsis, ), subtitle: Text( note.content.isEmpty ? 'No content' : note.content, maxLines: 2, overflow: TextOverflow.ellipsis, ), trailing: Text( _formatDate(note.updatedAt), style: const TextStyle(fontSize: 12, color: Colors.grey), ), onTap: () => _openNote(context, note.id), onLongPress: () => _confirmDelete(context, vm, note.id), ); }, ); } Future _createNote(BuildContext context, NoteViewModel vm) async { final note = await vm.createNote(); if (context.mounted) { Navigator.push( context, MaterialPageRoute(builder: (_) => NoteEditorScreen(noteId: note.id)), ); } } void _openNote(BuildContext context, String noteId) { Navigator.push( context, MaterialPageRoute(builder: (_) => NoteEditorScreen(noteId: noteId)), ); } void _showMenu(BuildContext context, NoteViewModel vm) { showModalBottomSheet( context: context, builder: (_) => SafeArea( child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( leading: const Icon(Icons.settings_outlined), title: const Text('Backup settings'), onTap: () async { Navigator.pop(context); await _openSettings(context); }, ), ListTile( leading: const Icon(Icons.cloud_upload_outlined), title: const Text('Backup to server'), onTap: () { Navigator.pop(context); _runBackup(context, vm); }, ), ListTile( leading: const Icon(Icons.cloud_download_outlined), title: const Text('Restore from server'), onTap: () { Navigator.pop(context); _runRestore(context, vm); }, ), ], ), ), ); } Future _openSettings(BuildContext context) async { await Navigator.push( context, MaterialPageRoute(builder: (_) => const SettingsScreen()), ); // Settings saved — user needs to restart the app for sync to activate. // We'll improve this later when we add a proper service locator. if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Restart the app to apply backup settings.'), ), ); } } Future _runBackup(BuildContext context, NoteViewModel vm) async { await vm.backup(); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( vm.backupStatus == BackupStatus.success ? 'Backup successful' : 'Backup failed: ${vm.error}', ), ), ); } } Future _runRestore(BuildContext context, NoteViewModel vm) async { await vm.restore(); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( vm.backupStatus == BackupStatus.success ? 'Restore successful' : 'Restore failed: ${vm.error}', ), ), ); } } Future _confirmDelete( BuildContext context, NoteViewModel vm, String id) async { final confirmed = await showDialog( context: context, builder: (_) => AlertDialog( title: const Text('Delete note?'), content: const Text('This cannot be undone.'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('Delete', style: TextStyle(color: Colors.red)), ), ], ), ); if (confirmed == true) await vm.deleteNote(id); } String _formatDate(DateTime dt) { final now = DateTime.now(); if (dt.year == now.year && dt.month == now.month && dt.day == now.day) { return '${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}'; } return '${dt.day}/${dt.month}/${dt.year}'; } }