diff --git a/app/lib/features/geckoview/features/bookmarks/presentation/dialogs/import_bookmarks_dialog.dart b/app/lib/features/geckoview/features/bookmarks/presentation/dialogs/import_bookmarks_dialog.dart
new file mode 100644
index 00000000..988b9953
--- /dev/null
+++ b/app/lib/features/geckoview/features/bookmarks/presentation/dialogs/import_bookmarks_dialog.dart
@@ -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 .
+ */
+import 'package:flutter/material.dart';
+
+Future showImportBookmarksDialog(BuildContext context) {
+ return showDialog(
+ 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: [
+ TextButton(
+ onPressed: () {
+ Navigator.pop(context, false);
+ },
+ child: const Text('Merge'),
+ ),
+ TextButton(
+ onPressed: () {
+ Navigator.pop(context, true);
+ },
+ child: const Text('Replace'),
+ ),
+ ],
+ );
+ },
+ );
+}
diff --git a/app/lib/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart b/app/lib/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart
index 27f32d89..49c39cd3 100644
--- a/app/lib/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart
+++ b/app/lib/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart
@@ -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');
diff --git a/app/lib/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart b/app/lib/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart
index 346b4568..73f5418a 100644
--- a/app/lib/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart
+++ b/app/lib/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart
@@ -387,7 +387,12 @@ class _BookmarkImporter {
Future _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();
diff --git a/app/lib/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart b/app/lib/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart
index 73874212..9d4ba1cc 100644
--- a/app/lib/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart
+++ b/app/lib/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart
@@ -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 = {};