Skip to content

Commit

Permalink
[194] feat: add archives page
Browse files Browse the repository at this point in the history
  • Loading branch information
maelchiotti committed Feb 14, 2025
1 parent ded6b30 commit e7e4bb8
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 105 deletions.
6 changes: 1 addition & 5 deletions lib/common/actions/notes/archive.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ import 'select.dart';
///
/// First, asks for a confirmation if needed.
/// Finally, pops the route if the note was archived from the editor page.
Future<bool> archiveNote(BuildContext context, WidgetRef ref, {Note? note, bool pop = false}) async {
if (note == null) {
return false;
}

Future<bool> archiveNote(BuildContext context, WidgetRef ref, {required Note note, bool pop = false}) async {
if (!await askForConfirmation(
context,
l.dialog_archive,
Expand Down
6 changes: 1 addition & 5 deletions lib/common/actions/notes/unarchive.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ import 'select.dart';
///
/// First, asks for a confirmation if needed.
/// Finally, pops the route if the note was unarchived from the editor page.
Future<bool> unarchiveNote(BuildContext context, WidgetRef ref, {Note? note, bool pop = false}) async {
if (note == null) {
return false;
}

Future<bool> unarchiveNote(BuildContext context, WidgetRef ref, {required Note note, bool pop = false}) async {
if (!await askForConfirmation(
context,
l.dialog_unarchive,
Expand Down
5 changes: 3 additions & 2 deletions lib/common/navigation/app_bars/editor_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import '../../constants/constants.dart';
import '../../constants/paddings.dart';
import '../../preferences/preference_key.dart';
import '../../utils.dart';
import '../../widgets/placeholders/empty_placeholder.dart';
import '../enums/archives_menu_option.dart';
import '../enums/bin_menu_option.dart';
import '../enums/editor_menu_option.dart';
Expand Down Expand Up @@ -58,7 +59,7 @@ class _BackAppBarState extends ConsumerState<EditorAppBar> {
case EditorMenuOption.share:
await shareNote(note: note);
case EditorMenuOption.archive:
await archiveNote(context, ref);
await archiveNote(context, ref, note: note);
case EditorMenuOption.delete:
await deleteNote(context, ref, note: note, pop: true);
case EditorMenuOption.about:
Expand Down Expand Up @@ -145,7 +146,7 @@ class _BackAppBarState extends ConsumerState<EditorAppBar> {
final note = currentNoteNotifier.value;

if (note == null) {
return SizedBox.shrink();
return EmptyPlaceholder();
}

final editorController = fleatherControllerNotifier.value;
Expand Down
4 changes: 2 additions & 2 deletions lib/common/navigation/app_bars/notes_selection_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ class NotesSelectionAppBar extends ConsumerWidget {
case NotesMenuOption.togglePin:
await togglePinNotes(context, ref, notes: notes);
case NotesMenuOption.addLabels:
addLabels(context, ref, notes: notes);
await addLabels(context, ref, notes: notes);
case NotesMenuOption.archive:
await archiveNote(context, ref);
await archiveNotes(context, ref, notes: notes);
case NotesMenuOption.delete:
await deleteNotes(context, ref, notes: notes);
}
Expand Down
25 changes: 18 additions & 7 deletions lib/common/navigation/side_navigation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:material_symbols_icons/material_symbols_icons.dart';
import '../../models/label/label.dart';
import '../../navigation/navigation_routes.dart';
import '../../navigation/navigator_utils.dart';
import '../../pages/archives/archives_page.dart';
import '../../pages/bin/bin_page.dart';
import '../../pages/labels/labels_page.dart';
import '../../pages/notes/notes_page.dart';
Expand Down Expand Up @@ -63,10 +64,12 @@ class _SideNavigationState extends ConsumerState<SideNavigation> {
index = labels.indexOf(label) + 1;
} else if (route == NavigationRoute.manageLabels.name) {
index = labels.length + 1;
} else if (route == NavigationRoute.bin.name) {
} else if (route == NavigationRoute.archives.name) {
index = labels.length + 2;
} else if (route == NavigationRoute.settings.name) {
} else if (route == NavigationRoute.bin.name) {
index = labels.length + 3;
} else if (route == NavigationRoute.settings.name) {
index = labels.length + 4;
} else {
throw Exception('Unknown route while setting the index of the navigation drawer: $route');
}
Expand All @@ -76,10 +79,12 @@ class _SideNavigationState extends ConsumerState<SideNavigation> {
else {
if (route == '/' || route == NavigationRoute.notes.name) {
index = 0;
} else if (route == NavigationRoute.bin.name) {
} else if (route == NavigationRoute.archives.name) {
index = 1;
} else if (route == NavigationRoute.settings.name) {
} else if (route == NavigationRoute.bin.name) {
index = 2;
} else if (route == NavigationRoute.settings.name) {
index = 3;
} else {
throw Exception('Unknown route while setting the index of the navigation drawer: $route');
}
Expand Down Expand Up @@ -134,8 +139,10 @@ class _SideNavigationState extends ConsumerState<SideNavigation> {
} else if (index == labels.length + 1) {
NavigationRoute.manageLabels.pushOrGo(context, isHomeRoute(route), LabelsPage());
} else if (index == labels.length + 2) {
NavigationRoute.bin.pushOrGo(context, isHomeRoute(route), BinPage());
NavigationRoute.archives.pushOrGo(context, isHomeRoute(route), ArchivesPage());
} else if (index == labels.length + 3) {
NavigationRoute.bin.pushOrGo(context, isHomeRoute(route), BinPage());
} else if (index == labels.length + 4) {
NavigationRoute.settings.pushOrGo(context, isHomeRoute(route), SettingsMainPage());
} else {
throw Exception('Invalid drawer index while navigating to a new route: $index');
Expand Down Expand Up @@ -219,12 +226,16 @@ class _SideNavigationState extends ConsumerState<SideNavigation> {
Divider(indent: 24, endIndent: 24),
],
NavigationDrawerDestination(
key: Keys.drawerNotesTab,
icon: const Icon(Icons.archive_outlined),
selectedIcon: const Icon(Icons.archive),
label: Text(l.navigation_archives),
),
NavigationDrawerDestination(
icon: const Icon(Icons.delete_outline),
selectedIcon: const Icon(Icons.delete),
label: Text(l.navigation_bin),
),
// Divider(indent: 24, endIndent: 24),
Divider(indent: 24, endIndent: 24),
NavigationDrawerDestination(
key: Keys.drawerSettingsTab,
icon: const Icon(Icons.settings_outlined),
Expand Down
2 changes: 1 addition & 1 deletion lib/common/widgets/placeholders/empty_placeholder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class EmptyPlaceholder extends StatelessWidget {
/// Empty archived notes list.
EmptyPlaceholder.archived({super.key})
: icon = Icons.archive_outlined,
text = l.placeholder_bin;
text = l.placeholder_archives;

/// Empty deleted notes list.
EmptyPlaceholder.deleted({super.key})
Expand Down
6 changes: 5 additions & 1 deletion lib/l10n/translations/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -939,9 +939,13 @@
"@placeholder_labels": {
"description": "Placeholder on the labels page when there are no labels."
},
"placeholder_archives": "No archived notes",
"@placeholder_archives": {
"description": "Placeholder on the archives notes page when there are no archived notes."
},
"placeholder_bin": "No deleted notes",
"@placeholder_bin": {
"description": "Placeholder on the bin page when there are no notes."
"description": "Placeholder on the bin page when there are no deleted notes."
},
"action_disabled": "Disabled",
"@action_disabled": {
Expand Down
3 changes: 0 additions & 3 deletions lib/models/note/note_status.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,4 @@ enum NoteStatus {
/// The note is deleted.
deleted,
;

/// Returns the list of status where the note can be edited.
static List<NoteStatus> get editable => [available, archived];
}
3 changes: 3 additions & 0 deletions lib/navigation/navigation_routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ enum NavigationRoute {
manageLabels,
label,

// Archives
archives,

// Bin
bin,

Expand Down
31 changes: 31 additions & 0 deletions lib/pages/archives/archives_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../common/navigation/app_bars/notes_app_bar.dart';
import '../../common/navigation/side_navigation.dart';
import '../../common/navigation/top_navigation.dart';
import '../../common/widgets/notes/notes_list.dart';
import '../../models/note/note_status.dart';

/// List of archived notes.
class ArchivesPage extends ConsumerStatefulWidget {
/// Default constructor.
const ArchivesPage({super.key});

@override
ConsumerState<ArchivesPage> createState() => _ArchivesPageState();
}

class _ArchivesPageState extends ConsumerState<ArchivesPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: TopNavigation(
appbar: NotesAppBar(notesStatus: NoteStatus.archived),
notesStatus: NoteStatus.archived,
),
drawer: SideNavigation(),
body: NotesList(notesStatus: NoteStatus.archived),
);
}
}
21 changes: 4 additions & 17 deletions lib/pages/bin/bin_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../common/navigation/app_bars/notes_app_bar.dart';
import '../../common/navigation/side_navigation.dart';
import '../../common/navigation/top_navigation.dart';
import '../../common/widgets/keys.dart';
import '../../common/widgets/notes/notes_list.dart';
import '../../models/note/note_status.dart';
import 'widgets/empty_bin_fab.dart';

/// Page displaying the deleted notes.
///
/// Contains:
/// - The list of deleted notes.
/// - The FAB to empty the bin.
/// List of deleted notes.
class BinPage extends ConsumerStatefulWidget {
/// Default constructor.
const BinPage({super.key});
Expand All @@ -27,20 +22,12 @@ class _BinPageState extends ConsumerState<BinPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: TopNavigation(
appbar: NotesAppBar(
key: Keys.appBarNotesBin,
notesStatus: NoteStatus.deleted,
),
appbar: NotesAppBar(notesStatus: NoteStatus.deleted),
notesStatus: NoteStatus.deleted,
),
drawer: SideNavigation(),
floatingActionButton: EmptyBinFab(
key: Keys.fabEmptyBin,
),
body: NotesList(
key: Keys.notesPageNotesList,
notesStatus: NoteStatus.deleted,
),
floatingActionButton: EmptyBinFab(),
body: NotesList(notesStatus: NoteStatus.deleted),
);
}
}
3 changes: 2 additions & 1 deletion lib/pages/bin/widgets/empty_bin_fab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../../common/actions/notes/delete.dart';
import '../../../common/constants/constants.dart';
import '../../../common/widgets/placeholders/empty_placeholder.dart';
import '../../../models/note/note_status.dart';
import '../../../providers/notes/notes_provider.dart';

Expand All @@ -21,6 +22,6 @@ class EmptyBinFab extends ConsumerWidget {
onPressed: () => emptyBin(context, ref),
child: const Icon(Icons.delete_forever),
)
: SizedBox.shrink();
: EmptyPlaceholder();
}
}
2 changes: 1 addition & 1 deletion lib/pages/notes/notes_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import '../../providers/notifiers/notifiers.dart';
import '../../providers/preferences/preferences_provider.dart';
import 'widgets/add_note_fab.dart';

/// List of notes.
/// List of available notes.
class NotesPage extends ConsumerStatefulWidget {
/// The list of the notes and the FAB to add a new note.
///
Expand Down
34 changes: 13 additions & 21 deletions lib/providers/notes/notes_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Notes extends _$Notes {
///
/// The note can be forcefully put into the database even it it's empty using [forcePut].
Future<bool> edit(Note editedNote, {bool forcePut = false}) async {
_checkEditableStatus();
_checkStatus([NoteStatus.available, NoteStatus.archived]);

editedNote.editedTime = DateTime.now();

Expand Down Expand Up @@ -86,7 +86,7 @@ class Notes extends _$Notes {

/// Saves the [note] with the new [selectedLabels] to the database.
Future<bool> editLabels(Note note, Iterable<Label> selectedLabels) async {
_checkEditableStatus();
_checkStatus([NoteStatus.available, NoteStatus.archived]);

try {
await _notesService.putLabels(note, selectedLabels);
Expand Down Expand Up @@ -121,7 +121,7 @@ class Notes extends _$Notes {

/// Saves the [notes] with the added [selectedLabels] to the database.
Future<bool> addLabels(List<Note> notesWhereToAdd, Iterable<Label> selectedLabels) async {
_checkEditableStatus();
_checkStatus([NoteStatus.available, NoteStatus.archived]);

try {
await _notesService.addLabels(notesWhereToAdd, selectedLabels);
Expand All @@ -143,7 +143,7 @@ class Notes extends _$Notes {

/// Toggles whether the [notesToToggle] are pinned in the database.
Future<bool> togglePin(List<Note> notesToToggle) async {
_checkEditableStatus();
_checkStatus([NoteStatus.available, NoteStatus.archived]);

for (final note in notesToToggle) {
note.pinned = !note.pinned;
Expand All @@ -169,11 +169,11 @@ class Notes extends _$Notes {

/// Sets whether the [notesToSet] are archived to [archived] in the database.
Future<bool> setArchived(List<Note> notesToSet, bool archived) async {
_checkEditableStatus();
_checkStatus([NoteStatus.available, NoteStatus.archived]);

for (final note in notesToSet) {
note.pinned = false;
note.archived = true;
note.archived = archived;
}

try {
Expand All @@ -189,14 +189,14 @@ class Notes extends _$Notes {
state = AsyncData(notes);

_updateUnlabeledProvider();
_updateStatusProvider(NoteStatus.archived);
archived ? _updateStatusProvider(NoteStatus.archived) : _updateStatusProvider(NoteStatus.available);

return true;
}

/// Sets whether the [notesToSet] are deleted to [deleted] in the database.
Future<bool> setDeleted(List<Note> notesToSet, bool deleted) async {
_checkEditableStatus();
_checkStatus([NoteStatus.available, NoteStatus.deleted]);

for (final note in notesToSet) {
note.pinned = false;
Expand All @@ -223,7 +223,7 @@ class Notes extends _$Notes {

/// Removes the [notesToPermanentlyDelete] from the database.
Future<bool> permanentlyDelete(List<Note> notesToPermanentlyDelete) async {
_checkDeletedStatus();
_checkStatus([NoteStatus.deleted]);

try {
await _notesService.deleteAll(notesToPermanentlyDelete);
Expand All @@ -245,7 +245,7 @@ class Notes extends _$Notes {

/// Removes all the deleted notes from the database.
Future<bool> emptyBin() async {
_checkDeletedStatus();
_checkStatus([NoteStatus.deleted]);

try {
await _notesService.emptyBin();
Expand Down Expand Up @@ -278,22 +278,14 @@ class Notes extends _$Notes {
]);
}

/// Checks that the current [status] is editable.
void _checkEditableStatus() {
/// Checks that the current [status] is one of [statuses].
void _checkStatus(List<NoteStatus> statuses) {
assert(
NoteStatus.editable.contains(status),
statuses.contains(status),
'This method of the notes provider cannot be called when its status is not editable: $status',
);
}

/// Checks that the current [status] is [NoteStatus.deleted].
void _checkDeletedStatus() {
assert(
status == NoteStatus.deleted,
'This method method of the notes provider cannot be called when its status is not deleted',
);
}

/// Updates the unlabeled notes provider if this provider is a provider filtered by a label.
void _updateUnlabeledProvider() {
if (label != null) {
Expand Down
Loading

0 comments on commit e7e4bb8

Please sign in to comment.