Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/lib/localization/arb/intl_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
},
"changesPropagationBanner_message": "Änderungen werden beim nächsten Öffnen der App von anderen Benutzern übernommen.",
"close": "Schließen",
"collectionView_deleteGemDialog_message": "Diese Gemme und alle ihre Zeilen werden endgültig gelöscht. Dies kann nicht rückgängig gemacht werden.",
"collectionView_deleteGemDialog_title": "Diese Gemme löschen?",
"collectionView_noGemsTitle": "Keine Gemme zu zeigen",
"collectionView_shareSheet_createLinkButton": "Link erstellen",
"collectionView_shareSheet_deleteLinkButton": "Link löschen",
Expand All @@ -30,6 +32,7 @@
"createChestPage_hint_chestName": "Name der Truhe",
"createChestPage_title": "Neue Truhe erstellen",
"delete": "Löschen",
"edit": "Bearbeiten",
"editGemPage_addNarrationButton": "Neue Erzählung",
"editGemPage_addQuoteButton": "Neues Zitat",
"editGemPage_dateTile_title": "Datum",
Expand Down
3 changes: 3 additions & 0 deletions app/lib/localization/arb/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
},
"changesPropagationBanner_message": "Changes will propagate to other users next time they open the app.",
"close": "Close",
"collectionView_deleteGemDialog_message": "This gem and all its lines will be permanently deleted. This can't be undone.",
"collectionView_deleteGemDialog_title": "Delete this gem?",
"collectionView_noGemsTitle": "No gems to show",
"collectionView_shareSheet_createLinkButton": "Create a share link",
"collectionView_shareSheet_deleteLinkButton": "Delete the link",
Expand All @@ -30,6 +32,7 @@
"createChestPage_hint_chestName": "Chest name",
"createChestPage_title": "Create a new chest",
"delete": "Delete",
"edit": "Edit",
"editGemPage_addNarrationButton": "Add a narration",
"editGemPage_addQuoteButton": "Add a quote",
"editGemPage_dateTile_title": "Date",
Expand Down
18 changes: 18 additions & 0 deletions app/lib/localization/generated/localizations.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,18 @@ abstract class CAppL10n {
/// **'Close'**
String get close;

/// No description provided for @collectionView_deleteGemDialog_message.
///
/// In en, this message translates to:
/// **'This gem and all its lines will be permanently deleted. This can\'t be undone.'**
String get collectionView_deleteGemDialog_message;

/// No description provided for @collectionView_deleteGemDialog_title.
///
/// In en, this message translates to:
/// **'Delete this gem?'**
String get collectionView_deleteGemDialog_title;

/// No description provided for @collectionView_noGemsTitle.
///
/// In en, this message translates to:
Expand Down Expand Up @@ -235,6 +247,12 @@ abstract class CAppL10n {
/// **'Delete'**
String get delete;

/// No description provided for @edit.
///
/// In en, this message translates to:
/// **'Edit'**
String get edit;

/// No description provided for @editGemPage_addNarrationButton.
///
/// In en, this message translates to:
Expand Down
10 changes: 10 additions & 0 deletions app/lib/localization/generated/localizations_de.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ class CAppL10nDe extends CAppL10n {
@override
String get close => 'Schließen';

@override
String get collectionView_deleteGemDialog_message =>
'Diese Gemme und alle ihre Zeilen werden endgültig gelöscht. Dies kann nicht rückgängig gemacht werden.';

@override
String get collectionView_deleteGemDialog_title => 'Diese Gemme löschen?';

@override
String get collectionView_noGemsTitle => 'Keine Gemme zu zeigen';

Expand Down Expand Up @@ -82,6 +89,9 @@ class CAppL10nDe extends CAppL10n {
@override
String get delete => 'Löschen';

@override
String get edit => 'Bearbeiten';

@override
String get editGemPage_addNarrationButton => 'Neue Erzählung';

Expand Down
10 changes: 10 additions & 0 deletions app/lib/localization/generated/localizations_en.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ class CAppL10nEn extends CAppL10n {
@override
String get close => 'Close';

@override
String get collectionView_deleteGemDialog_message =>
'This gem and all its lines will be permanently deleted. This can\'t be undone.';

@override
String get collectionView_deleteGemDialog_title => 'Delete this gem?';

@override
String get collectionView_noGemsTitle => 'No gems to show';

Expand Down Expand Up @@ -83,6 +90,9 @@ class CAppL10nEn extends CAppL10n {
@override
String get delete => 'Delete';

@override
String get edit => 'Edit';

@override
String get editGemPage_addNarrationButton => 'Add a narration';

Expand Down
1 change: 1 addition & 0 deletions app/lib/shared/views/collection/dialogs/_dialogs.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'delete_gem.dart';
53 changes: 53 additions & 0 deletions app/lib/shared/views/collection/dialogs/delete_gem.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import 'package:chuckle_chest/localization/l10n.dart';
import 'package:chuckle_chest/shared/_shared.dart';
import 'package:chuckle_chest/shared/views/collection/logic/_logic.dart';
import 'package:flutter/material.dart';

/// {@template CDeleteGemDialog}
///
/// The dialog that asks the user to confirm the deletion of a gem.
///
/// {@endtemplate}
class CDeleteGemDialog extends StatelessWidget with CDialogMixin {
/// {@macro CDeleteGemDialog}
const CDeleteGemDialog({
required this.gemID,
required this.cubit,
super.key,
});

/// The ID of the gem to delete.
final String gemID;

/// The cubit that will delete the gem.
///
/// Because the dialog is not a part of the page's context, the cubit is
/// passed in as a parameter.
final CGemDeleteCubit cubit;

void _onDeletePressed(BuildContext context) {
cubit.deleteGem(gemID: gemID);
Navigator.of(context).pop();
}

@override
Widget build(BuildContext context) {
return AlertDialog(
key: const Key('delete_gem_dialog'),
title: Text(context.cAppL10n.collectionView_deleteGemDialog_title),
content: Text(context.cAppL10n.collectionView_deleteGemDialog_message),
actions: [
TextButton(
key: const Key('delete_gem_dialog_cancel_button'),
onPressed: () => Navigator.of(context).pop(),
child: Text(context.cAppL10n.cancel),
),
TextButton(
key: const Key('delete_gem_dialog_delete_button'),
onPressed: () => _onDeletePressed(context),
child: Text(context.cAppL10n.delete),
),
],
);
}
}
1 change: 1 addition & 0 deletions app/lib/shared/views/collection/logic/_logic.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export 'collection_view_cubit.dart';
export 'gem_delete_cubit.dart';
export 'gem_share_cubit.dart';
export 'gem_share_token_creation_cubit.dart';
22 changes: 21 additions & 1 deletion app/lib/shared/views/collection/logic/collection_view_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class CCollectionViewState {
}

/// The currently displayed gem.
CGem? get currentGem => gems.elementAt(currentIndex).$2;
CGem? get currentGem => gems.isEmpty ? null : gems.elementAt(currentIndex).$2;

/// Whether the current gem is the last gem.
bool get isLastGem => currentIndex == gems.length - 1;
Expand Down Expand Up @@ -112,4 +112,24 @@ class CCollectionViewCubit extends Cubit<CCollectionViewState> {

emit(state.copyWith(gems: state.gems));
}

/// Removes the gem with the given [gemID] from the list.
///
/// Adjusts [CCollectionViewState.currentIndex] so it stays in bounds.
/// If the list becomes empty the index resets to 0.
void removeGem(String gemID) {
final index = state.gems.indexWhere((r) => r.$2?.id == gemID);
if (index == -1) return;

state.gems.removeAt(index);
gemTokens.removeAt(index);

if (state.gems.isEmpty) {
emit(state.copyWith(gems: state.gems, currentIndex: 0));
return;
}

final newIndex = index.clamp(0, state.gems.length - 1);
emit(state.copyWith(gems: state.gems, currentIndex: newIndex));
}
}
24 changes: 24 additions & 0 deletions app/lib/shared/views/collection/logic/gem_delete_cubit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:bloc/bloc.dart';
import 'package:cgem_repository/cgem_repository.dart';
import 'package:mallard_bloc/mallard_bloc.dart';

/// The state for the [CGemDeleteCubit].
typedef CGemDeleteState = TaskBlocState<String, CGemDeleteException>;

/// {@template CGemDeleteCubit}
///
/// The cubit that handles deleting gems.
///
/// {@endtemplate}
class CGemDeleteCubit extends Cubit<CGemDeleteState> with TaskCubitMixin {
/// {@macro CGemDeleteCubit}
CGemDeleteCubit({required this.gemRepository})
: super(TaskBlocState.initial());

/// The repository this cubit uses to delete gems.
final CGemRepository gemRepository;

/// Deletes the gem with the given `gemID`.
Future<void> deleteGem({required String gemID}) =>
request(gemRepository.deleteGem(gemID: gemID));
}
Loading
Loading