dialog replace or merge imported bookmarks

This commit is contained in:
Fabian Freund
2026-01-04 08:21:22 +01:00
parent c6bd60a0a7
commit 0bd25bfa9c
4 changed files with 70 additions and 4 deletions
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2024-2025 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
Future<bool?> showImportBookmarksDialog(BuildContext context) {
return showDialog<bool?>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Import Bookmarks'),
content: const Text(
'Do you want to erase all existing bookmarks before importing?\n\n'
'Choose "Replace" to delete existing bookmarks, or "Merge" to keep them.',
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.pop(context, false);
},
child: const Text('Merge'),
),
TextButton(
onPressed: () {
Navigator.pop(context, true);
},
child: const Text('Replace'),
),
],
);
},
);
}
@@ -33,6 +33,7 @@ import 'package:weblibre/core/routing/routes.dart';
import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/bookmark_item.dart';
import 'package:weblibre/features/geckoview/features/bookmarks/domain/providers/bookmarks.dart';
import 'package:weblibre/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart';
import 'package:weblibre/features/geckoview/features/bookmarks/presentation/dialogs/import_bookmarks_dialog.dart';
import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/hooks/menu_controller.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
@@ -359,12 +360,18 @@ class BookmarkListScreen extends HookConsumerWidget {
return;
}
if (!context.mounted) return;
// Ask user if they want to erase existing bookmarks
final shouldReplace = await showImportBookmarksDialog(context);
if (shouldReplace == null) return; // User cancelled dialog
final content = await File(file.path!).readAsString();
final repository = ref.read(bookmarksRepositoryProvider.notifier);
final count = format == 'json'
? await repository.importFromJSON(content)
: await repository.importFromHTML(content);
? await repository.importFromJSON(content, replace: shouldReplace)
: await repository.importFromHTML(content, replace: shouldReplace);
if (context.mounted) {
showInfoMessage(context, 'Imported $count bookmarks successfully');
@@ -387,7 +387,12 @@ class _BookmarkImporter {
Future<int> _importBookmarks() async {
if (_isImportDefaults) {
await _service.eraseEverything(BookmarkRoot.root);
// Delete bookmarks from each root folder (except root itself to avoid errors)
for (final root in BookmarkRoot.values) {
if (root != BookmarkRoot.root) {
await _service.eraseEverything(root);
}
}
}
final bookmarkTrees = _getBookmarkTrees();
@@ -64,7 +64,12 @@ class BookmarkJSONUtils {
// If replacing, erase existing bookmarks first
if (replace) {
await _service.eraseEverything(BookmarkRoot.root);
// Delete bookmarks from each root folder (except root itself to avoid errors)
for (final root in BookmarkRoot.values) {
if (root != BookmarkRoot.root) {
await _service.eraseEverything(root);
}
}
}
final folderIdToGuidMap = <String, String>{};