copy deck

This commit is contained in:
gitea
2026-01-03 06:14:14 +01:00
parent cad489b678
commit 51e88a4aaf
14 changed files with 646 additions and 69 deletions
+89 -21
View File
@@ -124,18 +124,7 @@ class _DeckImportScreenState extends State<DeckImportScreen> {
void _useDefaultDeck() async {
final deckStorage = DeckStorage();
// Check if default deck already exists
if (deckStorage.hasDeckSync(DefaultDeck.deck.id)) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Default deck already exists'),
backgroundColor: Colors.orange,
),
);
return;
}
// Show dialog to ask if user wants mock data
// Always show dialog to ask if user wants mock data
final includeMockData = await showDialog<bool>(
context: context,
builder: (context) => _MockDataDialog(),
@@ -151,18 +140,97 @@ class _DeckImportScreenState extends State<DeckImportScreen> {
? DefaultDeck.deckWithMockData
: DefaultDeck.deck;
// Save default deck to storage
deckStorage.saveDeckSync(defaultDeck);
final deckExists = deckStorage.hasDeckSync(DefaultDeck.deck.id);
if (deckExists) {
// Show dialog with options: Replace, Add Copy, or Cancel
final action = await showDialog<String>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Deck Already Exists'),
content: const Text(
'The General Knowledge Quiz already exists. What would you like to do?',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 'cancel'),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'copy'),
child: const Text('Add Copy'),
),
FilledButton(
onPressed: () => Navigator.pop(context, 'replace'),
child: const Text('Replace'),
),
],
),
);
if (action == null || action == 'cancel') {
return;
} else if (action == 'replace') {
deckStorage.saveDeckSync(defaultDeck);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Default deck replaced successfully'),
backgroundColor: Colors.green,
),
);
} else if (action == 'copy') {
// Find the next copy number
final allDecks = deckStorage.getAllDecksSync();
final baseTitle = defaultDeck.title;
final copyPattern = RegExp(r'^(.+?)\s*\(Copy\s+(\d+)\)$');
int maxCopyNumber = 0;
for (final deck in allDecks) {
if (deck.title == baseTitle) {
// Original deck exists
continue;
}
final match = copyPattern.firstMatch(deck.title);
if (match != null) {
final titlePart = match.group(1)?.trim();
if (titlePart == baseTitle) {
final copyNum = int.tryParse(match.group(2) ?? '0') ?? 0;
if (copyNum > maxCopyNumber) {
maxCopyNumber = copyNum;
}
}
}
}
final nextCopyNumber = maxCopyNumber + 1;
final copiedDeck = defaultDeck.copyWith(
id: '${defaultDeck.id}_${DateTime.now().millisecondsSinceEpoch}',
title: '$baseTitle (Copy $nextCopyNumber)',
);
deckStorage.saveDeckSync(copiedDeck);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Default deck copied successfully'),
backgroundColor: Colors.green,
),
);
}
} else {
// Save default deck to storage
deckStorage.saveDeckSync(defaultDeck);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Default deck added successfully'),
backgroundColor: Colors.green,
),
);
}
// Navigate back to deck list
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Default deck added successfully'),
backgroundColor: Colors.green,
),
);
}
void _loadSampleDeck() {
+81 -32
View File
@@ -191,22 +191,15 @@ class _DeckListScreenState extends State<DeckListScreen> {
}
void _useDefaultDeck() async {
// Check if default deck already exists
final baseDeck = DefaultDeck.deck;
final deckExists = await _deckStorage.hasDeck(baseDeck.id);
// Show dialog to ask if user wants mock data (only if deck doesn't exist)
bool? includeMockData = false;
if (!deckExists) {
includeMockData = await showDialog<bool>(
context: context,
builder: (context) => _MockDataDialog(),
);
// Always show dialog to ask if user wants mock data
final includeMockData = await showDialog<bool>(
context: context,
builder: (context) => _MockDataDialog(),
);
if (includeMockData == null) {
// User cancelled
return;
}
if (includeMockData == null) {
// User cancelled
return;
}
// Get the appropriate deck version
@@ -214,47 +207,103 @@ class _DeckListScreenState extends State<DeckListScreen> {
? DefaultDeck.deckWithMockData
: DefaultDeck.deck;
try {
if (deckExists) {
// If it exists, create a copy with a new ID
final clonedDeck = defaultDeck.copyWith(
id: '${defaultDeck.id}_${DateTime.now().millisecondsSinceEpoch}',
);
await _deckStorage.saveDeck(clonedDeck);
final baseDeck = DefaultDeck.deck;
final deckExists = _deckStorage.hasDeckSync(baseDeck.id);
if (deckExists) {
// Show dialog with options: Replace, Add Copy, or Cancel
final action = await showDialog<String>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Deck Already Exists'),
content: const Text(
'The General Knowledge Quiz already exists. What would you like to do?',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 'cancel'),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'copy'),
child: const Text('Add Copy'),
),
FilledButton(
onPressed: () => Navigator.pop(context, 'replace'),
child: const Text('Replace'),
),
],
),
);
if (action == null || action == 'cancel') {
return;
} else if (action == 'replace') {
_deckStorage.saveDeckSync(defaultDeck);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Default deck added successfully'),
content: Text('Default deck replaced successfully'),
backgroundColor: Colors.green,
),
);
}
} else {
// Save default deck to storage
await _deckStorage.saveDeck(defaultDeck);
} else if (action == 'copy') {
// Find the next copy number
final allDecks = _deckStorage.getAllDecksSync();
final baseTitle = defaultDeck.title;
final copyPattern = RegExp(r'^(.+?)\s*\(Copy\s+(\d+)\)$');
int maxCopyNumber = 0;
for (final deck in allDecks) {
if (deck.title == baseTitle) {
// Original deck exists
continue;
}
final match = copyPattern.firstMatch(deck.title);
if (match != null) {
final titlePart = match.group(1)?.trim();
if (titlePart == baseTitle) {
final copyNum = int.tryParse(match.group(2) ?? '0') ?? 0;
if (copyNum > maxCopyNumber) {
maxCopyNumber = copyNum;
}
}
}
}
final nextCopyNumber = maxCopyNumber + 1;
final copiedDeck = defaultDeck.copyWith(
id: '${defaultDeck.id}_${DateTime.now().millisecondsSinceEpoch}',
title: '$baseTitle (Copy $nextCopyNumber)',
);
_deckStorage.saveDeckSync(copiedDeck);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Default deck added successfully'),
content: Text('Default deck copied successfully'),
backgroundColor: Colors.green,
),
);
}
}
} else {
// Save default deck to storage
_deckStorage.saveDeckSync(defaultDeck);
_loadDecks();
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error adding deck: $e'),
backgroundColor: Colors.red,
const SnackBar(
content: Text('Default deck added successfully'),
backgroundColor: Colors.green,
),
);
}
}
_loadDecks();
}
@override