diff --git a/apps/weblibre/lib/features/app_links/domain/services/app_link_policy_replication.dart b/apps/weblibre/lib/features/app_links/domain/services/app_link_policy_replication.dart index 530261d3..68365530 100644 --- a/apps/weblibre/lib/features/app_links/domain/services/app_link_policy_replication.dart +++ b/apps/weblibre/lib/features/app_links/domain/services/app_link_policy_replication.dart @@ -82,7 +82,9 @@ AppLinkPolicySnapshot? appLinkPolicySnapshot(Ref ref) { final isolationLoaded = ref .watch(watchIsolatedContextContainerMapProvider) .hasValue; - final strictLoaded = ref.watch(watchStrictContextAssignmentsProvider).hasValue; + final strictLoaded = ref + .watch(watchStrictContextAssignmentsProvider) + .hasValue; final sitesLoaded = ref.watch(watchAllAssignedSitesProvider).hasValue; // The real proxy-routing settings drive `protectGeneralContext`; the // `...WithDefaults` view silently substitutes defaults while the row loads, diff --git a/apps/weblibre/lib/features/app_links/domain/services/app_link_policy_replication.g.dart b/apps/weblibre/lib/features/app_links/domain/services/app_link_policy_replication.g.dart index 24c96746..8b258c88 100644 --- a/apps/weblibre/lib/features/app_links/domain/services/app_link_policy_replication.g.dart +++ b/apps/weblibre/lib/features/app_links/domain/services/app_link_policy_replication.g.dart @@ -120,7 +120,7 @@ final class AppLinkPolicySnapshotProvider } String _$appLinkPolicySnapshotHash() => - r'7f700b67d3b7b0b435fe82a98de455c6e374a1a2'; + r'6fe2dca118d7162561fc7f6280d1a0411d50972a'; /// Single serialised writer that mirrors the Dart-owned app-link policy to the /// native profile-scoped store (§2.8), the sole policy source consulted by the diff --git a/apps/weblibre/lib/features/app_links/domain/services/effective_routing.dart b/apps/weblibre/lib/features/app_links/domain/services/effective_routing.dart index 3539367c..1ad886ac 100644 --- a/apps/weblibre/lib/features/app_links/domain/services/effective_routing.dart +++ b/apps/weblibre/lib/features/app_links/domain/services/effective_routing.dart @@ -311,7 +311,10 @@ AppLinkProtection computeAppLinkProtection({ final protectedContextIds = {}; for (final MapEntry(:key, :value) in assignmentByContextId.entries) { - if (isAssignmentProtected(value, protectGeneralContext: protectGeneralContext)) { + if (isAssignmentProtected( + value, + protectGeneralContext: protectGeneralContext, + )) { protectedContextIds.add(key); } } @@ -323,7 +326,10 @@ AppLinkProtection computeAppLinkProtection({ .toList(); if (assignments.isEmpty) continue; final chosen = resolveIsolationContextRouting(assignments).chosen; - if (isAssignmentProtected(chosen, protectGeneralContext: protectGeneralContext)) { + if (isAssignmentProtected( + chosen, + protectGeneralContext: protectGeneralContext, + )) { protectedContextIds.add(key); } } diff --git a/apps/weblibre/lib/features/app_links/presentation/widgets/container_app_link_settings_dialog.dart b/apps/weblibre/lib/features/app_links/presentation/widgets/container_app_link_settings_dialog.dart index 2fd56f87..d2b489c4 100644 --- a/apps/weblibre/lib/features/app_links/presentation/widgets/container_app_link_settings_dialog.dart +++ b/apps/weblibre/lib/features/app_links/presentation/widgets/container_app_link_settings_dialog.dart @@ -53,17 +53,17 @@ class ContainerAppLinkSettingsDialog extends ConsumerWidget { WidgetRef ref, ContextAppLinkPolicy Function(ContextAppLinkPolicy current) update, ) async { - await ref - .read(saveGeneralSettingsControllerProvider.notifier) - .save((current) { - final existing = - current.appLinkContextOverrides[contextId] ?? - ContextAppLinkPolicy.blank(); - return current.copyWith.appLinkContextOverrides({ - ...current.appLinkContextOverrides, - contextId: update(existing), - }); - }); + await ref.read(saveGeneralSettingsControllerProvider.notifier).save(( + current, + ) { + final existing = + current.appLinkContextOverrides[contextId] ?? + ContextAppLinkPolicy.blank(); + return current.copyWith.appLinkContextOverrides({ + ...current.appLinkContextOverrides, + contextId: update(existing), + }); + }); } @override @@ -120,7 +120,9 @@ class ContainerAppLinkSettingsDialog extends ConsumerWidget { RadioListTile.adaptive( value: AppLinksMode.ask, title: Text('Ask before opening'), - subtitle: Text('Show a prompt before opening links in apps'), + subtitle: Text( + 'Show a prompt before opening links in apps', + ), ), RadioListTile.adaptive( value: AppLinksMode.never, diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart new file mode 100644 index 00000000..1b929d4c --- /dev/null +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2024-2026 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 . + */ + +/// Parser output for bookmark imports. +/// +/// This is the hand-off between parsing (which is pure, and runs in a +/// background isolate) and insertion (which talks to Places). Nodes carry no +/// guids and no explicit positions: the tree is described purely by nesting and +/// child order, and storage assigns both while inserting. +/// +/// Netscape/Firefox metadata that Places cannot represent — `TAGS`, +/// `SHORTCUTURL`/keyword, `POST_DATA` and `LAST_CHARSET` — is intentionally +/// dropped during parsing rather than modelled here. +library; + +/// A single node of a parsed bookmark tree. +sealed class ImportBookmarkNode { + /// Creation time recorded in the imported file, or null if it had none. + final DateTime? dateAdded; + + /// Modification time recorded in the imported file, or null if it had none. + final DateTime? lastModified; + + const ImportBookmarkNode({this.dateAdded, this.lastModified}); +} + +/// A folder and everything nested underneath it. +final class ImportBookmarkFolder extends ImportBookmarkNode { + final String title; + + /// Children in the order they should appear under this folder. + final List children; + + const ImportBookmarkFolder({ + required this.title, + required this.children, + super.dateAdded, + super.lastModified, + }); +} + +/// A bookmark pointing at [url]. +final class ImportBookmarkItem extends ImportBookmarkNode { + final Uri url; + final String title; + + const ImportBookmarkItem({ + required this.url, + required this.title, + super.dateAdded, + super.lastModified, + }); +} + +/// A visual divider between sibling nodes. +final class ImportBookmarkSeparator extends ImportBookmarkNode { + const ImportBookmarkSeparator({super.dateAdded, super.lastModified}); +} + +/// What a parser found in a bookmark file, and where it belongs. +/// +/// [sections] maps the guid of a Places root onto the nodes that should be +/// appended underneath it. Files without root markers produce a single section; +/// Firefox exports that identify their menu/toolbar/unfiled roots produce one +/// section per recognised root. +class ImportBookmarkTree { + final Map> sections; + + /// Counters describing what the parser saw, including what it discarded. + final ImportBookmarkStats stats; + + const ImportBookmarkTree({required this.sections, required this.stats}); + + static const empty = ImportBookmarkTree( + sections: {}, + stats: ImportBookmarkStats(), + ); + + bool get isEmpty => sections.values.every((nodes) => nodes.isEmpty); +} + +/// Summary of a parse, useful for reporting and for regression tests that care +/// about what was skipped rather than only about what survived. +class ImportBookmarkStats { + /// Bookmark items that parsed successfully. + final int bookmarkCount; + + /// Folders that parsed successfully. + final int folderCount; + + /// Separators that parsed successfully. + final int separatorCount; + + /// Entries dropped because they had no URL, or one that could not be parsed + /// or carried no scheme. + final int skippedUrlCount; + + const ImportBookmarkStats({ + this.bookmarkCount = 0, + this.folderCount = 0, + this.separatorCount = 0, + this.skippedUrlCount = 0, + }); + + ImportBookmarkStats copyWith({ + int? bookmarkCount, + int? folderCount, + int? separatorCount, + int? skippedUrlCount, + }) { + return ImportBookmarkStats( + bookmarkCount: bookmarkCount ?? this.bookmarkCount, + folderCount: folderCount ?? this.folderCount, + separatorCount: separatorCount ?? this.separatorCount, + skippedUrlCount: skippedUrlCount ?? this.skippedUrlCount, + ); + } +} diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/providers/bookmarks.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/providers/bookmarks.dart index ee1ce8d3..a9e23db3 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/providers/bookmarks.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/providers/bookmarks.dart @@ -17,125 +17,38 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import 'dart:async'; - import 'package:flutter/services.dart'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; -import 'package:nullability/nullability.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/bookmark_item.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart'; part 'bookmarks.g.dart'; -/// Check if a root folder is effectively empty (has no non-root children) -bool _isEmptyRootFolder(BookmarkFolder folder) { - if (folder.children == null) return true; - // A root folder is empty if it has no children, or only contains other root folders - return folder.children!.every( - (child) => bookmarkRootIds.contains(child.guid), - ); -} - -T? _selectChildRecursive( - List children, - String guid, -) { - for (final child in children) { - if (child.guid == guid && child is T) { - return child; - } - - if (child case final BookmarkFolder folder) { - if (folder.children != null) { - final result = _selectChildRecursive(folder.children!, guid); - if (result != null) { - return result; - } - } - } - } - - return null; -} - -T _cloneAndFilterChildrenType(T node) { - if (node is BookmarkFolder) { - if (node.children != null) { - return node.copyWith.children( - node.children - ?.whereType() - .map((e) => _cloneAndFilterChildrenType(e)) - .toList(), - ) - as T; - } - } - - return node.clone() as T; -} - -BookmarkItem? _cloneAndFilterOnGuids(BookmarkItem node, Set guids) { - if (node is BookmarkFolder) { - if (node.children != null) { - final filtered = node.children - ?.where((e) => e is BookmarkFolder || guids.contains(e.guid)) - .map((e) => _cloneAndFilterOnGuids(e, guids)) - .nonNulls - .toList(); - - if (filtered.isNotEmpty) { - return node.copyWith.children(filtered); - } else { - return null; - } - } - } - - if (guids.contains(node.guid)) { - return node.clone(); - } - - return null; -} - -@Riverpod() -class BookmarksSearch extends _$BookmarksSearch { - final _service = GeckoBookmarksService(); - late StreamController> _streamController; - - Future search(String query, {int limit = 10}) async { - if (query.isNotEmpty) { - try { - await _service.searchBookmarks(query, limit: limit).then((value) { - if (!_streamController.isClosed) { - _streamController.add(value.map((e) => e.guid).toSet()); - } - }); - } on PlatformException catch (e) { - if (e.code == 'OperationInterrupted') return; - rethrow; - } - } - } - - @override - Stream> build() { - _streamController = StreamController(); - - ref.onDispose(() async { - await _streamController.close(); - }); - - return _streamController.stream; - } +/// Whether a root folder holds anything worth showing. +/// +/// Roots always contain each other, so a root that only contains other roots +/// counts as empty. +bool _hasVisibleContent(BookmarkFolder? folder) { + final children = folder?.children; + if (children == null) return false; + return children.any((child) => !bookmarkRootIds.contains(child.guid)); } @Riverpod() class BookmarkSearchResults extends _$BookmarkSearchResults { final _service = GeckoBookmarksService(); + /// Identifies the most recent request. + /// + /// Typing starts a search per keystroke and storage does not answer them in + /// order, so a slow early query could otherwise land after a fast later one + /// and leave the list showing results for text the user has moved on from. + int _latestRequest = 0; + Future search(String query, {int limit = 10}) async { + final request = ++_latestRequest; + if (query.isEmpty) { state = []; return; @@ -143,7 +56,7 @@ class BookmarkSearchResults extends _$BookmarkSearchResults { try { final results = await _service.searchBookmarks(query, limit: limit); - if (!ref.mounted) return; + if (!ref.mounted || request != _latestRequest) return; state = results .map(BookmarkItem.parseRecursive) .whereType() @@ -160,98 +73,75 @@ class BookmarkSearchResults extends _$BookmarkSearchResults { } } +/// A single folder with its direct children. +/// +/// The load is scoped to one folder, so its cost tracks the folder being shown +/// rather than the size of the library. Rebuilds whenever the repository +/// reports a change. @Riverpod() -AsyncValue bookmarks( +Future bookmarkFolder(Ref ref, String guid) { + ref.watch(bookmarksRepositoryProvider); + return ref.read(bookmarksRepositoryProvider.notifier).getFolder(guid); +} + +/// The folder shown by the bookmark list, with the roots the user asked to +/// hide already removed. +/// +/// Emptiness can only be judged by looking inside each root, but the root level +/// has a fixed handful of children, so the extra loads are bounded and shallow. +@Riverpod() +Future bookmarkListFolder( Ref ref, String entryGuid, { bool hideEmptyRoots = false, -}) { - final bookmarksAsync = ref.watch(bookmarksRepositoryProvider); +}) async { + final folder = await ref.watch(bookmarkFolderProvider(entryGuid).future); - return bookmarksAsync.whenData((bookmarkNode) { - T? selectedNode; + if (folder == null || + !hideEmptyRoots || + entryGuid != BookmarkRoot.root.id || + folder.children == null) { + return folder; + } - if (bookmarkNode != null && bookmarkNode is T) { - if (bookmarkNode.guid == entryGuid) { - selectedNode = bookmarkNode; - } else if (bookmarkNode case final BookmarkFolder folder) { - if (folder.children != null) { - selectedNode = _selectChildRecursive(folder.children!, entryGuid); - } - } + final visible = []; + for (final child in folder.children!) { + if (child is! BookmarkFolder || child.guid == BookmarkRoot.mobile.id) { + visible.add(child); + continue; } - if (selectedNode != null) { - var result = _cloneAndFilterChildrenType(selectedNode); - - // Filter empty root folders when viewing root level (excluding WebLibre root) - if (hideEmptyRoots && - entryGuid == BookmarkRoot.root.id && - result is BookmarkFolder) { - final filteredChildren = result.children - ?.where( - (child) => - child is! BookmarkFolder || - child.guid == BookmarkRoot.mobile.id || - !_isEmptyRootFolder(child), - ) - .toList(); - result = result.copyWith.children(filteredChildren) as T; - } - - return result; + final loaded = await ref.watch(bookmarkFolderProvider(child.guid).future); + if (_hasVisibleContent(loaded)) { + visible.add(child); } + } - return null; - }); + return folder.copyWith.children(visible); } +/// Guids of the bookmarks pointing at [url], or an empty list when there are +/// none. +/// +/// Backed by a storage lookup, so "is this page bookmarked?" costs the same +/// whether the user has ten bookmarks or fifty thousand. @Riverpod() -class SeamlessBookmarks extends _$SeamlessBookmarks { - bool _hasSearch = false; +Future> bookmarkGuidsForUrl(Ref ref, Uri? url) async { + if (url == null) return const []; - void search(String input) { - if (input.isNotEmpty) { - if (!_hasSearch) { - _hasSearch = true; - ref.invalidateSelf(); - } - - //Don't block - unawaited(ref.read(bookmarksSearchProvider.notifier).search(input)); - } else if (_hasSearch) { - _hasSearch = false; - ref.invalidateSelf(); - } - } - - @override - AsyncValue build( - String entryGuid, { - bool hideEmptyRoots = false, - }) { - final bookmarks = ref.watch( - bookmarksProvider( - entryGuid, - hideEmptyRoots: hideEmptyRoots, - ), - ); - - if (_hasSearch) { - final filterGuids = ref.watch(bookmarksSearchProvider); - return bookmarks.map( - data: (node) => - node.value.mapNotNull( - (node) => filterGuids.whenData( - (results) => _cloneAndFilterOnGuids(node, results), - ), - ) ?? - const AsyncValue.data(null), - error: (e) => e, - loading: (s) => s, - ); - } else { - return bookmarks; - } - } + ref.watch(bookmarksRepositoryProvider); + return ref + .read(bookmarksRepositoryProvider.notifier) + .bookmarkGuidsForUrl(url); +} + +/// Number of bookmarks inside the trees rooted at [guids]. +/// +/// Used to tell the user how much a destructive action will affect. +@Riverpod() +Future bookmarkCountInTrees(Ref ref, List guids) { + ref.watch(bookmarksRepositoryProvider); + return ref + .read(bookmarksRepositoryProvider.notifier) + .countBookmarksInTrees(guids); } diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/providers/bookmarks.g.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/providers/bookmarks.g.dart index 2a1973a5..5de156d0 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/providers/bookmarks.g.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/providers/bookmarks.g.dart @@ -9,50 +9,6 @@ part of 'bookmarks.dart'; // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: type=lint, type=warning -@ProviderFor(BookmarksSearch) -final bookmarksSearchProvider = BookmarksSearchProvider._(); - -final class BookmarksSearchProvider - extends $StreamNotifierProvider> { - BookmarksSearchProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'bookmarksSearchProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$bookmarksSearchHash(); - - @$internal - @override - BookmarksSearch create() => BookmarksSearch(); -} - -String _$bookmarksSearchHash() => r'41053cbc1014e0fdd04d9510bf15c9896a9f752d'; - -abstract class _$BookmarksSearch extends $StreamNotifier> { - Stream> build(); - @$mustCallSuper - @override - WhenComplete runBuild() { - final ref = this.ref as $Ref>, Set>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier>, Set>, - AsyncValue>, - Object?, - Object? - >; - return element.handleCreate(ref, build); - } -} - @ProviderFor(BookmarkSearchResults) final bookmarkSearchResultsProvider = BookmarkSearchResultsProvider._(); @@ -106,159 +62,70 @@ abstract class _$BookmarkSearchResults extends $Notifier> { } } -@ProviderFor(bookmarks) -final bookmarksProvider = BookmarksFamily._(); +/// A single folder with its direct children. +/// +/// The load is scoped to one folder, so its cost tracks the folder being shown +/// rather than the size of the library. Rebuilds whenever the repository +/// reports a change. -final class BookmarksProvider - extends $FunctionalProvider, AsyncValue, AsyncValue> - with $Provider> { - BookmarksProvider._({ - required BookmarksFamily super.from, - required (String, {bool hideEmptyRoots}) super.argument, +@ProviderFor(bookmarkFolder) +final bookmarkFolderProvider = BookmarkFolderFamily._(); + +/// A single folder with its direct children. +/// +/// The load is scoped to one folder, so its cost tracks the folder being shown +/// rather than the size of the library. Rebuilds whenever the repository +/// reports a change. + +final class BookmarkFolderProvider + extends + $FunctionalProvider< + AsyncValue, + BookmarkFolder?, + FutureOr + > + with $FutureModifier, $FutureProvider { + /// A single folder with its direct children. + /// + /// The load is scoped to one folder, so its cost tracks the folder being shown + /// rather than the size of the library. Rebuilds whenever the repository + /// reports a change. + BookmarkFolderProvider._({ + required BookmarkFolderFamily super.from, + required String super.argument, }) : super( retry: null, - name: r'bookmarksProvider', + name: r'bookmarkFolderProvider', isAutoDispose: true, dependencies: null, $allTransitiveDependencies: null, ); @override - String debugGetCreateSourceHash() => _$bookmarksHash(); + String debugGetCreateSourceHash() => _$bookmarkFolderHash(); @override String toString() { - return r'bookmarksProvider' - '<${T}>' - '$argument'; - } - - @$internal - @override - $ProviderElement> $createElement($ProviderPointer pointer) => - $ProviderElement(pointer); - - @override - AsyncValue create(Ref ref) { - final argument = this.argument as (String, {bool hideEmptyRoots}); - return bookmarks( - ref, - argument.$1, - hideEmptyRoots: argument.hideEmptyRoots, - ); - } - - $R _captureGenerics<$R>($R Function() cb) { - return cb(); - } - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(AsyncValue value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider>(value), - ); - } - - @override - bool operator ==(Object other) { - return other is BookmarksProvider && - other.runtimeType == runtimeType && - other.argument == argument; - } - - @override - int get hashCode { - return Object.hash(runtimeType, argument); - } -} - -String _$bookmarksHash() => r'72b54c4ff18cfdb60824a57607628be6b61d25d4'; - -final class BookmarksFamily extends $Family { - BookmarksFamily._() - : super( - retry: null, - name: r'bookmarksProvider', - dependencies: null, - $allTransitiveDependencies: null, - isAutoDispose: true, - ); - - BookmarksProvider call( - String entryGuid, { - bool hideEmptyRoots = false, - }) => BookmarksProvider._( - argument: (entryGuid, hideEmptyRoots: hideEmptyRoots), - from: this, - ); - - @override - String toString() => r'bookmarksProvider'; - - /// {@macro riverpod.override_with} - Override overrideWith( - AsyncValue Function( - Ref ref, - (String, {bool hideEmptyRoots}) args, - ) - create, - ) => $FamilyOverride( - from: this, - createElement: (pointer) { - final provider = pointer.origin as BookmarksProvider; - return provider._captureGenerics(() { - provider as BookmarksProvider; - final argument = provider.argument as (String, {bool hideEmptyRoots}); - return provider - .$view(create: (ref) => create(ref, argument)) - .$createElement(pointer); - }); - }, - ); -} - -@ProviderFor(SeamlessBookmarks) -final seamlessBookmarksProvider = SeamlessBookmarksFamily._(); - -final class SeamlessBookmarksProvider - extends $NotifierProvider> { - SeamlessBookmarksProvider._({ - required SeamlessBookmarksFamily super.from, - required (String, {bool hideEmptyRoots}) super.argument, - }) : super( - retry: null, - name: r'seamlessBookmarksProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$seamlessBookmarksHash(); - - @override - String toString() { - return r'seamlessBookmarksProvider' + return r'bookmarkFolderProvider' '' - '$argument'; + '($argument)'; } @$internal @override - SeamlessBookmarks create() => SeamlessBookmarks(); + $FutureProviderElement $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); - /// {@macro riverpod.override_with_value} - Override overrideWithValue(AsyncValue value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider>(value), - ); + @override + FutureOr create(Ref ref) { + final argument = this.argument as String; + return bookmarkFolder(ref, argument); } @override bool operator ==(Object other) { - return other is SeamlessBookmarksProvider && other.argument == argument; + return other is BookmarkFolderProvider && other.argument == argument; } @override @@ -267,64 +134,346 @@ final class SeamlessBookmarksProvider } } -String _$seamlessBookmarksHash() => r'240b213fa8fe595781ccc608c5d551be54c31992'; +String _$bookmarkFolderHash() => r'a0a3754a2b8099415cffad6358d9388dc7c4e7bf'; -final class SeamlessBookmarksFamily extends $Family - with - $ClassFamilyOverride< - SeamlessBookmarks, - AsyncValue, - AsyncValue, - AsyncValue, - (String, {bool hideEmptyRoots}) - > { - SeamlessBookmarksFamily._() +/// A single folder with its direct children. +/// +/// The load is scoped to one folder, so its cost tracks the folder being shown +/// rather than the size of the library. Rebuilds whenever the repository +/// reports a change. + +final class BookmarkFolderFamily extends $Family + with $FunctionalFamilyOverride, String> { + BookmarkFolderFamily._() : super( retry: null, - name: r'seamlessBookmarksProvider', + name: r'bookmarkFolderProvider', dependencies: null, $allTransitiveDependencies: null, isAutoDispose: true, ); - SeamlessBookmarksProvider call( + /// A single folder with its direct children. + /// + /// The load is scoped to one folder, so its cost tracks the folder being shown + /// rather than the size of the library. Rebuilds whenever the repository + /// reports a change. + + BookmarkFolderProvider call(String guid) => + BookmarkFolderProvider._(argument: guid, from: this); + + @override + String toString() => r'bookmarkFolderProvider'; +} + +/// The folder shown by the bookmark list, with the roots the user asked to +/// hide already removed. +/// +/// Emptiness can only be judged by looking inside each root, but the root level +/// has a fixed handful of children, so the extra loads are bounded and shallow. + +@ProviderFor(bookmarkListFolder) +final bookmarkListFolderProvider = BookmarkListFolderFamily._(); + +/// The folder shown by the bookmark list, with the roots the user asked to +/// hide already removed. +/// +/// Emptiness can only be judged by looking inside each root, but the root level +/// has a fixed handful of children, so the extra loads are bounded and shallow. + +final class BookmarkListFolderProvider + extends + $FunctionalProvider< + AsyncValue, + BookmarkFolder?, + FutureOr + > + with $FutureModifier, $FutureProvider { + /// The folder shown by the bookmark list, with the roots the user asked to + /// hide already removed. + /// + /// Emptiness can only be judged by looking inside each root, but the root level + /// has a fixed handful of children, so the extra loads are bounded and shallow. + BookmarkListFolderProvider._({ + required BookmarkListFolderFamily super.from, + required (String, {bool hideEmptyRoots}) super.argument, + }) : super( + retry: null, + name: r'bookmarkListFolderProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$bookmarkListFolderHash(); + + @override + String toString() { + return r'bookmarkListFolderProvider' + '' + '$argument'; + } + + @$internal + @override + $FutureProviderElement $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr create(Ref ref) { + final argument = this.argument as (String, {bool hideEmptyRoots}); + return bookmarkListFolder( + ref, + argument.$1, + hideEmptyRoots: argument.hideEmptyRoots, + ); + } + + @override + bool operator ==(Object other) { + return other is BookmarkListFolderProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$bookmarkListFolderHash() => + r'da6b257ef55b38021a2da7e41209b66a58cfbbb9'; + +/// The folder shown by the bookmark list, with the roots the user asked to +/// hide already removed. +/// +/// Emptiness can only be judged by looking inside each root, but the root level +/// has a fixed handful of children, so the extra loads are bounded and shallow. + +final class BookmarkListFolderFamily extends $Family + with + $FunctionalFamilyOverride< + FutureOr, + (String, {bool hideEmptyRoots}) + > { + BookmarkListFolderFamily._() + : super( + retry: null, + name: r'bookmarkListFolderProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + /// The folder shown by the bookmark list, with the roots the user asked to + /// hide already removed. + /// + /// Emptiness can only be judged by looking inside each root, but the root level + /// has a fixed handful of children, so the extra loads are bounded and shallow. + + BookmarkListFolderProvider call( String entryGuid, { bool hideEmptyRoots = false, - }) => SeamlessBookmarksProvider._( + }) => BookmarkListFolderProvider._( argument: (entryGuid, hideEmptyRoots: hideEmptyRoots), from: this, ); @override - String toString() => r'seamlessBookmarksProvider'; + String toString() => r'bookmarkListFolderProvider'; } -abstract class _$SeamlessBookmarks - extends $Notifier> { - late final _$args = ref.$arg as (String, {bool hideEmptyRoots}); - String get entryGuid => _$args.$1; - bool get hideEmptyRoots => _$args.hideEmptyRoots; +/// Guids of the bookmarks pointing at [url], or an empty list when there are +/// none. +/// +/// Backed by a storage lookup, so "is this page bookmarked?" costs the same +/// whether the user has ten bookmarks or fifty thousand. + +@ProviderFor(bookmarkGuidsForUrl) +final bookmarkGuidsForUrlProvider = BookmarkGuidsForUrlFamily._(); + +/// Guids of the bookmarks pointing at [url], or an empty list when there are +/// none. +/// +/// Backed by a storage lookup, so "is this page bookmarked?" costs the same +/// whether the user has ten bookmarks or fifty thousand. + +final class BookmarkGuidsForUrlProvider + extends + $FunctionalProvider< + AsyncValue>, + List, + FutureOr> + > + with $FutureModifier>, $FutureProvider> { + /// Guids of the bookmarks pointing at [url], or an empty list when there are + /// none. + /// + /// Backed by a storage lookup, so "is this page bookmarked?" costs the same + /// whether the user has ten bookmarks or fifty thousand. + BookmarkGuidsForUrlProvider._({ + required BookmarkGuidsForUrlFamily super.from, + required Uri? super.argument, + }) : super( + retry: null, + name: r'bookmarkGuidsForUrlProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); - AsyncValue build( - String entryGuid, { - bool hideEmptyRoots = false, - }); - @$mustCallSuper @override - WhenComplete runBuild() { - final ref = - this.ref as $Ref, AsyncValue>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, AsyncValue>, - AsyncValue, - Object?, - Object? - >; - return element.handleCreate( - ref, - () => build(_$args.$1, hideEmptyRoots: _$args.hideEmptyRoots), - ); + String debugGetCreateSourceHash() => _$bookmarkGuidsForUrlHash(); + + @override + String toString() { + return r'bookmarkGuidsForUrlProvider' + '' + '($argument)'; + } + + @$internal + @override + $FutureProviderElement> $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr> create(Ref ref) { + final argument = this.argument as Uri?; + return bookmarkGuidsForUrl(ref, argument); + } + + @override + bool operator ==(Object other) { + return other is BookmarkGuidsForUrlProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; } } + +String _$bookmarkGuidsForUrlHash() => + r'aeca791afdcad74c2e8af93c392860ea3cb92b20'; + +/// Guids of the bookmarks pointing at [url], or an empty list when there are +/// none. +/// +/// Backed by a storage lookup, so "is this page bookmarked?" costs the same +/// whether the user has ten bookmarks or fifty thousand. + +final class BookmarkGuidsForUrlFamily extends $Family + with $FunctionalFamilyOverride>, Uri?> { + BookmarkGuidsForUrlFamily._() + : super( + retry: null, + name: r'bookmarkGuidsForUrlProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + /// Guids of the bookmarks pointing at [url], or an empty list when there are + /// none. + /// + /// Backed by a storage lookup, so "is this page bookmarked?" costs the same + /// whether the user has ten bookmarks or fifty thousand. + + BookmarkGuidsForUrlProvider call(Uri? url) => + BookmarkGuidsForUrlProvider._(argument: url, from: this); + + @override + String toString() => r'bookmarkGuidsForUrlProvider'; +} + +/// Number of bookmarks inside the trees rooted at [guids]. +/// +/// Used to tell the user how much a destructive action will affect. + +@ProviderFor(bookmarkCountInTrees) +final bookmarkCountInTreesProvider = BookmarkCountInTreesFamily._(); + +/// Number of bookmarks inside the trees rooted at [guids]. +/// +/// Used to tell the user how much a destructive action will affect. + +final class BookmarkCountInTreesProvider + extends $FunctionalProvider, int, FutureOr> + with $FutureModifier, $FutureProvider { + /// Number of bookmarks inside the trees rooted at [guids]. + /// + /// Used to tell the user how much a destructive action will affect. + BookmarkCountInTreesProvider._({ + required BookmarkCountInTreesFamily super.from, + required List super.argument, + }) : super( + retry: null, + name: r'bookmarkCountInTreesProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$bookmarkCountInTreesHash(); + + @override + String toString() { + return r'bookmarkCountInTreesProvider' + '' + '($argument)'; + } + + @$internal + @override + $FutureProviderElement $createElement($ProviderPointer pointer) => + $FutureProviderElement(pointer); + + @override + FutureOr create(Ref ref) { + final argument = this.argument as List; + return bookmarkCountInTrees(ref, argument); + } + + @override + bool operator ==(Object other) { + return other is BookmarkCountInTreesProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$bookmarkCountInTreesHash() => + r'efe0cc45e7e77aa542d9ebbd9f4fee5cf9ee5903'; + +/// Number of bookmarks inside the trees rooted at [guids]. +/// +/// Used to tell the user how much a destructive action will affect. + +final class BookmarkCountInTreesFamily extends $Family + with $FunctionalFamilyOverride, List> { + BookmarkCountInTreesFamily._() + : super( + retry: null, + name: r'bookmarkCountInTreesProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + /// Number of bookmarks inside the trees rooted at [guids]. + /// + /// Used to tell the user how much a destructive action will affect. + + BookmarkCountInTreesProvider call(List guids) => + BookmarkCountInTreesProvider._(argument: guids, from: this); + + @override + String toString() => r'bookmarkCountInTreesProvider'; +} diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart index 5f14828c..901c0dce 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart @@ -18,11 +18,12 @@ * along with this program. If not, see . */ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; -import 'package:nullability/nullability.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:weblibre/core/logger.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/bookmark_item.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_import_isolate.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_importer.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart'; part 'bookmarks.g.dart'; @@ -40,7 +41,7 @@ class BookmarksRepository extends _$BookmarksRepository { int? position, }) async { await _service.addItem(parentGuid, url, title, position); - ref.invalidateSelf(); + _notifyChanged(); } Future addFolder({ @@ -49,7 +50,7 @@ class BookmarksRepository extends _$BookmarksRepository { int? position, }) async { await _service.addFolder(parentGuid, title, position); - ref.invalidateSelf(); + _notifyChanged(); } Future editBookmark({ @@ -68,7 +69,7 @@ class BookmarksRepository extends _$BookmarksRepository { position: position, ), ); - ref.invalidateSelf(); + _notifyChanged(); } Future editFolder({ @@ -81,12 +82,12 @@ class BookmarksRepository extends _$BookmarksRepository { guid, BookmarkInfo(title: title, parentGuid: parentGuid, position: position), ); - ref.invalidateSelf(); + _notifyChanged(); } Future delete(String guid) async { await _service.deleteNode(guid); - ref.invalidateSelf(); + _notifyChanged(); } Future moveMany({ @@ -104,7 +105,7 @@ class BookmarksRepository extends _$BookmarksRepository { BookmarkInfo(parentGuid: targetParentGuid), ); } - ref.invalidateSelf(); + _notifyChanged(); } Future deleteMany(Iterable guids) async { @@ -115,7 +116,7 @@ class BookmarksRepository extends _$BookmarksRepository { } await _service.deleteNode(guid); } - ref.invalidateSelf(); + _notifyChanged(); } Future flattenFolder({required BookmarkFolder folder}) async { @@ -137,7 +138,45 @@ class BookmarksRepository extends _$BookmarksRepository { } } await _service.deleteNode(folder.guid); - ref.invalidateSelf(); + _notifyChanged(); + } + + /// Loads a single folder and its direct children. + /// + /// This is the load the bookmark UI is built on: the cost is proportional to + /// the folder being shown, not to the size of the library. Reach for + /// [getFolderTree] only when an operation genuinely needs descendants. + Future getFolder(String guid) async { + final node = await _service.getTree(guid); + if (node == null || node.type != BookmarkNodeType.folder) return null; + return BookmarkItem.parseRecursive(node) as BookmarkFolder?; + } + + /// Loads a folder with every descendant. + /// + /// Only for operations that need the whole subtree — export, flatten, "open + /// all in folder". Never for rendering a list. + Future getFolderTree(String guid) async { + final node = await _service.getTree(guid, recursive: true); + if (node == null || node.type != BookmarkNodeType.folder) return null; + return BookmarkItem.parseRecursive(node) as BookmarkFolder?; + } + + /// Number of bookmark items inside the trees rooted at [guids]. + /// + /// Counted in storage, so this stays cheap on a large library. + Future countBookmarksInTrees(Iterable guids) { + if (guids.isEmpty) return Future.value(0); + return _service.countBookmarksInTrees(guids.toList()); + } + + /// Guids of every bookmark entry pointing at [url]. + /// + /// Answers "is this page bookmarked?" through a storage lookup instead of + /// scanning an in-memory tree. + Future> bookmarkGuidsForUrl(Uri url) async { + final nodes = await _service.getBookmarksWithUrl(url); + return nodes.map((node) => node.guid).toList(); } /// Returns the GUIDs of all descendant folders of [guid] by fetching the @@ -163,18 +202,44 @@ class BookmarksRepository extends _$BookmarksRepository { Future eraseEverything(BookmarkRoot root) async { await _service.eraseEverything(root); - ref.invalidateSelf(); + _notifyChanged(); } Future importFromJSON(String jsonString, {bool replace = false}) async { final count = await _jsonUtils.importFromJSON(jsonString, replace: replace); - ref.invalidateSelf(); + _notifyChanged(); return count; } Future importFromHTML(String htmlString, {bool replace = false}) async { final count = await _htmlUtils.importFromHTML(htmlString, replace: replace); - ref.invalidateSelf(); + _notifyChanged(); + return count; + } + + /// Imports the bookmark file at [path], parsing it in a background isolate. + /// + /// Preferred over [importFromHTML]/[importFromJSON] for user-initiated + /// imports: neither the raw file nor the intermediate parse tree ever touches + /// the UI isolate. + Future importFromFile({ + required String path, + required BookmarkImportFormat format, + bool replace = false, + }) async { + final tree = await parseBookmarkFile( + path: path, + format: format, + // Replacing the library is the only case where a file's own root folders + // should take over the corresponding Places roots. + preserveRootFolders: replace, + ); + + final count = await BookmarkTreeImporter( + _service, + ).import(tree, replace: replace); + + _notifyChanged(); return count; } @@ -188,9 +253,16 @@ class BookmarksRepository extends _$BookmarksRepository { return await _htmlUtils.exportToHTML(root: root); } + /// A revision that advances whenever bookmarks change. + /// + /// The repository deliberately holds no bookmark data. It used to build the + /// entire tree recursively from [BookmarkRoot.root], which meant every + /// consumer paid for the whole library — the reason opening bookmarks after + /// a large import or sync could bring the app down. Data now comes from the + /// folder-scoped providers, which watch this value to know when to reload. @override - Future build() async { - final node = await _service.getTree(BookmarkRoot.root.id, recursive: true); - return node.mapNotNull(BookmarkItem.parseRecursive); - } + int build() => 0; + + /// Signals that stored bookmarks changed, prompting dependents to reload. + void _notifyChanged() => state++; } diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/repositories/bookmarks.g.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/repositories/bookmarks.g.dart index d6fee072..66b353c0 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/repositories/bookmarks.g.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/repositories/bookmarks.g.dart @@ -13,7 +13,7 @@ part of 'bookmarks.dart'; final bookmarksRepositoryProvider = BookmarksRepositoryProvider._(); final class BookmarksRepositoryProvider - extends $AsyncNotifierProvider { + extends $NotifierProvider { BookmarksRepositoryProvider._() : super( from: null, @@ -31,22 +31,30 @@ final class BookmarksRepositoryProvider @$internal @override BookmarksRepository create() => BookmarksRepository(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(int value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } } String _$bookmarksRepositoryHash() => - r'2169d5b354c4a22192096451c96ab1490cf55ab4'; + r'bf95d30f21773e931b12fd85d03d072d88d5b715'; -abstract class _$BookmarksRepository extends $AsyncNotifier { - FutureOr build(); +abstract class _$BookmarksRepository extends $Notifier { + int build(); @$mustCallSuper @override WhenComplete runBuild() { - final ref = this.ref as $Ref, BookmarkItem?>; + final ref = this.ref as $Ref; final element = ref.element as $ClassProviderElement< - AnyNotifier, BookmarkItem?>, - AsyncValue, + AnyNotifier, + int, Object?, Object? >; diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils.dart index 30cd4624..c184f693 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils.dart @@ -21,142 +21,101 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/bookmark_item.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/bookmark_sort_type.dart'; -/// Recursively sorts a bookmark tree by the given sort type. -/// Root-level built-in folders are kept in their canonical order. -BookmarkItem sortBookmarkTree( - BookmarkItem item, +/// Sorts one folder's direct children by the given sort type. +/// +/// Only the level being displayed is sorted; descendants are not loaded, so +/// there is nothing deeper to order. Root-level built-in folders are kept +/// pinned in their canonical order ahead of everything else. +List sortBookmarkChildren( + List children, BookmarkSortType sortType, { bool isRoot = false, }) { - if (sortType == BookmarkSortType.manual) return item; + if (sortType == BookmarkSortType.manual) return children; - if (item is BookmarkFolder && item.children != null) { - final sortedChildren = item.children!.map((child) { - return sortBookmarkTree(child, sortType); - }).toList(); - - // At root level, keep built-in root folders pinned in original order - if (isRoot) { - final rootFolders = []; - final nonRootItems = []; - for (final child in sortedChildren) { - if (bookmarkRootIds.contains(child.guid)) { - rootFolders.add(child); - } else { - nonRootItems.add(child); - } - } - nonRootItems.sort((a, b) => compareBookmarkItems(a, b, sortType)); - return BookmarkFolder( - guid: item.guid, - parentGuid: item.parentGuid, - title: item.title, - position: item.position, - dateAdded: item.dateAdded, - children: [...rootFolders, ...nonRootItems], - ); - } - - sortedChildren.sort((a, b) => compareBookmarkItems(a, b, sortType)); - return BookmarkFolder( - guid: item.guid, - parentGuid: item.parentGuid, - title: item.title, - position: item.position, - dateAdded: item.dateAdded, - children: sortedChildren, - ); + if (!isRoot) { + return [...children]..sort((a, b) => compareBookmarkItems(a, b, sortType)); } - return item; -} - -/// Collects all descendant folder GUIDs from a folder (not including the folder itself). -Set collectDescendantFolderGuids(BookmarkFolder folder) { - final result = {}; - if (folder.children != null) { - for (final child in folder.children!) { - if (child is BookmarkFolder) { - result.add(child.guid); - result.addAll(collectDescendantFolderGuids(child)); - } + final rootFolders = []; + final rest = []; + for (final child in children) { + if (bookmarkRootIds.contains(child.guid)) { + rootFolders.add(child); + } else { + rest.add(child); } } - return result; + rest.sort((a, b) => compareBookmarkItems(a, b, sortType)); + + return [...rootFolders, ...rest]; } -/// Resolves BookmarkItems from a tree by their GUIDs. -List resolveSelectedItems(BookmarkItem root, Set guids) { - final result = []; - _collectByGuids(root, guids, result); - return result; +/// One rendered line of the bookmark list: an item and how deep it sits. +/// +/// The list flattens the expanded folders into rows rather than nesting +/// widgets, so it can stay a `ListView.builder` and only build what is on +/// screen — a folder with thousands of entries costs the same to expand as a +/// small one. +class BookmarkRow { + final BookmarkItem item; + final int depth; + + /// True when this row only stands in for [item]'s children while they load. + /// + /// A placeholder repeats the folder it belongs to, so it must never be + /// treated as a second occurrence of that folder — acting on it would apply + /// the same operation twice. + final bool isPlaceholder; + + const BookmarkRow(this.item, this.depth, {this.isPlaceholder = false}); } -void _collectByGuids( - BookmarkItem item, +/// Resolves the items of [children] whose GUIDs are in [guids]. +/// +/// The caller passes whatever is currently displayed, which may be one folder's +/// children, several expanded levels, or search hits from all over the library. +List resolveSelectedItems( + List children, Set guids, - List result, ) { - if (guids.contains(item.guid)) { - result.add(item); - } - if (item is BookmarkFolder && item.children != null) { - for (final child in item.children!) { - _collectByGuids(child, guids, result); - } - } + return children.where((child) => guids.contains(child.guid)).toList(); } -/// Whether a folder can be flattened (non-root, has a parent, has children). -bool canFlattenFolder(BookmarkFolder folder) { - return folder.parentGuid != null && - !bookmarkRootIds.contains(folder.guid) && - folder.children != null && - folder.children!.isNotEmpty; -} +/// Drops selections that sit inside another selected folder. +/// +/// Expanding a folder makes its children selectable alongside it, and acting on +/// both would move a child out of the very folder that just moved, or delete it +/// twice. A folder's descendants are exactly the rows that follow it until the +/// depth returns to its own, so one pass over [rows] is enough. +Set normalizeSelection(List rows, Set selected) { + final result = {}; + var skipBelowDepth = -1; -/// Normalizes a selection set: removes items that are descendants of selected folders. -/// This prevents double-applying moves when both a folder and its children are selected. -Set normalizeSelection(BookmarkItem root, Set selectedGuids) { - final items = resolveSelectedItems(root, selectedGuids); - final folderGuidsToRemove = {}; - - for (final item in items) { - if (item is BookmarkFolder) { - _collectAllDescendantGuids(item, folderGuidsToRemove); + for (final row in rows) { + if (skipBelowDepth >= 0) { + if (row.depth > skipBelowDepth) continue; + skipBelowDepth = -1; } - } - return selectedGuids.difference(folderGuidsToRemove); -} + if (row.isPlaceholder) continue; -void _collectAllDescendantGuids(BookmarkFolder folder, Set result) { - if (folder.children != null) { - for (final child in folder.children!) { - result.add(child.guid); - if (child is BookmarkFolder) { - _collectAllDescendantGuids(child, result); - } - } - } -} - -/// Returns GUIDs of all bookmark entries matching [url] in the tree. -List bookmarkGuidsForUrl(BookmarkItem? root, Uri? url) { - final result = []; - if (root == null || url == null) return result; - - void collect(BookmarkItem item) { - if (item is BookmarkEntry && item.url == url) { - result.add(item.guid); - } - if (item is BookmarkFolder) { - for (final child in item.children ?? const []) { - collect(child); + if (selected.contains(row.item.guid)) { + result.add(row.item.guid); + if (row.item is BookmarkFolder) { + skipBelowDepth = row.depth; } } } - collect(root); return result; } + +/// Whether a folder can be flattened (non-root and has a parent). +/// +/// Whether it actually holds anything is left to the repository, which reads +/// the folder's children at the moment of the operation rather than relying on +/// what the list happens to have loaded. +bool canFlattenFolder(BookmarkFolder folder) { + return folder.parentGuid != null && !bookmarkRootIds.contains(folder.guid); +} diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/dialogs/delete_folder_dialog.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/dialogs/delete_folder_dialog.dart index 3a0ae2df..c5d71d9d 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/dialogs/delete_folder_dialog.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/dialogs/delete_folder_dialog.dart @@ -19,16 +19,33 @@ */ import 'package:flutter/material.dart'; -Future showDeleteFolderDialog(BuildContext context) { +/// Confirms deleting a folder and everything inside it. +/// +/// Pass [bookmarkCount] to name how many bookmarks go with it. The list only +/// shows one level at a time, so the contents of a folder are usually off +/// screen when this is asked. +Future showDeleteFolderDialog( + BuildContext context, { + int? bookmarkCount, +}) { return showDialog( context: context, builder: (BuildContext context) { return AlertDialog( icon: const Icon(Icons.warning), title: const Text('Delete Folder'), - content: const Text( - 'Are you sure you want to delete this Folder including all bookmarks?', - ), + content: Text(switch (bookmarkCount) { + null => + 'Are you sure you want to delete this Folder including ' + 'all bookmarks?', + 0 => 'Are you sure you want to delete this Folder?', + 1 => + 'Are you sure you want to delete this Folder and the ' + '1 bookmark inside it?', + final count => + 'Are you sure you want to delete this Folder and the ' + '$count bookmarks inside it?', + }), actions: [ TextButton( onPressed: () { diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart index 13d2c2a7..64788795 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart @@ -17,10 +17,9 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +import 'dart:async'; import 'dart:convert'; -import 'dart:io'; -import 'package:animated_tree_view/animated_tree_view.dart'; import 'package:convert/convert.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; @@ -44,6 +43,7 @@ import 'package:weblibre/features/geckoview/features/bookmarks/presentation/dial import 'package:weblibre/features/geckoview/features/bookmarks/presentation/dialogs/delete_folder_dialog.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/presentation/dialogs/import_bookmarks_dialog.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/presentation/dialogs/select_bookmark_folder_dialog.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_import_isolate.dart'; import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_mode.dart'; import 'package:weblibre/features/user/domain/repositories/general_settings.dart'; import 'package:weblibre/presentation/hooks/menu_controller.dart'; @@ -52,6 +52,15 @@ import 'package:weblibre/presentation/widgets/uri_breadcrumb.dart'; import 'package:weblibre/presentation/widgets/url_icon.dart'; import 'package:weblibre/utils/ui_helper.dart'; +/// How many hits an in-list search asks storage for. +/// +/// Generous enough to be useful on a large library while staying a bounded, +/// lazily rendered list. +const _searchResultLimit = 200; + +/// Indentation applied per level of folder nesting. +const _indentPerDepth = 20.0; + class BookmarkListScreen extends HookConsumerWidget { final String entryGuid; @@ -59,18 +68,15 @@ class BookmarkListScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final treeController = - useState>?>( - null, - ); - // Tracks which folder GUIDs are expanded, so expansion state survives - // tree rebuilds caused by sort type changes. - final expandedGuids = useRef({}); final hideEmptyRoots = useState(true); final uiState = ref.watch(bookmarkListUiStateProvider); final uiStateNotifier = ref.read(bookmarkListUiStateProvider.notifier); - final bookmarkList = ref.watch( - seamlessBookmarksProvider( + + // Only the folder being shown is loaded. Descendants stay in storage until + // the user navigates into them, which is what keeps this screen openable on + // a large library. + final folderAsync = ref.watch( + bookmarkListFolderProvider( entryGuid, hideEmptyRoots: hideEmptyRoots.value, ), @@ -78,25 +84,46 @@ class BookmarkListScreen extends HookConsumerWidget { final textFilterEnabled = useState(false); final textFilterController = useTextEditingController(); + final searchQuery = useState(''); useOnListenableChange(textFilterController, () { - if (ref.exists( - seamlessBookmarksProvider( - entryGuid, - hideEmptyRoots: hideEmptyRoots.value, - ), - )) { + searchQuery.value = textFilterController.text; + // Searching goes through storage rather than filtering a loaded tree, so + // it reaches bookmarks this screen never loaded. + unawaited( ref - .read( - seamlessBookmarksProvider( - entryGuid, - hideEmptyRoots: hideEmptyRoots.value, - ).notifier, - ) - .search(textFilterController.text); - } + .read(bookmarkSearchResultsProvider.notifier) + .search(textFilterController.text, limit: _searchResultLimit), + ); }); + final isSearching = searchQuery.value.isNotEmpty; + final searchResults = ref.watch(bookmarkSearchResultsProvider); + + // Folders the user has opened. Keyed by guid so expansion survives sort and + // filter changes. + final expandedGuids = useState({}); + + // Storage can only match bookmarks, never folders, so "Folders Only" and a + // search query have no overlap to show. + final searchSuppressedByFilter = isSearching && uiState.foldersOnly; + + // Everything currently on screen, flattened. Selection is resolved against + // exactly these rows — search hits come from anywhere in the library, and + // expanded folders contribute items from below the entry folder. + final rows = isSearching + ? [ + if (!searchSuppressedByFilter) + for (final result in searchResults) BookmarkRow(result, 0), + ] + : _buildRows( + ref, + folderAsync.value, + uiState, + expandedGuids.value, + depth: 0, + ); + return PopScope( canPop: !uiState.selectionMode, onPopInvokedWithResult: (didPop, _) { @@ -106,13 +133,18 @@ class BookmarkListScreen extends HookConsumerWidget { }, child: Scaffold( appBar: uiState.selectionMode - ? _buildSelectionAppBar(context, ref, uiState, uiStateNotifier) + ? _buildSelectionAppBar( + context, + ref, + uiState, + uiStateNotifier, + rows, + ) : _buildNormalAppBar( context, ref, - treeController, - expandedGuids, hideEmptyRoots, + expandedGuids, textFilterEnabled, textFilterController, uiStateNotifier, @@ -121,117 +153,173 @@ class BookmarkListScreen extends HookConsumerWidget { body: SafeArea( child: Padding( padding: const EdgeInsets.only(left: 12.0), - child: bookmarkList.when( - skipLoadingOnReload: true, - data: (list) { - final sortedList = list != null - ? sortBookmarkTree( - list, - uiState.sortType, - isRoot: entryGuid == BookmarkRoot.root.id, - ) - : null; - - TreeNode addChildren( - TreeNode? parent, - BookmarkItem item, - ) { - if (uiState.foldersOnly && item is BookmarkEntry) { - return parent ?? TreeNode.root(); - } - - final node = TreeNode( - key: item.guid, - data: item, - parent: parent, - ); - final targetNode = (parent?..add(node)) ?? node; - - if (item is BookmarkFolder && item.children != null) { - for (final child in item.children!) { - addChildren(node, child); - } - } - - return targetNode; - } - - final root = (sortedList != null) - ? addChildren(null, sortedList) - : TreeNode.root(); - - return TreeView.simple( - key: ValueKey((uiState.sortType, uiState.foldersOnly)), - tree: root, - showRootNode: entryGuid != BookmarkRoot.root.id, - onTreeReady: (controller) { - treeController.value = controller; - if (expandedGuids.value.isNotEmpty) { - _restoreExpansion(controller, root, expandedGuids.value); - } else { - controller.expandAllChildren(root, recursive: true); - } - }, - expansionIndicatorBuilder: (context, tree) => - ChevronIndicator.upDown( - tree: tree, - padding: const EdgeInsets.symmetric( - vertical: 16.0, - horizontal: 12.0, - ), + child: isSearching + ? _buildRowList( + context, + ref, + rows, + uiState, + uiStateNotifier, + expandedGuids, + emptyLabel: searchSuppressedByFilter + ? 'Search matches bookmarks, which "Folders Only" is ' + 'hiding' + : 'No bookmarks match "${searchQuery.value}"', + ) + : folderAsync.when( + skipLoadingOnReload: true, + data: (_) => _buildRowList( + context, + ref, + rows, + uiState, + uiStateNotifier, + expandedGuids, + emptyLabel: 'Empty', + ), + error: (error, stackTrace) => Center( + child: FailureWidget( + title: 'Failed to load Bookmarks', + exception: error, + onRetry: () { + ref.invalidate(bookmarkFolderProvider(entryGuid)); + }, ), - builder: (context, item) { - final BookmarkItem? data = item.data; - final isSelected = uiState.selectedGuids.contains( - data?.guid, - ); - final bool isLeaf = item.isLeaf; - final bool isExpanded = item.isExpanded; - - return switch (data) { - final BookmarkEntry bookmark => _buildEntryTile( - context, - ref, - bookmark, - uiState, - uiStateNotifier, - isSelected, - sortedList, - ), - final BookmarkFolder folder => _buildFolderTile( - context, - ref, - folder, - isLeaf: isLeaf, - isExpanded: isExpanded, - uiState: uiState, - uiStateNotifier: uiStateNotifier, - isSelected: isSelected, - rootItem: sortedList, - ), - null => const Center(child: Text('Empty')), - }; - }, - ); - }, - error: (error, stackTrace) => Center( - child: FailureWidget( - title: 'Failed to load Bookmarks', - exception: error, - onRetry: () { - // ignore: unused_result - ref.refresh(bookmarksProvider(entryGuid)); - }, - ), - ), - loading: () => const Center(child: CircularProgressIndicator()), - ), + ), + loading: () => + const Center(child: CircularProgressIndicator()), + ), ), ), ), ); } + /// Flattens the entry folder and every expanded folder beneath it into rows. + /// + /// A folder's children are only requested once it is expanded, so a collapsed + /// subtree costs nothing — this is what keeps the screen openable after a + /// large import or sync. Watching the child providers here means expanding + /// starts the load and the row list rebuilds when it lands. + List _buildRows( + WidgetRef ref, + BookmarkFolder? folder, + BookmarkListUiState uiState, + Set expandedGuids, { + required int depth, + }) { + final rows = []; + + for (final item in _visibleChildren(folder, uiState, depth: depth)) { + rows.add(BookmarkRow(item, depth)); + + if (item is! BookmarkFolder || !expandedGuids.contains(item.guid)) { + continue; + } + + final child = ref.watch(bookmarkFolderProvider(item.guid)); + if (child.value == null) { + rows.add(BookmarkRow(item, depth + 1, isPlaceholder: true)); + continue; + } + + rows.addAll( + _buildRows(ref, child.value, uiState, expandedGuids, depth: depth + 1), + ); + } + + return rows; + } + + /// The children of [folder] in display order, with the folders-only filter + /// applied. + List _visibleChildren( + BookmarkFolder? folder, + BookmarkListUiState uiState, { + required int depth, + }) { + var children = folder?.children ?? const []; + + if (uiState.foldersOnly) { + children = children.whereType().toList(); + } + + return sortBookmarkChildren( + children, + uiState.sortType, + // Only the entry level can be the tree root, and only there do the + // built-in folders need pinning. + isRoot: depth == 0 && entryGuid == BookmarkRoot.root.id, + ); + } + + /// Renders the flattened rows lazily. + /// + /// [ListView.builder] only builds the tiles actually on screen, so expanding + /// a folder with thousands of entries stays as cheap as a small one. + Widget _buildRowList( + BuildContext context, + WidgetRef ref, + List rows, + BookmarkListUiState uiState, + BookmarkListUiStateNotifier uiStateNotifier, + ValueNotifier> expandedGuids, { + required String emptyLabel, + }) { + if (rows.isEmpty) { + return Center(child: Text(emptyLabel)); + } + + return ListView.builder( + itemCount: rows.length, + itemBuilder: (context, index) { + final row = rows[index]; + final item = row.item; + final isSelected = uiState.selectedGuids.contains(item.guid); + + return Padding( + padding: EdgeInsets.only(left: row.depth * _indentPerDepth), + child: row.isPlaceholder + ? const Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: EdgeInsets.symmetric(vertical: 12.0), + child: SizedBox( + height: 16.0, + width: 16.0, + child: CircularProgressIndicator(strokeWidth: 2.0), + ), + ), + ) + : switch (item) { + final BookmarkEntry bookmark => _buildEntryTile( + context, + ref, + bookmark, + uiState, + uiStateNotifier, + isSelected, + ), + final BookmarkFolder folder => _buildFolderTile( + context, + ref, + folder, + uiState: uiState, + uiStateNotifier: uiStateNotifier, + isSelected: isSelected, + isExpanded: expandedGuids.value.contains(folder.guid), + onToggleExpanded: () { + final next = {...expandedGuids.value}; + if (!next.remove(folder.guid)) next.add(folder.guid); + expandedGuids.value = next; + }, + ), + }, + ); + }, + ); + } + // -- App Bars -- PreferredSizeWidget _buildSelectionAppBar( @@ -239,6 +327,7 @@ class BookmarkListScreen extends HookConsumerWidget { WidgetRef ref, BookmarkListUiState uiState, BookmarkListUiStateNotifier uiStateNotifier, + List rows, ) { final count = uiState.selectedGuids.length; return AppBar( @@ -252,19 +341,21 @@ class BookmarkListScreen extends HookConsumerWidget { icon: const Icon(MdiIcons.tabPlus), tooltip: 'Open in background', onPressed: count > 0 - ? () => _bulkOpenInBackground(context, ref, uiState) + ? () => _bulkOpenInBackground(context, ref, uiState, rows) : null, ), IconButton( icon: const Icon(MdiIcons.folderMove), tooltip: 'Move selected', - onPressed: count > 0 ? () => _bulkMove(context, ref, uiState) : null, + onPressed: count > 0 + ? () => _bulkMove(context, ref, uiState, rows) + : null, ), IconButton( icon: const Icon(MdiIcons.delete), tooltip: 'Delete selected', onPressed: count > 0 - ? () => _bulkDelete(context, ref, uiState, uiStateNotifier) + ? () => _bulkDelete(context, ref, uiState, uiStateNotifier, rows) : null, ), ], @@ -274,10 +365,8 @@ class BookmarkListScreen extends HookConsumerWidget { AppBar _buildNormalAppBar( BuildContext context, WidgetRef ref, - ValueNotifier>?> - treeController, - ObjectRef> expandedGuids, ValueNotifier hideEmptyRoots, + ValueNotifier> expandedGuids, ValueNotifier textFilterEnabled, TextEditingController textFilterController, BookmarkListUiStateNotifier uiStateNotifier, @@ -315,21 +404,41 @@ class BookmarkListScreen extends HookConsumerWidget { ), MenuAnchor( menuChildren: [ + // Adding is otherwise only reachable from a child folder's row + // menu, which leaves an empty folder with no way to fill it. + // BookmarkRoot.root holds only the built-in folders, so it takes + // no children of its own. + if (entryGuid != BookmarkRoot.root.id) ...[ + MenuItemButton( + leadingIcon: const Icon(MdiIcons.bookmarkPlus), + child: const Text('Add Bookmark Here'), + onPressed: () async { + await BookmarkEntryAddRoute( + bookmarkInfo: jsonEncode( + BookmarkInfo(parentGuid: entryGuid).encode(), + ), + ).push(context); + }, + ), + MenuItemButton( + leadingIcon: const Icon(MdiIcons.folderPlus), + child: const Text('Add Subfolder Here'), + onPressed: () async { + await BookmarkFolderAddRoute( + parentGuid: entryGuid, + ).push(context); + }, + ), + ], SubmenuButton( leadingIcon: const Icon(MdiIcons.eye), menuChildren: [ MenuItemButton( - leadingIcon: const Icon(MdiIcons.expandAll), - child: const Text('Expand All'), - onPressed: () { - final controller = treeController.value; - if (controller != null) { - controller.expandAllChildren( - controller.tree, - recursive: true, - ); - } - }, + leadingIcon: const Icon(MdiIcons.collapseAll), + onPressed: expandedGuids.value.isEmpty + ? null + : () => expandedGuids.value = {}, + child: const Text('Collapse All'), ), if (entryGuid == BookmarkRoot.root.id) MenuItemButton( @@ -353,13 +462,10 @@ class BookmarkListScreen extends HookConsumerWidget { ? MdiIcons.bookmarkMultiple : MdiIcons.folderOutline, ), + onPressed: uiStateNotifier.toggleFoldersOnly, child: Text( uiState.foldersOnly ? 'Show Bookmarks' : 'Folders Only', ), - onPressed: () { - _snapshotExpansion(treeController.value, expandedGuids); - uiStateNotifier.toggleFoldersOnly(); - }, ), ], child: const Text('Visibility'), @@ -373,10 +479,7 @@ class BookmarkListScreen extends HookConsumerWidget { ? const Icon(Icons.check) : const SizedBox(width: 24), child: Text(sortType.label), - onPressed: () { - _snapshotExpansion(treeController.value, expandedGuids); - uiStateNotifier.setSortType(sortType); - }, + onPressed: () => uiStateNotifier.setSortType(sortType), ), ], child: const Text('Sort'), @@ -387,12 +490,14 @@ class BookmarkListScreen extends HookConsumerWidget { MenuItemButton( leadingIcon: const Icon(MdiIcons.codeJson), child: const Text('JSON'), - onPressed: () => _handleImport(context, ref, 'json'), + onPressed: () => + _handleImport(context, ref, BookmarkImportFormat.json), ), MenuItemButton( leadingIcon: const Icon(MdiIcons.xml), child: const Text('HTML'), - onPressed: () => _handleImport(context, ref, 'html'), + onPressed: () => + _handleImport(context, ref, BookmarkImportFormat.html), ), ], child: const Text('Import'), @@ -438,7 +543,6 @@ class BookmarkListScreen extends HookConsumerWidget { BookmarkListUiState uiState, BookmarkListUiStateNotifier uiStateNotifier, bool isSelected, - BookmarkItem? rootItem, ) { if (uiState.selectionMode) { return ListTile( @@ -463,7 +567,7 @@ class BookmarkListScreen extends HookConsumerWidget { key: ValueKey(bookmark.guid), contentPadding: EdgeInsets.zero, leading: UrlIcon([bookmark.url], iconSize: 34.0), - trailing: _buildEntryMenu(context, ref, bookmark, rootItem), + trailing: _buildEntryMenu(context, ref, bookmark), title: Text(bookmark.title, maxLines: 3, overflow: TextOverflow.ellipsis), subtitle: UriBreadcrumb(uri: bookmark.url), onTap: () async { @@ -487,7 +591,6 @@ class BookmarkListScreen extends HookConsumerWidget { BuildContext context, WidgetRef ref, BookmarkEntry bookmark, - BookmarkItem? rootItem, ) { return HookBuilder( builder: (context) { @@ -605,26 +708,21 @@ class BookmarkListScreen extends HookConsumerWidget { BuildContext context, WidgetRef ref, BookmarkFolder folder, { - required bool isLeaf, - required bool isExpanded, required BookmarkListUiState uiState, required BookmarkListUiStateNotifier uiStateNotifier, required bool isSelected, - required BookmarkItem? rootItem, + required bool isExpanded, + required VoidCallback onToggleExpanded, }) { final isRoot = bookmarkRootIds.contains(folder.guid); if (uiState.selectionMode) { return Padding( key: ValueKey(folder.guid), - padding: isLeaf - ? const EdgeInsets.only(right: 4.0) - : const EdgeInsets.only(right: 42.0), + padding: const EdgeInsets.only(right: 4.0), child: ListTile( contentPadding: EdgeInsets.zero, - leading: isExpanded - ? const Icon(MdiIcons.folderOpen) - : const Icon(MdiIcons.folder), + leading: Icon(isExpanded ? MdiIcons.folderOpen : MdiIcons.folder), title: Text(folder.title), trailing: isRoot ? null @@ -642,18 +740,21 @@ class BookmarkListScreen extends HookConsumerWidget { return Padding( key: ValueKey(folder.guid), - padding: isLeaf - ? const EdgeInsets.only(right: 4.0) - : const EdgeInsets.only(right: 42.0), + padding: const EdgeInsets.only(right: 4.0), child: HookBuilder( builder: (context) { final controller = useMenuController(); return ListTile( contentPadding: EdgeInsets.zero, - leading: isExpanded - ? const Icon(MdiIcons.folderOpen) - : const Icon(MdiIcons.folder), + // Whether a folder has children is unknown until it is opened, so + // every folder offers the toggle. Tapping the row still navigates + // into it, as it did before. + leading: IconButton( + icon: Icon(isExpanded ? MdiIcons.folderOpen : MdiIcons.folder), + tooltip: isExpanded ? 'Collapse' : 'Expand', + onPressed: onToggleExpanded, + ), title: Text(folder.title), trailing: MenuAnchor( controller: controller, @@ -777,15 +878,14 @@ class BookmarkListScreen extends HookConsumerWidget { BuildContext context, WidgetRef ref, BookmarkListUiState uiState, + List rows, ) async { - final bookmarkData = ref.read( - seamlessBookmarksProvider(entryGuid, hideEmptyRoots: true), - ); - final root = bookmarkData.value; - if (root == null) return; - - final items = resolveSelectedItems(root, uiState.selectedGuids); - final entries = items.whereType().toList(); + // Not normalised: opening is additive, so a bookmark selected inside an + // also-selected folder should still open rather than be dropped. + final entries = resolveSelectedItems([ + for (final row in rows) + if (!row.isPlaceholder) row.item, + ], uiState.selectedGuids).whereType().toList(); if (entries.isEmpty) { if (context.mounted) { @@ -820,18 +920,14 @@ class BookmarkListScreen extends HookConsumerWidget { BuildContext context, WidgetRef ref, BookmarkListUiState uiState, + List rows, ) async { - final bookmarkData = ref.read( - seamlessBookmarksProvider(entryGuid, hideEmptyRoots: true), - ); - final root = bookmarkData.value; - if (root == null) return; + final items = _selectedItems(rows, uiState.selectedGuids); + if (items.isEmpty) return; - final items = resolveSelectedItems(root, uiState.selectedGuids); - - // Build exclusion set from selected folders and their full descendant - // trees fetched from storage, so hidden folders (e.g. filtered by search) - // are still properly excluded as move targets. + // A folder cannot be moved inside itself, so exclude each selected folder + // and its descendants. Fetched from storage rather than read off the list, + // which only knows the level currently on screen. final repo = ref.read(bookmarksRepositoryProvider.notifier); final excludeGuids = {}; for (final item in items) { @@ -850,18 +946,12 @@ class BookmarkListScreen extends HookConsumerWidget { if (targetGuid == null) return; - // Normalize selection to avoid double-moves - final normalizedGuids = normalizeSelection(root, uiState.selectedGuids); - final normalizedItems = resolveSelectedItems(root, normalizedGuids); - - await ref - .read(bookmarksRepositoryProvider.notifier) - .moveMany(items: normalizedItems, targetParentGuid: targetGuid); + await repo.moveMany(items: items, targetParentGuid: targetGuid); ref.read(bookmarkListUiStateProvider.notifier).exitSelectionMode(); if (context.mounted) { - showInfoMessage(context, 'Moved ${normalizedItems.length} items'); + showInfoMessage(context, 'Moved ${items.length} items'); } } @@ -870,81 +960,56 @@ class BookmarkListScreen extends HookConsumerWidget { WidgetRef ref, BookmarkListUiState uiState, BookmarkListUiStateNotifier uiStateNotifier, + List rows, ) async { - final bookmarkData = ref.read( - seamlessBookmarksProvider(entryGuid, hideEmptyRoots: true), - ); - final root = bookmarkData.value; - if (root == null) return; + final items = _selectedItems(rows, uiState.selectedGuids); + if (items.isEmpty) return; - final items = resolveSelectedItems(root, uiState.selectedGuids); - final hasFolders = items.any((item) => item is BookmarkFolder); + final folderGuids = items + .whereType() + .map((folder) => folder.guid) + .toList(); + + // Deleting a folder takes everything under it, which the user cannot see + // from here — so say how much before asking. + final nestedCount = folderGuids.isEmpty + ? 0 + : await ref + .read(bookmarksRepositoryProvider.notifier) + .countBookmarksInTrees(folderGuids); if (!context.mounted) return; - final result = await (hasFolders - ? showDeleteFolderDialog(context) + final result = await (folderGuids.isNotEmpty + ? showDeleteFolderDialog(context, bookmarkCount: nestedCount) : showDeleteBookmarkDialog(context)); if (result != true) return; - // Normalize to avoid deleting children whose parent folder is also being deleted - final normalizedGuids = normalizeSelection(root, uiState.selectedGuids); - - await ref - .read(bookmarksRepositoryProvider.notifier) - .deleteMany(normalizedGuids); + final guids = items.map((item) => item.guid).toSet(); + await ref.read(bookmarksRepositoryProvider.notifier).deleteMany(guids); uiStateNotifier.exitSelectionMode(); if (context.mounted) { - showInfoMessage(context, 'Deleted ${normalizedGuids.length} items'); + showInfoMessage(context, 'Deleted ${guids.length} items'); } } - // -- Tree Expansion State Helpers -- - - /// Collects the GUIDs of all currently expanded nodes from the tree. - void _snapshotExpansion( - TreeViewController>? controller, - ObjectRef> expandedGuids, + /// The selected items, with anything nested inside another selected folder + /// dropped. + /// + /// Expanding a folder puts its children on screen next to it, so a user can + /// select both — acting on each in turn would move a child out of the folder + /// that just moved, or delete it a second time. + List _selectedItems( + List rows, + Set selectedGuids, ) { - if (controller == null) return; - final guids = {}; - _collectExpandedGuids(controller.tree, guids); - expandedGuids.value = guids; - } + final guids = normalizeSelection(rows, selectedGuids); - void _collectExpandedGuids(TreeNode node, Set guids) { - if (node.isExpanded && node.key != INode.ROOT_KEY) { - guids.add(node.key); - } - for (final child in node.childrenAsList) { - _collectExpandedGuids(child as TreeNode, guids); - } - } - - /// Restores expansion state by expanding nodes whose GUIDs are in the set. - void _restoreExpansion( - TreeViewController> controller, - TreeNode root, - Set guids, - ) { - // Always expand root - controller.expandNode(root); - _expandMatchingNodes(controller, root, guids); - } - - void _expandMatchingNodes( - TreeViewController> controller, - TreeNode node, - Set guids, - ) { - for (final child in node.childrenAsList) { - final typedChild = child as TreeNode; - if (guids.contains(typedChild.key)) { - controller.expandNode(typedChild); - } - _expandMatchingNodes(controller, typedChild, guids); - } + return resolveSelectedItems([ + for (final row in rows) + if (!row.isPlaceholder) row.item, + ], guids); } // -- Tab Opening Helper -- @@ -995,12 +1060,14 @@ class BookmarkListScreen extends HookConsumerWidget { Future _handleImport( BuildContext context, WidgetRef ref, - String format, + BookmarkImportFormat format, ) async { try { final result = await FilePicker.pickFiles( type: FileType.custom, - allowedExtensions: format == 'json' ? ['json'] : ['html', 'htm'], + allowedExtensions: format == BookmarkImportFormat.json + ? ['json'] + : ['html', 'htm'], ); if (result == null || result.files.isEmpty) return; @@ -1019,12 +1086,15 @@ class BookmarkListScreen extends HookConsumerWidget { 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, replace: shouldReplace) - : await repository.importFromHTML(content, replace: shouldReplace); + // Reading and parsing happen in a background isolate, so a large file + // does not freeze the UI while it is being processed. + final count = await ref + .read(bookmarksRepositoryProvider.notifier) + .importFromFile( + path: file.path!, + format: format, + replace: shouldReplace, + ); if (context.mounted) { showInfoMessage(context, 'Imported $count bookmarks successfully'); diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/widgets/folder_tree_picker.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/widgets/folder_tree_picker.dart index 8a1d6617..78db0c7f 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/widgets/folder_tree_picker.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/presentation/widgets/folder_tree_picker.dart @@ -17,7 +17,6 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import 'package:animated_tree_view/animated_tree_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; @@ -28,11 +27,19 @@ import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/b import 'package:weblibre/features/geckoview/features/bookmarks/domain/providers/bookmarks.dart'; import 'package:weblibre/presentation/widgets/failure_widget.dart'; +/// Indentation applied per level of folder nesting. +const _indentPerDepth = 20.0; + /// A widget that displays a tree view of bookmark folders and allows the user /// to select a parent folder. /// +/// Folders are loaded one level at a time as the user expands them, so opening +/// the picker never pulls in the whole bookmark tree. +/// /// When editing a folder, pass [excludeFolderGuids] to prevent selecting the -/// folders or their descendants as the parent (which would create a circular reference). +/// folders or their descendants as the parent (which would create a circular +/// reference). Descendants are excluded implicitly: an excluded folder is never +/// rendered, so nothing underneath it can be reached or expanded. class FolderTreePicker extends HookConsumerWidget { /// The currently selected folder GUID final ValueNotifier selectedFolderGuid; @@ -52,99 +59,39 @@ class FolderTreePicker extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final treeKey = useMemoized(() => GlobalKey()); + // Folders start collapsed apart from the entry point, so the picker opens + // after a single shallow load. + final expandedGuids = useState({entryGuid}); - final folderList = ref.watch(bookmarksProvider(entryGuid)); + final rootFolder = ref.watch(bookmarkFolderProvider(entryGuid)); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Folder', style: Theme.of(context).textTheme.labelMedium), - folderList.when( + rootFolder.when( skipLoadingOnReload: true, - data: (list) { - TreeNode addChildren( - TreeNode? parent, - BookmarkFolder item, - ) { - final node = TreeNode(key: item.guid, data: item, parent: parent); - final targetNode = (parent?..add(node)) ?? node; + data: (folder) { + if (folder == null) return const SizedBox.shrink(); - if (item.children != null) { - for (final child in item.children!) { - // Skip excluded folders and their descendants - if (child is BookmarkFolder && - !excludeFolderGuids.contains(child.guid)) { - addChildren(node, child); - } - } - } - - return targetNode; - } - - final root = (list != null) - ? addChildren(null, list) - : TreeNode.root(); - - return TreeView.simple( - key: treeKey, - tree: root, - shrinkWrap: true, - showRootNode: entryGuid != BookmarkRoot.root.id, - onTreeReady: (controller) { - controller.expandAllChildren(root, recursive: true); - }, - expansionIndicatorBuilder: (context, tree) => - ChevronIndicator.upDown( - tree: tree, - padding: const EdgeInsets.symmetric( - vertical: 16.0, - horizontal: 12.0, - ), + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (entryGuid != BookmarkRoot.root.id) + _FolderRow( + folder: folder, + depth: 0, + expandedGuids: expandedGuids, + selectedFolderGuid: selectedFolderGuid, ), - builder: (context, item) { - final isSelected = item.data?.guid == selectedFolderGuid.value; - - // BookmarkRoot.root cannot be selected as a parent - final isRootFolder = item.data?.guid == BookmarkRoot.root.id; - - return Padding( - padding: const EdgeInsets.only(right: 42.0), - child: switch (item.data) { - final BookmarkFolder folder => ListTile( - key: ValueKey(folder.guid), - contentPadding: EdgeInsets.zero, - selected: isSelected, - enabled: !isRootFolder, - leading: (item.isExpanded) - ? const Icon(MdiIcons.folderOpen) - : const Icon(MdiIcons.folder), - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (isSelected) const Icon(Icons.check), - IconButton( - onPressed: () async { - await BookmarkFolderAddRoute( - parentGuid: folder.guid, - ).push(context); - }, - icon: const Icon(MdiIcons.folderPlus), - ), - ], - ), - title: Text(folder.title), - onTap: !isRootFolder - ? () { - selectedFolderGuid.value = folder.guid; - } - : null, - ), - null => const SizedBox.shrink(), - }, - ); - }, + _FolderChildren( + parentGuid: folder.guid, + depth: entryGuid != BookmarkRoot.root.id ? 1 : 0, + expandedGuids: expandedGuids, + selectedFolderGuid: selectedFolderGuid, + excludeFolderGuids: excludeFolderGuids, + ), + ], ); }, error: (error, stackTrace) => Center( @@ -152,7 +99,7 @@ class FolderTreePicker extends HookConsumerWidget { title: 'Failed to load Bookmark Folders', exception: error, onRetry: () { - ref.invalidate(bookmarksProvider(entryGuid)); + ref.invalidate(bookmarkFolderProvider(entryGuid)); }, ), ), @@ -162,3 +109,133 @@ class FolderTreePicker extends HookConsumerWidget { ); } } + +/// The direct subfolders of [parentGuid], rendered only while its parent is +/// expanded. +/// +/// Mounting this widget is what triggers the load, so a collapsed folder costs +/// nothing. +class _FolderChildren extends HookConsumerWidget { + final String parentGuid; + final int depth; + final ValueNotifier> expandedGuids; + final ValueNotifier selectedFolderGuid; + final Set excludeFolderGuids; + + const _FolderChildren({ + required this.parentGuid, + required this.depth, + required this.expandedGuids, + required this.selectedFolderGuid, + required this.excludeFolderGuids, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final folder = ref.watch(bookmarkFolderProvider(parentGuid)); + + final subfolders = (folder.value?.children ?? const []) + .whereType() + .where((child) => !excludeFolderGuids.contains(child.guid)) + .toList(); + + if (folder.isLoading && folder.value == null) { + return Padding( + padding: EdgeInsets.only(left: depth * _indentPerDepth, top: 8.0), + child: const Align( + alignment: Alignment.centerLeft, + child: SizedBox( + height: 16.0, + width: 16.0, + child: CircularProgressIndicator(strokeWidth: 2.0), + ), + ), + ); + } + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + for (final subfolder in subfolders) ...[ + _FolderRow( + folder: subfolder, + depth: depth, + expandedGuids: expandedGuids, + selectedFolderGuid: selectedFolderGuid, + ), + if (expandedGuids.value.contains(subfolder.guid)) + _FolderChildren( + parentGuid: subfolder.guid, + depth: depth + 1, + expandedGuids: expandedGuids, + selectedFolderGuid: selectedFolderGuid, + excludeFolderGuids: excludeFolderGuids, + ), + ], + ], + ); + } +} + +class _FolderRow extends HookConsumerWidget { + final BookmarkFolder folder; + final int depth; + final ValueNotifier> expandedGuids; + final ValueNotifier selectedFolderGuid; + + const _FolderRow({ + required this.folder, + required this.depth, + required this.expandedGuids, + required this.selectedFolderGuid, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final isExpanded = expandedGuids.value.contains(folder.guid); + final isSelected = folder.guid == selectedFolderGuid.value; + + // BookmarkRoot.root cannot be selected as a parent + final isRootFolder = folder.guid == BookmarkRoot.root.id; + + return Padding( + padding: EdgeInsets.only(left: depth * _indentPerDepth, right: 42.0), + child: ListTile( + key: ValueKey(folder.guid), + contentPadding: EdgeInsets.zero, + selected: isSelected, + enabled: !isRootFolder, + // Whether a folder has subfolders is unknown until it is opened, so + // every folder offers the toggle. + leading: IconButton( + icon: Icon(isExpanded ? MdiIcons.folderOpen : MdiIcons.folder), + onPressed: () { + expandedGuids.value = isExpanded + ? ({...expandedGuids.value}..remove(folder.guid)) + : ({...expandedGuids.value}..add(folder.guid)); + }, + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (isSelected) const Icon(Icons.check), + IconButton( + onPressed: () async { + await BookmarkFolderAddRoute( + parentGuid: folder.guid, + ).push(context); + }, + icon: const Icon(MdiIcons.folderPlus), + ), + ], + ), + title: Text(folder.title), + onTap: !isRootFolder + ? () { + selectedFolderGuid.value = folder.guid; + } + : null, + ), + ); + } +} diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart index 8c08da51..8108ca27 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart @@ -20,7 +20,8 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:html/dom.dart' as dom; import 'package:html/parser.dart' as html_parser; -import 'package:weblibre/core/logger.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_importer.dart'; const _containerNormal = 0; const _containerToolbar = 1; @@ -30,18 +31,22 @@ const _containerPlaces = 4; const _exportIndent = ' '; -class _Frame { - final Map folder; - int containerNesting = 0; - int lastContainerType = _containerNormal; - String previousText = ''; - bool inDescription = false; - String? previousLink; - Map? previousItem; - DateTime? previousDateAdded; - DateTime? previousLastModifiedDate; - - _Frame(this.folder); +/// Parses a Netscape bookmark file into an [ImportBookmarkTree]. +/// +/// Pure and free of platform channels, so it is safe to run inside an isolate; +/// see `bookmark_import_isolate.dart`. +/// +/// When [preserveRootFolders] is set, folders carrying Firefox root markers +/// (`PERSONAL_TOOLBAR_FOLDER`, `BOOKMARKS_MENU`, `UNFILED_BOOKMARKS_FOLDER`, +/// `PLACES_ROOT`) at the top level are routed to the matching Places root +/// instead of being imported as ordinary folders. Everything else lands under +/// [BookmarkRoot.menu]. +ImportBookmarkTree parseBookmarkHtml( + String htmlString, { + required bool preserveRootFolders, +}) { + final parser = _BookmarkHtmlParser(preserveRootFolders: preserveRootFolders); + return parser.parse(htmlString); } class BookmarkHTMLUtils { @@ -50,9 +55,9 @@ class BookmarkHTMLUtils { BookmarkHTMLUtils(this._service); /// Import bookmarks from HTML string - Future importFromHTML(String htmlString, {bool replace = false}) async { - final importer = _BookmarkImporter(_service, replace); - return await importer.importFromHTML(htmlString); + Future importFromHTML(String htmlString, {bool replace = false}) { + final tree = parseBookmarkHtml(htmlString, preserveRootFolders: replace); + return BookmarkTreeImporter(_service).import(tree, replace: replace); } /// Export bookmarks to HTML string @@ -67,27 +72,80 @@ class BookmarkHTMLUtils { } } -class _BookmarkImporter { - final GeckoBookmarksService _service; - final bool _isImportDefaults; - final Map _bookmarkTree; +/// A node collected while parsing. +/// +/// Folders stay mutable until their closing tag so children can be appended in +/// place; leaves are immutable as soon as they are complete. +sealed class _ParsedNode {} + +final class _ParsedLeaf extends _ParsedNode { + final ImportBookmarkNode node; + + _ParsedLeaf(this.node); +} + +final class _ParsedFolder extends _ParsedNode { + String title = ''; + + /// Set when the folder carried a Firefox root marker, naming the Places root + /// its children belong to. + String? rootGuid; + DateTime? dateAdded; + DateTime? lastModified; + final List<_ParsedNode> children = []; +} + +/// A bookmark whose `` tag has been opened but whose title text has not been +/// read yet. +class _PendingItem { + final Uri url; + final DateTime? dateAdded; + final DateTime? lastModified; + + _PendingItem({required this.url, this.dateAdded, this.lastModified}); +} + +class _Frame { + final _ParsedFolder folder; + int containerNesting = 0; + int lastContainerType = _containerNormal; + String previousText = ''; + bool inDescription = false; + _PendingItem? pendingItem; + DateTime? previousDateAdded; + DateTime? previousLastModifiedDate; + + _Frame(this.folder); +} + +class _BookmarkHtmlParser { + final bool preserveRootFolders; + + final _ParsedFolder _root = _ParsedFolder(); final List<_Frame> _frames = []; - _BookmarkImporter(this._service, this._isImportDefaults) - : _bookmarkTree = { - 'type': BookmarkNodeType.folder.index, - 'guid': BookmarkRoot.menu.id, - 'children': >[], - } { - _frames.add(_Frame(_bookmarkTree)); + int _bookmarkCount = 0; + int _folderCount = 0; + int _separatorCount = 0; + int _skippedUrlCount = 0; + + _BookmarkHtmlParser({required this.preserveRootFolders}) { + _frames.add(_Frame(_root)); } _Frame get _curFrame => _frames.last; - Future importFromHTML(String htmlString) async { + ImportBookmarkTree parse(String htmlString) { final document = html_parser.parse(htmlString); _walkTreeForImport(document.body); - return await _importBookmarks(); + + // Close whatever the document left open so nothing is dropped. + while (_frames.length > 1) { + _popFrame(); + } + _flushPendingItem(); + + return _buildTree(); } dom.Node? _nextSibling(dom.Node node) { @@ -186,29 +244,30 @@ class _BookmarkImporter { } void _handleHeadBegin(dom.Element element) { - final frame = _curFrame; - - frame.previousLink = null; - frame.lastContainerType = _containerNormal; - - if (frame.containerNesting == 0 && _frames.length > 1) { - _frames.removeLast(); + // A heading that arrives while the current folder never opened its `
` + // closes that folder first. Everything below must describe the *new* + // heading, so the frame is only captured once the stack has settled. + if (_curFrame.containerNesting == 0 && _frames.length > 1) { + _popFrame(); } + final frame = _curFrame; + frame.lastContainerType = _containerNormal; + if (element.attributes.containsKey('personal_toolbar_folder')) { - if (_isImportDefaults) { + if (preserveRootFolders) { frame.lastContainerType = _containerToolbar; } } else if (element.attributes.containsKey('bookmarks_menu')) { - if (_isImportDefaults) { + if (preserveRootFolders) { frame.lastContainerType = _containerMenu; } } else if (element.attributes.containsKey('unfiled_bookmarks_folder')) { - if (_isImportDefaults) { + if (preserveRootFolders) { frame.lastContainerType = _containerUnfiled; } } else if (element.attributes.containsKey('places_root')) { - if (_isImportDefaults) { + if (preserveRootFolders) { frame.lastContainerType = _containerPlaces; } } else { @@ -227,67 +286,76 @@ class _BookmarkImporter { } void _handleLinkBegin(dom.Element element) { - final frame = _curFrame; + // An unterminated `` must not swallow the one that follows it. + _flushPendingItem(); - frame.previousItem = null; + final frame = _curFrame; frame.previousText = ''; + // TAGS, SHORTCUTURL, POST_DATA and LAST_CHARSET are read by Firefox but + // have no representation in Places' bookmark storage, so they are dropped. final href = element.attributes['href']?.trim(); final dateAdded = element.attributes['add_date']?.trim(); final lastModified = element.attributes['last_modified']?.trim(); - final tags = element.attributes['tags']?.trim(); - final keyword = element.attributes['shortcuturl']?.trim(); - final postData = element.attributes['post_data']?.trim(); - final lastCharset = element.attributes['last_charset']?.trim(); if (href == null || href.isEmpty) { - frame.previousLink = null; + _skippedUrlCount++; return; } + final Uri url; try { final uri = Uri.parse(href); if (!uri.hasScheme) { - frame.previousLink = null; + _skippedUrlCount++; return; } - frame.previousLink = uri.toString(); + url = uri; } catch (e) { - frame.previousLink = null; + _skippedUrlCount++; return; } - final bookmark = {'url': frame.previousLink}; + final lastModifiedDate = lastModified != null + ? _convertImportedDateToInternalDate(lastModified) + : null; - if (dateAdded != null) { - bookmark['dateAdded'] = _convertImportedDateToInternalDate( - dateAdded, - ).millisecondsSinceEpoch; - } - if (lastModified != null) { - bookmark['lastModified'] = _convertImportedDateToInternalDate( - lastModified, - ).millisecondsSinceEpoch; - } - if (dateAdded == null && lastModified != null) { - bookmark['dateAdded'] = bookmark['lastModified']; - } + frame.pendingItem = _PendingItem( + url: url, + // A bookmark that only records a modification time is treated as having + // been added then, matching Firefox's own importer. + dateAdded: dateAdded != null + ? _convertImportedDateToInternalDate(dateAdded) + : lastModifiedDate, + lastModified: lastModifiedDate, + ); + } - if (tags != null && tags.isNotEmpty) { - bookmark['tags'] = tags; - } - if (keyword != null && keyword.isNotEmpty) { - bookmark['keyword'] = keyword; - } - if (postData != null && postData.isNotEmpty) { - bookmark['postData'] = postData; - } - if (lastCharset != null && lastCharset.isNotEmpty) { - bookmark['charset'] = lastCharset; - } + /// Materialises the frame's open bookmark, if any, using [title]. + void _flushPendingItem({String title = ''}) { + final frame = _curFrame; + final pending = frame.pendingItem; + if (pending == null) return; - (frame.folder['children'] as List).add(bookmark); - frame.previousItem = bookmark; + frame.pendingItem = null; + frame.folder.children.add( + _ParsedLeaf( + ImportBookmarkItem( + url: pending.url, + title: title, + dateAdded: pending.dateAdded, + lastModified: pending.lastModified, + ), + ), + ); + _bookmarkCount++; + } + + /// Completes the innermost folder and hands it to its parent. + void _popFrame() { + _flushPendingItem(); + final frame = _frames.removeLast(); + _curFrame.folder.children.add(frame.folder); } void _handleContainerBegin() { @@ -300,7 +368,7 @@ class _BookmarkImporter { frame.containerNesting--; } if (_frames.length > 1 && frame.containerNesting == 0) { - _frames.removeLast(); + _popFrame(); } } @@ -310,163 +378,111 @@ class _BookmarkImporter { void _handleLinkEnd() { final frame = _curFrame; - frame.previousText = frame.previousText.trim(); - - if (frame.previousItem != null) { - frame.previousItem!['title'] = frame.previousText; - } - + _flushPendingItem(title: frame.previousText.trim()); frame.previousText = ''; } void _handleSeparator() { - final frame = _curFrame; - final separator = { - 'type': BookmarkNodeType.separator.index, - }; - (frame.folder['children'] as List).add(separator); - frame.previousItem = separator; + _flushPendingItem(); + _curFrame.folder.children.add(_ParsedLeaf(const ImportBookmarkSeparator())); + _separatorCount++; } void _newFrame() { + _flushPendingItem(); + final frame = _curFrame; final containerTitle = frame.previousText; frame.previousText = ''; - final containerType = frame.lastContainerType; - final folder = { - 'children': >[], - 'type': BookmarkNodeType.folder.index, - }; + final folder = _ParsedFolder(); - switch (containerType) { + switch (frame.lastContainerType) { case _containerNormal: - folder['title'] = containerTitle; + folder.title = containerTitle; case _containerPlaces: - folder['guid'] = BookmarkRoot.root.id; + folder.rootGuid = BookmarkRoot.root.id; case _containerMenu: - folder['guid'] = BookmarkRoot.menu.id; + folder.rootGuid = BookmarkRoot.menu.id; case _containerUnfiled: - folder['guid'] = BookmarkRoot.unfiled.id; + folder.rootGuid = BookmarkRoot.unfiled.id; case _containerToolbar: - folder['guid'] = BookmarkRoot.toolbar.id; + folder.rootGuid = BookmarkRoot.toolbar.id; } - (frame.folder['children'] as List).add(folder); + folder.lastModified = frame.previousLastModifiedDate; + // As for items, a folder that only records a modification time is treated + // as having been created then. + folder.dateAdded = frame.previousDateAdded ?? folder.lastModified; + frame.previousDateAdded = null; + frame.previousLastModifiedDate = null; - if (frame.previousDateAdded != null) { - folder['dateAdded'] = frame.previousDateAdded!.millisecondsSinceEpoch; - frame.previousDateAdded = null; - } - if (frame.previousLastModifiedDate != null) { - folder['lastModified'] = - frame.previousLastModifiedDate!.millisecondsSinceEpoch; - frame.previousLastModifiedDate = null; - } - if (!folder.containsKey('dateAdded') && - folder.containsKey('lastModified')) { - folder['dateAdded'] = folder['lastModified']; - } - - frame.previousItem = folder; _frames.add(_Frame(folder)); } DateTime _convertImportedDateToInternalDate(String seconds) { - try { - final parsed = int.tryParse(seconds); - if (parsed != null) { - return DateTime.fromMillisecondsSinceEpoch(parsed * 1000); - } - } catch (e) { - // Fall through + final parsed = int.tryParse(seconds); + if (parsed != null) { + return DateTime.fromMillisecondsSinceEpoch(parsed * 1000); } return DateTime.now(); } - List> _getBookmarkTrees() { - if (!_isImportDefaults) { - return [_bookmarkTree]; + /// Groups the parsed top level into per-root sections. + /// + /// Only top-level folders carrying a root marker are routed to their own + /// Places root; a marker deeper in the file describes a folder that Firefox + /// itself would have nested, so it is imported as an ordinary (untitled) + /// folder. + ImportBookmarkTree _buildTree() { + final menuNodes = []; + final rootSections = >{}; + + for (final child in _root.children) { + if (child is _ParsedFolder && child.rootGuid != null) { + rootSections + .putIfAbsent(child.rootGuid!, () => []) + .addAll(child.children.map(_toImmutable)); + } else { + menuNodes.add(_toImmutable(child)); + } } - final bookmarkTrees = >[_bookmarkTree]; - final children = _bookmarkTree['children'] as List>; + final sections = >{ + if (menuNodes.isNotEmpty) BookmarkRoot.menu.id: menuNodes, + }; + for (final section in rootSections.entries) { + sections.update( + section.key, + (existing) => existing..addAll(section.value), + ifAbsent: () => section.value, + ); + } - _bookmarkTree['children'] = children.where((child) { - final guid = child['guid'] as String?; - if (guid != null && bookmarkRootIds.contains(guid)) { - bookmarkTrees.add(child); - return false; - } - return true; - }).toList(); - - return bookmarkTrees; + return ImportBookmarkTree( + sections: sections, + stats: ImportBookmarkStats( + bookmarkCount: _bookmarkCount, + folderCount: _folderCount, + separatorCount: _separatorCount, + skippedUrlCount: _skippedUrlCount, + ), + ); } - Future _importBookmarks() async { - if (_isImportDefaults) { - // 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); - } - } + ImportBookmarkNode _toImmutable(_ParsedNode node) { + switch (node) { + case final _ParsedLeaf leaf: + return leaf.node; + case final _ParsedFolder folder: + _folderCount++; + return ImportBookmarkFolder( + title: folder.title, + children: folder.children.map(_toImmutable).toList(), + dateAdded: folder.dateAdded, + lastModified: folder.lastModified, + ); } - - final bookmarkTrees = _getBookmarkTrees(); - int bookmarkCount = 0; - - for (final tree in bookmarkTrees) { - final children = tree['children'] as List?; - if (children == null || children.isEmpty) continue; - - bookmarkCount += await _insertTree(tree); - } - - return bookmarkCount; - } - - Future _insertTree(Map node) async { - int count = 0; - final children = node['children'] as List?; - - if (children == null || children.isEmpty) return 0; - - final parentGuid = node['guid'] as String; - - for (int i = 0; i < children.length; i++) { - final child = children[i] as Map; - final type = child['type'] as int? ?? BookmarkNodeType.item.index; - - if (type == BookmarkNodeType.item.index) { - final url = child['url'] as String?; - final title = child['title'] as String? ?? ''; - - if (url != null && url.isNotEmpty) { - try { - final uri = Uri.parse(url); - if (uri.hasScheme) { - await _service.addItem(parentGuid, uri, title, i); - count++; - } - } catch (e) { - logger.e('Failed to import bookmark "$title": $e'); - } - } - } else if (type == BookmarkNodeType.folder.index) { - final title = child['title'] as String? ?? ''; - try { - final newGuid = await _service.addFolder(parentGuid, title, i); - child['guid'] = newGuid; - count += await _insertTree(child); - } catch (e) { - logger.e('Failed to import folder "$title": $e'); - } - } - } - - return count; } } diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_import_isolate.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_import_isolate.dart new file mode 100644 index 00000000..a4b0284e --- /dev/null +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_import_isolate.dart @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024-2026 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 'dart:io'; +import 'dart:isolate'; + +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart'; + +/// The bookmark file formats WebLibre can read. +enum BookmarkImportFormat { html, json } + +/// Reads and parses the bookmark file at [path] in a background isolate. +/// +/// Both the file read and the parse happen off the UI isolate, so a large +/// export — the reported problem case is around 25k bookmarks — does not block +/// frames. Only the resulting [ImportBookmarkTree] crosses back, which is far +/// smaller than the HTML DOM or decoded JSON it was built from. +/// +/// The file is read inside the isolate rather than handed over as a string, so +/// the UI isolate never holds the raw document in memory. +Future parseBookmarkFile({ + required String path, + required BookmarkImportFormat format, + required bool preserveRootFolders, +}) { + return Isolate.run( + () => _parseBookmarkFile(path, format, preserveRootFolders), + debugName: 'bookmark-import-parse', + ); +} + +/// Runs inside the spawned isolate; must stay free of platform channels and of +/// anything tied to the UI isolate's state. +ImportBookmarkTree _parseBookmarkFile( + String path, + BookmarkImportFormat format, + bool preserveRootFolders, +) { + final content = File(path).readAsStringSync(); + + return switch (format) { + BookmarkImportFormat.html => parseBookmarkHtml( + content, + preserveRootFolders: preserveRootFolders, + ), + BookmarkImportFormat.json => parseBookmarkJson(content), + }; +} diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_importer.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_importer.dart new file mode 100644 index 00000000..75059252 --- /dev/null +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_importer.dart @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024-2026 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_mozilla_components/flutter_mozilla_components.dart'; +import 'package:weblibre/core/logger.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart'; + +/// Writes a parsed [ImportBookmarkTree] into Places. +/// +/// Insertion is bulk: one native call per destination root, with each top-level +/// folder written as a single storage tree insertion. A 25k-bookmark file +/// therefore costs a handful of platform channel round trips rather than one +/// per node. +class BookmarkTreeImporter { + final GeckoBookmarksService _service; + + const BookmarkTreeImporter(this._service); + + /// Inserts [tree] and returns the number of bookmark items written. + /// + /// When [replace] is set every root except [BookmarkRoot.root] is emptied + /// first; the root itself is never deleted. A tree that parsed to nothing + /// erases nothing either, so a malformed or empty file cannot wipe the + /// user's bookmarks and leave them with an empty library. + Future import(ImportBookmarkTree tree, {required bool replace}) async { + if (tree.isEmpty) return 0; + + if (replace) { + for (final root in BookmarkRoot.values) { + if (root != BookmarkRoot.root) { + await _service.eraseEverything(root); + } + } + } + + var importedCount = 0; + + for (final section in tree.sections.entries) { + if (section.value.isEmpty) continue; + + final result = await _service.insertTree( + section.key, + section.value.map(toPigeonImportNode).toList(), + ); + + importedCount += result.insertedItemCount; + + if (result.failedNodeCount > 0) { + logger.e( + 'Failed to import ${result.failedNodeCount} top-level nodes into ${section.key}', + ); + } + } + + return importedCount; + } +} + +/// Converts a parsed node into the Pigeon transport type. +/// +/// Timestamps become milliseconds since epoch, with 0 standing in for "the file +/// did not say", which is what Places expects for an unknown timestamp. +BookmarkImportNode toPigeonImportNode(ImportBookmarkNode node) { + return switch (node) { + final ImportBookmarkFolder folder => BookmarkImportNode( + type: BookmarkNodeType.folder, + title: folder.title, + url: null, + dateAdded: _toMillis(folder.dateAdded), + lastModified: _toMillis(folder.lastModified), + children: folder.children.map(toPigeonImportNode).toList(), + ), + final ImportBookmarkItem item => BookmarkImportNode( + type: BookmarkNodeType.item, + title: item.title, + url: item.url.toString(), + dateAdded: _toMillis(item.dateAdded), + lastModified: _toMillis(item.lastModified), + children: const [], + ), + final ImportBookmarkSeparator separator => BookmarkImportNode( + type: BookmarkNodeType.separator, + title: null, + url: null, + dateAdded: _toMillis(separator.dateAdded), + lastModified: _toMillis(separator.lastModified), + children: const [], + ), + }; +} + +int _toMillis(DateTime? value) => value?.millisecondsSinceEpoch ?? 0; diff --git a/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart b/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart index 4b534f69..8e0c7a08 100644 --- a/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart +++ b/apps/weblibre/lib/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart @@ -23,8 +23,28 @@ import 'dart:convert'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:weblibre/core/logger.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_importer.dart'; import 'package:weblibre/utils/uri_input_parser.dart'; +/// Parses a Firefox JSON bookmark backup into an [ImportBookmarkTree]. +/// +/// Pure and free of platform channels, so it is safe to run inside an isolate; +/// see `bookmark_import_isolate.dart`. +/// +/// Only top-level nodes that identify themselves as a Places root are imported, +/// each into its matching root. `place:` query URLs have their folder ids +/// rewritten to guids, and the tags folder is ignored. +ImportBookmarkTree parseBookmarkJson(String jsonString) { + final data = jsonDecode(jsonString); + + if (data is! Map) { + throw const FormatException('Invalid JSON format'); + } + + return const _BookmarkJsonParser().parse(data); +} + class BookmarkJSONUtils { final GeckoBookmarksService _service; @@ -33,18 +53,10 @@ class BookmarkJSONUtils { /// Import bookmarks from JSON string Future importFromJSON(String jsonString, {bool replace = false}) async { try { - final data = jsonDecode(jsonString); - - if (data is! Map) { - throw Exception('Invalid JSON format'); - } - - final children = data['children'] as List?; - if (children == null || children.isEmpty) { - return 0; - } - - return await _import(data, replace: replace); + final tree = parseBookmarkJson(jsonString); + return await BookmarkTreeImporter( + _service, + ).import(tree, replace: replace); } catch (ex) { logger.e('Failed to import bookmarks: $ex'); rethrow; @@ -63,206 +75,6 @@ class BookmarkJSONUtils { return _nodeToJson(tree, isRoot: true); } - /// Import implementation - Future _import( - Map rootNode, { - required bool replace, - }) async { - final nodes = - (rootNode['children'] as List?) - ?.whereType>() - .where( - (node) => - node['root'] != 'tagsFolder' && - node['guid'] != 'tags________', - ) - .toList() ?? - []; - - if (nodes.isEmpty) { - return 0; - } - - // If replacing, erase existing bookmarks first - if (replace) { - // 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 = {}; - - // Translate tree types and build folder map - for (final node in nodes) { - if (node['children'] == null || (node['children'] as List).isEmpty) { - continue; - } - - final folders = _translateTreeTypes(node); - folderIdToGuidMap.addAll(folders); - } - - int bookmarkCount = 0; - - // Insert nodes - for (final node in nodes) { - if (node['children'] == null || (node['children'] as List).isEmpty) { - continue; - } - - final guid = node['guid'] as String?; - if (guid == null || !bookmarkRootIds.contains(guid)) { - continue; - } - - _fixupSearchQueries(node, folderIdToGuidMap); - - // Insert the tree recursively - bookmarkCount += await _insertTree(node, folderIdToGuidMap); - } - - return bookmarkCount; - } - - /// Recursively insert bookmark tree - Future _insertTree( - Map node, - Map folderIdToGuidMap, - ) async { - int count = 0; - final children = node['children'] as List?; - - if (children == null || children.isEmpty) { - return 0; - } - - final parentGuid = node['guid'] as String; - - for (int i = 0; i < children.length; i++) { - final child = children[i] as Map; - final type = _getNodeType(child); - - if (type == BookmarkNodeType.item) { - final url = _getNodeUrl(child); - final title = child['title'] as String? ?? ''; - - if (url != null && url.isNotEmpty) { - try { - // Validate URL before inserting - final uri = Uri.tryParse(url); - if (uri != null && uri.hasScheme) { - await _service.addItem(parentGuid, uri, title, i); - count++; - } else { - final parsed = Uri.tryParse(url); - final redacted = parsed != null - ? redactUriCredentials(parsed) - : url; - logger.w('Skipping invalid URL: $redacted'); - } - } catch (e) { - logger.e('Failed to import bookmark "$title": $e'); - } - } - } else if (type == BookmarkNodeType.folder) { - final title = child['title'] as String? ?? ''; - try { - final newGuid = await _service.addFolder(parentGuid, title, i); - child['guid'] = newGuid; - - // Recursively insert children - count += await _insertTree(child, folderIdToGuidMap); - } catch (e) { - logger.e('Failed to import folder "$title": $e'); - } - } - // Note: Separators are not supported by the Android API - } - - return count; - } - - /// Translate tree types from JSON format to internal format - Map _translateTreeTypes(Map node) { - final folderIdToGuidMap = {}; - - _normalizeNodeUrl(node); - - final type = node['type']; - if (type == 'text/x-moz-place-container') { - node['type'] = BookmarkNodeType.folder.index; - - final id = node['id']?.toString(); - final guid = node['guid'] as String?; - if (id != null && guid != null) { - folderIdToGuidMap[id] = guid; - } - } else if (type == 'text/x-moz-place') { - node['type'] = BookmarkNodeType.item.index; - } else if (type == 'text/x-moz-place-separator') { - node['type'] = BookmarkNodeType.separator.index; - node.remove('title'); - } - - final children = node['children'] as List?; - if (children != null) { - for (final child in children) { - if (child is Map) { - folderIdToGuidMap.addAll(_translateTreeTypes(child)); - } - } - } - - return folderIdToGuidMap; - } - - /// Fix up search queries with folder mappings - void _fixupSearchQueries( - Map node, - Map folderIdToGuidMap, - ) { - final url = _getNodeUrl(node); - if (url != null && url.startsWith('place:')) { - node['url'] = _fixupQuery(url, folderIdToGuidMap); - } - - final children = node['children'] as List?; - if (children != null) { - for (final child in children) { - if (child is Map) { - _fixupSearchQueries(child, folderIdToGuidMap); - } - } - } - } - - /// Replace folder IDs with GUIDs in place: URIs - String _fixupQuery(String queryURL, Map folderIdToGuidMap) { - final regex = RegExp(r'folder=([A-Za-z0-9_]+)'); - bool invalid = false; - - final result = queryURL.replaceAllMapped(regex, (match) { - final folderId = match.group(1)!; - final guid = folderIdToGuidMap[folderId]; - - if (guid == null) { - invalid = true; - return 'invalidOldParentId=$folderId'; - } - - return 'parent=$guid'; - }); - - if (invalid) { - return '$result&excludeItems=1'; - } - - return result; - } - /// Convert BookmarkNode to JSON (for export) Map? _nodeToJson(BookmarkNode node, {bool isRoot = false}) { // Skip invalid bookmarks @@ -344,20 +156,188 @@ class BookmarkJSONUtils { if (guid == BookmarkRoot.mobile.id) return 'mobileFolder'; return null; } +} + +/// Running totals collected while converting a JSON backup. +class _Counters { + int bookmarks = 0; + int folders = 0; + int separators = 0; + int skippedUrls = 0; +} + +class _BookmarkJsonParser { + const _BookmarkJsonParser(); + + ImportBookmarkTree parse(Map data) { + final nodes = + (data['children'] as List?) + ?.whereType>() + .where( + (node) => + node['root'] != 'tagsFolder' && + node['guid'] != 'tags________', + ) + .toList() ?? + const []; + + // `place:` query URLs reference folders by numeric id, which is meaningless + // once imported. Collect every id -> guid pair up front, including from + // sections that are not themselves imported, so the rewrite below can + // resolve references that point across roots. + final folderIdToGuid = {}; + for (final node in nodes) { + if (_childrenOf(node).isEmpty) continue; + _collectFolderGuids(node, folderIdToGuid); + } + + final counters = _Counters(); + final sections = >{}; + + for (final node in nodes) { + final children = _childrenOf(node); + if (children.isEmpty) continue; + + // Anything that does not name a Places root has nowhere to go: a backup + // always describes its roots explicitly. + final guid = node['guid'] as String?; + if (guid == null || !bookmarkRootIds.contains(guid)) continue; + + final converted = []; + for (final child in children) { + final node = _convert(child, folderIdToGuid, counters); + if (node != null) converted.add(node); + } + + if (converted.isEmpty) continue; + sections + .putIfAbsent(guid, () => []) + .addAll(converted); + } + + return ImportBookmarkTree( + sections: sections, + stats: ImportBookmarkStats( + bookmarkCount: counters.bookmarks, + folderCount: counters.folders, + separatorCount: counters.separators, + skippedUrlCount: counters.skippedUrls, + ), + ); + } + + ImportBookmarkNode? _convert( + Map node, + Map folderIdToGuid, + _Counters counters, + ) { + final dateAdded = _parseTimestamp(node['dateAdded']); + final lastModified = _parseTimestamp(node['lastModified']); + + switch (_getNodeType(node)) { + case BookmarkNodeType.folder: + final children = []; + for (final child in _childrenOf(node)) { + final converted = _convert(child, folderIdToGuid, counters); + if (converted != null) children.add(converted); + } + counters.folders++; + return ImportBookmarkFolder( + title: node['title'] as String? ?? '', + children: children, + dateAdded: dateAdded, + lastModified: lastModified, + ); + + case BookmarkNodeType.item: + var url = _getNodeUrl(node); + if (url == null || url.isEmpty) { + counters.skippedUrls++; + return null; + } + if (url.startsWith('place:')) { + url = _fixupQuery(url, folderIdToGuid); + } + + final uri = Uri.tryParse(url); + if (uri == null || !uri.hasScheme) { + counters.skippedUrls++; + logger.w( + 'Skipping invalid URL: ${uri != null ? redactUriCredentials(uri) : url}', + ); + return null; + } + + counters.bookmarks++; + return ImportBookmarkItem( + url: uri, + title: node['title'] as String? ?? '', + dateAdded: dateAdded, + lastModified: lastModified, + ); + + case BookmarkNodeType.separator: + counters.separators++; + return ImportBookmarkSeparator( + dateAdded: dateAdded, + lastModified: lastModified, + ); + } + } + + void _collectFolderGuids( + Map node, + Map folderIdToGuid, + ) { + if (node['type'] == 'text/x-moz-place-container') { + final id = node['id']?.toString(); + final guid = node['guid'] as String?; + if (id != null && guid != null) { + folderIdToGuid[id] = guid; + } + } + + for (final child in _childrenOf(node)) { + _collectFolderGuids(child, folderIdToGuid); + } + } + + List> _childrenOf(Map node) { + return (node['children'] as List?) + ?.whereType>() + .toList() ?? + const []; + } + + /// Replace folder IDs with GUIDs in place: URIs + String _fixupQuery(String queryURL, Map folderIdToGuidMap) { + final regex = RegExp(r'folder=([A-Za-z0-9_]+)'); + bool invalid = false; + + final result = queryURL.replaceAllMapped(regex, (match) { + final folderId = match.group(1)!; + final guid = folderIdToGuidMap[folderId]; + + if (guid == null) { + invalid = true; + return 'invalidOldParentId=$folderId'; + } + + return 'parent=$guid'; + }); + + if (invalid) { + return '$result&excludeItems=1'; + } + + return result; + } /// Get URL from node (accepts both 'url' and 'uri') String? _getNodeUrl(Map node) { return node['url'] as String? ?? node['uri'] as String?; } - /// Normalize 'uri' to 'url' during import - void _normalizeNodeUrl(Map node) { - if (node.containsKey('uri')) { - node['url'] = node['uri']; - node.remove('uri'); - } - } - /// Get node type from JSON BookmarkNodeType _getNodeType(Map node) { final type = node['type']; @@ -373,4 +353,21 @@ class BookmarkJSONUtils { return BookmarkNodeType.separator; } } + + /// Reads a backup timestamp, which may be in either unit. + /// + /// Firefox writes PRTime (microseconds), while WebLibre's own JSON export + /// writes Places' native milliseconds. Any microsecond value for a date after + /// ~1973 exceeds [_microsecondThreshold], whereas a millisecond value would + /// have to be a date past the year 5138 to reach it. + static const _microsecondThreshold = 100000000000000; + + DateTime? _parseTimestamp(Object? value) { + final raw = value is int ? value : int.tryParse(value?.toString() ?? ''); + if (raw == null || raw <= 0) return null; + + return DateTime.fromMillisecondsSinceEpoch( + raw > _microsecondThreshold ? raw ~/ 1000 : raw, + ); + } } diff --git a/apps/weblibre/lib/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart b/apps/weblibre/lib/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart index 0f3909fd..3a1e1a7a 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart @@ -17,7 +17,6 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import 'package:fast_equatable/fast_equatable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; @@ -31,8 +30,8 @@ import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart'; import 'package:weblibre/features/geckoview/domain/providers/tab_state.dart'; import 'package:weblibre/features/geckoview/domain/providers/web_extensions_state.dart'; import 'package:weblibre/features/geckoview/domain/repositories/tab.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/domain/utils/bookmark_tree_utils.dart'; import 'package:weblibre/features/geckoview/features/browser/domain/entities/font_size_constants.dart'; import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart'; import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_id.dart'; @@ -783,18 +782,16 @@ class _BookmarkToolbarButton extends HookConsumerWidget { final tabUrl = scope.tabState?.url; final bookmarkable = tabUrl != null && !scope.isPreview; - final existingGuids = ref - .watch( - bookmarksRepositoryProvider.select( - (async) => EquatableValue( - bookmarkable - ? bookmarkGuidsForUrl(async.value, tabUrl) - : const [], - ), - ), - ) - .value; + // Answered by a storage lookup keyed on the URL, so this does not depend on + // the whole bookmark tree being resident in memory. + final bookmarkLookup = ref.watch( + bookmarkGuidsForUrlProvider(bookmarkable ? tabUrl : null), + ); + final existingGuids = bookmarkLookup.value ?? const []; + // Until the lookup settles an existing bookmark is indistinguishable from + // none, and assuming none would let a quick tap add a second copy. + final canToggleBookmark = bookmarkable && bookmarkLookup.hasValue; final isBookmarked = existingGuids.isNotEmpty; return MenuAnchor( @@ -819,7 +816,7 @@ class _BookmarkToolbarButton extends HookConsumerWidget { else MenuItemButton( leadingIcon: const Icon(MdiIcons.bookmarkPlus), - onPressed: !bookmarkable + onPressed: !canToggleBookmark ? null : () async { await ref @@ -869,25 +866,23 @@ class _BookmarkToggleToolbarButton extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final tabUrl = scope.tabState?.url; final bookmarkable = tabUrl != null && !scope.isPreview; - final existingGuids = ref - .watch( - bookmarksRepositoryProvider.select( - (async) => EquatableValue( - bookmarkable - ? bookmarkGuidsForUrl(async.value, tabUrl) - : const [], - ), - ), - ) - .value; + // Answered by a storage lookup keyed on the URL, so this does not depend on + // the whole bookmark tree being resident in memory. + final bookmarkLookup = ref.watch( + bookmarkGuidsForUrlProvider(bookmarkable ? tabUrl : null), + ); + final existingGuids = bookmarkLookup.value ?? const []; + // Until the lookup settles an existing bookmark is indistinguishable from + // none, and assuming none would let a quick tap add a second copy. + final canToggleBookmark = bookmarkable && bookmarkLookup.hasValue; final isBookmarked = existingGuids.isNotEmpty; return IconButton( tooltip: isBookmarked ? 'Remove bookmark' : 'Add bookmark', onPressed: scope.isPreview ? () {} - : !bookmarkable + : !canToggleBookmark ? null : () async { if (isBookmarked) { diff --git a/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart b/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart index a633187b..03653436 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart @@ -628,7 +628,8 @@ class RailAppBarTitleView extends StatelessWidget { : MdiIcons.shieldAlert, size: 10, color: - siteSettingsBadgeState == SiteSettingsBadgeState.improved + siteSettingsBadgeState == + SiteSettingsBadgeState.improved ? Colors.green : appColors.warningAmber, ), diff --git a/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/quick_tab_switcher_accordion.dart b/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/quick_tab_switcher_accordion.dart index f53f4444..74116fc7 100644 --- a/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/quick_tab_switcher_accordion.dart +++ b/apps/weblibre/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/quick_tab_switcher_accordion.dart @@ -317,7 +317,9 @@ class AccordionQuickTabSwitcher extends HookConsumerWidget { if (entries.isEmpty) { // Hold the 48px slot; the bar visibility is decided upstream by // quickTabSwitcherRowCountProvider. - return isVertical ? const SizedBox(width: 48) : const SizedBox(height: 48); + return isVertical + ? const SizedBox(width: 48) + : const SizedBox(height: 48); } return NotificationListener( @@ -522,19 +524,54 @@ class _AccordionHeaderChip extends StatelessWidget { // count badge inside the label instead, dropping the avatar slot. return wrapLongPress( FilterChip( - labelPadding: EdgeInsets.zero, - label: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (iconAvatar != null) iconAvatar, - if (countBadge != null) ...[ - if (iconAvatar != null) const SizedBox(height: 4), - // Multi-digit counts can exceed the narrow rail's fixed 48px chip - // width; scale the badge down to fit instead of overflowing. - FittedBox(fit: BoxFit.scaleDown, child: countBadge), + labelPadding: EdgeInsets.zero, + label: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (iconAvatar != null) iconAvatar, + if (countBadge != null) ...[ + if (iconAvatar != null) const SizedBox(height: 4), + // Multi-digit counts can exceed the narrow rail's fixed 48px chip + // width; scale the badge down to fit instead of overflowing. + FittedBox(fit: BoxFit.scaleDown, child: countBadge), + ], ], - ], + ), + color: WidgetStatePropertyAll(fill), + selected: false, + showCheckmark: false, + onSelected: (value) { + if (value) { + onSelected(); + } + }, + side: side, + shape: shape, ), + ); + } + + return wrapLongPress( + FilterChip( + avatar: iconAvatar, + label: container != null + ? buildContainerChipLabel( + context, + container, + true, + trailing: countBadge, + ) + : SizedBox( + height: 20, + child: Center( + child: + countBadge ?? + DefaultTextStyle.merge( + style: TextStyle(color: nullForeground), + child: const SizedBox.shrink(), + ), + ), + ), color: WidgetStatePropertyAll(fill), selected: false, showCheckmark: false, @@ -545,41 +582,6 @@ class _AccordionHeaderChip extends StatelessWidget { }, side: side, shape: shape, - ), - ); - } - - return wrapLongPress( - FilterChip( - avatar: iconAvatar, - label: container != null - ? buildContainerChipLabel( - context, - container, - true, - trailing: countBadge, - ) - : SizedBox( - height: 20, - child: Center( - child: - countBadge ?? - DefaultTextStyle.merge( - style: TextStyle(color: nullForeground), - child: const SizedBox.shrink(), - ), - ), - ), - color: WidgetStatePropertyAll(fill), - selected: false, - showCheckmark: false, - onSelected: (value) { - if (value) { - onSelected(); - } - }, - side: side, - shape: shape, ), ); } diff --git a/apps/weblibre/lib/features/geckoview/features/contextmenu/presentation/candidates/open_new_tab.dart b/apps/weblibre/lib/features/geckoview/features/contextmenu/presentation/candidates/open_new_tab.dart index a13f4a2e..50bf40fb 100644 --- a/apps/weblibre/lib/features/geckoview/features/contextmenu/presentation/candidates/open_new_tab.dart +++ b/apps/weblibre/lib/features/geckoview/features/contextmenu/presentation/candidates/open_new_tab.dart @@ -82,12 +82,11 @@ class OpenInNewTab extends HookConsumerWidget { // Alternative tab types the user can explicitly choose, excluding the type // that the main tile action already opens (the current tab's type). - final alternativeTypes = - [ - TabType.regular, - TabType.private, - if (settings.showIsolatedTabUi) TabType.isolated, - ]..remove(currentTabMode.toTabType()); + final alternativeTypes = [ + TabType.regular, + TabType.private, + if (settings.showIsolatedTabUi) TabType.isolated, + ]..remove(currentTabMode.toTabType()); return ListTile( leading: const Icon(MdiIcons.tabPlus), diff --git a/apps/weblibre/lib/features/geckoview/features/history/domain/services/visit_container_recorder.dart b/apps/weblibre/lib/features/geckoview/features/history/domain/services/visit_container_recorder.dart index d0cc925c..83c92c62 100644 --- a/apps/weblibre/lib/features/geckoview/features/history/domain/services/visit_container_recorder.dart +++ b/apps/weblibre/lib/features/geckoview/features/history/domain/services/visit_container_recorder.dart @@ -90,7 +90,9 @@ class VisitContainerRecorder extends _$VisitContainerRecorder { // permanently. A genuine miss (deleted container) leaves the cache // non-empty, so this fallback does not fire repeatedly in steady state. if (containerId == null && contextIdToContainerId.isEmpty) { - applyContainers(await ref.read(watchContainersWithCountProvider.future)); + applyContainers( + await ref.read(watchContainersWithCountProvider.future), + ); containerId = contextIdToContainerId[contextId]; } diff --git a/apps/weblibre/lib/features/geckoview/features/tabs/data/database/daos/visit_container.dart b/apps/weblibre/lib/features/geckoview/features/tabs/data/database/daos/visit_container.dart index 21124935..5be0920c 100644 --- a/apps/weblibre/lib/features/geckoview/features/tabs/data/database/daos/visit_container.dart +++ b/apps/weblibre/lib/features/geckoview/features/tabs/data/database/daos/visit_container.dart @@ -75,9 +75,9 @@ class VisitContainerDao extends DatabaseAccessor start, math.min(start + chunkSize, canonicalList.length), ); - final rows = await (db.select(db.visitContainer) - ..where((t) => t.urlCanonical.isIn(chunk))) - .get(); + final rows = await (db.select( + db.visitContainer, + )..where((t) => t.urlCanonical.isIn(chunk))).get(); results.addAll(rows); } return results; @@ -103,9 +103,9 @@ class VisitContainerDao extends DatabaseAccessor /// Container deletion dissolves relations automatically via ON DELETE CASCADE /// and does not go through here. Future deleteForContainer(String containerId) { - return (db.delete(db.visitContainer) - ..where((t) => t.containerId.equals(containerId))) - .go(); + return (db.delete( + db.visitContainer, + )..where((t) => t.containerId.equals(containerId))).go(); } /// Remove every relation row, all containers. Used when the user clears all diff --git a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_edit.dart b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_edit.dart index 99540064..033031e3 100644 --- a/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_edit.dart +++ b/apps/weblibre/lib/features/geckoview/features/tabs/presentation/screens/container_edit.dart @@ -62,7 +62,8 @@ Future _removeAppLinkOverrides( ) { if (!ids.any(current.appLinkContextOverrides.containsKey)) return current; return current.copyWith.appLinkContextOverrides( - {...current.appLinkContextOverrides}..removeWhere((key, _) => ids.contains(key)), + {...current.appLinkContextOverrides} + ..removeWhere((key, _) => ids.contains(key)), ); }); } diff --git a/apps/weblibre/lib/features/gestures/domain/services/gesture_control.dart b/apps/weblibre/lib/features/gestures/domain/services/gesture_control.dart index 77b0036e..e2c4d4cf 100644 --- a/apps/weblibre/lib/features/gestures/domain/services/gesture_control.dart +++ b/apps/weblibre/lib/features/gestures/domain/services/gesture_control.dart @@ -34,7 +34,6 @@ import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart'; import 'package:weblibre/features/geckoview/domain/providers/tab_state.dart'; import 'package:weblibre/features/geckoview/domain/repositories/tab.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart'; -import 'package:weblibre/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils.dart'; import 'package:weblibre/features/geckoview/features/browser/domain/entities/font_size_constants.dart'; import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/translation_bottom_sheet.dart'; import 'package:weblibre/features/geckoview/features/find_in_page/presentation/controllers/find_in_page.dart'; @@ -229,10 +228,8 @@ class GestureControlService extends _$GestureControlService { final bookmarkUrl = ref.read(sandboxSourceUriForTabProvider(tabId: tabId)) ?? tabState.url; - final bookmarks = ref.read(bookmarksRepositoryProvider).value; - final existingGuids = bookmarkGuidsForUrl(bookmarks, bookmarkUrl); - final repository = ref.read(bookmarksRepositoryProvider.notifier); + final existingGuids = await repository.bookmarkGuidsForUrl(bookmarkUrl); if (existingGuids.isNotEmpty) { for (final guid in existingGuids) { await repository.delete(guid); diff --git a/apps/weblibre/lib/features/gestures/domain/services/gesture_control.g.dart b/apps/weblibre/lib/features/gestures/domain/services/gesture_control.g.dart index 7224a1b2..27841d7c 100644 --- a/apps/weblibre/lib/features/gestures/domain/services/gesture_control.g.dart +++ b/apps/weblibre/lib/features/gestures/domain/services/gesture_control.g.dart @@ -66,7 +66,7 @@ final class GestureControlServiceProvider } String _$gestureControlServiceHash() => - r'12bd852a5b90b67bee4a94e7bd55fccc53c11bd4'; + r'3741c0a3d9cb6726c044bab1efd4ce80208f21d8'; /// Bridges gesture settings and recognized-gesture events to app actions. /// diff --git a/apps/weblibre/lib/features/settings/presentation/screens/browsing_settings.dart b/apps/weblibre/lib/features/settings/presentation/screens/browsing_settings.dart index c4055e97..331f3907 100644 --- a/apps/weblibre/lib/features/settings/presentation/screens/browsing_settings.dart +++ b/apps/weblibre/lib/features/settings/presentation/screens/browsing_settings.dart @@ -781,8 +781,8 @@ class _AppLinksModeSection extends HookConsumerWidget { await ref .read(saveGeneralSettingsControllerProvider.notifier) .save( - (current) => - current.copyWith.appLinkMarketplaceFallback(value), + (current) => current.copyWith + .appLinkMarketplaceFallback(value), ); }, ), @@ -845,9 +845,9 @@ class _AppLinkRulesSubsection extends ConsumerWidget { await ref .read(saveGeneralSettingsControllerProvider.notifier) .save( - (current) => current.copyWith.appLinkRules({ - ...current.appLinkRules, - }..remove(key)), + (current) => current.copyWith.appLinkRules( + {...current.appLinkRules}..remove(key), + ), ); }, ), diff --git a/apps/weblibre/lib/features/small_web/presentation/widgets/small_web_bottom_bar.dart b/apps/weblibre/lib/features/small_web/presentation/widgets/small_web_bottom_bar.dart index 0a0bde62..2540c37c 100644 --- a/apps/weblibre/lib/features/small_web/presentation/widgets/small_web_bottom_bar.dart +++ b/apps/weblibre/lib/features/small_web/presentation/widgets/small_web_bottom_bar.dart @@ -19,13 +19,12 @@ */ import 'dart:math'; -import 'package:fast_equatable/fast_equatable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:hooks_riverpod/hooks_riverpod.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/domain/utils/bookmark_tree_utils.dart'; import 'package:weblibre/utils/ui_helper.dart' as ui_helper; // What words does the wanderer whisper? @@ -173,18 +172,16 @@ class SmallWebBottomBar extends HookConsumerWidget { final tabUrl = currentTabUrl; final bookmarkable = tabUrl != null; - final existingGuids = ref - .watch( - bookmarksRepositoryProvider.select( - (async) => EquatableValue( - bookmarkable - ? bookmarkGuidsForUrl(async.value, tabUrl) - : const [], - ), - ), - ) - .value; + // Answered by a storage lookup keyed on the URL, so this does not depend on + // the whole bookmark tree being resident in memory. + final bookmarkLookup = ref.watch( + bookmarkGuidsForUrlProvider(bookmarkable ? tabUrl : null), + ); + final existingGuids = bookmarkLookup.value ?? const []; + // Until the lookup settles an existing bookmark is indistinguishable from + // none, and assuming none would let a quick tap add a second copy. + final canToggleBookmark = bookmarkable && bookmarkLookup.hasValue; final isBookmarked = existingGuids.isNotEmpty; return SizedBox( @@ -224,7 +221,7 @@ class SmallWebBottomBar extends HookConsumerWidget { IconButton( icon: Icon(isBookmarked ? Icons.bookmark : Icons.bookmark_border), tooltip: isBookmarked ? 'Remove bookmark' : 'Add bookmark', - onPressed: !bookmarkable + onPressed: !canToggleBookmark ? null : () async { if (isBookmarked) { diff --git a/apps/weblibre/pubspec.yaml b/apps/weblibre/pubspec.yaml index bcc39211..38d175c7 100644 --- a/apps/weblibre/pubspec.yaml +++ b/apps/weblibre/pubspec.yaml @@ -8,7 +8,6 @@ environment: sdk: '>=3.8.0 <4.0.0' dependencies: - animated_tree_view: ^2.3.0 background_fetch: ^1.7.0 collection: ^1.19.1 convert: ^3.1.2 diff --git a/apps/weblibre/test/features/app_links/app_link_prompt_rules_test.dart b/apps/weblibre/test/features/app_links/app_link_prompt_rules_test.dart index 505ca066..72a442f9 100644 --- a/apps/weblibre/test/features/app_links/app_link_prompt_rules_test.dart +++ b/apps/weblibre/test/features/app_links/app_link_prompt_rules_test.dart @@ -86,7 +86,9 @@ void main() { test('is producible even for an ambiguous resolution', () { // neverOpen never launches, so it does not need a bound package. - final rule = neverOpenRuleFor(_target(isAmbiguous: true, packageName: null)); + final rule = neverOpenRuleFor( + _target(isAmbiguous: true, packageName: null), + ); expect(rule.decision, AppLinkRuleDecision.neverOpen); expect(rule.isValid, isTrue); }); diff --git a/apps/weblibre/test/features/app_links/app_link_rule_test.dart b/apps/weblibre/test/features/app_links/app_link_rule_test.dart index ad0424b8..faa569c4 100644 --- a/apps/weblibre/test/features/app_links/app_link_rule_test.dart +++ b/apps/weblibre/test/features/app_links/app_link_rule_test.dart @@ -80,15 +80,15 @@ void main() { }, }); expect(parsed.length, 2); - expect(parsed['host:youtube.com']!.decision, AppLinkRuleDecision.alwaysOpen); + expect( + parsed['host:youtube.com']!.decision, + AppLinkRuleDecision.alwaysOpen, + ); }); test('drops entries whose map key disagrees with the rule scope', () { final parsed = parseAppLinkRules({ - 'host:wrong.com': { - 'decision': 'neverOpen', - 'scope': 'host:right.com', - }, + 'host:wrong.com': {'decision': 'neverOpen', 'scope': 'host:right.com'}, }); expect(parsed, isEmpty); }); diff --git a/apps/weblibre/test/features/app_links/effective_routing_test.dart b/apps/weblibre/test/features/app_links/effective_routing_test.dart index 5d93985c..7e08852c 100644 --- a/apps/weblibre/test/features/app_links/effective_routing_test.dart +++ b/apps/weblibre/test/features/app_links/effective_routing_test.dart @@ -23,11 +23,8 @@ import 'package:weblibre/features/app_links/domain/services/effective_routing.da import 'package:weblibre/features/geckoview/features/tabs/data/models/site_assignment.dart'; import 'package:weblibre/features/proxy/data/proxy_connection.dart'; -SiteAssignment _assignment(String site, {String? contextId}) => SiteAssignment( - id: site, - contextualIdentity: contextId, - assignedSite: site, -); +SiteAssignment _assignment(String site, {String? contextId}) => + SiteAssignment(id: site, contextualIdentity: contextId, assignedSite: site); void main() { group('resolveContainerAssignment', () { diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils_test.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils_test.dart new file mode 100644 index 00000000..f03befb7 --- /dev/null +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils_test.dart @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2024-2026 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_mozilla_components/flutter_mozilla_components.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/bookmark_item.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/bookmark_sort_type.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils.dart'; + +BookmarkEntry entry(String guid, String title) => BookmarkEntry( + guid: guid, + parentGuid: BookmarkRoot.menu.id, + url: Uri.parse('https://example.com/$guid'), + title: title, + previewImageUrl: Uri.parse('https://example.com/$guid'), + position: 0, + dateAdded: 0, +); + +BookmarkFolder folder(String guid, String title, {List? kids}) => + BookmarkFolder( + guid: guid, + parentGuid: BookmarkRoot.root.id, + title: title, + position: 0, + dateAdded: 0, + children: kids, + ); + +void main() { + group('sortBookmarkChildren', () { + test('should leave order untouched for manual sorting', () { + final children = [entry('b', 'Beta'), entry('a', 'Alpha')]; + + final sorted = sortBookmarkChildren(children, BookmarkSortType.manual); + + expect(sorted.map((c) => c.guid), equals(['b', 'a'])); + }); + + test('should sort a plain level by title', () { + final children = [ + entry('c', 'Charlie'), + entry('a', 'Alpha'), + entry('b', 'Bravo'), + ]; + + final sorted = sortBookmarkChildren(children, BookmarkSortType.titleAsc); + + expect(sorted.map((c) => c.title), equals(['Alpha', 'Bravo', 'Charlie'])); + }); + + test('should not mutate the list it was given', () { + final children = [entry('c', 'Charlie'), entry('a', 'Alpha')]; + + sortBookmarkChildren(children, BookmarkSortType.titleAsc); + + expect(children.map((c) => c.guid), equals(['c', 'a'])); + }); + + test('should keep built-in roots pinned ahead of the rest at root', () { + final children = [ + entry('z', 'Zulu'), + folder(BookmarkRoot.mobile.id, 'WebLibre'), + entry('a', 'Alpha'), + folder(BookmarkRoot.menu.id, 'Menu'), + ]; + + final sorted = sortBookmarkChildren( + children, + BookmarkSortType.titleAsc, + isRoot: true, + ); + + expect( + sorted.map((c) => c.guid), + equals([BookmarkRoot.mobile.id, BookmarkRoot.menu.id, 'a', 'z']), + ); + }); + }); + + group('resolveSelectedItems', () { + test('should return the children whose guids are selected', () { + final children = [entry('a', 'Alpha'), entry('b', 'Bravo')]; + + final selected = resolveSelectedItems(children, {'b'}); + + expect(selected.single.guid, equals('b')); + }); + + test('should ignore guids that are not in the given list', () { + final children = [entry('a', 'Alpha')]; + + expect(resolveSelectedItems(children, {'somewhere-else'}), isEmpty); + }); + + test('should resolve items that live in other folders', () { + // Search results come from anywhere in the library, so the list handed to + // this function is not always one folder's children. Callers must pass + // whatever is actually on screen — resolving against the current folder + // instead would silently drop every result from a subfolder. + final results = [ + entry('a', 'Alpha').copyWith(parentGuid: 'folder_one__'), + entry('b', 'Bravo').copyWith(parentGuid: 'folder_two__'), + ]; + + final selected = resolveSelectedItems(results, {'a', 'b'}); + + expect(selected.map((item) => item.guid), equals(['a', 'b'])); + }); + }); + + group('normalizeSelection', () { + test('should keep selections that are siblings', () { + final rows = [ + BookmarkRow(entry('a', 'Alpha'), 0), + BookmarkRow(entry('b', 'Bravo'), 0), + ]; + + expect(normalizeSelection(rows, {'a', 'b'}), equals({'a', 'b'})); + }); + + test('should drop children of a selected folder', () { + final rows = [ + BookmarkRow(folder('f1__________', 'Folder'), 0), + BookmarkRow(entry('child_______', 'Child'), 1), + BookmarkRow(entry('after_______', 'After'), 0), + ]; + + final normalized = normalizeSelection(rows, { + 'f1__________', + 'child_______', + 'after_______', + }); + + expect(normalized, equals({'f1__________', 'after_______'})); + }); + + test('should drop the whole subtree under a selected folder', () { + final rows = [ + BookmarkRow(folder('outer_______', 'Outer'), 0), + BookmarkRow(folder('inner_______', 'Inner'), 1), + BookmarkRow(entry('deep________', 'Deep'), 2), + BookmarkRow(entry('sibling_____', 'Sibling'), 0), + ]; + + final normalized = normalizeSelection(rows, { + 'outer_______', + 'inner_______', + 'deep________', + 'sibling_____', + }); + + expect(normalized, equals({'outer_______', 'sibling_____'})); + }); + + test('should keep a nested selection when its parent is not selected', () { + final rows = [ + BookmarkRow(folder('f1__________', 'Folder'), 0), + BookmarkRow(entry('child_______', 'Child'), 1), + ]; + + expect( + normalizeSelection(rows, {'child_______'}), + equals({'child_______'}), + ); + }); + + test('should not count a loading placeholder as a second occurrence', () { + // While an expanded folder loads, a placeholder row repeats it one level + // down. Treating that as a real row would resolve the folder twice and + // apply the same move or delete to it twice over. + final selectedFolder = folder('f1__________', 'Folder'); + final rows = [ + BookmarkRow(selectedFolder, 0), + BookmarkRow(selectedFolder, 1, isPlaceholder: true), + ]; + + final normalized = normalizeSelection(rows, {'f1__________'}); + + expect(normalized, equals({'f1__________'})); + }); + + test('should resume after leaving a selected folder subtree', () { + final rows = [ + BookmarkRow(folder('f1__________', 'One'), 0), + BookmarkRow(entry('inside______', 'Inside'), 1), + BookmarkRow(folder('f2__________', 'Two'), 0), + BookmarkRow(entry('later_______', 'Later'), 1), + ]; + + final normalized = normalizeSelection(rows, { + 'f1__________', + 'inside______', + 'later_______', + }); + + expect(normalized, equals({'f1__________', 'later_______'})); + }); + }); + + group('canFlattenFolder', () { + test('should reject built-in roots', () { + expect(canFlattenFolder(folder(BookmarkRoot.menu.id, 'Menu')), isFalse); + }); + + test('should accept an ordinary folder even before its children load', () { + // The list only loads one level, so a folder shown in it has no children + // attached; emptiness is decided by the repository at operation time. + expect(canFlattenFolder(folder('normal______', 'Normal')), isTrue); + }); + + test('should reject a folder without a parent', () { + final orphan = BookmarkFolder( + guid: 'orphan______', + parentGuid: null, + title: 'Orphan', + position: 0, + dateAdded: 0, + children: null, + ); + + expect(canFlattenFolder(orphan), isFalse); + }); + }); +} diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.dart index 9a574a47..d7cae3e7 100644 --- a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.dart +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.dart @@ -24,11 +24,26 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_html_utils.dart'; @GenerateMocks([GeckoBookmarksService]) import 'bookmark_html_utils_test.mocks.dart'; +/// Nodes the parser routed to [root], or an empty list if it produced no such +/// section. +List section(ImportBookmarkTree tree, BookmarkRoot root) => + tree.sections[root.id] ?? const []; + +/// Mirrors what the native side reports back: bookmark items only, recursively. +int countItems(List nodes) => nodes.fold( + 0, + (total, node) => + total + + (node.type == BookmarkNodeType.item ? 1 : 0) + + countItems(node.children), +); + void main() { late MockGeckoBookmarksService mockService; late BookmarkHTMLUtils utils; @@ -36,72 +51,20 @@ void main() { setUp(() { mockService = MockGeckoBookmarksService(); utils = BookmarkHTMLUtils(mockService); + + when(mockService.eraseEverything(any)).thenAnswer((_) async {}); + when(mockService.insertTree(any, any)).thenAnswer( + (invocation) async => BookmarkInsertTreeResult( + insertedItemCount: countItems( + invocation.positionalArguments[1] as List, + ), + failedNodeCount: 0, + ), + ); }); - group('BookmarkHTMLUtils - Import', () { - test('should handle corrupt HTML file with malformed URIs', () async { - // Load the corrupt fixture - final fixtureFile = File( - 'test/utils/bookmarks/fixtures/bookmarks.corrupt.html', - ); - final htmlString = await fixtureFile.readAsString(); - - // Mock the service calls - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - when( - mockService.addFolder(any, any, any), - ).thenAnswer((_) async => 'generated_guid'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'generated_guid'); - - final count = await utils.importFromHTML(htmlString, replace: true); - - // Should import valid bookmarks and skip the corrupt one - expect(count, greaterThan(0)); - verify(mockService.eraseEverything(BookmarkRoot.root)).called(1); - }); - - test('should import from valid HTML file', () async { - final fixtureFile = File( - 'test/utils/bookmarks/fixtures/bookmarks.preplaces.html', - ); - final htmlString = await fixtureFile.readAsString(); - - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - when( - mockService.addFolder(any, any, any), - ).thenAnswer((_) async => 'folder_guid'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'bookmark_guid'); - - final count = await utils.importFromHTML(htmlString, replace: true); - - expect(count, greaterThan(0)); - verify(mockService.eraseEverything(BookmarkRoot.root)).called(1); - // Verify some bookmarks were added - verify(mockService.addItem(any, any, any, any)).called(greaterThan(0)); - }); - - test('should handle empty HTML', () async { - const emptyHtml = ''' - - Bookmarks -

Bookmarks

-

-

- '''; - - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - - final count = await utils.importFromHTML(emptyHtml, replace: true); - - expect(count, equals(0)); - verify(mockService.eraseEverything(BookmarkRoot.root)).called(1); - }); - - test('should not erase when replace is false', () async { + group('parseBookmarkHtml', () { + test('should route everything under menu without root markers', () { const simpleHtml = ''' Bookmarks @@ -111,16 +74,19 @@ void main() {
'''; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'guid'); + final tree = parseBookmarkHtml(simpleHtml, preserveRootFolders: false); - await utils.importFromHTML(simpleHtml); - - verifyNever(mockService.eraseEverything(any)); + expect(tree.sections.keys, equals([BookmarkRoot.menu.id])); + expect( + section(tree, BookmarkRoot.menu).single, + isA() + .having((i) => i.url, 'url', Uri.parse('https://example.com')) + .having((i) => i.title, 'title', 'Example'), + ); + expect(tree.stats.bookmarkCount, equals(1)); }); - test('should handle bookmarks with special characters in title', () async { + test('should decode HTML entities in titles', () { const htmlWithSpecialChars = ''' Bookmarks @@ -130,21 +96,16 @@ void main() { '''; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'guid'); + final tree = parseBookmarkHtml( + htmlWithSpecialChars, + preserveRootFolders: false, + ); - final count = await utils.importFromHTML(htmlWithSpecialChars); - - expect(count, equals(1)); - final captured = verify( - mockService.addItem(any, any, captureAny, any), - ).captured; - // Should properly decode HTML entities - expect(captured[0], equals('')); + final item = section(tree, BookmarkRoot.menu).single; + expect((item as ImportBookmarkItem).title, equals('')); }); - test('should import bookmarks with timestamps', () async { + test('should preserve item timestamps as seconds since epoch', () { const htmlWithDates = ''' Bookmarks @@ -154,16 +115,63 @@ void main() { '''; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'guid'); + final tree = parseBookmarkHtml(htmlWithDates, preserveRootFolders: false); - final count = await utils.importFromHTML(htmlWithDates); - - expect(count, equals(1)); + final item = + section(tree, BookmarkRoot.menu).single as ImportBookmarkItem; + expect( + item.dateAdded, + equals(DateTime.fromMillisecondsSinceEpoch(1177375336 * 1000)), + ); + expect( + item.lastModified, + equals(DateTime.fromMillisecondsSinceEpoch(1177375423 * 1000)), + ); }); - test('should handle folder hierarchy', () async { + test('should fall back to LAST_MODIFIED when ADD_DATE is absent', () { + const html = ''' + +

Bookmarks

+

+

Test +
+ '''; + + final tree = parseBookmarkHtml(html, preserveRootFolders: false); + + final item = + section(tree, BookmarkRoot.menu).single as ImportBookmarkItem; + expect(item.dateAdded, equals(item.lastModified)); + }); + + test('should preserve folder timestamps', () { + const html = ''' + +

Bookmarks

+

+

Dated

+

+

Child +

+

+ '''; + + final tree = parseBookmarkHtml(html, preserveRootFolders: false); + + final folder = + section(tree, BookmarkRoot.menu).single as ImportBookmarkFolder; + expect( + folder.dateAdded, + equals(DateTime.fromMillisecondsSinceEpoch(1177375336 * 1000)), + ); + expect( + folder.lastModified, + equals(DateTime.fromMillisecondsSinceEpoch(1177375423 * 1000)), + ); + }); + + test('should nest folders and keep child order', () { const htmlWithFolders = ''' Bookmarks @@ -180,24 +188,98 @@ void main() { '''; - when( - mockService.addFolder(any, any, any), - ).thenAnswer((_) async => 'folder_guid'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'bookmark_guid'); + final tree = parseBookmarkHtml( + htmlWithFolders, + preserveRootFolders: false, + ); - final count = await utils.importFromHTML(htmlWithFolders); + final parent = + section(tree, BookmarkRoot.menu).single as ImportBookmarkFolder; + expect(parent.title, equals('Parent Folder')); + expect(parent.children, hasLength(2)); - expect(count, equals(2)); // 2 bookmarks - verify(mockService.addFolder(any, any, any)).called(2); // 2 folders + expect( + (parent.children[0] as ImportBookmarkItem).title, + equals('Child 1'), + ); + + final nested = parent.children[1] as ImportBookmarkFolder; + expect(nested.title, equals('Nested Folder')); + expect( + (nested.children.single as ImportBookmarkItem).title, + equals('Grandchild'), + ); + + expect(tree.stats.bookmarkCount, equals(2)); + expect(tree.stats.folderCount, equals(2)); }); - test('should recognize toolbar folder', () async { - const htmlWithToolbar = ''' + test('should keep empty folders', () { + const html = ''' + +

Bookmarks

+

+

Empty

+

+

+

After +
+ '''; + + final tree = parseBookmarkHtml(html, preserveRootFolders: false); + final nodes = section(tree, BookmarkRoot.menu); + + expect(nodes, hasLength(2)); + expect( + nodes[0], + isA() + .having((f) => f.title, 'title', 'Empty') + .having((f) => f.children, 'children', isEmpty), + ); + expect(nodes[1], isA()); + }); + + test('should route root-marked folders when preserving roots', () { + const htmlWithRoots = ''' Bookmarks

Bookmarks

+

+

Bookmarks Toolbar

+

+

Toolbar Bookmark +

+

Unsorted Bookmarks

+

+

Unfiled Bookmark +

+

Loose +
+ '''; + + final tree = parseBookmarkHtml(htmlWithRoots, preserveRootFolders: true); + + expect( + (section(tree, BookmarkRoot.toolbar).single as ImportBookmarkItem) + .title, + equals('Toolbar Bookmark'), + ); + expect( + (section(tree, BookmarkRoot.unfiled).single as ImportBookmarkItem) + .title, + equals('Unfiled Bookmark'), + ); + // The marked folders themselves are not recreated, only their contents. + expect( + (section(tree, BookmarkRoot.menu).single as ImportBookmarkItem).title, + equals('Loose'), + ); + }); + + test('should treat root markers as plain folders when not preserving', () { + const htmlWithToolbar = ''' + +

Bookmarks

Bookmarks Toolbar

@@ -206,47 +288,19 @@ void main() {

'''; - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'guid'); + final tree = parseBookmarkHtml( + htmlWithToolbar, + preserveRootFolders: false, + ); - await utils.importFromHTML(htmlWithToolbar, replace: true); - - // When replace is true, should add to toolbar - final captured = verify( - mockService.addItem(captureAny, any, any, any), - ).captured; - expect(captured[0], equals(BookmarkRoot.toolbar.id)); + expect(tree.sections.keys, equals([BookmarkRoot.menu.id])); + expect( + (section(tree, BookmarkRoot.menu).single as ImportBookmarkFolder).title, + equals('Bookmarks Toolbar'), + ); }); - test('should recognize unfiled folder', () async { - const htmlWithUnfiled = ''' - - Bookmarks -

Bookmarks

-

-

Unsorted Bookmarks

-

-

Unfiled Bookmark -

-

- '''; - - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'guid'); - - await utils.importFromHTML(htmlWithUnfiled, replace: true); - - final captured = verify( - mockService.addItem(captureAny, any, any, any), - ).captured; - expect(captured[0], equals(BookmarkRoot.unfiled.id)); - }); - - test('should handle separators', () async { + test('should keep separators between bookmarks', () { const htmlWithSeparator = ''' Bookmarks @@ -258,17 +312,19 @@ void main() {
'''; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'guid'); + final tree = parseBookmarkHtml( + htmlWithSeparator, + preserveRootFolders: false, + ); + final nodes = section(tree, BookmarkRoot.menu); - final count = await utils.importFromHTML(htmlWithSeparator); - - // Should import 2 bookmarks (separator is not supported by Android API) - expect(count, equals(2)); + expect(nodes, hasLength(3)); + expect(nodes[1], isA()); + expect(tree.stats.bookmarkCount, equals(2)); + expect(tree.stats.separatorCount, equals(1)); }); - test('should skip bookmarks without URLs', () async { + test('should skip bookmarks without URLs', () { const htmlWithoutUrl = ''' Bookmarks @@ -279,16 +335,16 @@ void main() { '''; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'guid'); + final tree = parseBookmarkHtml( + htmlWithoutUrl, + preserveRootFolders: false, + ); - final count = await utils.importFromHTML(htmlWithoutUrl); - - expect(count, equals(1)); // Only the valid one + expect(section(tree, BookmarkRoot.menu), hasLength(1)); + expect(tree.stats.skippedUrlCount, equals(1)); }); - test('should skip bookmarks with invalid URLs', () async { + test('should skip bookmarks with schemeless URLs', () { const htmlWithInvalidUrl = ''' Bookmarks @@ -299,31 +355,209 @@ void main() { '''; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'guid'); + final tree = parseBookmarkHtml( + htmlWithInvalidUrl, + preserveRootFolders: false, + ); - final count = await utils.importFromHTML(htmlWithInvalidUrl); - - expect(count, equals(1)); + expect(section(tree, BookmarkRoot.menu), hasLength(1)); + expect(tree.stats.skippedUrlCount, equals(1)); }); - test('should handle single frame HTML', () async { - final fixtureFile = File( - 'test/utils/bookmarks/fixtures/bookmarks_html_singleframe.html', + test('should produce no sections for an empty document', () { + const emptyHtml = ''' + + Bookmarks +

Bookmarks

+

+

+ '''; + + final tree = parseBookmarkHtml(emptyHtml, preserveRootFolders: true); + + expect(tree.isEmpty, isTrue); + expect(tree.stats.bookmarkCount, equals(0)); + }); + + test('should keep headings that never open a list', () { + // Firefox writes empty folders without a `
`; the folder must still be + // emitted, and the heading after it must not inherit its metadata. + const html = ''' + +

Bookmarks

+

+

First

+

Second

+

+

Child +

+

+ '''; + + final tree = parseBookmarkHtml(html, preserveRootFolders: false); + final nodes = section(tree, BookmarkRoot.menu); + + expect(nodes, hasLength(2)); + expect((nodes[0] as ImportBookmarkFolder).title, equals('First')); + expect((nodes[0] as ImportBookmarkFolder).dateAdded, isNull); + + final second = nodes[1] as ImportBookmarkFolder; + expect(second.title, equals('Second')); + expect( + second.dateAdded, + equals(DateTime.fromMillisecondsSinceEpoch(1177375336 * 1000)), ); - final htmlString = await fixtureFile.readAsString(); + expect(second.children, hasLength(1)); + }); - when( - mockService.addFolder(any, any, any), - ).thenAnswer((_) async => 'folder_guid'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'bookmark_guid'); + test('should handle deeply nested folders', () { + const depth = 60; + final buffer = StringBuffer( + '\n

', + ); + for (var i = 0; i < depth; i++) { + buffer.write('

Level $i

\n

'); + } + buffer.write('

Deep'); + for (var i = 0; i < depth; i++) { + buffer.write('

'); + } + buffer.write('

'); - final count = await utils.importFromHTML(htmlString); + final tree = parseBookmarkHtml( + buffer.toString(), + preserveRootFolders: false, + ); - expect(count, greaterThan(0)); + var node = section(tree, BookmarkRoot.menu).single; + for (var i = 0; i < depth; i++) { + node = (node as ImportBookmarkFolder).children.single; + } + expect(node, isA()); + expect(tree.stats.folderCount, equals(depth)); + }); + + test('should parse the corrupt fixture without throwing', () async { + final htmlString = await File( + 'test/utils/bookmarks/fixtures/bookmarks.corrupt.html', + ).readAsString(); + + final tree = parseBookmarkHtml(htmlString, preserveRootFolders: true); + + expect(tree.stats.bookmarkCount, greaterThan(0)); + }); + + test('should parse the pre-places fixture', () async { + final htmlString = await File( + 'test/utils/bookmarks/fixtures/bookmarks.preplaces.html', + ).readAsString(); + + final tree = parseBookmarkHtml(htmlString, preserveRootFolders: true); + + expect(tree.stats.bookmarkCount, greaterThan(0)); + }); + + test('should parse the single frame fixture', () async { + final htmlString = await File( + 'test/utils/bookmarks/fixtures/bookmarks_html_singleframe.html', + ).readAsString(); + + final tree = parseBookmarkHtml(htmlString, preserveRootFolders: false); + + expect(tree.stats.bookmarkCount, greaterThan(0)); + }); + }); + + group('BookmarkHTMLUtils - Import', () { + test('should insert each section with a single bulk call', () async { + const htmlWithFolders = ''' + +

Bookmarks

+

+

Parent Folder

+

+

Child 1 +

Nested Folder

+

+

Grandchild +

+

+

+ '''; + + final count = await utils.importFromHTML(htmlWithFolders); + + expect(count, equals(2)); + verify(mockService.insertTree(BookmarkRoot.menu.id, any)).called(1); + verifyNever(mockService.addItem(any, any, any, any)); + verifyNever(mockService.addFolder(any, any, any)); + }); + + test( + 'should erase every root except the tree root when replacing', + () async { + final htmlString = await File( + 'test/utils/bookmarks/fixtures/bookmarks.preplaces.html', + ).readAsString(); + + final count = await utils.importFromHTML(htmlString, replace: true); + + expect(count, greaterThan(0)); + for (final root in BookmarkRoot.values) { + if (root == BookmarkRoot.root) { + verifyNever(mockService.eraseEverything(root)); + } else { + verify(mockService.eraseEverything(root)).called(1); + } + } + }, + ); + + test('should not erase when replace is false', () async { + const simpleHtml = ''' + +

Bookmarks

+

+

Example +
+ '''; + + await utils.importFromHTML(simpleHtml); + + verifyNever(mockService.eraseEverything(any)); + }); + + test('should route root-marked sections to their Places roots', () async { + const htmlWithToolbar = ''' + +

Bookmarks

+

+

Bookmarks Toolbar

+

+

Toolbar Bookmark +

+

+ '''; + + await utils.importFromHTML(htmlWithToolbar, replace: true); + + verify(mockService.insertTree(BookmarkRoot.toolbar.id, any)).called(1); + }); + + test('should insert nothing for an empty document', () async { + const emptyHtml = ''' + +

Bookmarks

+

+

+ '''; + + final count = await utils.importFromHTML(emptyHtml, replace: true); + + expect(count, equals(0)); + verifyNever(mockService.insertTree(any, any)); + // Nothing parsed means nothing to replace, so existing bookmarks survive. + verifyNever(mockService.eraseEverything(any)); }); }); @@ -747,18 +981,24 @@ void main() { expect(html, isNotEmpty); // Re-import - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - when( - mockService.addFolder(any, any, any), - ).thenAnswer((_) async => 'folder1_____'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'bookmark1___'); - final count = await utils.importFromHTML(html, replace: true); expect(count, equals(1)); // One bookmark imported - verify(mockService.eraseEverything(BookmarkRoot.root)).called(1); + verify(mockService.eraseEverything(BookmarkRoot.menu)).called(1); + + final inserted = + verify( + mockService.insertTree(BookmarkRoot.menu.id, captureAny), + ).captured.single + as List; + + final folder = inserted.single; + expect(folder.type, equals(BookmarkNodeType.folder)); + expect(folder.title, equals('Test Folder')); + + final bookmark = folder.children.single; + expect(bookmark.title, equals('Test Bookmark')); + expect(bookmark.url, equals('https://example.com')); }); }); } diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.mocks.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.mocks.dart index 6112b7dc..a3d8307a 100644 --- a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.mocks.dart +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_html_utils_test.mocks.dart @@ -3,11 +3,11 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i3; +import 'dart:async' as _i4; import 'package:flutter_mozilla_components/src/domain/services/gecko_bookmarks.dart' - as _i2; -import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart' as _i4; + as _i3; +import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart' as _i2; import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i5; @@ -26,46 +26,52 @@ import 'package:mockito/src/dummies.dart' as _i5; // ignore_for_file: subtype_of_sealed_class // ignore_for_file: invalid_use_of_internal_member +class _FakeBookmarkInsertTreeResult_0 extends _i1.SmartFake + implements _i2.BookmarkInsertTreeResult { + _FakeBookmarkInsertTreeResult_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + /// A class which mocks [GeckoBookmarksService]. /// /// See the documentation for Mockito's code generation for more information. class MockGeckoBookmarksService extends _i1.Mock - implements _i2.GeckoBookmarksService { + implements _i3.GeckoBookmarksService { MockGeckoBookmarksService() { _i1.throwOnMissingStub(this); } @override - _i3.Future<_i4.BookmarkNode?> getTree( + _i4.Future<_i2.BookmarkNode?> getTree( String? guid, { bool? recursive = false, }) => (super.noSuchMethod( Invocation.method(#getTree, [guid], {#recursive: recursive}), - returnValue: _i3.Future<_i4.BookmarkNode?>.value(), + returnValue: _i4.Future<_i2.BookmarkNode?>.value(), ) - as _i3.Future<_i4.BookmarkNode?>); + as _i4.Future<_i2.BookmarkNode?>); @override - _i3.Future<_i4.BookmarkNode?> getBookmark(String? guid) => + _i4.Future<_i2.BookmarkNode?> getBookmark(String? guid) => (super.noSuchMethod( Invocation.method(#getBookmark, [guid]), - returnValue: _i3.Future<_i4.BookmarkNode?>.value(), + returnValue: _i4.Future<_i2.BookmarkNode?>.value(), ) - as _i3.Future<_i4.BookmarkNode?>); + as _i4.Future<_i2.BookmarkNode?>); @override - _i3.Future> getBookmarksWithUrl(Uri? url) => + _i4.Future> getBookmarksWithUrl(Uri? url) => (super.noSuchMethod( Invocation.method(#getBookmarksWithUrl, [url]), - returnValue: _i3.Future>.value( - <_i4.BookmarkNode>[], + returnValue: _i4.Future>.value( + <_i2.BookmarkNode>[], ), ) - as _i3.Future>); + as _i4.Future>); @override - _i3.Future> getRecentBookmarks( + _i4.Future> getRecentBookmarks( int? limit, { Duration? maxAge = Duration.zero, DateTime? currentTime, @@ -76,27 +82,27 @@ class MockGeckoBookmarksService extends _i1.Mock [limit], {#maxAge: maxAge, #currentTime: currentTime}, ), - returnValue: _i3.Future>.value( - <_i4.BookmarkNode>[], + returnValue: _i4.Future>.value( + <_i2.BookmarkNode>[], ), ) - as _i3.Future>); + as _i4.Future>); @override - _i3.Future> searchBookmarks( + _i4.Future> searchBookmarks( String? query, { int? limit = 10, }) => (super.noSuchMethod( Invocation.method(#searchBookmarks, [query], {#limit: limit}), - returnValue: _i3.Future>.value( - <_i4.BookmarkNode>[], + returnValue: _i4.Future>.value( + <_i2.BookmarkNode>[], ), ) - as _i3.Future>); + as _i4.Future>); @override - _i3.Future addItem( + _i4.Future addItem( String? parentGuid, Uri? url, String? title, @@ -104,55 +110,79 @@ class MockGeckoBookmarksService extends _i1.Mock ) => (super.noSuchMethod( Invocation.method(#addItem, [parentGuid, url, title, position]), - returnValue: _i3.Future.value( + returnValue: _i4.Future.value( _i5.dummyValue( this, Invocation.method(#addItem, [parentGuid, url, title, position]), ), ), ) - as _i3.Future); + as _i4.Future); @override - _i3.Future addFolder( + _i4.Future addFolder( String? parentGuid, String? title, int? position, ) => (super.noSuchMethod( Invocation.method(#addFolder, [parentGuid, title, position]), - returnValue: _i3.Future.value( + returnValue: _i4.Future.value( _i5.dummyValue( this, Invocation.method(#addFolder, [parentGuid, title, position]), ), ), ) - as _i3.Future); + as _i4.Future); @override - _i3.Future updateNode(String? guid, _i4.BookmarkInfo? info) => + _i4.Future updateNode(String? guid, _i2.BookmarkInfo? info) => (super.noSuchMethod( Invocation.method(#updateNode, [guid, info]), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), ) - as _i3.Future); + as _i4.Future); @override - _i3.Future deleteNode(String? guid) => + _i4.Future deleteNode(String? guid) => (super.noSuchMethod( Invocation.method(#deleteNode, [guid]), - returnValue: _i3.Future.value(false), + returnValue: _i4.Future.value(false), ) - as _i3.Future); + as _i4.Future); @override - _i3.Future eraseEverything(_i2.BookmarkRoot? root) => + _i4.Future<_i2.BookmarkInsertTreeResult> insertTree( + String? parentGuid, + List<_i2.BookmarkImportNode>? children, + ) => + (super.noSuchMethod( + Invocation.method(#insertTree, [parentGuid, children]), + returnValue: _i4.Future<_i2.BookmarkInsertTreeResult>.value( + _FakeBookmarkInsertTreeResult_0( + this, + Invocation.method(#insertTree, [parentGuid, children]), + ), + ), + ) + as _i4.Future<_i2.BookmarkInsertTreeResult>); + + @override + _i4.Future countBookmarksInTrees(List? guids) => + (super.noSuchMethod( + Invocation.method(#countBookmarksInTrees, [guids]), + returnValue: _i4.Future.value(0), + ) + as _i4.Future); + + @override + _i4.Future eraseEverything(_i3.BookmarkRoot? root) => (super.noSuchMethod( Invocation.method(#eraseEverything, [root]), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), ) - as _i3.Future); + as _i4.Future); } diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_import_isolate_test.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_import_isolate_test.dart new file mode 100644 index 00000000..e87fcdfb --- /dev/null +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_import_isolate_test.dart @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024-2026 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 'dart:io'; + +import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_import_isolate.dart'; + +void main() { + late Directory tempDir; + + setUp(() async { + tempDir = await Directory.systemTemp.createTemp('bookmark-import-test'); + }); + + tearDown(() async { + await tempDir.delete(recursive: true); + }); + + Future writeFixture(String name, String contents) async { + final file = File('${tempDir.path}/$name'); + await file.writeAsString(contents); + return file; + } + + group('parseBookmarkFile', () { + test('should return an HTML tree across the isolate boundary', () async { + final file = await writeFixture('bookmarks.html', ''' + +

Bookmarks

+

+

Folder

+

+

Example +
+

+

+ '''); + + final tree = await parseBookmarkFile( + path: file.path, + format: BookmarkImportFormat.html, + preserveRootFolders: false, + ); + + final folder = + tree.sections[BookmarkRoot.menu.id]!.single as ImportBookmarkFolder; + expect(folder.title, equals('Folder')); + + final item = folder.children[0] as ImportBookmarkItem; + expect(item.url, equals(Uri.parse('https://example.com'))); + expect( + item.dateAdded, + equals(DateTime.fromMillisecondsSinceEpoch(1177375336 * 1000)), + ); + expect(folder.children[1], isA()); + + expect(tree.stats.bookmarkCount, equals(1)); + expect(tree.stats.separatorCount, equals(1)); + }); + + test('should return a JSON tree across the isolate boundary', () async { + final file = await writeFixture('bookmarks.json', ''' + { + "children": [ + { + "guid": "menu________", + "type": "text/x-moz-place-container", + "children": [ + { + "guid": "bookmark1___", + "title": "Example", + "type": "text/x-moz-place", + "uri": "https://example.com" + } + ] + } + ] + } + '''); + + final tree = await parseBookmarkFile( + path: file.path, + format: BookmarkImportFormat.json, + preserveRootFolders: false, + ); + + final item = + tree.sections[BookmarkRoot.menu.id]!.single as ImportBookmarkItem; + expect(item.title, equals('Example')); + expect(item.url, equals(Uri.parse('https://example.com'))); + }); + + test('should propagate a missing file as an error', () { + expect( + parseBookmarkFile( + path: '${tempDir.path}/does-not-exist.html', + format: BookmarkImportFormat.html, + preserveRootFolders: false, + ), + throwsA(isA()), + ); + }); + + test('should propagate a malformed JSON document as an error', () async { + final file = await writeFixture('broken.json', '{not json'); + + expect( + parseBookmarkFile( + path: file.path, + format: BookmarkImportFormat.json, + preserveRootFolders: false, + ), + throwsA(isA()), + ); + }); + }); +} diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.dart index afabc7dd..d69e7ad9 100644 --- a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.dart +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.dart @@ -27,11 +27,26 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/import_bookmark_node.dart'; import 'package:weblibre/features/geckoview/features/bookmarks/utils/bookmark_json_utils.dart'; @GenerateMocks([GeckoBookmarksService]) import 'bookmark_json_utils_test.mocks.dart'; +/// Nodes the parser routed to [root], or an empty list if it produced no such +/// section. +List section(ImportBookmarkTree tree, BookmarkRoot root) => + tree.sections[root.id] ?? const []; + +/// Mirrors what the native side reports back: bookmark items only, recursively. +int countItems(List nodes) => nodes.fold( + 0, + (total, node) => + total + + (node.type == BookmarkNodeType.item ? 1 : 0) + + countItems(node.children), +); + void main() { late MockGeckoBookmarksService mockService; late BookmarkJSONUtils utils; @@ -39,108 +54,52 @@ void main() { setUp(() { mockService = MockGeckoBookmarksService(); utils = BookmarkJSONUtils(mockService); + + when(mockService.eraseEverything(any)).thenAnswer((_) async {}); + when(mockService.insertTree(any, any)).thenAnswer( + (invocation) async => BookmarkInsertTreeResult( + insertedItemCount: countItems( + invocation.positionalArguments[1] as List, + ), + failedNodeCount: 0, + ), + ); }); - group('BookmarkJSONUtils - Import', () { - test('should reject invalid JSON format', () { - const invalidJson = '[]'; - - expect( - () => utils.importFromJSON(invalidJson), - throwsA(isA()), - ); + group('parseBookmarkJson', () { + test('should reject a document that is not an object', () { + expect(() => parseBookmarkJson('[]'), throwsA(isA())); }); - test('should return 0 for empty children', () async { - const emptyJson = '{"children": []}'; - - final count = await utils.importFromJSON(emptyJson); - - expect(count, equals(0)); + test('should produce nothing for empty or missing children', () { + expect(parseBookmarkJson('{"children": []}').isEmpty, isTrue); + expect(parseBookmarkJson('{"guid": "root________"}').isEmpty, isTrue); }); - test('should return 0 when children is null', () async { - const noChildrenJson = '{"guid": "root________"}'; - - final count = await utils.importFromJSON(noChildrenJson); - - expect(count, equals(0)); - }); - - test('should filter out tags folder during import', () async { + test('should filter out the tags folder', () { final jsonData = { 'children': [ { 'guid': 'tags________', 'root': 'tagsFolder', 'type': 'text/x-moz-place-container', - 'children': [], + 'children': [ + { + 'guid': 'tag1________', + 'title': 'Tagged', + 'type': 'text/x-moz-place', + 'uri': 'https://example.com/tagged', + }, + ], }, { 'guid': 'menu________', 'root': 'bookmarksMenuFolder', 'type': 'text/x-moz-place-container', - 'children': [], - }, - ], - }; - - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - - final count = await utils.importFromJSON( - jsonEncode(jsonData), - replace: true, - ); - - // Only the menu folder should be processed, tags should be filtered - expect(count, equals(0)); // No bookmarks, just folders - verify(mockService.eraseEverything(BookmarkRoot.root)).called(1); - }); - - test('should erase everything when replace is true', () async { - final jsonData = { - 'children': [ - { - 'guid': 'menu________', - 'type': 'text/x-moz-place-container', - 'children': [], - }, - ], - }; - - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - - await utils.importFromJSON(jsonEncode(jsonData), replace: true); - - verify(mockService.eraseEverything(BookmarkRoot.root)).called(1); - }); - - test('should not erase when replace is false', () async { - final jsonData = { - 'children': [ - { - 'guid': 'menu________', - 'type': 'text/x-moz-place-container', - 'children': [], - }, - ], - }; - - await utils.importFromJSON(jsonEncode(jsonData)); - - verifyNever(mockService.eraseEverything(any)); - }); - - test('should import bookmarks with URI field', () async { - final jsonData = { - 'children': [ - { - 'guid': 'menu________', - 'type': 'text/x-moz-place-container', 'children': [ { 'guid': 'bookmark1___', - 'title': 'Test Bookmark', + 'title': 'Kept', 'type': 'text/x-moz-place', 'uri': 'https://example.com', }, @@ -149,59 +108,65 @@ void main() { ], }; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'bookmark1___'); + final tree = parseBookmarkJson(jsonEncode(jsonData)); - final count = await utils.importFromJSON(jsonEncode(jsonData)); - - expect(count, equals(1)); - verify( - mockService.addItem( - 'menu________', - Uri.parse('https://example.com'), - 'Test Bookmark', - 0, - ), - ).called(1); + expect(tree.sections.keys, equals([BookmarkRoot.menu.id])); + expect(tree.stats.bookmarkCount, equals(1)); }); - test('should import bookmarks with URL field', () async { + test('should ignore top-level nodes that are not Places roots', () { final jsonData = { 'children': [ { - 'guid': 'menu________', + 'guid': 'notaroot____', 'type': 'text/x-moz-place-container', 'children': [ { 'guid': 'bookmark1___', - 'title': 'Test Bookmark', + 'title': 'Orphan', 'type': 'text/x-moz-place', - 'url': 'https://example.com', + 'uri': 'https://example.com', }, ], }, ], }; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'bookmark1___'); - - final count = await utils.importFromJSON(jsonEncode(jsonData)); - - expect(count, equals(1)); - verify( - mockService.addItem( - 'menu________', - Uri.parse('https://example.com'), - 'Test Bookmark', - 0, - ), - ).called(1); + expect(parseBookmarkJson(jsonEncode(jsonData)).isEmpty, isTrue); }); - test('should skip bookmarks with invalid URLs', () async { + test('should accept both the uri and url fields', () { + for (final field in ['uri', 'url']) { + final jsonData = { + 'children': [ + { + 'guid': 'menu________', + 'type': 'text/x-moz-place-container', + 'children': [ + { + 'guid': 'bookmark1___', + 'title': 'Test Bookmark', + 'type': 'text/x-moz-place', + field: 'https://example.com', + }, + ], + }, + ], + }; + + final tree = parseBookmarkJson(jsonEncode(jsonData)); + + expect( + section(tree, BookmarkRoot.menu).single, + isA() + .having((i) => i.url, 'url', Uri.parse('https://example.com')) + .having((i) => i.title, 'title', 'Test Bookmark'), + reason: 'field "$field" should be read as the bookmark URL', + ); + } + }); + + test('should skip bookmarks with invalid URLs', () { final jsonData = { 'children': [ { @@ -225,26 +190,13 @@ void main() { ], }; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'valid1______'); + final tree = parseBookmarkJson(jsonEncode(jsonData)); - final count = await utils.importFromJSON(jsonEncode(jsonData)); - - // Only one valid bookmark should be imported - expect(count, equals(1)); - // Note: position is 1 because the invalid bookmark was skipped first - verify( - mockService.addItem( - 'menu________', - Uri.parse('https://example.com'), - 'Valid URL', - 1, - ), - ).called(1); + expect(section(tree, BookmarkRoot.menu), hasLength(1)); + expect(tree.stats.skippedUrlCount, equals(1)); }); - test('should import nested folders recursively', () async { + test('should nest folders recursively', () { final jsonData = { 'children': [ { @@ -269,28 +221,20 @@ void main() { ], }; - when( - mockService.addFolder(any, any, any), - ).thenAnswer((_) async => 'folder1_____'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'bookmark1___'); + final tree = parseBookmarkJson(jsonEncode(jsonData)); - final count = await utils.importFromJSON(jsonEncode(jsonData)); - - expect(count, equals(1)); - verify(mockService.addFolder('menu________', 'Folder 1', 0)).called(1); - verify( - mockService.addItem( - 'folder1_____', - Uri.parse('https://example.com'), - 'Nested Bookmark', - 0, - ), - ).called(1); + final folder = + section(tree, BookmarkRoot.menu).single as ImportBookmarkFolder; + expect(folder.title, equals('Folder 1')); + expect( + (folder.children.single as ImportBookmarkItem).title, + equals('Nested Bookmark'), + ); + expect(tree.stats.bookmarkCount, equals(1)); + expect(tree.stats.folderCount, equals(1)); }); - test('should handle separators gracefully (skip them)', () async { + test('should keep separators', () { final jsonData = { 'children': [ { @@ -315,18 +259,80 @@ void main() { ], }; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((invocation) async => 'generated_guid'); + final tree = parseBookmarkJson(jsonEncode(jsonData)); + final nodes = section(tree, BookmarkRoot.menu); - final count = await utils.importFromJSON(jsonEncode(jsonData)); - - // Two bookmarks, separator should be skipped - expect(count, equals(2)); - verify(mockService.addItem(any, any, any, any)).called(2); + expect(nodes, hasLength(3)); + expect(nodes[1], isA()); + expect(tree.stats.bookmarkCount, equals(2)); + expect(tree.stats.separatorCount, equals(1)); }); - test('should fixup place: queries with folder shortcuts', () async { + test('should read microsecond timestamps from Firefox backups', () { + final jsonData = { + 'children': [ + { + 'guid': 'menu________', + 'type': 'text/x-moz-place-container', + 'children': [ + { + 'guid': 'bookmark1___', + 'title': 'Dated', + 'type': 'text/x-moz-place', + 'uri': 'https://example.com', + 'dateAdded': 1361551979350273, + 'lastModified': 1361551979376699, + }, + ], + }, + ], + }; + + final tree = parseBookmarkJson(jsonEncode(jsonData)); + + final item = + section(tree, BookmarkRoot.menu).single as ImportBookmarkItem; + expect( + item.dateAdded, + equals(DateTime.fromMillisecondsSinceEpoch(1361551979350)), + ); + expect( + item.lastModified, + equals(DateTime.fromMillisecondsSinceEpoch(1361551979376)), + ); + }); + + test('should read millisecond timestamps from WebLibre exports', () { + final jsonData = { + 'children': [ + { + 'guid': 'menu________', + 'type': 'text/x-moz-place-container', + 'children': [ + { + 'guid': 'bookmark1___', + 'title': 'Dated', + 'type': 'text/x-moz-place', + 'uri': 'https://example.com', + 'dateAdded': 1361551979350, + }, + ], + }, + ], + }; + + final tree = parseBookmarkJson(jsonEncode(jsonData)); + + final item = + section(tree, BookmarkRoot.menu).single as ImportBookmarkItem; + expect( + item.dateAdded, + equals(DateTime.fromMillisecondsSinceEpoch(1361551979350)), + ); + expect(item.lastModified, isNull); + }); + + test('should fixup place: queries with folder shortcuts', () { final jsonData = { 'children': [ { @@ -352,25 +358,14 @@ void main() { ], }; - when( - mockService.addFolder(any, any, any), - ).thenAnswer((_) async => 'folder1_____'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'shortcut1___'); + final tree = parseBookmarkJson(jsonEncode(jsonData)); - await utils.importFromJSON(jsonEncode(jsonData)); - - // Capture the URI argument to verify it was fixed up - // Note: position is 1 because the folder was added first at position 0 - final captured = verify( - mockService.addItem('unfiled_____', captureAny, 'Folder Shortcut', 1), - ).captured; - - expect((captured[0] as Uri).toString(), contains('parent=folder1_____')); + final shortcut = + section(tree, BookmarkRoot.unfiled)[1] as ImportBookmarkItem; + expect(shortcut.url.toString(), contains('parent=folder1_____')); }); - test('should handle invalid folder references in place: queries', () async { + test('should handle invalid folder references in place: queries', () { final jsonData = { 'children': [ { @@ -388,48 +383,129 @@ void main() { ], }; - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'shortcut1___'); + final tree = parseBookmarkJson(jsonEncode(jsonData)); - await utils.importFromJSON(jsonEncode(jsonData)); - - final captured = verify( - mockService.addItem( - 'unfiled_____', - captureAny, - 'Invalid Folder Shortcut', - 0, - ), - ).captured; - - final url = (captured[0] as Uri).toString(); + final url = + (section(tree, BookmarkRoot.unfiled).single as ImportBookmarkItem).url + .toString(); expect(url, contains('invalidOldParentId=999999')); expect(url, contains('excludeItems=1')); }); - test('should count imported bookmarks correctly from fixture', () async { - // Load the fixture - final fixtureFile = File('test/utils/bookmarks/fixtures/bookmarks.json'); - final jsonString = await fixtureFile.readAsString(); + test('should parse the bookmarks fixture', () async { + final jsonString = await File( + 'test/utils/bookmarks/fixtures/bookmarks.json', + ).readAsString(); - // Mock the service calls - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - when( - mockService.addFolder(any, any, any), - ).thenAnswer((invocation) async => 'generated_guid'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((invocation) async => 'generated_guid'); + final tree = parseBookmarkJson(jsonString); - final count = await utils.importFromJSON(jsonString, replace: true); + expect(tree.stats.bookmarkCount, greaterThan(0)); + }); + }); - // The fixture has several bookmarks - we should count only valid ones - expect(count, greaterThan(0)); - verify(mockService.eraseEverything(BookmarkRoot.root)).called(1); + group('BookmarkJSONUtils - Import', () { + test('should reject invalid JSON format', () { + expect(() => utils.importFromJSON('[]'), throwsA(isA())); }); - test('should handle import errors gracefully', () async { + test('should return 0 without touching storage for empty input', () async { + expect(await utils.importFromJSON('{"children": []}'), equals(0)); + expect(await utils.importFromJSON('{"guid": "root________"}'), equals(0)); + + verifyNever(mockService.insertTree(any, any)); + verifyNever(mockService.eraseEverything(any)); + }); + + test('should insert each root section with a single bulk call', () async { + final jsonData = { + 'children': [ + { + 'guid': 'menu________', + 'type': 'text/x-moz-place-container', + 'children': [ + { + 'guid': 'folder1_____', + 'title': 'Folder 1', + 'type': 'text/x-moz-place-container', + 'children': [ + { + 'guid': 'bookmark1___', + 'title': 'Nested Bookmark', + 'type': 'text/x-moz-place', + 'uri': 'https://example.com', + }, + ], + }, + ], + }, + { + 'guid': 'unfiled_____', + 'type': 'text/x-moz-place-container', + 'children': [ + { + 'guid': 'bookmark2___', + 'title': 'Unfiled Bookmark', + 'type': 'text/x-moz-place', + 'uri': 'https://example.com/2', + }, + ], + }, + ], + }; + + final count = await utils.importFromJSON(jsonEncode(jsonData)); + + expect(count, equals(2)); + verify(mockService.insertTree(BookmarkRoot.menu.id, any)).called(1); + verify(mockService.insertTree(BookmarkRoot.unfiled.id, any)).called(1); + verifyNever(mockService.addItem(any, any, any, any)); + verifyNever(mockService.addFolder(any, any, any)); + }); + + test( + 'should erase every root except the tree root when replacing', + () async { + final jsonString = await File( + 'test/utils/bookmarks/fixtures/bookmarks.json', + ).readAsString(); + + final count = await utils.importFromJSON(jsonString, replace: true); + + expect(count, greaterThan(0)); + for (final root in BookmarkRoot.values) { + if (root == BookmarkRoot.root) { + verifyNever(mockService.eraseEverything(root)); + } else { + verify(mockService.eraseEverything(root)).called(1); + } + } + }, + ); + + test('should not erase when replace is false', () async { + final jsonData = { + 'children': [ + { + 'guid': 'menu________', + 'type': 'text/x-moz-place-container', + 'children': [ + { + 'guid': 'bookmark1___', + 'title': 'Test Bookmark', + 'type': 'text/x-moz-place', + 'uri': 'https://example.com', + }, + ], + }, + ], + }; + + await utils.importFromJSON(jsonEncode(jsonData)); + + verifyNever(mockService.eraseEverything(any)); + }); + + test('should rethrow storage failures', () { final jsonData = { 'children': [ { @@ -448,13 +524,13 @@ void main() { }; when( - mockService.addItem(any, any, any, any), + mockService.insertTree(any, any), ).thenThrow(Exception('Database error')); - // Should not throw, but should log and continue - final count = await utils.importFromJSON(jsonEncode(jsonData)); - - expect(count, equals(0)); // Failed to add + expect( + () => utils.importFromJSON(jsonEncode(jsonData)), + throwsA(isA()), + ); }); }); @@ -776,21 +852,27 @@ void main() { expect(exported, isNotNull); // Re-import - when(mockService.eraseEverything(any)).thenAnswer((_) async {}); - when( - mockService.addFolder(any, any, any), - ).thenAnswer((_) async => 'folder1_____'); - when( - mockService.addItem(any, any, any, any), - ).thenAnswer((_) async => 'bookmark1___'); - final jsonString = jsonEncode({ 'children': [exported], }); final count = await utils.importFromJSON(jsonString, replace: true); expect(count, equals(1)); // One bookmark imported - verify(mockService.eraseEverything(BookmarkRoot.root)).called(1); + verify(mockService.eraseEverything(BookmarkRoot.menu)).called(1); + + final inserted = + verify( + mockService.insertTree(BookmarkRoot.menu.id, captureAny), + ).captured.single + as List; + + final folder = inserted.single; + expect(folder.type, equals(BookmarkNodeType.folder)); + expect(folder.title, equals('Test Folder')); + + final bookmark = folder.children.single; + expect(bookmark.title, equals('Test Bookmark')); + expect(bookmark.url, equals('https://example.com')); }); }); } diff --git a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.mocks.dart b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.mocks.dart index b5a7657a..ceb4d86b 100644 --- a/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.mocks.dart +++ b/apps/weblibre/test/features/geckoview/features/bookmarks/utils/bookmark_json_utils_test.mocks.dart @@ -3,11 +3,11 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i3; +import 'dart:async' as _i4; import 'package:flutter_mozilla_components/src/domain/services/gecko_bookmarks.dart' - as _i2; -import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart' as _i4; + as _i3; +import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart' as _i2; import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i5; @@ -26,46 +26,52 @@ import 'package:mockito/src/dummies.dart' as _i5; // ignore_for_file: subtype_of_sealed_class // ignore_for_file: invalid_use_of_internal_member +class _FakeBookmarkInsertTreeResult_0 extends _i1.SmartFake + implements _i2.BookmarkInsertTreeResult { + _FakeBookmarkInsertTreeResult_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + /// A class which mocks [GeckoBookmarksService]. /// /// See the documentation for Mockito's code generation for more information. class MockGeckoBookmarksService extends _i1.Mock - implements _i2.GeckoBookmarksService { + implements _i3.GeckoBookmarksService { MockGeckoBookmarksService() { _i1.throwOnMissingStub(this); } @override - _i3.Future<_i4.BookmarkNode?> getTree( + _i4.Future<_i2.BookmarkNode?> getTree( String? guid, { bool? recursive = false, }) => (super.noSuchMethod( Invocation.method(#getTree, [guid], {#recursive: recursive}), - returnValue: _i3.Future<_i4.BookmarkNode?>.value(), + returnValue: _i4.Future<_i2.BookmarkNode?>.value(), ) - as _i3.Future<_i4.BookmarkNode?>); + as _i4.Future<_i2.BookmarkNode?>); @override - _i3.Future<_i4.BookmarkNode?> getBookmark(String? guid) => + _i4.Future<_i2.BookmarkNode?> getBookmark(String? guid) => (super.noSuchMethod( Invocation.method(#getBookmark, [guid]), - returnValue: _i3.Future<_i4.BookmarkNode?>.value(), + returnValue: _i4.Future<_i2.BookmarkNode?>.value(), ) - as _i3.Future<_i4.BookmarkNode?>); + as _i4.Future<_i2.BookmarkNode?>); @override - _i3.Future> getBookmarksWithUrl(Uri? url) => + _i4.Future> getBookmarksWithUrl(Uri? url) => (super.noSuchMethod( Invocation.method(#getBookmarksWithUrl, [url]), - returnValue: _i3.Future>.value( - <_i4.BookmarkNode>[], + returnValue: _i4.Future>.value( + <_i2.BookmarkNode>[], ), ) - as _i3.Future>); + as _i4.Future>); @override - _i3.Future> getRecentBookmarks( + _i4.Future> getRecentBookmarks( int? limit, { Duration? maxAge = Duration.zero, DateTime? currentTime, @@ -76,27 +82,27 @@ class MockGeckoBookmarksService extends _i1.Mock [limit], {#maxAge: maxAge, #currentTime: currentTime}, ), - returnValue: _i3.Future>.value( - <_i4.BookmarkNode>[], + returnValue: _i4.Future>.value( + <_i2.BookmarkNode>[], ), ) - as _i3.Future>); + as _i4.Future>); @override - _i3.Future> searchBookmarks( + _i4.Future> searchBookmarks( String? query, { int? limit = 10, }) => (super.noSuchMethod( Invocation.method(#searchBookmarks, [query], {#limit: limit}), - returnValue: _i3.Future>.value( - <_i4.BookmarkNode>[], + returnValue: _i4.Future>.value( + <_i2.BookmarkNode>[], ), ) - as _i3.Future>); + as _i4.Future>); @override - _i3.Future addItem( + _i4.Future addItem( String? parentGuid, Uri? url, String? title, @@ -104,55 +110,79 @@ class MockGeckoBookmarksService extends _i1.Mock ) => (super.noSuchMethod( Invocation.method(#addItem, [parentGuid, url, title, position]), - returnValue: _i3.Future.value( + returnValue: _i4.Future.value( _i5.dummyValue( this, Invocation.method(#addItem, [parentGuid, url, title, position]), ), ), ) - as _i3.Future); + as _i4.Future); @override - _i3.Future addFolder( + _i4.Future addFolder( String? parentGuid, String? title, int? position, ) => (super.noSuchMethod( Invocation.method(#addFolder, [parentGuid, title, position]), - returnValue: _i3.Future.value( + returnValue: _i4.Future.value( _i5.dummyValue( this, Invocation.method(#addFolder, [parentGuid, title, position]), ), ), ) - as _i3.Future); + as _i4.Future); @override - _i3.Future updateNode(String? guid, _i4.BookmarkInfo? info) => + _i4.Future updateNode(String? guid, _i2.BookmarkInfo? info) => (super.noSuchMethod( Invocation.method(#updateNode, [guid, info]), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), ) - as _i3.Future); + as _i4.Future); @override - _i3.Future deleteNode(String? guid) => + _i4.Future deleteNode(String? guid) => (super.noSuchMethod( Invocation.method(#deleteNode, [guid]), - returnValue: _i3.Future.value(false), + returnValue: _i4.Future.value(false), ) - as _i3.Future); + as _i4.Future); @override - _i3.Future eraseEverything(_i2.BookmarkRoot? root) => + _i4.Future<_i2.BookmarkInsertTreeResult> insertTree( + String? parentGuid, + List<_i2.BookmarkImportNode>? children, + ) => + (super.noSuchMethod( + Invocation.method(#insertTree, [parentGuid, children]), + returnValue: _i4.Future<_i2.BookmarkInsertTreeResult>.value( + _FakeBookmarkInsertTreeResult_0( + this, + Invocation.method(#insertTree, [parentGuid, children]), + ), + ), + ) + as _i4.Future<_i2.BookmarkInsertTreeResult>); + + @override + _i4.Future countBookmarksInTrees(List? guids) => + (super.noSuchMethod( + Invocation.method(#countBookmarksInTrees, [guids]), + returnValue: _i4.Future.value(0), + ) + as _i4.Future); + + @override + _i4.Future eraseEverything(_i3.BookmarkRoot? root) => (super.noSuchMethod( Invocation.method(#eraseEverything, [root]), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), ) - as _i3.Future); + as _i4.Future); } diff --git a/apps/weblibre/test/features/geckoview/features/tabs/data/models/container_data_test.dart b/apps/weblibre/test/features/geckoview/features/tabs/data/models/container_data_test.dart index c6d09309..7b7807cb 100644 --- a/apps/weblibre/test/features/geckoview/features/tabs/data/models/container_data_test.dart +++ b/apps/weblibre/test/features/geckoview/features/tabs/data/models/container_data_test.dart @@ -66,10 +66,7 @@ void main() { }); test('defaults to false', () { - expect( - ContainerMetadata.withDefaults().isolatedAppLinkSettings, - isFalse, - ); + expect(ContainerMetadata.withDefaults().isolatedAppLinkSettings, isFalse); }); }); diff --git a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoBookmarksApiImpl.kt b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoBookmarksApiImpl.kt index 959c97e8..d3f289bb 100644 --- a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoBookmarksApiImpl.kt +++ b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/api/GeckoBookmarksApiImpl.kt @@ -2,7 +2,9 @@ package eu.weblibre.flutter_mozilla_components.api import eu.weblibre.flutter_mozilla_components.GlobalComponents import eu.weblibre.flutter_mozilla_components.feature.GeckoBookmarksExtensionBridge +import eu.weblibre.flutter_mozilla_components.pigeons.BookmarkImportNode import eu.weblibre.flutter_mozilla_components.pigeons.BookmarkInfo +import eu.weblibre.flutter_mozilla_components.pigeons.BookmarkInsertTreeResult import eu.weblibre.flutter_mozilla_components.pigeons.BookmarkNode import eu.weblibre.flutter_mozilla_components.pigeons.BookmarkNodeType import eu.weblibre.flutter_mozilla_components.pigeons.GeckoBookmarksApi @@ -11,10 +13,19 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import mozilla.components.concept.storage.BookmarkInfo as MozillaBookmarkInfo +import mozilla.components.concept.storage.bookmarks.InsertableBookmarkTreeNode +import mozilla.components.concept.storage.bookmarks.InsertableBookmarkTreeRoot class GeckoBookmarksApiImpl() : GeckoBookmarksApi { companion object { private val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob()) + + /** + * Name of the short-lived folder that loose top-level nodes pass through + * during an import. Only visible if an import is interrupted partway. + */ + private const val SCRATCH_FOLDER_TITLE = "Importing bookmarks…" } private val components by lazy { @@ -231,6 +242,261 @@ class GeckoBookmarksApiImpl() : GeckoBookmarksApi { } } + override fun insertTree( + parentGuid: String, + children: List, + callback: (Result) -> Unit + ) { + coroutineScope.launch { + // Imports can carry tens of thousands of nodes, so the whole batch runs + // off the main thread. Only the callback returns to it, because Pigeon + // replies must be delivered on the platform thread. + val result = withContext(Dispatchers.IO) { + runCatching { insertImportNodes(parentGuid, children) } + } + callback(result) + } + } + + /** + * Appends [nodes] underneath [parentGuid], handing every top-level folder to + * storage as a single tree insertion. + * + * `insertTree` is the only storage call that carries timestamps, and it can + * only create a *folder*. Loose top-level items and separators would + * therefore lose their `ADD_DATE` if inserted with `addItem`/`addSeparator`, + * which have no timestamp parameters — so they are staged inside a scratch + * folder and reparented instead. See [stageLooseNodes]. + * + * A failing top-level node is counted and skipped rather than aborting the + * whole import, matching the per-node importer this replaced. Deliberately + * does not emit `bookmarks.onCreated`: one event per imported node would + * flood every installed WebExtension. + */ + private suspend fun insertImportNodes( + parentGuid: String, + nodes: List + ): BookmarkInsertTreeResult { + val storage = components.core.bookmarksStorage + var insertedItemCount = 0L + var failedNodeCount = 0L + + val staged = stageLooseNodes(parentGuid, nodes) + + for (node in nodes) { + // Every branch appends (position = null). Walking the nodes in order + // therefore reproduces the file's order, and merging into a folder + // that already has children leaves those in place. + val outcome: Result = when (node.type) { + BookmarkNodeType.FOLDER -> { + val folder = node.toInsertableFolder(position = null) + storage.insertTree(InsertableBookmarkTreeRoot(parentGuid, folder)) + .map { folder.itemCount() } + } + + // Already written by stageLooseNodes; only the move is left. + else -> staged.reparent(node, parentGuid) + } + + outcome.fold( + { count -> insertedItemCount += count }, + { failedNodeCount += 1 } + ) + } + + staged.discardScratchFolder() + + return BookmarkInsertTreeResult(insertedItemCount, failedNodeCount) + } + + override fun countBookmarksInTrees( + guids: List, + callback: (Result) -> Unit + ) { + coroutineScope.launch { + val result = withContext(Dispatchers.IO) { + runCatching { + components.core.bookmarksStorage.countBookmarksInTrees(guids).toLong() + } + } + callback(result) + } + } + + /** + * Loose top-level nodes written into a scratch folder, waiting to be moved + * to their real parent. + * + * The scratch folder is created under the import destination and holds the + * loose nodes in file order; [reparent] hands them out one at a time as the + * caller walks the top level, and [discardScratchFolder] removes the folder + * once it has been emptied. + */ + private inner class StagedLooseNodes( + private val scratchGuid: String?, + /** The loose nodes that made it into the scratch folder, in order. */ + private val staged: List, + /** Guid assigned to each entry of [staged], by index. */ + private val guids: List, + private val failure: Throwable? + ) { + private var next = 0 + + /** + * Moves the next staged node under [parentGuid]. + * + * Reparenting preserves `dateAdded`, which is what bookmark ordering and + * "recently added" depend on. It does refresh `lastModified` — the pair + * cannot both survive, because the only storage call that accepts + * timestamps creates a folder. + */ + suspend fun reparent(node: BookmarkImportNode, parentGuid: String): Result { + failure?.let { return Result.failure(it) } + + // Nodes dropped while converting (an item with no usable url) were + // never staged, so the cursor must not advance past them. + if (staged.getOrNull(next) !== node) { + return Result.failure( + IllegalArgumentException("Unusable bookmark node of type ${node.type}") + ) + } + + val guid = guids.getOrNull(next) + ?: return Result.failure( + IllegalStateException("Storage did not report a guid for ${node.type}") + ) + next++ + + // A null field means "leave unchanged"; appending (null position) + // keeps the file's order as the caller walks the top level. + val move = MozillaBookmarkInfo( + parentGuid = parentGuid, + position = null, + title = null, + url = null + ) + + return components.core.bookmarksStorage + .updateNode(guid, move) + .map { if (node.type == BookmarkNodeType.ITEM) 1L else 0L } + } + + /** + * Deletes the scratch folder, but only once it is empty. + * + * Deleting cascades to children, so anything that failed to move is left + * behind in a visible folder rather than being silently destroyed. + */ + suspend fun discardScratchFolder() { + val guid = scratchGuid ?: return + val storage = components.core.bookmarksStorage + + val remaining = storage.getTree(guid, false).getOrNull()?.children + if (remaining.isNullOrEmpty()) { + storage.deleteNode(guid) + } + } + } + + /** + * Writes every loose top-level node of [nodes] into a scratch folder under + * [parentGuid] in a single tree insertion, so their timestamps survive. + * + * Returns an empty staging area when the import has no loose top-level + * nodes, which is the common case for Firefox exports and costs nothing. + */ + private suspend fun stageLooseNodes( + parentGuid: String, + nodes: List + ): StagedLooseNodes { + val empty = StagedLooseNodes(null, emptyList(), emptyList(), null) + + val staged = ArrayList() + val insertable = ArrayList() + for (node in nodes) { + if (node.type == BookmarkNodeType.FOLDER) continue + val converted = node.toInsertableNode(insertable.size.toUInt()) ?: continue + insertable.add(converted) + staged.add(node) + } + + if (staged.isEmpty()) return empty + + val scratch = InsertableBookmarkTreeNode.Folder( + title = SCRATCH_FOLDER_TITLE, + dateAddedTimestamp = 0L, + lastModifiedTimestamp = 0L, + position = null, + children = insertable + ) + + val storage = components.core.bookmarksStorage + + return storage.insertTree(InsertableBookmarkTreeRoot(parentGuid, scratch)).fold( + { scratchGuid -> + // Read the assigned guids back in position order, which is the + // order the nodes were handed to insertTree. + val children = storage.getTree(scratchGuid, false).getOrNull()?.children + StagedLooseNodes( + scratchGuid = scratchGuid, + staged = staged, + guids = children.orEmpty().map { it.guid }, + failure = null + ) + }, + { error -> StagedLooseNodes(null, staged, emptyList(), error) } + ) + } + + private fun BookmarkImportNode.toInsertableFolder(position: UInt?) = + InsertableBookmarkTreeNode.Folder( + title = this.title, + dateAddedTimestamp = this.dateAdded, + lastModifiedTimestamp = this.lastModified, + position = position, + children = this.children.toInsertableNodes() + ) + + /** + * Converts children to their insertable form, dropping unusable nodes and + * assigning positions from the surviving order so no gaps are left behind. + */ + private fun List.toInsertableNodes(): List { + val converted = ArrayList(this.size) + for (node in this) { + converted.add(node.toInsertableNode(converted.size.toUInt()) ?: continue) + } + return converted + } + + private fun BookmarkImportNode.toInsertableNode(position: UInt): InsertableBookmarkTreeNode? = + when (this.type) { + BookmarkNodeType.FOLDER -> this.toInsertableFolder(position) + + BookmarkNodeType.ITEM -> this.url?.takeIf { it.isNotEmpty() }?.let { url -> + InsertableBookmarkTreeNode.Item( + title = this.title, + url = url, + dateAddedTimestamp = this.dateAdded, + lastModifiedTimestamp = this.lastModified, + position = position + ) + } + + BookmarkNodeType.SEPARATOR -> InsertableBookmarkTreeNode.Separator( + dateAddedTimestamp = this.dateAdded, + lastModifiedTimestamp = this.lastModified, + position = position + ) + } + + /** Number of bookmark items in this subtree, excluding folders and separators. */ + private fun InsertableBookmarkTreeNode.itemCount(): Long = when (this) { + is InsertableBookmarkTreeNode.Item -> 1L + is InsertableBookmarkTreeNode.Folder -> this.children.sumOf { it.itemCount() } + is InsertableBookmarkTreeNode.Separator -> 0L + } + /** * Notifies extension `bookmarks.onCreated` listeners about a node created * through the app UI, so extensions (e.g. floccus) observe app-side edits to diff --git a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/pigeons/Gecko.g.kt b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/pigeons/Gecko.g.kt index fe91986e..1c40a3bf 100644 --- a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/pigeons/Gecko.g.kt +++ b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/pigeons/Gecko.g.kt @@ -5271,6 +5271,127 @@ data class BookmarkNode ( } } +/** + * A node of a bookmark tree that is about to be bulk-inserted into storage. + * + * Unlike [BookmarkNode] this carries no guids or parent links: the tree is + * described purely by nesting, and storage assigns guids while inserting. + * + * @property type Whether this node is an item, a folder or a separator. + * @property title The title of the item or folder. Ignored for separators. + * @property url The URL of the item. Must be non-null for items, ignored otherwise. + * @property dateAdded Creation timestamp in milliseconds since epoch, or 0 if unknown. + * @property lastModified Modification timestamp in milliseconds since epoch, or 0 if unknown. + * @property children Child nodes of a folder, in insertion order. Empty for items and separators. + * + * Generated class from Pigeon that represents data sent in messages. + */ +data class BookmarkImportNode ( + val type: BookmarkNodeType, + val title: String? = null, + val url: String? = null, + val dateAdded: Long, + val lastModified: Long, + val children: List +) + { + companion object { + fun fromList(pigeonVar_list: List): BookmarkImportNode { + val type = pigeonVar_list[0] as BookmarkNodeType + val title = pigeonVar_list[1] as String? + val url = pigeonVar_list[2] as String? + val dateAdded = pigeonVar_list[3] as Long + val lastModified = pigeonVar_list[4] as Long + val children = pigeonVar_list[5] as List + return BookmarkImportNode(type, title, url, dateAdded, lastModified, children) + } + } + fun toList(): List { + return listOf( + type, + title, + url, + dateAdded, + lastModified, + children, + ) + } + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as BookmarkImportNode + return GeckoPigeonUtils.deepEquals(this.type, other.type) && GeckoPigeonUtils.deepEquals(this.title, other.title) && GeckoPigeonUtils.deepEquals(this.url, other.url) && GeckoPigeonUtils.deepEquals(this.dateAdded, other.dateAdded) && GeckoPigeonUtils.deepEquals(this.lastModified, other.lastModified) && GeckoPigeonUtils.deepEquals(this.children, other.children) + } + + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeckoPigeonUtils.deepHash(this.type) + result = 31 * result + GeckoPigeonUtils.deepHash(this.title) + result = 31 * result + GeckoPigeonUtils.deepHash(this.url) + result = 31 * result + GeckoPigeonUtils.deepHash(this.dateAdded) + result = 31 * result + GeckoPigeonUtils.deepHash(this.lastModified) + result = 31 * result + GeckoPigeonUtils.deepHash(this.children) + return result + } + override fun toString(): String { + return "BookmarkImportNode(type=$type, title=$title, url=$url, dateAdded=$dateAdded, lastModified=$lastModified, children=$children)" + } +} + +/** + * Outcome of a bulk bookmark tree insertion. + * + * @property insertedItemCount The number of bookmark items (not folders or + * separators) that were inserted. + * @property failedNodeCount The number of top-level nodes that could not be + * inserted. Their subtrees are missing entirely. + * + * Generated class from Pigeon that represents data sent in messages. + */ +data class BookmarkInsertTreeResult ( + val insertedItemCount: Long, + val failedNodeCount: Long +) + { + companion object { + fun fromList(pigeonVar_list: List): BookmarkInsertTreeResult { + val insertedItemCount = pigeonVar_list[0] as Long + val failedNodeCount = pigeonVar_list[1] as Long + return BookmarkInsertTreeResult(insertedItemCount, failedNodeCount) + } + } + fun toList(): List { + return listOf( + insertedItemCount, + failedNodeCount, + ) + } + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as BookmarkInsertTreeResult + return GeckoPigeonUtils.deepEquals(this.insertedItemCount, other.insertedItemCount) && GeckoPigeonUtils.deepEquals(this.failedNodeCount, other.failedNodeCount) + } + + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeckoPigeonUtils.deepHash(this.insertedItemCount) + result = 31 * result + GeckoPigeonUtils.deepHash(this.failedNodeCount) + return result + } + override fun toString(): String { + return "BookmarkInsertTreeResult(insertedItemCount=$insertedItemCount, failedNodeCount=$failedNodeCount)" + } +} + /** * Class for making alterations to any bookmark node * @@ -6613,28 +6734,32 @@ private data class GeckoPigeonInternalCodecOverflow ( when (type.toInt()) { 0 -> - return AppLinkResolutionResult.fromList(wrapped as List) + return AppLinkPolicySnapshot.fromList(wrapped as List) 1 -> - return PwaIcon.fromList(wrapped as List) + return AppLinkPromptRequest.fromList(wrapped as List) 2 -> - return ShareTargetFiles.fromList(wrapped as List) + return AppLinkResolutionResult.fromList(wrapped as List) 3 -> - return ShareTargetParams.fromList(wrapped as List) + return PwaIcon.fromList(wrapped as List) 4 -> - return ShareTarget.fromList(wrapped as List) + return ShareTargetFiles.fromList(wrapped as List) 5 -> - return ExternalApplicationResource.fromList(wrapped as List) + return ShareTargetParams.fromList(wrapped as List) 6 -> - return PwaManifest.fromList(wrapped as List) + return ShareTarget.fromList(wrapped as List) 7 -> - return SandboxCaptureEntry.fromList(wrapped as List) + return ExternalApplicationResource.fromList(wrapped as List) 8 -> - return GestureConfig.fromList(wrapped as List) + return PwaManifest.fromList(wrapped as List) 9 -> - return PushDistributor.fromList(wrapped as List) + return SandboxCaptureEntry.fromList(wrapped as List) 10 -> - return PushStatus.fromList(wrapped as List) + return GestureConfig.fromList(wrapped as List) 11 -> + return PushDistributor.fromList(wrapped as List) + 12 -> + return PushStatus.fromList(wrapped as List) + 13 -> return PushSubscription.fromList(wrapped as List) } return null @@ -7230,47 +7355,47 @@ private open class GeckoPigeonCodec : StandardMessageCodec() { } 246.toByte() -> { return (readValue(buffer) as? List)?.let { - BookmarkInfo.fromList(it) + BookmarkImportNode.fromList(it) } } 247.toByte() -> { return (readValue(buffer) as? List)?.let { - SitePermissions.fromList(it) + BookmarkInsertTreeResult.fromList(it) } } 248.toByte() -> { return (readValue(buffer) as? List)?.let { - TrackingProtectionException.fromList(it) + BookmarkInfo.fromList(it) } } 249.toByte() -> { return (readValue(buffer) as? List)?.let { - AppLinkTarget.fromList(it) + SitePermissions.fromList(it) } } 250.toByte() -> { return (readValue(buffer) as? List)?.let { - ProtectedTargetPattern.fromList(it) + TrackingProtectionException.fromList(it) } } 251.toByte() -> { return (readValue(buffer) as? List)?.let { - NativeAppLinkRule.fromList(it) + AppLinkTarget.fromList(it) } } 252.toByte() -> { return (readValue(buffer) as? List)?.let { - NativeContextAppLinkPolicy.fromList(it) + ProtectedTargetPattern.fromList(it) } } 253.toByte() -> { return (readValue(buffer) as? List)?.let { - AppLinkPolicySnapshot.fromList(it) + NativeAppLinkRule.fromList(it) } } 254.toByte() -> { return (readValue(buffer) as? List)?.let { - AppLinkPromptRequest.fromList(it) + NativeContextAppLinkPolicy.fromList(it) } } 255.toByte() -> { @@ -7751,102 +7876,112 @@ private open class GeckoPigeonCodec : StandardMessageCodec() { stream.write(245) writeValue(stream, value.toList()) } - is BookmarkInfo -> { + is BookmarkImportNode -> { stream.write(246) writeValue(stream, value.toList()) } - is SitePermissions -> { + is BookmarkInsertTreeResult -> { stream.write(247) writeValue(stream, value.toList()) } - is TrackingProtectionException -> { + is BookmarkInfo -> { stream.write(248) writeValue(stream, value.toList()) } - is AppLinkTarget -> { + is SitePermissions -> { stream.write(249) writeValue(stream, value.toList()) } - is ProtectedTargetPattern -> { + is TrackingProtectionException -> { stream.write(250) writeValue(stream, value.toList()) } - is NativeAppLinkRule -> { + is AppLinkTarget -> { stream.write(251) writeValue(stream, value.toList()) } - is NativeContextAppLinkPolicy -> { + is ProtectedTargetPattern -> { stream.write(252) writeValue(stream, value.toList()) } - is AppLinkPolicySnapshot -> { + is NativeAppLinkRule -> { stream.write(253) writeValue(stream, value.toList()) } - is AppLinkPromptRequest -> { + is NativeContextAppLinkPolicy -> { stream.write(254) writeValue(stream, value.toList()) } - is AppLinkResolutionResult -> { + is AppLinkPolicySnapshot -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 0, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is PwaIcon -> { + is AppLinkPromptRequest -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 1, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is ShareTargetFiles -> { + is AppLinkResolutionResult -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 2, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is ShareTargetParams -> { + is PwaIcon -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 3, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is ShareTarget -> { + is ShareTargetFiles -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 4, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is ExternalApplicationResource -> { + is ShareTargetParams -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 5, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is PwaManifest -> { + is ShareTarget -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 6, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is SandboxCaptureEntry -> { + is ExternalApplicationResource -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 7, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is GestureConfig -> { + is PwaManifest -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 8, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is PushDistributor -> { + is SandboxCaptureEntry -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 9, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is PushStatus -> { + is GestureConfig -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 10, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } - is PushSubscription -> { + is PushDistributor -> { val wrap = GeckoPigeonInternalCodecOverflow(type = 11, wrapped = value.toList()) stream.write(255) writeValue(stream, wrap.toList()) } + is PushStatus -> { + val wrap = GeckoPigeonInternalCodecOverflow(type = 12, wrapped = value.toList()) + stream.write(255) + writeValue(stream, wrap.toList()) + } + is PushSubscription -> { + val wrap = GeckoPigeonInternalCodecOverflow(type = 13, wrapped = value.toList()) + stream.write(255) + writeValue(stream, wrap.toList()) + } else -> super.writeValue(stream, value) } } @@ -12253,6 +12388,42 @@ interface GeckoBookmarksApi { * @return Whether the bookmark existed or not. */ fun deleteNode(guid: String, callback: (Result) -> Unit) + /** + * Bulk-inserts [children] underneath [parentGuid], appending them after any + * nodes the parent already contains. + * + * Each top-level folder is handed to the storage layer as a single tree + * insertion, so importing a large bookmark file costs one platform channel + * call instead of one per node. Separators are preserved. + * + * Timestamps survive in full for everything nested inside a top-level + * folder. Loose top-level items and separators keep their [dateAdded], but + * their [lastModified] is set to the time of import: the only storage call + * that accepts timestamps creates a folder, so nodes landing directly in + * [parentGuid] have to be moved into place afterwards. + * + * Sync behavior: will add the inserted bookmarks to remote devices. + * + * Unlike [addItem] and [addFolder] this does *not* emit a + * `bookmarks.onCreated` extension event per node, since a large import would + * otherwise flood every installed WebExtension. + * + * @param parentGuid The guid of the existing folder to insert underneath. + * @param children The nodes to insert, in the order they should appear. + * @return The number of inserted bookmark items and failed top-level nodes. + */ + fun insertTree(parentGuid: String, children: List, callback: (Result) -> Unit) + /** + * Counts the bookmark items contained in the trees rooted at [guids]. + * + * Folders and separators are not counted, and a guid that does not exist + * contributes nothing. Lets the app report how much a destructive action + * affects without loading the subtrees into Dart. + * + * @param guids The guids of the folders to count within. + * @return The total number of bookmark items across all trees. + */ + fun countBookmarksInTrees(guids: List, callback: (Result) -> Unit) companion object { /** The codec used by GeckoBookmarksApi. */ @@ -12452,6 +12623,47 @@ interface GeckoBookmarksApi { channel.setMessageHandler(null) } } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.insertTree$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val parentGuidArg = args[0] as String + val childrenArg = args[1] as List + api.insertTree(parentGuidArg, childrenArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeckoPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeckoPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.countBookmarksInTrees$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val guidsArg = args[0] as List + api.countBookmarksInTrees(guidsArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeckoPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeckoPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } } } } diff --git a/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart b/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart index 85f92b61..9d13f76c 100644 --- a/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart +++ b/packages/flutter_mozilla_components/lib/flutter_mozilla_components.dart @@ -59,7 +59,9 @@ export 'src/pigeons/gecko.g.dart' AppLinksMode, AudioHitResult, AutoplayStatus, + BookmarkImportNode, BookmarkInfo, + BookmarkInsertTreeResult, BookmarkNode, BookmarkNodeType, BounceTrackingProtectionMode, diff --git a/packages/flutter_mozilla_components/lib/src/domain/services/gecko_bookmarks.dart b/packages/flutter_mozilla_components/lib/src/domain/services/gecko_bookmarks.dart index 6350a328..577c009a 100644 --- a/packages/flutter_mozilla_components/lib/src/domain/services/gecko_bookmarks.dart +++ b/packages/flutter_mozilla_components/lib/src/domain/services/gecko_bookmarks.dart @@ -129,6 +129,42 @@ class GeckoBookmarksService { return _api.deleteNode(guid); } + /// Bulk-inserts [children] underneath [parentGuid], appending them after any + /// nodes the parent already contains. + /// + /// Prefer this over looping [addItem]/[addFolder] when inserting a whole + /// tree: the entire batch crosses the platform channel once and each + /// top-level folder is written as a single storage operation. Separators are + /// preserved, and no per-node `bookmarks.onCreated` extension events are + /// emitted. + /// + /// Timestamps survive in full for everything nested inside a top-level + /// folder. Loose top-level items and separators keep their `dateAdded` but + /// get a fresh `lastModified`, because the only storage call that accepts + /// timestamps creates a folder. + /// + /// @param parentGuid The guid of the existing folder to insert underneath. + /// @param children The nodes to insert, in the order they should appear. + /// @return The number of inserted bookmark items and failed top-level nodes. + Future insertTree( + String parentGuid, + List children, + ) { + return _api.insertTree(parentGuid, children); + } + + /// Counts the bookmark items contained in the trees rooted at [guids]. + /// + /// Folders and separators are not counted. Prefer this over walking a + /// [getTree] result: the count is computed in storage, so no subtree has to + /// be materialised in Dart. + /// + /// @param guids The guids of the folders to count within. + /// @return The total number of bookmark items across all trees. + Future countBookmarksInTrees(List guids) { + return _api.countBookmarksInTrees(guids); + } + /// Removes ALL bookmarks from the specified root folder. /// The root folder itself is preserved, only its children are removed. Future eraseEverything(BookmarkRoot root) async { diff --git a/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart b/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart index fa24349e..6d7cbb79 100644 --- a/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart +++ b/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart @@ -10,9 +10,9 @@ import 'package:flutter/services.dart'; import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; Object? _extractReplyValueOrThrow( - List? replyList, - String channelName, { - required bool isNullValid, + List? replyList, + String channelName, { + required bool isNullValid, }) { if (replyList == null) { throw PlatformException( @@ -34,8 +34,11 @@ Object? _extractReplyValueOrThrow( return replyList.firstOrNull; } - -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -44,6 +47,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + bool _deepEquals(Object? a, Object? b) { if (identical(a, b)) { return true; @@ -56,8 +60,9 @@ bool _deepEquals(Object? a, Object? b) { } if (a is List && b is List) { return a.length == b.length && - a.indexed - .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + a.indexed.every( + ((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]), + ); } if (a is Map && b is Map) { if (a.length != b.length) { @@ -106,13 +111,14 @@ int _deepHash(Object? value) { return value.hashCode; } - /// Indicates what location the tabs should be restored at enum RestoreLocation { /// Restore tabs at the beginning of the tab list beginning, + /// Restore tabs at the end of the tab list end, + /// Restore tabs at a specific index in the tab list atIndex, } @@ -133,80 +139,71 @@ enum IconType { /// Supported sizes. /// /// We are trying to limit the supported sizes in order to optimize our caching strategy. -enum IconSize { - defaultSize, - launcher, - launcherAdaptive, -} +enum IconSize { defaultSize, launcher, launcherAdaptive } /// The source of an [Icon]. enum IconSource { /// This icon was generated. generator, + /// This icon was downloaded. download, + /// This icon was inlined in the document. inline, + /// This icon was loaded from an in-memory cache. memory, + /// This icon was loaded from a disk cache. disk, } -enum CookieSameSiteStatus { - noRestriction, - lax, - strict, - unspecified, -} +enum CookieSameSiteStatus { noRestriction, lax, strict, unspecified } enum VisitType { /// The user followed a link and got a new toplevel window. link, + /// The user typed the page's URL in the URL bar or selected it from /// URL bar autocomplete results, clicked on it from a history query /// (from the History sidebar, History menu, or history query in the /// personal toolbar or Places organizer. typed, + /// The user followed a bookmark to get to the page. bookmark, + /// Some inner content is loaded. This is true of all images on a /// page, and the contents of the iframe. It is also true of any /// content in a frame if the user did not explicitly follow a link /// to get there. embed, + /// Set when the transition was a permanent redirect. redirectPermanent, + /// Set when the transition was a temporary redirect. redirectTemporary, + /// Set when the transition is a download. download, + /// The user followed a link and got a visit in a frame. framedLink, + /// The user reloaded a page. reload, } -enum FrecencyThresholdOption { - none, - skipOneTimePages, -} +enum FrecencyThresholdOption { none, skipOneTimePages } /// Document type associated with a [HistoryMetadata] record. -enum DocumentType { - regular, - media, -} +enum DocumentType { regular, media } -enum SelectionPattern { - phone, - email, -} +enum SelectionPattern { phone, email } -enum WebExtensionActionType { - browser, - page, -} +enum WebExtensionActionType { browser, page } enum AddonDisabledReason { unsupported, @@ -217,11 +214,7 @@ enum AddonDisabledReason { softBlocked, } -enum AddonIncognito { - spanning, - split, - notAllowed, -} +enum AddonIncognito { spanning, split, notAllowed } enum AddonUpdateStatus { notInstalled, @@ -230,74 +223,47 @@ enum AddonUpdateStatus { error, } -enum AddonStoreApp { - android, - firefox, -} +enum AddonStoreApp { android, firefox } -enum AddonStorePromoted { - none, - recommended, - line, -} +enum AddonStorePromoted { none, recommended, line } -enum GeckoSuggestionType { - session, - clipboard, - history, -} +enum GeckoSuggestionType { session, clipboard, history } -enum TrackingProtectionPolicy { - none, - recommended, - strict, - custom, -} +enum TrackingProtectionPolicy { none, recommended, strict, custom } -enum HttpsOnlyMode { - disabled, - privateOnly, - enabled, -} +enum HttpsOnlyMode { disabled, privateOnly, enabled } -enum QueryParameterStripping { - disabled, - privateOnly, - enabled, -} +enum QueryParameterStripping { disabled, privateOnly, enabled } enum BounceTrackingProtectionMode { /// Fully disabled. disabled, + /// Fully enabled. enabled, + /// Disabled, but collects user interaction data. Use this mode as the /// "disabled" state when the feature can be toggled on and off, e.g. via /// preferences. enabledStandby, + /// Feature enabled, but tracker purging is only simulated. Used for /// testing and telemetry collection. enabledDryRun, } -enum ColorScheme { - system, - light, - dark, -} +enum ColorScheme { system, light, dark } -enum CookieBannerHandlingMode { - disabled, - rejectAll, - rejectOrAcceptAll, -} +enum CookieBannerHandlingMode { disabled, rejectAll, rejectOrAcceptAll } /// App links behavior mode - controls how external app links are handled enum AppLinksMode { /// Always open links in their native apps without prompting always, + /// Prompt user before opening in app (with "Always open" checkbox) ask, + /// Never open links in external apps, always use browser never, } @@ -314,15 +280,19 @@ enum CustomCookiePolicy { /// Total Cookie Protection - Dynamic First-Party Isolation (dFPI) /// Most private option, isolates cookies per site totalProtection, + /// Block cross-site and social media tracker cookies /// Allows most cookies but blocks tracking cookies crossSiteTrackers, + /// Block cookies from sites you haven't visited /// Balances privacy with functionality unvisited, + /// Block all third-party cookies /// Only allows first-party cookies thirdParty, + /// Block all cookies (may break many sites) allCookies, } @@ -331,108 +301,77 @@ enum CustomCookiePolicy { enum TrackingScope { /// Apply to all browsing (normal + private) all, + /// Apply only to private browsing tabs privateOnly, } -enum DohSettingsMode { - geckoDefault, - increased, - max, - off, -} +enum DohSettingsMode { geckoDefault, increased, max, off } /// Status that represents every state that a download can be in. enum DownloadStatus { /// Indicates that the download is in the first state after creation but not yet [DOWNLOADING]. initiated, + /// Indicates that an [INITIATED] download is now actively being downloaded. downloading, + /// Indicates that the download that has been [DOWNLOADING] has been paused. paused, + /// Indicates that the download that has been [DOWNLOADING] has been cancelled. cancelled, + /// Indicates that the download that has been [DOWNLOADING] has moved to failed because /// something unexpected has happened. failed, + /// Indicates that the [DOWNLOADING] download has been completed. completed, } -enum LogLevel { - debug, - info, - warn, - error, -} +enum LogLevel { debug, info, warn, error } -enum SyncEngineValue { - history, - bookmarks, - tabs, -} +enum SyncEngineValue { history, bookmarks, tabs } /// Type of ML model operation -enum MlProgressType { - downloading, - loadingFromCache, - runningInference, -} +enum MlProgressType { downloading, loadingFromCache, runningInference } /// Status of the ML operation -enum MlProgressStatus { - initiate, - sizeEstimate, - inProgress, - done, -} +enum MlProgressStatus { initiate, sizeEstimate, inProgress, done } /// Types of browsing data that can be cleared enum ClearDataType { /// Authentication sessions authSessions, + /// All site data (cookies, storage, etc.) /// WARNING: If this is set it already includes cookies and allCaches. Passing the additionally will lead to issues allSiteData, + /// Cookies only onlyCookies, + /// Cache only onlyCaches, } -enum GeckoFetchMethod { - get, - head, - post, - put, - delete, - connect, - options, - trace, -} +enum GeckoFetchMethod { get, head, post, put, delete, connect, options, trace } -enum GeckoFetchRedircet { - follow, - manual, -} +enum GeckoFetchRedircet { follow, manual } -enum GeckoFetchCookiePolicy { - include, - omit, -} +enum GeckoFetchCookiePolicy { include, omit } -enum BookmarkNodeType { - item, - folder, - separator, -} +enum BookmarkNodeType { item, folder, separator } /// Permission status for a site permission enum SitePermissionStatus { /// Permission has been granted allowed, + /// Permission has been denied blocked, + /// No decision has been made yet (ask to allow) noDecision, } @@ -441,42 +380,39 @@ enum SitePermissionStatus { enum AutoplayStatus { /// Allow all autoplay (audible and inaudible) allowed, + /// Block all autoplay blocked, + /// Block audible autoplay only (allow inaudible) blockAudible, + /// Allow autoplay on WiFi only allowOnWifi, } -enum NativeAppLinkRuleDecision { - alwaysOpen, - neverOpen, -} +enum NativeAppLinkRuleDecision { alwaysOpen, neverOpen } /// Which surface owns a pending prompt (§2.6). Fixed at creation, never transfers. -enum AppLinkPromptOwner { - flutterBrowser, - nativeExternal, -} +enum AppLinkPromptOwner { flutterBrowser, nativeExternal } /// User decision on a pending prompt (§2.6). -enum AppLinkDecision { - open, - cancel, - dismiss, -} +enum AppLinkDecision { open, cancel, dismiss } /// Lifecycle state of the selected UnifiedPush distributor. enum PushDistributorStatus { /// No distributor app is installed on the device. noneAvailable, + /// Distributors are installed but the user has not chosen one. notSelected, + /// A distributor is chosen but has not acknowledged our registration yet. pending, + /// A distributor is chosen and has acknowledged our registration. ready, + /// A distributor was chosen previously but is no longer installed. Web push /// is dead in this state and there is no fallback transport. unavailable, @@ -487,26 +423,21 @@ enum PushDistributorStatus { /// @property downloadModel If the necessary models should be downloaded on request. If false, then /// the translation will not complete and throw an exception if the models are not already available. class TranslationOptions { - TranslationOptions({ - required this.downloadModel, - }); + TranslationOptions({required this.downloadModel}); bool downloadModel; List _toList() { - return [ - downloadModel, - ]; + return [downloadModel]; } Object encode() { - return _toList(); } + return _toList(); + } static TranslationOptions decode(Object result) { result as List; - return TranslationOptions( - downloadModel: result[0]! as bool, - ); + return TranslationOptions(downloadModel: result[0]! as bool); } @override @@ -533,24 +464,19 @@ class TranslationOptions { /// A language supported by the translation engine. class TranslationLanguage { - TranslationLanguage({ - required this.code, - required this.localizedDisplayName, - }); + TranslationLanguage({required this.code, required this.localizedDisplayName}); String code; String localizedDisplayName; List _toList() { - return [ - code, - localizedDisplayName, - ]; + return [code, localizedDisplayName]; } Object encode() { - return _toList(); } + return _toList(); + } static TranslationLanguage decode(Object result) { result as List; @@ -569,7 +495,8 @@ class TranslationLanguage { if (identical(this, other)) { return true; } - return _deepEquals(code, other.code) && _deepEquals(localizedDisplayName, other.localizedDisplayName); + return _deepEquals(code, other.code) && + _deepEquals(localizedDisplayName, other.localizedDisplayName); } @override @@ -605,7 +532,8 @@ class TranslationDetectedLanguages { } Object encode() { - return _toList(); } + return _toList(); + } static TranslationDetectedLanguages decode(Object result) { result as List; @@ -619,13 +547,16 @@ class TranslationDetectedLanguages { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) { - if (other is! TranslationDetectedLanguages || other.runtimeType != runtimeType) { + if (other is! TranslationDetectedLanguages || + other.runtimeType != runtimeType) { return false; } if (identical(this, other)) { return true; } - return _deepEquals(documentLangTag, other.documentLangTag) && _deepEquals(supportedDocumentLang, other.supportedDocumentLang) && _deepEquals(userPreferredLangTag, other.userPreferredLangTag); + return _deepEquals(documentLangTag, other.documentLangTag) && + _deepEquals(supportedDocumentLang, other.supportedDocumentLang) && + _deepEquals(userPreferredLangTag, other.userPreferredLangTag); } @override @@ -640,24 +571,19 @@ class TranslationDetectedLanguages { /// A from/to language pair for translation. class TranslationPair { - TranslationPair({ - required this.fromLanguage, - required this.toLanguage, - }); + TranslationPair({required this.fromLanguage, required this.toLanguage}); String fromLanguage; String toLanguage; List _toList() { - return [ - fromLanguage, - toLanguage, - ]; + return [fromLanguage, toLanguage]; } Object encode() { - return _toList(); } + return _toList(); + } static TranslationPair decode(Object result) { result as List; @@ -676,7 +602,8 @@ class TranslationPair { if (identical(this, other)) { return true; } - return _deepEquals(fromLanguage, other.fromLanguage) && _deepEquals(toLanguage, other.toLanguage); + return _deepEquals(fromLanguage, other.fromLanguage) && + _deepEquals(toLanguage, other.toLanguage); } @override @@ -704,21 +631,19 @@ class TranslationEngineStateData { List? toLanguages; List _toList() { - return [ - isEngineSupported, - fromLanguages, - toLanguages, - ]; + return [isEngineSupported, fromLanguages, toLanguages]; } Object encode() { - return _toList(); } + return _toList(); + } static TranslationEngineStateData decode(Object result) { result as List; return TranslationEngineStateData( isEngineSupported: result[0] as bool?, - fromLanguages: (result[1] as List?)?.cast(), + fromLanguages: (result[1] as List?) + ?.cast(), toLanguages: (result[2] as List?)?.cast(), ); } @@ -726,13 +651,16 @@ class TranslationEngineStateData { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) { - if (other is! TranslationEngineStateData || other.runtimeType != runtimeType) { + if (other is! TranslationEngineStateData || + other.runtimeType != runtimeType) { return false; } if (identical(this, other)) { return true; } - return _deepEquals(isEngineSupported, other.isEngineSupported) && _deepEquals(fromLanguages, other.fromLanguages) && _deepEquals(toLanguages, other.toLanguages); + return _deepEquals(isEngineSupported, other.isEngineSupported) && + _deepEquals(fromLanguages, other.fromLanguages) && + _deepEquals(toLanguages, other.toLanguages); } @override @@ -800,7 +728,8 @@ class TabTranslationStateData { } Object encode() { - return _toList(); } + return _toList(); + } static TabTranslationStateData decode(Object result) { result as List; @@ -828,7 +757,20 @@ class TabTranslationStateData { if (identical(this, other)) { return true; } - return _deepEquals(tabId, other.tabId) && _deepEquals(isTranslated, other.isTranslated) && _deepEquals(isTranslateProcessing, other.isTranslateProcessing) && _deepEquals(isOfferTranslate, other.isOfferTranslate) && _deepEquals(isExpectedTranslate, other.isExpectedTranslate) && _deepEquals(detectedLanguageCode, other.detectedLanguageCode) && _deepEquals(userPreferredLanguageCode, other.userPreferredLanguageCode) && _deepEquals(requestedFromLanguage, other.requestedFromLanguage) && _deepEquals(requestedToLanguage, other.requestedToLanguage) && _deepEquals(translationErrorName, other.translationErrorName) && _deepEquals(displayError, other.displayError); + return _deepEquals(tabId, other.tabId) && + _deepEquals(isTranslated, other.isTranslated) && + _deepEquals(isTranslateProcessing, other.isTranslateProcessing) && + _deepEquals(isOfferTranslate, other.isOfferTranslate) && + _deepEquals(isExpectedTranslate, other.isExpectedTranslate) && + _deepEquals(detectedLanguageCode, other.detectedLanguageCode) && + _deepEquals( + userPreferredLanguageCode, + other.userPreferredLanguageCode, + ) && + _deepEquals(requestedFromLanguage, other.requestedFromLanguage) && + _deepEquals(requestedToLanguage, other.requestedToLanguage) && + _deepEquals(translationErrorName, other.translationErrorName) && + _deepEquals(displayError, other.displayError); } @override @@ -891,7 +833,8 @@ class ReaderState { } Object encode() { - return _toList(); } + return _toList(); + } static ReaderState decode(Object result) { result as List; @@ -915,7 +858,13 @@ class ReaderState { if (identical(this, other)) { return true; } - return _deepEquals(readerable, other.readerable) && _deepEquals(active, other.active) && _deepEquals(checkRequired, other.checkRequired) && _deepEquals(connectRequired, other.connectRequired) && _deepEquals(baseUrl, other.baseUrl) && _deepEquals(activeUrl, other.activeUrl) && _deepEquals(scrollY, other.scrollY); + return _deepEquals(readerable, other.readerable) && + _deepEquals(active, other.active) && + _deepEquals(checkRequired, other.checkRequired) && + _deepEquals(connectRequired, other.connectRequired) && + _deepEquals(baseUrl, other.baseUrl) && + _deepEquals(activeUrl, other.activeUrl) && + _deepEquals(scrollY, other.scrollY); } @override @@ -975,7 +924,8 @@ class AddTabParams { } Object encode() { - return _toList(); } + return _toList(); + } static AddTabParams decode(Object result) { result as List; @@ -988,7 +938,8 @@ class AddTabParams { source: result[5]! as SourceValue, private: result[6]! as bool, historyMetadata: result[7] as HistoryMetadataKey?, - additionalHeaders: (result[8] as Map?)?.cast(), + additionalHeaders: (result[8] as Map?) + ?.cast(), ); } @@ -1001,7 +952,15 @@ class AddTabParams { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(startLoading, other.startLoading) && _deepEquals(parentId, other.parentId) && _deepEquals(flags, other.flags) && _deepEquals(contextId, other.contextId) && _deepEquals(source, other.source) && _deepEquals(private, other.private) && _deepEquals(historyMetadata, other.historyMetadata) && _deepEquals(additionalHeaders, other.additionalHeaders); + return _deepEquals(url, other.url) && + _deepEquals(startLoading, other.startLoading) && + _deepEquals(parentId, other.parentId) && + _deepEquals(flags, other.flags) && + _deepEquals(contextId, other.contextId) && + _deepEquals(source, other.source) && + _deepEquals(private, other.private) && + _deepEquals(historyMetadata, other.historyMetadata) && + _deepEquals(additionalHeaders, other.additionalHeaders); } @override @@ -1041,15 +1000,12 @@ class LastMediaAccessState { bool mediaSessionActive; List _toList() { - return [ - lastMediaUrl, - lastMediaAccess, - mediaSessionActive, - ]; + return [lastMediaUrl, lastMediaAccess, mediaSessionActive]; } Object encode() { - return _toList(); } + return _toList(); + } static LastMediaAccessState decode(Object result) { result as List; @@ -1069,7 +1025,9 @@ class LastMediaAccessState { if (identical(this, other)) { return true; } - return _deepEquals(lastMediaUrl, other.lastMediaUrl) && _deepEquals(lastMediaAccess, other.lastMediaAccess) && _deepEquals(mediaSessionActive, other.mediaSessionActive); + return _deepEquals(lastMediaUrl, other.lastMediaUrl) && + _deepEquals(lastMediaAccess, other.lastMediaAccess) && + _deepEquals(mediaSessionActive, other.mediaSessionActive); } @override @@ -1087,11 +1045,7 @@ class LastMediaAccessState { /// created, depending on the de-bouncing logic of the underlying storage i.e. recording history /// metadata observations with the exact same values may be combined into a single record. class HistoryMetadataKey { - HistoryMetadataKey({ - required this.url, - this.searchTerm, - this.referrerUrl, - }); + HistoryMetadataKey({required this.url, this.searchTerm, this.referrerUrl}); /// A url of the page. String url; @@ -1106,15 +1060,12 @@ class HistoryMetadataKey { String? referrerUrl; List _toList() { - return [ - url, - searchTerm, - referrerUrl, - ]; + return [url, searchTerm, referrerUrl]; } Object encode() { - return _toList(); } + return _toList(); + } static HistoryMetadataKey decode(Object result) { result as List; @@ -1134,7 +1085,9 @@ class HistoryMetadataKey { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(searchTerm, other.searchTerm) && _deepEquals(referrerUrl, other.referrerUrl); + return _deepEquals(url, other.url) && + _deepEquals(searchTerm, other.searchTerm) && + _deepEquals(referrerUrl, other.referrerUrl); } @override @@ -1148,26 +1101,21 @@ class HistoryMetadataKey { } class PackageCategoryValue { - PackageCategoryValue({ - required this.value, - }); + PackageCategoryValue({required this.value}); int value; List _toList() { - return [ - value, - ]; + return [value]; } Object encode() { - return _toList(); } + return _toList(); + } static PackageCategoryValue decode(Object result) { result as List; - return PackageCategoryValue( - value: result[0]! as int, - ); + return PackageCategoryValue(value: result[0]! as int); } @override @@ -1194,10 +1142,7 @@ class PackageCategoryValue { /// Describes an external package. class ExternalPackage { - ExternalPackage({ - required this.packageId, - required this.category, - }); + ExternalPackage({required this.packageId, required this.category}); /// An Android package id. String packageId; @@ -1206,14 +1151,12 @@ class ExternalPackage { PackageCategoryValue category; List _toList() { - return [ - packageId, - category, - ]; + return [packageId, category]; } Object encode() { - return _toList(); } + return _toList(); + } static ExternalPackage decode(Object result) { result as List; @@ -1232,7 +1175,8 @@ class ExternalPackage { if (identical(this, other)) { return true; } - return _deepEquals(packageId, other.packageId) && _deepEquals(category, other.category); + return _deepEquals(packageId, other.packageId) && + _deepEquals(category, other.category); } @override @@ -1246,26 +1190,21 @@ class ExternalPackage { } class LoadUrlFlagsValue { - LoadUrlFlagsValue({ - required this.value, - }); + LoadUrlFlagsValue({required this.value}); int value; List _toList() { - return [ - value, - ]; + return [value]; } Object encode() { - return _toList(); } + return _toList(); + } static LoadUrlFlagsValue decode(Object result) { result as List; - return LoadUrlFlagsValue( - value: result[0]! as int, - ); + return LoadUrlFlagsValue(value: result[0]! as int); } @override @@ -1291,24 +1230,19 @@ class LoadUrlFlagsValue { } class SourceValue { - SourceValue({ - required this.id, - this.caller, - }); + SourceValue({required this.id, this.caller}); int id; ExternalPackage? caller; List _toList() { - return [ - id, - caller, - ]; + return [id, caller]; } Object encode() { - return _toList(); } + return _toList(); + } static SourceValue decode(Object result) { result as List; @@ -1432,7 +1366,8 @@ class TabState { } Object encode() { - return _toList(); } + return _toList(); + } static TabState decode(Object result) { result as List; @@ -1464,7 +1399,21 @@ class TabState { if (identical(this, other)) { return true; } - return _deepEquals(id, other.id) && _deepEquals(url, other.url) && _deepEquals(parentId, other.parentId) && _deepEquals(title, other.title) && _deepEquals(searchTerm, other.searchTerm) && _deepEquals(contextId, other.contextId) && _deepEquals(readerState, other.readerState) && _deepEquals(lastAccess, other.lastAccess) && _deepEquals(createdAt, other.createdAt) && _deepEquals(lastMediaAccessState, other.lastMediaAccessState) && _deepEquals(private, other.private) && _deepEquals(historyMetadata, other.historyMetadata) && _deepEquals(source, other.source) && _deepEquals(index, other.index) && _deepEquals(hasFormData, other.hasFormData); + return _deepEquals(id, other.id) && + _deepEquals(url, other.url) && + _deepEquals(parentId, other.parentId) && + _deepEquals(title, other.title) && + _deepEquals(searchTerm, other.searchTerm) && + _deepEquals(contextId, other.contextId) && + _deepEquals(readerState, other.readerState) && + _deepEquals(lastAccess, other.lastAccess) && + _deepEquals(createdAt, other.createdAt) && + _deepEquals(lastMediaAccessState, other.lastMediaAccessState) && + _deepEquals(private, other.private) && + _deepEquals(historyMetadata, other.historyMetadata) && + _deepEquals(source, other.source) && + _deepEquals(index, other.index) && + _deepEquals(hasFormData, other.hasFormData); } @override @@ -1479,10 +1428,7 @@ class TabState { /// A recoverable version of [TabState]. class RecoverableTab { - RecoverableTab({ - this.engineSessionStateJson, - required this.state, - }); + RecoverableTab({this.engineSessionStateJson, required this.state}); /// The [EngineSessionState] needed for restoring the previous state of this tab. String? engineSessionStateJson; @@ -1491,14 +1437,12 @@ class RecoverableTab { TabState state; List _toList() { - return [ - engineSessionStateJson, - state, - ]; + return [engineSessionStateJson, state]; } Object encode() { - return _toList(); } + return _toList(); + } static RecoverableTab decode(Object result) { result as List; @@ -1517,7 +1461,8 @@ class RecoverableTab { if (identical(this, other)) { return true; } - return _deepEquals(engineSessionStateJson, other.engineSessionStateJson) && _deepEquals(state, other.state); + return _deepEquals(engineSessionStateJson, other.engineSessionStateJson) && + _deepEquals(state, other.state); } @override @@ -1554,18 +1499,12 @@ class IconRequest { bool waitOnNetworkLoad; List _toList() { - return [ - url, - size, - resources, - color, - isPrivate, - waitOnNetworkLoad, - ]; + return [url, size, resources, color, isPrivate, waitOnNetworkLoad]; } Object encode() { - return _toList(); } + return _toList(); + } static IconRequest decode(Object result) { result as List; @@ -1588,7 +1527,12 @@ class IconRequest { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(size, other.size) && _deepEquals(resources, other.resources) && _deepEquals(color, other.color) && _deepEquals(isPrivate, other.isPrivate) && _deepEquals(waitOnNetworkLoad, other.waitOnNetworkLoad); + return _deepEquals(url, other.url) && + _deepEquals(size, other.size) && + _deepEquals(resources, other.resources) && + _deepEquals(color, other.color) && + _deepEquals(isPrivate, other.isPrivate) && + _deepEquals(waitOnNetworkLoad, other.waitOnNetworkLoad); } @override @@ -1602,31 +1546,23 @@ class IconRequest { } class ResourceSize { - ResourceSize({ - required this.height, - required this.width, - }); + ResourceSize({required this.height, required this.width}); int height; int width; List _toList() { - return [ - height, - width, - ]; + return [height, width]; } Object encode() { - return _toList(); } + return _toList(); + } static ResourceSize decode(Object result) { result as List; - return ResourceSize( - height: result[0]! as int, - width: result[1]! as int, - ); + return ResourceSize(height: result[0]! as int, width: result[1]! as int); } @override @@ -1672,17 +1608,12 @@ class Resource { bool maskable; List _toList() { - return [ - url, - type, - sizes, - mimeType, - maskable, - ]; + return [url, type, sizes, mimeType, maskable]; } Object encode() { - return _toList(); } + return _toList(); + } static Resource decode(Object result) { result as List; @@ -1704,7 +1635,11 @@ class Resource { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(type, other.type) && _deepEquals(sizes, other.sizes) && _deepEquals(mimeType, other.mimeType) && _deepEquals(maskable, other.maskable); + return _deepEquals(url, other.url) && + _deepEquals(type, other.type) && + _deepEquals(sizes, other.sizes) && + _deepEquals(mimeType, other.mimeType) && + _deepEquals(maskable, other.maskable); } @override @@ -1739,16 +1674,12 @@ class IconResult { bool maskable; List _toList() { - return [ - image, - color, - source, - maskable, - ]; + return [image, color, source, maskable]; } Object encode() { - return _toList(); } + return _toList(); + } static IconResult decode(Object result) { result as List; @@ -1769,7 +1700,10 @@ class IconResult { if (identical(this, other)) { return true; } - return _deepEquals(image, other.image) && _deepEquals(color, other.color) && _deepEquals(source, other.source) && _deepEquals(maskable, other.maskable); + return _deepEquals(image, other.image) && + _deepEquals(color, other.color) && + _deepEquals(source, other.source) && + _deepEquals(maskable, other.maskable); } @override @@ -1783,26 +1717,21 @@ class IconResult { } class CookiePartitionKey { - CookiePartitionKey({ - required this.topLevelSite, - }); + CookiePartitionKey({required this.topLevelSite}); String topLevelSite; List _toList() { - return [ - topLevelSite, - ]; + return [topLevelSite]; } Object encode() { - return _toList(); } + return _toList(); + } static CookiePartitionKey decode(Object result) { result as List; - return CookiePartitionKey( - topLevelSite: result[0]! as String, - ); + return CookiePartitionKey(topLevelSite: result[0]! as String); } @override @@ -1889,7 +1818,8 @@ class Cookie { } Object encode() { - return _toList(); } + return _toList(); + } static Cookie decode(Object result) { result as List; @@ -1919,7 +1849,19 @@ class Cookie { if (identical(this, other)) { return true; } - return _deepEquals(domain, other.domain) && _deepEquals(expirationDate, other.expirationDate) && _deepEquals(firstPartyDomain, other.firstPartyDomain) && _deepEquals(hostOnly, other.hostOnly) && _deepEquals(httpOnly, other.httpOnly) && _deepEquals(name, other.name) && _deepEquals(partitionKey, other.partitionKey) && _deepEquals(path, other.path) && _deepEquals(secure, other.secure) && _deepEquals(session, other.session) && _deepEquals(sameSite, other.sameSite) && _deepEquals(storeId, other.storeId) && _deepEquals(value, other.value); + return _deepEquals(domain, other.domain) && + _deepEquals(expirationDate, other.expirationDate) && + _deepEquals(firstPartyDomain, other.firstPartyDomain) && + _deepEquals(hostOnly, other.hostOnly) && + _deepEquals(httpOnly, other.httpOnly) && + _deepEquals(name, other.name) && + _deepEquals(partitionKey, other.partitionKey) && + _deepEquals(path, other.path) && + _deepEquals(secure, other.secure) && + _deepEquals(session, other.session) && + _deepEquals(sameSite, other.sameSite) && + _deepEquals(storeId, other.storeId) && + _deepEquals(value, other.value); } @override @@ -1970,7 +1912,8 @@ class VisitInfo { } Object encode() { - return _toList(); } + return _toList(); + } static VisitInfo decode(Object result) { result as List; @@ -1994,7 +1937,13 @@ class VisitInfo { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(title, other.title) && _deepEquals(visitTime, other.visitTime) && _deepEquals(visitType, other.visitType) && _deepEquals(previewImageUrl, other.previewImageUrl) && _deepEquals(isRemote, other.isRemote) && _deepEquals(contentId, other.contentId); + return _deepEquals(url, other.url) && + _deepEquals(title, other.title) && + _deepEquals(visitTime, other.visitTime) && + _deepEquals(visitType, other.visitType) && + _deepEquals(previewImageUrl, other.previewImageUrl) && + _deepEquals(isRemote, other.isRemote) && + _deepEquals(contentId, other.contentId); } @override @@ -2008,24 +1957,19 @@ class VisitInfo { } class HistoryHighlightWeights { - HistoryHighlightWeights({ - required this.viewTime, - required this.frequency, - }); + HistoryHighlightWeights({required this.viewTime, required this.frequency}); double viewTime; double frequency; List _toList() { - return [ - viewTime, - frequency, - ]; + return [viewTime, frequency]; } Object encode() { - return _toList(); } + return _toList(); + } static HistoryHighlightWeights decode(Object result) { result as List; @@ -2044,7 +1988,8 @@ class HistoryHighlightWeights { if (identical(this, other)) { return true; } - return _deepEquals(viewTime, other.viewTime) && _deepEquals(frequency, other.frequency); + return _deepEquals(viewTime, other.viewTime) && + _deepEquals(frequency, other.frequency); } @override @@ -2077,17 +2022,12 @@ class HistoryHighlight { String? previewImageUrl; List _toList() { - return [ - score, - placeId, - url, - title, - previewImageUrl, - ]; + return [score, placeId, url, title, previewImageUrl]; } Object encode() { - return _toList(); } + return _toList(); + } static HistoryHighlight decode(Object result) { result as List; @@ -2109,7 +2049,11 @@ class HistoryHighlight { if (identical(this, other)) { return true; } - return _deepEquals(score, other.score) && _deepEquals(placeId, other.placeId) && _deepEquals(url, other.url) && _deepEquals(title, other.title) && _deepEquals(previewImageUrl, other.previewImageUrl); + return _deepEquals(score, other.score) && + _deepEquals(placeId, other.placeId) && + _deepEquals(url, other.url) && + _deepEquals(title, other.title) && + _deepEquals(previewImageUrl, other.previewImageUrl); } @override @@ -2123,24 +2067,19 @@ class HistoryHighlight { } class TopFrecentSiteInfo { - TopFrecentSiteInfo({ - required this.url, - this.title, - }); + TopFrecentSiteInfo({required this.url, this.title}); String url; String? title; List _toList() { - return [ - url, - title, - ]; + return [url, title]; } Object encode() { - return _toList(); } + return _toList(); + } static TopFrecentSiteInfo decode(Object result) { result as List; @@ -2216,7 +2155,8 @@ class HistoryMetadata { } Object encode() { - return _toList(); } + return _toList(); + } static HistoryMetadata decode(Object result) { result as List; @@ -2240,7 +2180,13 @@ class HistoryMetadata { if (identical(this, other)) { return true; } - return _deepEquals(key, other.key) && _deepEquals(title, other.title) && _deepEquals(createdAt, other.createdAt) && _deepEquals(updatedAt, other.updatedAt) && _deepEquals(totalViewTime, other.totalViewTime) && _deepEquals(documentType, other.documentType) && _deepEquals(previewImageUrl, other.previewImageUrl); + return _deepEquals(key, other.key) && + _deepEquals(title, other.title) && + _deepEquals(createdAt, other.createdAt) && + _deepEquals(updatedAt, other.updatedAt) && + _deepEquals(totalViewTime, other.totalViewTime) && + _deepEquals(documentType, other.documentType) && + _deepEquals(previewImageUrl, other.previewImageUrl); } @override @@ -2255,11 +2201,7 @@ class HistoryMetadata { /// Frecency-ranked autocomplete suggestion. Backs `getSuggestions`. class HistorySuggestion { - HistorySuggestion({ - required this.url, - this.title, - required this.score, - }); + HistorySuggestion({required this.url, this.title, required this.score}); String url; @@ -2270,15 +2212,12 @@ class HistorySuggestion { int score; List _toList() { - return [ - url, - title, - score, - ]; + return [url, title, score]; } Object encode() { - return _toList(); } + return _toList(); + } static HistorySuggestion decode(Object result) { result as List; @@ -2298,7 +2237,9 @@ class HistorySuggestion { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(title, other.title) && _deepEquals(score, other.score); + return _deepEquals(url, other.url) && + _deepEquals(title, other.title) && + _deepEquals(score, other.score); } @override @@ -2313,24 +2254,19 @@ class HistorySuggestion { /// Optional metadata observation for a URL. `null` fields are not written. class PageObservation { - PageObservation({ - this.title, - this.previewImageUrl, - }); + PageObservation({this.title, this.previewImageUrl}); String? title; String? previewImageUrl; List _toList() { - return [ - title, - previewImageUrl, - ]; + return [title, previewImageUrl]; } Object encode() { - return _toList(); } + return _toList(); + } static PageObservation decode(Object result) { result as List; @@ -2349,7 +2285,8 @@ class PageObservation { if (identical(this, other)) { return true; } - return _deepEquals(title, other.title) && _deepEquals(previewImageUrl, other.previewImageUrl); + return _deepEquals(title, other.title) && + _deepEquals(previewImageUrl, other.previewImageUrl); } @override @@ -2363,31 +2300,23 @@ class PageObservation { } class HistoryItem { - HistoryItem({ - required this.url, - required this.title, - }); + HistoryItem({required this.url, required this.title}); String url; String title; List _toList() { - return [ - url, - title, - ]; + return [url, title]; } Object encode() { - return _toList(); } + return _toList(); + } static HistoryItem decode(Object result) { result as List; - return HistoryItem( - url: result[0]! as String, - title: result[1]! as String, - ); + return HistoryItem(url: result[0]! as String, title: result[1]! as String); } @override @@ -2429,16 +2358,12 @@ class HistoryState { bool canGoForward; List _toList() { - return [ - items, - currentIndex, - canGoBack, - canGoForward, - ]; + return [items, currentIndex, canGoBack, canGoForward]; } Object encode() { - return _toList(); } + return _toList(); + } static HistoryState decode(Object result) { result as List; @@ -2459,7 +2384,10 @@ class HistoryState { if (identical(this, other)) { return true; } - return _deepEquals(items, other.items) && _deepEquals(currentIndex, other.currentIndex) && _deepEquals(canGoBack, other.canGoBack) && _deepEquals(canGoForward, other.canGoForward); + return _deepEquals(items, other.items) && + _deepEquals(currentIndex, other.currentIndex) && + _deepEquals(canGoBack, other.canGoBack) && + _deepEquals(canGoForward, other.canGoForward); } @override @@ -2473,10 +2401,7 @@ class HistoryState { } class ReaderableState { - ReaderableState({ - required this.readerable, - required this.active, - }); + ReaderableState({required this.readerable, required this.active}); /// Whether or not the current page can be transformed to /// be displayed in a reader view. @@ -2486,14 +2411,12 @@ class ReaderableState { bool active; List _toList() { - return [ - readerable, - active, - ]; + return [readerable, active]; } Object encode() { - return _toList(); } + return _toList(); + } static ReaderableState decode(Object result) { result as List; @@ -2512,7 +2435,8 @@ class ReaderableState { if (identical(this, other)) { return true; } - return _deepEquals(readerable, other.readerable) && _deepEquals(active, other.active); + return _deepEquals(readerable, other.readerable) && + _deepEquals(active, other.active); } @override @@ -2539,15 +2463,12 @@ class SecurityInfoState { String issuer; List _toList() { - return [ - secure, - host, - issuer, - ]; + return [secure, host, issuer]; } Object encode() { - return _toList(); } + return _toList(); + } static SecurityInfoState decode(Object result) { result as List; @@ -2567,7 +2488,9 @@ class SecurityInfoState { if (identical(this, other)) { return true; } - return _deepEquals(secure, other.secure) && _deepEquals(host, other.host) && _deepEquals(issuer, other.issuer); + return _deepEquals(secure, other.secure) && + _deepEquals(host, other.host) && + _deepEquals(issuer, other.issuer); } @override @@ -2630,7 +2553,8 @@ class TabContentState { } Object encode() { - return _toList(); } + return _toList(); + } static TabContentState decode(Object result) { result as List; @@ -2657,7 +2581,16 @@ class TabContentState { if (identical(this, other)) { return true; } - return _deepEquals(id, other.id) && _deepEquals(parentId, other.parentId) && _deepEquals(contextId, other.contextId) && _deepEquals(url, other.url) && _deepEquals(title, other.title) && _deepEquals(progress, other.progress) && _deepEquals(isPrivate, other.isPrivate) && _deepEquals(isFullScreen, other.isFullScreen) && _deepEquals(isLoading, other.isLoading) && _deepEquals(showToolbarAsExpanded, other.showToolbarAsExpanded); + return _deepEquals(id, other.id) && + _deepEquals(parentId, other.parentId) && + _deepEquals(contextId, other.contextId) && + _deepEquals(url, other.url) && + _deepEquals(title, other.title) && + _deepEquals(progress, other.progress) && + _deepEquals(isPrivate, other.isPrivate) && + _deepEquals(isFullScreen, other.isFullScreen) && + _deepEquals(isLoading, other.isLoading) && + _deepEquals(showToolbarAsExpanded, other.showToolbarAsExpanded); } @override @@ -2684,15 +2617,12 @@ class FindResultState { bool isDoneCounting; List _toList() { - return [ - activeMatchOrdinal, - numberOfMatches, - isDoneCounting, - ]; + return [activeMatchOrdinal, numberOfMatches, isDoneCounting]; } Object encode() { - return _toList(); } + return _toList(); + } static FindResultState decode(Object result) { result as List; @@ -2712,7 +2642,9 @@ class FindResultState { if (identical(this, other)) { return true; } - return _deepEquals(activeMatchOrdinal, other.activeMatchOrdinal) && _deepEquals(numberOfMatches, other.numberOfMatches) && _deepEquals(isDoneCounting, other.isDoneCounting); + return _deepEquals(activeMatchOrdinal, other.activeMatchOrdinal) && + _deepEquals(numberOfMatches, other.numberOfMatches) && + _deepEquals(isDoneCounting, other.isDoneCounting); } @override @@ -2726,11 +2658,7 @@ class FindResultState { } class CustomSelectionAction { - CustomSelectionAction({ - required this.id, - required this.title, - this.pattern, - }); + CustomSelectionAction({required this.id, required this.title, this.pattern}); String id; @@ -2739,15 +2667,12 @@ class CustomSelectionAction { SelectionPattern? pattern; List _toList() { - return [ - id, - title, - pattern, - ]; + return [id, title, pattern]; } Object encode() { - return _toList(); } + return _toList(); + } static CustomSelectionAction decode(Object result) { result as List; @@ -2767,7 +2692,9 @@ class CustomSelectionAction { if (identical(this, other)) { return true; } - return _deepEquals(id, other.id) && _deepEquals(title, other.title) && _deepEquals(pattern, other.pattern); + return _deepEquals(id, other.id) && + _deepEquals(title, other.title) && + _deepEquals(pattern, other.pattern); } @override @@ -2814,7 +2741,8 @@ class WebExtensionData { } Object encode() { - return _toList(); } + return _toList(); + } static WebExtensionData decode(Object result) { result as List; @@ -2837,7 +2765,12 @@ class WebExtensionData { if (identical(this, other)) { return true; } - return _deepEquals(extensionId, other.extensionId) && _deepEquals(title, other.title) && _deepEquals(enabled, other.enabled) && _deepEquals(badgeText, other.badgeText) && _deepEquals(badgeTextColor, other.badgeTextColor) && _deepEquals(badgeBackgroundColor, other.badgeBackgroundColor); + return _deepEquals(extensionId, other.extensionId) && + _deepEquals(title, other.title) && + _deepEquals(enabled, other.enabled) && + _deepEquals(badgeText, other.badgeText) && + _deepEquals(badgeTextColor, other.badgeTextColor) && + _deepEquals(badgeBackgroundColor, other.badgeBackgroundColor); } @override @@ -2976,7 +2909,8 @@ class AddonInfo { } Object encode() { - return _toList(); } + return _toList(); + } static AddonInfo decode(Object result) { result as List; @@ -2989,7 +2923,8 @@ class AddonInfo { version: result[5]! as String, installedVersion: result[6] as String?, translatedPermissions: (result[7]! as List).cast(), - translatedRequiredDataCollectionPermissions: (result[8]! as List).cast(), + translatedRequiredDataCollectionPermissions: (result[8]! as List) + .cast(), authorName: result[9] as String?, authorUrl: result[10] as String?, homepageUrl: result[11]! as String, @@ -3022,7 +2957,41 @@ class AddonInfo { if (identical(this, other)) { return true; } - return _deepEquals(id, other.id) && _deepEquals(displayName, other.displayName) && _deepEquals(summary, other.summary) && _deepEquals(description, other.description) && _deepEquals(downloadUrl, other.downloadUrl) && _deepEquals(version, other.version) && _deepEquals(installedVersion, other.installedVersion) && _deepEquals(translatedPermissions, other.translatedPermissions) && _deepEquals(translatedRequiredDataCollectionPermissions, other.translatedRequiredDataCollectionPermissions) && _deepEquals(authorName, other.authorName) && _deepEquals(authorUrl, other.authorUrl) && _deepEquals(homepageUrl, other.homepageUrl) && _deepEquals(detailUrl, other.detailUrl) && _deepEquals(ratingUrl, other.ratingUrl) && _deepEquals(ratingAverage, other.ratingAverage) && _deepEquals(ratingReviews, other.ratingReviews) && _deepEquals(createdAt, other.createdAt) && _deepEquals(updatedAt, other.updatedAt) && _deepEquals(icon, other.icon) && _deepEquals(isInstalled, other.isInstalled) && _deepEquals(isEnabled, other.isEnabled) && _deepEquals(isSupported, other.isSupported) && _deepEquals(isAllowedInPrivateBrowsing, other.isAllowedInPrivateBrowsing) && _deepEquals(isAutoUpdateEnabled, other.isAutoUpdateEnabled) && _deepEquals(isLocalFileInstalled, other.isLocalFileInstalled) && _deepEquals(optionsPageUrl, other.optionsPageUrl) && _deepEquals(openOptionsPageInTab, other.openOptionsPageInTab) && _deepEquals(disabledReason, other.disabledReason) && _deepEquals(incognito, other.incognito); + return _deepEquals(id, other.id) && + _deepEquals(displayName, other.displayName) && + _deepEquals(summary, other.summary) && + _deepEquals(description, other.description) && + _deepEquals(downloadUrl, other.downloadUrl) && + _deepEquals(version, other.version) && + _deepEquals(installedVersion, other.installedVersion) && + _deepEquals(translatedPermissions, other.translatedPermissions) && + _deepEquals( + translatedRequiredDataCollectionPermissions, + other.translatedRequiredDataCollectionPermissions, + ) && + _deepEquals(authorName, other.authorName) && + _deepEquals(authorUrl, other.authorUrl) && + _deepEquals(homepageUrl, other.homepageUrl) && + _deepEquals(detailUrl, other.detailUrl) && + _deepEquals(ratingUrl, other.ratingUrl) && + _deepEquals(ratingAverage, other.ratingAverage) && + _deepEquals(ratingReviews, other.ratingReviews) && + _deepEquals(createdAt, other.createdAt) && + _deepEquals(updatedAt, other.updatedAt) && + _deepEquals(icon, other.icon) && + _deepEquals(isInstalled, other.isInstalled) && + _deepEquals(isEnabled, other.isEnabled) && + _deepEquals(isSupported, other.isSupported) && + _deepEquals( + isAllowedInPrivateBrowsing, + other.isAllowedInPrivateBrowsing, + ) && + _deepEquals(isAutoUpdateEnabled, other.isAutoUpdateEnabled) && + _deepEquals(isLocalFileInstalled, other.isLocalFileInstalled) && + _deepEquals(optionsPageUrl, other.optionsPageUrl) && + _deepEquals(openOptionsPageInTab, other.openOptionsPageInTab) && + _deepEquals(disabledReason, other.disabledReason) && + _deepEquals(incognito, other.incognito); } @override @@ -3049,15 +3018,12 @@ class AddonListingPreview { String? caption; List _toList() { - return [ - imageUrl, - thumbnailUrl, - caption, - ]; + return [imageUrl, thumbnailUrl, caption]; } Object encode() { - return _toList(); } + return _toList(); + } static AddonListingPreview decode(Object result) { result as List; @@ -3077,7 +3043,9 @@ class AddonListingPreview { if (identical(this, other)) { return true; } - return _deepEquals(imageUrl, other.imageUrl) && _deepEquals(thumbnailUrl, other.thumbnailUrl) && _deepEquals(caption, other.caption); + return _deepEquals(imageUrl, other.imageUrl) && + _deepEquals(thumbnailUrl, other.thumbnailUrl) && + _deepEquals(caption, other.caption); } @override @@ -3220,7 +3188,8 @@ class AddonListing { } Object encode() { - return _toList(); } + return _toList(); + } static AddonListing decode(Object result) { result as List; @@ -3267,7 +3236,39 @@ class AddonListing { if (identical(this, other)) { return true; } - return _deepEquals(id, other.id) && _deepEquals(name, other.name) && _deepEquals(summary, other.summary) && _deepEquals(description, other.description) && _deepEquals(iconUrl, other.iconUrl) && _deepEquals(latestVersion, other.latestVersion) && _deepEquals(downloadUrl, other.downloadUrl) && _deepEquals(ratingAverage, other.ratingAverage) && _deepEquals(ratingReviews, other.ratingReviews) && _deepEquals(authorName, other.authorName) && _deepEquals(authorUrl, other.authorUrl) && _deepEquals(homepageUrl, other.homepageUrl) && _deepEquals(detailUrl, other.detailUrl) && _deepEquals(ratingUrl, other.ratingUrl) && _deepEquals(averageDailyUsers, other.averageDailyUsers) && _deepEquals(promoted, other.promoted) && _deepEquals(previews, other.previews) && _deepEquals(permissions, other.permissions) && _deepEquals(hostPermissions, other.hostPermissions) && _deepEquals(optionalPermissions, other.optionalPermissions) && _deepEquals(dataCollectionPermissions, other.dataCollectionPermissions) && _deepEquals(fileSize, other.fileSize) && _deepEquals(lastUpdated, other.lastUpdated) && _deepEquals(licenseName, other.licenseName) && _deepEquals(licenseUrl, other.licenseUrl) && _deepEquals(supportUrl, other.supportUrl) && _deepEquals(supportEmail, other.supportEmail) && _deepEquals(categories, other.categories) && _deepEquals(hasPrivacyPolicy, other.hasPrivacyPolicy) && _deepEquals(slug, other.slug); + return _deepEquals(id, other.id) && + _deepEquals(name, other.name) && + _deepEquals(summary, other.summary) && + _deepEquals(description, other.description) && + _deepEquals(iconUrl, other.iconUrl) && + _deepEquals(latestVersion, other.latestVersion) && + _deepEquals(downloadUrl, other.downloadUrl) && + _deepEquals(ratingAverage, other.ratingAverage) && + _deepEquals(ratingReviews, other.ratingReviews) && + _deepEquals(authorName, other.authorName) && + _deepEquals(authorUrl, other.authorUrl) && + _deepEquals(homepageUrl, other.homepageUrl) && + _deepEquals(detailUrl, other.detailUrl) && + _deepEquals(ratingUrl, other.ratingUrl) && + _deepEquals(averageDailyUsers, other.averageDailyUsers) && + _deepEquals(promoted, other.promoted) && + _deepEquals(previews, other.previews) && + _deepEquals(permissions, other.permissions) && + _deepEquals(hostPermissions, other.hostPermissions) && + _deepEquals(optionalPermissions, other.optionalPermissions) && + _deepEquals( + dataCollectionPermissions, + other.dataCollectionPermissions, + ) && + _deepEquals(fileSize, other.fileSize) && + _deepEquals(lastUpdated, other.lastUpdated) && + _deepEquals(licenseName, other.licenseName) && + _deepEquals(licenseUrl, other.licenseUrl) && + _deepEquals(supportUrl, other.supportUrl) && + _deepEquals(supportEmail, other.supportEmail) && + _deepEquals(categories, other.categories) && + _deepEquals(hasPrivacyPolicy, other.hasPrivacyPolicy) && + _deepEquals(slug, other.slug); } @override @@ -3334,7 +3335,8 @@ class AddonStoreInfo { } Object encode() { - return _toList(); } + return _toList(); + } static AddonStoreInfo decode(Object result) { result as List; @@ -3362,7 +3364,17 @@ class AddonStoreInfo { if (identical(this, other)) { return true; } - return _deepEquals(latestVersion, other.latestVersion) && _deepEquals(latestXpiUrl, other.latestXpiUrl) && _deepEquals(ratingAverage, other.ratingAverage) && _deepEquals(ratingReviews, other.ratingReviews) && _deepEquals(summary, other.summary) && _deepEquals(description, other.description) && _deepEquals(homepageUrl, other.homepageUrl) && _deepEquals(detailUrl, other.detailUrl) && _deepEquals(ratingUrl, other.ratingUrl) && _deepEquals(authorName, other.authorName) && _deepEquals(authorUrl, other.authorUrl); + return _deepEquals(latestVersion, other.latestVersion) && + _deepEquals(latestXpiUrl, other.latestXpiUrl) && + _deepEquals(ratingAverage, other.ratingAverage) && + _deepEquals(ratingReviews, other.ratingReviews) && + _deepEquals(summary, other.summary) && + _deepEquals(description, other.description) && + _deepEquals(homepageUrl, other.homepageUrl) && + _deepEquals(detailUrl, other.detailUrl) && + _deepEquals(ratingUrl, other.ratingUrl) && + _deepEquals(authorName, other.authorName) && + _deepEquals(authorUrl, other.authorUrl); } @override @@ -3392,16 +3404,12 @@ class AddonUpdateAttemptInfo { String? message; List _toList() { - return [ - addonId, - dateMillisecondsSinceEpoch, - status, - message, - ]; + return [addonId, dateMillisecondsSinceEpoch, status, message]; } Object encode() { - return _toList(); } + return _toList(); + } static AddonUpdateAttemptInfo decode(Object result) { result as List; @@ -3422,7 +3430,13 @@ class AddonUpdateAttemptInfo { if (identical(this, other)) { return true; } - return _deepEquals(addonId, other.addonId) && _deepEquals(dateMillisecondsSinceEpoch, other.dateMillisecondsSinceEpoch) && _deepEquals(status, other.status) && _deepEquals(message, other.message); + return _deepEquals(addonId, other.addonId) && + _deepEquals( + dateMillisecondsSinceEpoch, + other.dateMillisecondsSinceEpoch, + ) && + _deepEquals(status, other.status) && + _deepEquals(message, other.message); } @override @@ -3461,19 +3475,12 @@ class GeckoSuggestion { Uint8List? icon; List _toList() { - return [ - id, - type, - score, - title, - description, - editSuggestion, - icon, - ]; + return [id, type, score, title, description, editSuggestion, icon]; } Object encode() { - return _toList(); } + return _toList(); + } static GeckoSuggestion decode(Object result) { result as List; @@ -3497,7 +3504,13 @@ class GeckoSuggestion { if (identical(this, other)) { return true; } - return _deepEquals(id, other.id) && _deepEquals(type, other.type) && _deepEquals(score, other.score) && _deepEquals(title, other.title) && _deepEquals(description, other.description) && _deepEquals(editSuggestion, other.editSuggestion) && _deepEquals(icon, other.icon); + return _deepEquals(id, other.id) && + _deepEquals(type, other.type) && + _deepEquals(score, other.score) && + _deepEquals(title, other.title) && + _deepEquals(description, other.description) && + _deepEquals(editSuggestion, other.editSuggestion) && + _deepEquals(icon, other.icon); } @override @@ -3544,7 +3557,8 @@ class TabContent { } Object encode() { - return _toList(); } + return _toList(); + } static TabContent decode(Object result) { result as List; @@ -3567,7 +3581,12 @@ class TabContent { if (identical(this, other)) { return true; } - return _deepEquals(tabId, other.tabId) && _deepEquals(fullContentMarkdown, other.fullContentMarkdown) && _deepEquals(fullContentPlain, other.fullContentPlain) && _deepEquals(isProbablyReaderable, other.isProbablyReaderable) && _deepEquals(extractedContentMarkdown, other.extractedContentMarkdown) && _deepEquals(extractedContentPlain, other.extractedContentPlain); + return _deepEquals(tabId, other.tabId) && + _deepEquals(fullContentMarkdown, other.fullContentMarkdown) && + _deepEquals(fullContentPlain, other.fullContentPlain) && + _deepEquals(isProbablyReaderable, other.isProbablyReaderable) && + _deepEquals(extractedContentMarkdown, other.extractedContentMarkdown) && + _deepEquals(extractedContentPlain, other.extractedContentPlain); } @override @@ -3606,7 +3625,8 @@ class ContentBlocking { } Object encode() { - return _toList(); } + return _toList(); + } static ContentBlocking decode(Object result) { result as List; @@ -3627,7 +3647,22 @@ class ContentBlocking { if (identical(this, other)) { return true; } - return _deepEquals(queryParameterStripping, other.queryParameterStripping) && _deepEquals(queryParameterStrippingAllowList, other.queryParameterStrippingAllowList) && _deepEquals(queryParameterStrippingStripList, other.queryParameterStrippingStripList) && _deepEquals(bounceTrackingProtectionMode, other.bounceTrackingProtectionMode); + return _deepEquals( + queryParameterStripping, + other.queryParameterStripping, + ) && + _deepEquals( + queryParameterStrippingAllowList, + other.queryParameterStrippingAllowList, + ) && + _deepEquals( + queryParameterStrippingStripList, + other.queryParameterStrippingStripList, + ) && + _deepEquals( + bounceTrackingProtectionMode, + other.bounceTrackingProtectionMode, + ); } @override @@ -3666,7 +3701,8 @@ class DohSettings { } Object encode() { - return _toList(); } + return _toList(); + } static DohSettings decode(Object result) { result as List; @@ -3687,7 +3723,10 @@ class DohSettings { if (identical(this, other)) { return true; } - return _deepEquals(dohSettingsMode, other.dohSettingsMode) && _deepEquals(dohProviderUrl, other.dohProviderUrl) && _deepEquals(dohDefaultProviderUrl, other.dohDefaultProviderUrl) && _deepEquals(dohExceptionsList, other.dohExceptionsList); + return _deepEquals(dohSettingsMode, other.dohSettingsMode) && + _deepEquals(dohProviderUrl, other.dohProviderUrl) && + _deepEquals(dohDefaultProviderUrl, other.dohDefaultProviderUrl) && + _deepEquals(dohExceptionsList, other.dohExceptionsList); } @override @@ -3901,7 +3940,8 @@ class GeckoEngineSettings { } Object encode() { - return _toList(); } + return _toList(); + } static GeckoEngineSettings decode(Object result) { result as List; @@ -3912,7 +3952,8 @@ class GeckoEngineSettings { globalPrivacyControlEnabled: result[3] as bool?, preferredColorScheme: result[4] as ColorScheme?, cookieBannerHandlingMode: result[5] as CookieBannerHandlingMode?, - cookieBannerHandlingModePrivateBrowsing: result[6] as CookieBannerHandlingMode?, + cookieBannerHandlingModePrivateBrowsing: + result[6] as CookieBannerHandlingMode?, cookieBannerHandlingGlobalRules: result[7] as bool?, cookieBannerHandlingGlobalRulesSubFrames: result[8] as bool?, webContentIsolationStrategy: result[9] as WebContentIsolationStrategy?, @@ -3962,7 +4003,83 @@ class GeckoEngineSettings { if (identical(this, other)) { return true; } - return _deepEquals(javascriptEnabled, other.javascriptEnabled) && _deepEquals(trackingProtectionPolicy, other.trackingProtectionPolicy) && _deepEquals(httpsOnlyMode, other.httpsOnlyMode) && _deepEquals(globalPrivacyControlEnabled, other.globalPrivacyControlEnabled) && _deepEquals(preferredColorScheme, other.preferredColorScheme) && _deepEquals(cookieBannerHandlingMode, other.cookieBannerHandlingMode) && _deepEquals(cookieBannerHandlingModePrivateBrowsing, other.cookieBannerHandlingModePrivateBrowsing) && _deepEquals(cookieBannerHandlingGlobalRules, other.cookieBannerHandlingGlobalRules) && _deepEquals(cookieBannerHandlingGlobalRulesSubFrames, other.cookieBannerHandlingGlobalRulesSubFrames) && _deepEquals(webContentIsolationStrategy, other.webContentIsolationStrategy) && _deepEquals(userAgent, other.userAgent) && _deepEquals(contentBlocking, other.contentBlocking) && _deepEquals(enterpriseRootsEnabled, other.enterpriseRootsEnabled) && _deepEquals(dohSettings, other.dohSettings) && _deepEquals(fingerprintingProtectionOverrides, other.fingerprintingProtectionOverrides) && _deepEquals(locales, other.locales) && _deepEquals(useContentBlockingDatabase, other.useContentBlockingDatabase) && _deepEquals(blockCookies, other.blockCookies) && _deepEquals(customCookiePolicy, other.customCookiePolicy) && _deepEquals(blockTrackingContent, other.blockTrackingContent) && _deepEquals(trackingContentScope, other.trackingContentScope) && _deepEquals(blockCryptominers, other.blockCryptominers) && _deepEquals(blockFingerprinters, other.blockFingerprinters) && _deepEquals(blockRedirectTrackers, other.blockRedirectTrackers) && _deepEquals(blockSuspectedFingerprinters, other.blockSuspectedFingerprinters) && _deepEquals(suspectedFingerprintersScope, other.suspectedFingerprintersScope) && _deepEquals(allowListBaseline, other.allowListBaseline) && _deepEquals(allowListConvenience, other.allowListConvenience) && _deepEquals(blockAdsAnalyticsSocialTrackers, other.blockAdsAnalyticsSocialTrackers) && _deepEquals(webFontsEnabled, other.webFontsEnabled) && _deepEquals(automaticFontSizeAdjustment, other.automaticFontSizeAdjustment) && _deepEquals(fontSizeFactor, other.fontSizeFactor) && _deepEquals(fontInflationEnabled, other.fontInflationEnabled) && _deepEquals(displayDensityOverride, other.displayDensityOverride) && _deepEquals(screenWidthOverride, other.screenWidthOverride) && _deepEquals(screenHeightOverride, other.screenHeightOverride) && _deepEquals(inputAutoZoomEnabled, other.inputAutoZoomEnabled) && _deepEquals(fissionEnabled, other.fissionEnabled) && _deepEquals(isolatedProcessEnabled, other.isolatedProcessEnabled) && _deepEquals(appZygoteProcessEnabled, other.appZygoteProcessEnabled) && _deepEquals(extensionsWebAPIEnabled, other.extensionsWebAPIEnabled) && _deepEquals(lnaBlocking, other.lnaBlocking) && _deepEquals(lnaBlockTrackers, other.lnaBlockTrackers) && _deepEquals(lnaEnabled, other.lnaEnabled); + return _deepEquals(javascriptEnabled, other.javascriptEnabled) && + _deepEquals(trackingProtectionPolicy, other.trackingProtectionPolicy) && + _deepEquals(httpsOnlyMode, other.httpsOnlyMode) && + _deepEquals( + globalPrivacyControlEnabled, + other.globalPrivacyControlEnabled, + ) && + _deepEquals(preferredColorScheme, other.preferredColorScheme) && + _deepEquals(cookieBannerHandlingMode, other.cookieBannerHandlingMode) && + _deepEquals( + cookieBannerHandlingModePrivateBrowsing, + other.cookieBannerHandlingModePrivateBrowsing, + ) && + _deepEquals( + cookieBannerHandlingGlobalRules, + other.cookieBannerHandlingGlobalRules, + ) && + _deepEquals( + cookieBannerHandlingGlobalRulesSubFrames, + other.cookieBannerHandlingGlobalRulesSubFrames, + ) && + _deepEquals( + webContentIsolationStrategy, + other.webContentIsolationStrategy, + ) && + _deepEquals(userAgent, other.userAgent) && + _deepEquals(contentBlocking, other.contentBlocking) && + _deepEquals(enterpriseRootsEnabled, other.enterpriseRootsEnabled) && + _deepEquals(dohSettings, other.dohSettings) && + _deepEquals( + fingerprintingProtectionOverrides, + other.fingerprintingProtectionOverrides, + ) && + _deepEquals(locales, other.locales) && + _deepEquals( + useContentBlockingDatabase, + other.useContentBlockingDatabase, + ) && + _deepEquals(blockCookies, other.blockCookies) && + _deepEquals(customCookiePolicy, other.customCookiePolicy) && + _deepEquals(blockTrackingContent, other.blockTrackingContent) && + _deepEquals(trackingContentScope, other.trackingContentScope) && + _deepEquals(blockCryptominers, other.blockCryptominers) && + _deepEquals(blockFingerprinters, other.blockFingerprinters) && + _deepEquals(blockRedirectTrackers, other.blockRedirectTrackers) && + _deepEquals( + blockSuspectedFingerprinters, + other.blockSuspectedFingerprinters, + ) && + _deepEquals( + suspectedFingerprintersScope, + other.suspectedFingerprintersScope, + ) && + _deepEquals(allowListBaseline, other.allowListBaseline) && + _deepEquals(allowListConvenience, other.allowListConvenience) && + _deepEquals( + blockAdsAnalyticsSocialTrackers, + other.blockAdsAnalyticsSocialTrackers, + ) && + _deepEquals(webFontsEnabled, other.webFontsEnabled) && + _deepEquals( + automaticFontSizeAdjustment, + other.automaticFontSizeAdjustment, + ) && + _deepEquals(fontSizeFactor, other.fontSizeFactor) && + _deepEquals(fontInflationEnabled, other.fontInflationEnabled) && + _deepEquals(displayDensityOverride, other.displayDensityOverride) && + _deepEquals(screenWidthOverride, other.screenWidthOverride) && + _deepEquals(screenHeightOverride, other.screenHeightOverride) && + _deepEquals(inputAutoZoomEnabled, other.inputAutoZoomEnabled) && + _deepEquals(fissionEnabled, other.fissionEnabled) && + _deepEquals(isolatedProcessEnabled, other.isolatedProcessEnabled) && + _deepEquals(appZygoteProcessEnabled, other.appZygoteProcessEnabled) && + _deepEquals(extensionsWebAPIEnabled, other.extensionsWebAPIEnabled) && + _deepEquals(lnaBlocking, other.lnaBlocking) && + _deepEquals(lnaBlockTrackers, other.lnaBlockTrackers) && + _deepEquals(lnaEnabled, other.lnaEnabled); } @override @@ -3995,17 +4112,12 @@ class AutocompleteResult { int totalItems; List _toList() { - return [ - input, - text, - url, - source, - totalItems, - ]; + return [input, text, url, source, totalItems]; } Object encode() { - return _toList(); } + return _toList(); + } static AutocompleteResult decode(Object result) { result as List; @@ -4027,7 +4139,11 @@ class AutocompleteResult { if (identical(this, other)) { return true; } - return _deepEquals(input, other.input) && _deepEquals(text, other.text) && _deepEquals(url, other.url) && _deepEquals(source, other.source) && _deepEquals(totalItems, other.totalItems); + return _deepEquals(input, other.input) && + _deepEquals(text, other.text) && + _deepEquals(url, other.url) && + _deepEquals(source, other.source) && + _deepEquals(totalItems, other.totalItems); } @override @@ -4042,29 +4158,23 @@ class AutocompleteResult { /// Represents all the different supported types of data that can be found from long clicking /// an element. -sealed class HitResult { -} +sealed class HitResult {} /// Default type if we're unable to match the type to anything. It may or may not have a src. class UnknownHitResult extends HitResult { - UnknownHitResult({ - required this.src, - this.linkText, - }); + UnknownHitResult({required this.src, this.linkText}); String src; String? linkText; List _toList() { - return [ - src, - linkText, - ]; + return [src, linkText]; } Object encode() { - return _toList(); } + return _toList(); + } static UnknownHitResult decode(Object result) { result as List; @@ -4098,24 +4208,19 @@ class UnknownHitResult extends HitResult { /// If the HTML element was of type 'HTMLImageElement'. class ImageHitResult extends HitResult { - ImageHitResult({ - required this.src, - this.title, - }); + ImageHitResult({required this.src, this.title}); String src; String? title; List _toList() { - return [ - src, - title, - ]; + return [src, title]; } Object encode() { - return _toList(); } + return _toList(); + } static ImageHitResult decode(Object result) { result as List; @@ -4149,24 +4254,19 @@ class ImageHitResult extends HitResult { /// If the HTML element was of type 'HTMLVideoElement'. class VideoHitResult extends HitResult { - VideoHitResult({ - required this.src, - this.title, - }); + VideoHitResult({required this.src, this.title}); String src; String? title; List _toList() { - return [ - src, - title, - ]; + return [src, title]; } Object encode() { - return _toList(); } + return _toList(); + } static VideoHitResult decode(Object result) { result as List; @@ -4200,24 +4300,19 @@ class VideoHitResult extends HitResult { /// If the HTML element was of type 'HTMLAudioElement'. class AudioHitResult extends HitResult { - AudioHitResult({ - required this.src, - this.title, - }); + AudioHitResult({required this.src, this.title}); String src; String? title; List _toList() { - return [ - src, - title, - ]; + return [src, title]; } Object encode() { - return _toList(); } + return _toList(); + } static AudioHitResult decode(Object result) { result as List; @@ -4251,24 +4346,19 @@ class AudioHitResult extends HitResult { /// If the HTML element was of type 'HTMLImageElement' and contained a URI. class ImageSrcHitResult extends HitResult { - ImageSrcHitResult({ - required this.src, - required this.uri, - }); + ImageSrcHitResult({required this.src, required this.uri}); String src; String uri; List _toList() { - return [ - src, - uri, - ]; + return [src, uri]; } Object encode() { - return _toList(); } + return _toList(); + } static ImageSrcHitResult decode(Object result) { result as List; @@ -4302,26 +4392,21 @@ class ImageSrcHitResult extends HitResult { /// The type used if the URI is prepended with 'tel:'. class PhoneHitResult extends HitResult { - PhoneHitResult({ - required this.src, - }); + PhoneHitResult({required this.src}); String src; List _toList() { - return [ - src, - ]; + return [src]; } Object encode() { - return _toList(); } + return _toList(); + } static PhoneHitResult decode(Object result) { result as List; - return PhoneHitResult( - src: result[0]! as String, - ); + return PhoneHitResult(src: result[0]! as String); } @override @@ -4348,26 +4433,21 @@ class PhoneHitResult extends HitResult { /// The type used if the URI is prepended with 'mailto:'. class EmailHitResult extends HitResult { - EmailHitResult({ - required this.src, - }); + EmailHitResult({required this.src}); String src; List _toList() { - return [ - src, - ]; + return [src]; } Object encode() { - return _toList(); } + return _toList(); + } static EmailHitResult decode(Object result) { result as List; - return EmailHitResult( - src: result[0]! as String, - ); + return EmailHitResult(src: result[0]! as String); } @override @@ -4394,26 +4474,21 @@ class EmailHitResult extends HitResult { /// The type used if the URI is prepended with 'geo:'. class GeoHitResult extends HitResult { - GeoHitResult({ - required this.src, - }); + GeoHitResult({required this.src}); String src; List _toList() { - return [ - src, - ]; + return [src]; } Object encode() { - return _toList(); } + return _toList(); + } static GeoHitResult decode(Object result) { result as List; - return GeoHitResult( - src: result[0]! as String, - ); + return GeoHitResult(src: result[0]! as String); } @override @@ -4516,7 +4591,8 @@ class DownloadState { } Object encode() { - return _toList(); } + return _toList(); + } static DownloadState decode(Object result) { result as List; @@ -4550,7 +4626,23 @@ class DownloadState { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(fileName, other.fileName) && _deepEquals(contentType, other.contentType) && _deepEquals(contentLength, other.contentLength) && _deepEquals(currentBytesCopied, other.currentBytesCopied) && _deepEquals(status, other.status) && _deepEquals(userAgent, other.userAgent) && _deepEquals(destinationDirectory, other.destinationDirectory) && _deepEquals(directoryPath, other.directoryPath) && _deepEquals(referrerUrl, other.referrerUrl) && _deepEquals(skipConfirmation, other.skipConfirmation) && _deepEquals(openInApp, other.openInApp) && _deepEquals(id, other.id) && _deepEquals(sessionId, other.sessionId) && _deepEquals(private, other.private) && _deepEquals(createdTime, other.createdTime) && _deepEquals(notificationId, other.notificationId); + return _deepEquals(url, other.url) && + _deepEquals(fileName, other.fileName) && + _deepEquals(contentType, other.contentType) && + _deepEquals(contentLength, other.contentLength) && + _deepEquals(currentBytesCopied, other.currentBytesCopied) && + _deepEquals(status, other.status) && + _deepEquals(userAgent, other.userAgent) && + _deepEquals(destinationDirectory, other.destinationDirectory) && + _deepEquals(directoryPath, other.directoryPath) && + _deepEquals(referrerUrl, other.referrerUrl) && + _deepEquals(skipConfirmation, other.skipConfirmation) && + _deepEquals(openInApp, other.openInApp) && + _deepEquals(id, other.id) && + _deepEquals(sessionId, other.sessionId) && + _deepEquals(private, other.private) && + _deepEquals(createdTime, other.createdTime) && + _deepEquals(notificationId, other.notificationId); } @override @@ -4580,16 +4672,12 @@ class ShareInternetResourceState { String? referrerUrl; List _toList() { - return [ - url, - contentType, - private, - referrerUrl, - ]; + return [url, contentType, private, referrerUrl]; } Object encode() { - return _toList(); } + return _toList(); + } static ShareInternetResourceState decode(Object result) { result as List; @@ -4604,13 +4692,17 @@ class ShareInternetResourceState { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) { - if (other is! ShareInternetResourceState || other.runtimeType != runtimeType) { + if (other is! ShareInternetResourceState || + other.runtimeType != runtimeType) { return false; } if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(contentType, other.contentType) && _deepEquals(private, other.private) && _deepEquals(referrerUrl, other.referrerUrl); + return _deepEquals(url, other.url) && + _deepEquals(contentType, other.contentType) && + _deepEquals(private, other.private) && + _deepEquals(referrerUrl, other.referrerUrl); } @override @@ -4637,15 +4729,12 @@ class AddonCollection { String collectionName; List _toList() { - return [ - serverURL, - collectionUser, - collectionName, - ]; + return [serverURL, collectionUser, collectionName]; } Object encode() { - return _toList(); } + return _toList(); + } static AddonCollection decode(Object result) { result as List; @@ -4665,7 +4754,9 @@ class AddonCollection { if (identical(this, other)) { return true; } - return _deepEquals(serverURL, other.serverURL) && _deepEquals(collectionUser, other.collectionUser) && _deepEquals(collectionName, other.collectionName); + return _deepEquals(serverURL, other.serverURL) && + _deepEquals(collectionUser, other.collectionUser) && + _deepEquals(collectionName, other.collectionName); } @override @@ -4679,24 +4770,19 @@ class AddonCollection { } class SyncEngineStatus { - SyncEngineStatus({ - required this.engine, - required this.enabled, - }); + SyncEngineStatus({required this.engine, required this.enabled}); SyncEngineValue engine; bool enabled; List _toList() { - return [ - engine, - enabled, - ]; + return [engine, enabled]; } Object encode() { - return _toList(); } + return _toList(); + } static SyncEngineStatus decode(Object result) { result as List; @@ -4715,7 +4801,8 @@ class SyncEngineStatus { if (identical(this, other)) { return true; } - return _deepEquals(engine, other.engine) && _deepEquals(enabled, other.enabled); + return _deepEquals(engine, other.engine) && + _deepEquals(enabled, other.enabled); } @override @@ -4766,7 +4853,8 @@ class SyncAccountInfo { } Object encode() { - return _toList(); } + return _toList(); + } static SyncAccountInfo decode(Object result) { result as List; @@ -4790,7 +4878,13 @@ class SyncAccountInfo { if (identical(this, other)) { return true; } - return _deepEquals(authenticated, other.authenticated) && _deepEquals(syncing, other.syncing) && _deepEquals(needsReauth, other.needsReauth) && _deepEquals(email, other.email) && _deepEquals(displayName, other.displayName) && _deepEquals(lastSyncedAt, other.lastSyncedAt) && _deepEquals(engines, other.engines); + return _deepEquals(authenticated, other.authenticated) && + _deepEquals(syncing, other.syncing) && + _deepEquals(needsReauth, other.needsReauth) && + _deepEquals(email, other.email) && + _deepEquals(displayName, other.displayName) && + _deepEquals(lastSyncedAt, other.lastSyncedAt) && + _deepEquals(engines, other.engines); } @override @@ -4820,16 +4914,12 @@ class SyncDevice { bool canSendTab; List _toList() { - return [ - deviceId, - displayName, - isCurrentDevice, - canSendTab, - ]; + return [deviceId, displayName, isCurrentDevice, canSendTab]; } Object encode() { - return _toList(); } + return _toList(); + } static SyncDevice decode(Object result) { result as List; @@ -4850,7 +4940,10 @@ class SyncDevice { if (identical(this, other)) { return true; } - return _deepEquals(deviceId, other.deviceId) && _deepEquals(displayName, other.displayName) && _deepEquals(isCurrentDevice, other.isCurrentDevice) && _deepEquals(canSendTab, other.canSendTab); + return _deepEquals(deviceId, other.deviceId) && + _deepEquals(displayName, other.displayName) && + _deepEquals(isCurrentDevice, other.isCurrentDevice) && + _deepEquals(canSendTab, other.canSendTab); } @override @@ -4880,16 +4973,12 @@ class SyncIncomingTab { String? fromDeviceName; List _toList() { - return [ - title, - url, - fromDeviceId, - fromDeviceName, - ]; + return [title, url, fromDeviceId, fromDeviceName]; } Object encode() { - return _toList(); } + return _toList(); + } static SyncIncomingTab decode(Object result) { result as List; @@ -4910,7 +4999,10 @@ class SyncIncomingTab { if (identical(this, other)) { return true; } - return _deepEquals(title, other.title) && _deepEquals(url, other.url) && _deepEquals(fromDeviceId, other.fromDeviceId) && _deepEquals(fromDeviceName, other.fromDeviceName); + return _deepEquals(title, other.title) && + _deepEquals(url, other.url) && + _deepEquals(fromDeviceId, other.fromDeviceId) && + _deepEquals(fromDeviceName, other.fromDeviceName); } @override @@ -4943,17 +5035,12 @@ class SyncRemoteTab { bool inactive; List _toList() { - return [ - title, - url, - iconUrl, - lastUsed, - inactive, - ]; + return [title, url, iconUrl, lastUsed, inactive]; } Object encode() { - return _toList(); } + return _toList(); + } static SyncRemoteTab decode(Object result) { result as List; @@ -4975,7 +5062,11 @@ class SyncRemoteTab { if (identical(this, other)) { return true; } - return _deepEquals(title, other.title) && _deepEquals(url, other.url) && _deepEquals(iconUrl, other.iconUrl) && _deepEquals(lastUsed, other.lastUsed) && _deepEquals(inactive, other.inactive); + return _deepEquals(title, other.title) && + _deepEquals(url, other.url) && + _deepEquals(iconUrl, other.iconUrl) && + _deepEquals(lastUsed, other.lastUsed) && + _deepEquals(inactive, other.inactive); } @override @@ -5002,15 +5093,12 @@ class SyncDeviceTabs { List tabs; List _toList() { - return [ - deviceId, - deviceName, - tabs, - ]; + return [deviceId, deviceName, tabs]; } Object encode() { - return _toList(); } + return _toList(); + } static SyncDeviceTabs decode(Object result) { result as List; @@ -5030,7 +5118,9 @@ class SyncDeviceTabs { if (identical(this, other)) { return true; } - return _deepEquals(deviceId, other.deviceId) && _deepEquals(deviceName, other.deviceName) && _deepEquals(tabs, other.tabs); + return _deepEquals(deviceId, other.deviceId) && + _deepEquals(deviceName, other.deviceName) && + _deepEquals(tabs, other.tabs); } @override @@ -5063,17 +5153,12 @@ class GeckoPref { bool hasUserChangedValue; List _toList() { - return [ - name, - value, - defaultValue, - userValue, - hasUserChangedValue, - ]; + return [name, value, defaultValue, userValue, hasUserChangedValue]; } Object encode() { - return _toList(); } + return _toList(); + } static GeckoPref decode(Object result) { result as List; @@ -5095,7 +5180,11 @@ class GeckoPref { if (identical(this, other)) { return true; } - return _deepEquals(name, other.name) && _deepEquals(value, other.value) && _deepEquals(defaultValue, other.defaultValue) && _deepEquals(userValue, other.userValue) && _deepEquals(hasUserChangedValue, other.hasUserChangedValue); + return _deepEquals(name, other.name) && + _deepEquals(value, other.value) && + _deepEquals(defaultValue, other.defaultValue) && + _deepEquals(userValue, other.userValue) && + _deepEquals(hasUserChangedValue, other.hasUserChangedValue); } @override @@ -5169,7 +5258,8 @@ class MlProgressData { } Object encode() { - return _toList(); } + return _toList(); + } static MlProgressData decode(Object result) { result as List; @@ -5196,7 +5286,16 @@ class MlProgressData { if (identical(this, other)) { return true; } - return _deepEquals(modelType, other.modelType) && _deepEquals(progress, other.progress) && _deepEquals(type, other.type) && _deepEquals(status, other.status) && _deepEquals(totalLoaded, other.totalLoaded) && _deepEquals(currentLoaded, other.currentLoaded) && _deepEquals(total, other.total) && _deepEquals(units, other.units) && _deepEquals(ok, other.ok) && _deepEquals(id, other.id); + return _deepEquals(modelType, other.modelType) && + _deepEquals(progress, other.progress) && + _deepEquals(type, other.type) && + _deepEquals(status, other.status) && + _deepEquals(totalLoaded, other.totalLoaded) && + _deepEquals(currentLoaded, other.currentLoaded) && + _deepEquals(total, other.total) && + _deepEquals(units, other.units) && + _deepEquals(ok, other.ok) && + _deepEquals(id, other.id); } @override @@ -5255,7 +5354,8 @@ class GeckoProxySettings { } Object encode() { - return _toList(); } + return _toList(); + } static GeckoProxySettings decode(Object result) { result as List; @@ -5281,7 +5381,15 @@ class GeckoProxySettings { if (identical(this, other)) { return true; } - return _deepEquals(id, other.id) && _deepEquals(title, other.title) && _deepEquals(type, other.type) && _deepEquals(host, other.host) && _deepEquals(port, other.port) && _deepEquals(username, other.username) && _deepEquals(password, other.password) && _deepEquals(proxyDNS, other.proxyDNS) && _deepEquals(doNotProxyLocal, other.doNotProxyLocal); + return _deepEquals(id, other.id) && + _deepEquals(title, other.title) && + _deepEquals(type, other.type) && + _deepEquals(host, other.host) && + _deepEquals(port, other.port) && + _deepEquals(username, other.username) && + _deepEquals(password, other.password) && + _deepEquals(proxyDNS, other.proxyDNS) && + _deepEquals(doNotProxyLocal, other.doNotProxyLocal); } @override @@ -5321,18 +5429,12 @@ class ContainerSiteAssignment { bool strict; List _toList() { - return [ - requestId, - tabId, - originUrl, - url, - blocked, - strict, - ]; + return [requestId, tabId, originUrl, url, blocked, strict]; } Object encode() { - return _toList(); } + return _toList(); + } static ContainerSiteAssignment decode(Object result) { result as List; @@ -5355,7 +5457,12 @@ class ContainerSiteAssignment { if (identical(this, other)) { return true; } - return _deepEquals(requestId, other.requestId) && _deepEquals(tabId, other.tabId) && _deepEquals(originUrl, other.originUrl) && _deepEquals(url, other.url) && _deepEquals(blocked, other.blocked) && _deepEquals(strict, other.strict); + return _deepEquals(requestId, other.requestId) && + _deepEquals(tabId, other.tabId) && + _deepEquals(originUrl, other.originUrl) && + _deepEquals(url, other.url) && + _deepEquals(blocked, other.blocked) && + _deepEquals(strict, other.strict); } @override @@ -5385,16 +5492,12 @@ class ProxyLoadError { String errorType; List _toList() { - return [ - tabId, - contextId, - url, - errorType, - ]; + return [tabId, contextId, url, errorType]; } Object encode() { - return _toList(); } + return _toList(); + } static ProxyLoadError decode(Object result) { result as List; @@ -5415,7 +5518,10 @@ class ProxyLoadError { if (identical(this, other)) { return true; } - return _deepEquals(tabId, other.tabId) && _deepEquals(contextId, other.contextId) && _deepEquals(url, other.url) && _deepEquals(errorType, other.errorType); + return _deepEquals(tabId, other.tabId) && + _deepEquals(contextId, other.contextId) && + _deepEquals(url, other.url) && + _deepEquals(errorType, other.errorType); } @override @@ -5429,31 +5535,23 @@ class ProxyLoadError { } class GeckoHeader { - GeckoHeader({ - required this.key, - required this.value, - }); + GeckoHeader({required this.key, required this.value}); String key; String value; List _toList() { - return [ - key, - value, - ]; + return [key, value]; } Object encode() { - return _toList(); } + return _toList(); + } static GeckoHeader decode(Object result) { result as List; - return GeckoHeader( - key: result[0]! as String, - value: result[1]! as String, - ); + return GeckoHeader(key: result[0]! as String, value: result[1]! as String); } @override @@ -5540,7 +5638,8 @@ class GeckoFetchRequest { } Object encode() { - return _toList(); } + return _toList(); + } static GeckoFetchRequest decode(Object result) { result as List; @@ -5570,7 +5669,19 @@ class GeckoFetchRequest { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(method, other.method) && _deepEquals(headers, other.headers) && _deepEquals(connectTimeoutMillis, other.connectTimeoutMillis) && _deepEquals(readTimeoutMillis, other.readTimeoutMillis) && _deepEquals(body, other.body) && _deepEquals(redirect, other.redirect) && _deepEquals(cookiePolicy, other.cookiePolicy) && _deepEquals(useCaches, other.useCaches) && _deepEquals(private, other.private) && _deepEquals(useOhttp, other.useOhttp) && _deepEquals(referrerUrl, other.referrerUrl) && _deepEquals(conservative, other.conservative); + return _deepEquals(url, other.url) && + _deepEquals(method, other.method) && + _deepEquals(headers, other.headers) && + _deepEquals(connectTimeoutMillis, other.connectTimeoutMillis) && + _deepEquals(readTimeoutMillis, other.readTimeoutMillis) && + _deepEquals(body, other.body) && + _deepEquals(redirect, other.redirect) && + _deepEquals(cookiePolicy, other.cookiePolicy) && + _deepEquals(useCaches, other.useCaches) && + _deepEquals(private, other.private) && + _deepEquals(useOhttp, other.useOhttp) && + _deepEquals(referrerUrl, other.referrerUrl) && + _deepEquals(conservative, other.conservative); } @override @@ -5600,16 +5711,12 @@ class GeckoFetchResponse { Uint8List body; List _toList() { - return [ - url, - status, - headers, - body, - ]; + return [url, status, headers, body]; } Object encode() { - return _toList(); } + return _toList(); + } static GeckoFetchResponse decode(Object result) { result as List; @@ -5630,7 +5737,10 @@ class GeckoFetchResponse { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(status, other.status) && _deepEquals(headers, other.headers) && _deepEquals(body, other.body); + return _deepEquals(url, other.url) && + _deepEquals(status, other.status) && + _deepEquals(headers, other.headers) && + _deepEquals(body, other.body); } @override @@ -5689,7 +5799,8 @@ class BookmarkNode { } Object encode() { - return _toList(); } + return _toList(); + } static BookmarkNode decode(Object result) { result as List; @@ -5715,7 +5826,15 @@ class BookmarkNode { if (identical(this, other)) { return true; } - return _deepEquals(type, other.type) && _deepEquals(guid, other.guid) && _deepEquals(parentGuid, other.parentGuid) && _deepEquals(position, other.position) && _deepEquals(title, other.title) && _deepEquals(url, other.url) && _deepEquals(dateAdded, other.dateAdded) && _deepEquals(lastModified, other.lastModified) && _deepEquals(children, other.children); + return _deepEquals(type, other.type) && + _deepEquals(guid, other.guid) && + _deepEquals(parentGuid, other.parentGuid) && + _deepEquals(position, other.position) && + _deepEquals(title, other.title) && + _deepEquals(url, other.url) && + _deepEquals(dateAdded, other.dateAdded) && + _deepEquals(lastModified, other.lastModified) && + _deepEquals(children, other.children); } @override @@ -5728,15 +5847,146 @@ class BookmarkNode { } } -/// Class for making alterations to any bookmark node -class BookmarkInfo { - BookmarkInfo({ - this.parentGuid, - this.position, +/// A node of a bookmark tree that is about to be bulk-inserted into storage. +/// +/// Unlike [BookmarkNode] this carries no guids or parent links: the tree is +/// described purely by nesting, and storage assigns guids while inserting. +/// +/// @property type Whether this node is an item, a folder or a separator. +/// @property title The title of the item or folder. Ignored for separators. +/// @property url The URL of the item. Must be non-null for items, ignored otherwise. +/// @property dateAdded Creation timestamp in milliseconds since epoch, or 0 if unknown. +/// @property lastModified Modification timestamp in milliseconds since epoch, or 0 if unknown. +/// @property children Child nodes of a folder, in insertion order. Empty for items and separators. +class BookmarkImportNode { + BookmarkImportNode({ + required this.type, this.title, this.url, + required this.dateAdded, + required this.lastModified, + required this.children, }); + BookmarkNodeType type; + + String? title; + + String? url; + + int dateAdded; + + int lastModified; + + List children; + + List _toList() { + return [type, title, url, dateAdded, lastModified, children]; + } + + Object encode() { + return _toList(); + } + + static BookmarkImportNode decode(Object result) { + result as List; + return BookmarkImportNode( + type: result[0]! as BookmarkNodeType, + title: result[1] as String?, + url: result[2] as String?, + dateAdded: result[3]! as int, + lastModified: result[4]! as int, + children: (result[5]! as List).cast(), + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! BookmarkImportNode || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(type, other.type) && + _deepEquals(title, other.title) && + _deepEquals(url, other.url) && + _deepEquals(dateAdded, other.dateAdded) && + _deepEquals(lastModified, other.lastModified) && + _deepEquals(children, other.children); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'BookmarkImportNode(type: $type, title: $title, url: $url, dateAdded: $dateAdded, lastModified: $lastModified, children: $children)'; + } +} + +/// Outcome of a bulk bookmark tree insertion. +/// +/// @property insertedItemCount The number of bookmark items (not folders or +/// separators) that were inserted. +/// @property failedNodeCount The number of top-level nodes that could not be +/// inserted. Their subtrees are missing entirely. +class BookmarkInsertTreeResult { + BookmarkInsertTreeResult({ + required this.insertedItemCount, + required this.failedNodeCount, + }); + + int insertedItemCount; + + int failedNodeCount; + + List _toList() { + return [insertedItemCount, failedNodeCount]; + } + + Object encode() { + return _toList(); + } + + static BookmarkInsertTreeResult decode(Object result) { + result as List; + return BookmarkInsertTreeResult( + insertedItemCount: result[0]! as int, + failedNodeCount: result[1]! as int, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! BookmarkInsertTreeResult || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(insertedItemCount, other.insertedItemCount) && + _deepEquals(failedNodeCount, other.failedNodeCount); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); + + @override + String toString() { + return 'BookmarkInsertTreeResult(insertedItemCount: $insertedItemCount, failedNodeCount: $failedNodeCount)'; + } +} + +/// Class for making alterations to any bookmark node +class BookmarkInfo { + BookmarkInfo({this.parentGuid, this.position, this.title, this.url}); + String? parentGuid; int? position; @@ -5746,16 +5996,12 @@ class BookmarkInfo { String? url; List _toList() { - return [ - parentGuid, - position, - title, - url, - ]; + return [parentGuid, position, title, url]; } Object encode() { - return _toList(); } + return _toList(); + } static BookmarkInfo decode(Object result) { result as List; @@ -5776,7 +6022,10 @@ class BookmarkInfo { if (identical(this, other)) { return true; } - return _deepEquals(parentGuid, other.parentGuid) && _deepEquals(position, other.position) && _deepEquals(title, other.title) && _deepEquals(url, other.url); + return _deepEquals(parentGuid, other.parentGuid) && + _deepEquals(position, other.position) && + _deepEquals(title, other.title) && + _deepEquals(url, other.url); } @override @@ -5852,7 +6101,8 @@ class SitePermissions { } Object encode() { - return _toList(); } + return _toList(); + } static SitePermissions decode(Object result) { result as List; @@ -5882,7 +6132,19 @@ class SitePermissions { if (identical(this, other)) { return true; } - return _deepEquals(origin, other.origin) && _deepEquals(camera, other.camera) && _deepEquals(microphone, other.microphone) && _deepEquals(location, other.location) && _deepEquals(notification, other.notification) && _deepEquals(persistentStorage, other.persistentStorage) && _deepEquals(crossOriginStorageAccess, other.crossOriginStorageAccess) && _deepEquals(mediaKeySystemAccess, other.mediaKeySystemAccess) && _deepEquals(localDeviceAccess, other.localDeviceAccess) && _deepEquals(localNetworkAccess, other.localNetworkAccess) && _deepEquals(autoplayAudible, other.autoplayAudible) && _deepEquals(autoplayInaudible, other.autoplayInaudible) && _deepEquals(savedAt, other.savedAt); + return _deepEquals(origin, other.origin) && + _deepEquals(camera, other.camera) && + _deepEquals(microphone, other.microphone) && + _deepEquals(location, other.location) && + _deepEquals(notification, other.notification) && + _deepEquals(persistentStorage, other.persistentStorage) && + _deepEquals(crossOriginStorageAccess, other.crossOriginStorageAccess) && + _deepEquals(mediaKeySystemAccess, other.mediaKeySystemAccess) && + _deepEquals(localDeviceAccess, other.localDeviceAccess) && + _deepEquals(localNetworkAccess, other.localNetworkAccess) && + _deepEquals(autoplayAudible, other.autoplayAudible) && + _deepEquals(autoplayInaudible, other.autoplayInaudible) && + _deepEquals(savedAt, other.savedAt); } @override @@ -5900,32 +6162,28 @@ class SitePermissions { /// This represents a site that has been added to the exceptions list, /// meaning tracking protection is disabled for this specific site. class TrackingProtectionException { - TrackingProtectionException({ - required this.url, - }); + TrackingProtectionException({required this.url}); String url; List _toList() { - return [ - url, - ]; + return [url]; } Object encode() { - return _toList(); } + return _toList(); + } static TrackingProtectionException decode(Object result) { result as List; - return TrackingProtectionException( - url: result[0]! as String, - ); + return TrackingProtectionException(url: result[0]! as String); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) { - if (other is! TrackingProtectionException || other.runtimeType != runtimeType) { + if (other is! TrackingProtectionException || + other.runtimeType != runtimeType) { return false; } if (identical(this, other)) { @@ -5995,7 +6253,8 @@ class AppLinkTarget { } Object encode() { - return _toList(); } + return _toList(); + } static AppLinkTarget decode(Object result) { result as List; @@ -6020,7 +6279,14 @@ class AppLinkTarget { if (identical(this, other)) { return true; } - return _deepEquals(url, other.url) && _deepEquals(appName, other.appName) && _deepEquals(packageName, other.packageName) && _deepEquals(fallbackUrl, other.fallbackUrl) && _deepEquals(isMarketplace, other.isMarketplace) && _deepEquals(isAmbiguous, other.isAmbiguous) && _deepEquals(engineSupportsScheme, other.engineSupportsScheme) && _deepEquals(scopeKey, other.scopeKey); + return _deepEquals(url, other.url) && + _deepEquals(appName, other.appName) && + _deepEquals(packageName, other.packageName) && + _deepEquals(fallbackUrl, other.fallbackUrl) && + _deepEquals(isMarketplace, other.isMarketplace) && + _deepEquals(isAmbiguous, other.isAmbiguous) && + _deepEquals(engineSupportsScheme, other.engineSupportsScheme) && + _deepEquals(scopeKey, other.scopeKey); } @override @@ -6054,16 +6320,12 @@ class ProtectedTargetPattern { int? port; List _toList() { - return [ - scheme, - hostOrSuffix, - includeSubdomains, - port, - ]; + return [scheme, hostOrSuffix, includeSubdomains, port]; } Object encode() { - return _toList(); } + return _toList(); + } static ProtectedTargetPattern decode(Object result) { result as List; @@ -6084,7 +6346,10 @@ class ProtectedTargetPattern { if (identical(this, other)) { return true; } - return _deepEquals(scheme, other.scheme) && _deepEquals(hostOrSuffix, other.hostOrSuffix) && _deepEquals(includeSubdomains, other.includeSubdomains) && _deepEquals(port, other.port); + return _deepEquals(scheme, other.scheme) && + _deepEquals(hostOrSuffix, other.hostOrSuffix) && + _deepEquals(includeSubdomains, other.includeSubdomains) && + _deepEquals(port, other.port); } @override @@ -6113,15 +6378,12 @@ class NativeAppLinkRule { String? packageName; List _toList() { - return [ - decision, - scope, - packageName, - ]; + return [decision, scope, packageName]; } Object encode() { - return _toList(); } + return _toList(); + } static NativeAppLinkRule decode(Object result) { result as List; @@ -6141,7 +6403,9 @@ class NativeAppLinkRule { if (identical(this, other)) { return true; } - return _deepEquals(decision, other.decision) && _deepEquals(scope, other.scope) && _deepEquals(packageName, other.packageName); + return _deepEquals(decision, other.decision) && + _deepEquals(scope, other.scope) && + _deepEquals(packageName, other.packageName); } @override @@ -6159,10 +6423,7 @@ class NativeAppLinkRule { /// navigation's source contextId has an entry here, it fully *replaces* the /// global mode + rules for that navigation (no layering with the global policy). class NativeContextAppLinkPolicy { - NativeContextAppLinkPolicy({ - required this.mode, - required this.rules, - }); + NativeContextAppLinkPolicy({required this.mode, required this.rules}); AppLinksMode mode; @@ -6170,27 +6431,27 @@ class NativeContextAppLinkPolicy { Map rules; List _toList() { - return [ - mode, - rules, - ]; + return [mode, rules]; } Object encode() { - return _toList(); } + return _toList(); + } static NativeContextAppLinkPolicy decode(Object result) { result as List; return NativeContextAppLinkPolicy( mode: result[0]! as AppLinksMode, - rules: (result[1]! as Map).cast(), + rules: (result[1]! as Map) + .cast(), ); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) { - if (other is! NativeContextAppLinkPolicy || other.runtimeType != runtimeType) { + if (other is! NativeContextAppLinkPolicy || + other.runtimeType != runtimeType) { return false; } if (identical(this, other)) { @@ -6261,19 +6522,23 @@ class AppLinkPolicySnapshot { } Object encode() { - return _toList(); } + return _toList(); + } static AppLinkPolicySnapshot decode(Object result) { result as List; return AppLinkPolicySnapshot( globalMode: result[0]! as AppLinksMode, - rules: (result[1]! as Map).cast(), + rules: (result[1]! as Map) + .cast(), marketplaceFallbackEnabled: result[2]! as bool, protectGeneralContext: result[3]! as bool, protectedContextIds: (result[4]! as List).cast(), strictContextIds: (result[5]! as List).cast(), - protectedTargetPatterns: (result[6]! as List).cast(), - contextOverrides: (result[7]! as Map).cast(), + protectedTargetPatterns: (result[6]! as List) + .cast(), + contextOverrides: (result[7]! as Map) + .cast(), ); } @@ -6286,7 +6551,17 @@ class AppLinkPolicySnapshot { if (identical(this, other)) { return true; } - return _deepEquals(globalMode, other.globalMode) && _deepEquals(rules, other.rules) && _deepEquals(marketplaceFallbackEnabled, other.marketplaceFallbackEnabled) && _deepEquals(protectGeneralContext, other.protectGeneralContext) && _deepEquals(protectedContextIds, other.protectedContextIds) && _deepEquals(strictContextIds, other.strictContextIds) && _deepEquals(protectedTargetPatterns, other.protectedTargetPatterns) && _deepEquals(contextOverrides, other.contextOverrides); + return _deepEquals(globalMode, other.globalMode) && + _deepEquals(rules, other.rules) && + _deepEquals( + marketplaceFallbackEnabled, + other.marketplaceFallbackEnabled, + ) && + _deepEquals(protectGeneralContext, other.protectGeneralContext) && + _deepEquals(protectedContextIds, other.protectedContextIds) && + _deepEquals(strictContextIds, other.strictContextIds) && + _deepEquals(protectedTargetPatterns, other.protectedTargetPatterns) && + _deepEquals(contextOverrides, other.contextOverrides); } @override @@ -6359,7 +6634,8 @@ class AppLinkPromptRequest { } Object encode() { - return _toList(); } + return _toList(); + } static AppLinkPromptRequest decode(Object result) { result as List; @@ -6387,7 +6663,17 @@ class AppLinkPromptRequest { if (identical(this, other)) { return true; } - return _deepEquals(requestId, other.requestId) && _deepEquals(owner, other.owner) && _deepEquals(tabId, other.tabId) && _deepEquals(contextId, other.contextId) && _deepEquals(sourceUrl, other.sourceUrl) && _deepEquals(isPrivate, other.isPrivate) && _deepEquals(isWallet, other.isWallet) && _deepEquals(isProtectedContext, other.isProtectedContext) && _deepEquals(canRemember, other.canRemember) && _deepEquals(isModal, other.isModal) && _deepEquals(target, other.target); + return _deepEquals(requestId, other.requestId) && + _deepEquals(owner, other.owner) && + _deepEquals(tabId, other.tabId) && + _deepEquals(contextId, other.contextId) && + _deepEquals(sourceUrl, other.sourceUrl) && + _deepEquals(isPrivate, other.isPrivate) && + _deepEquals(isWallet, other.isWallet) && + _deepEquals(isProtectedContext, other.isProtectedContext) && + _deepEquals(canRemember, other.canRemember) && + _deepEquals(isModal, other.isModal) && + _deepEquals(target, other.target); } @override @@ -6416,15 +6702,12 @@ class AppLinkResolutionResult { String? failureReason; List _toList() { - return [ - launched, - loadedFallback, - failureReason, - ]; + return [launched, loadedFallback, failureReason]; } Object encode() { - return _toList(); } + return _toList(); + } static AppLinkResolutionResult decode(Object result) { result as List; @@ -6444,7 +6727,9 @@ class AppLinkResolutionResult { if (identical(this, other)) { return true; } - return _deepEquals(launched, other.launched) && _deepEquals(loadedFallback, other.loadedFallback) && _deepEquals(failureReason, other.failureReason); + return _deepEquals(launched, other.launched) && + _deepEquals(loadedFallback, other.loadedFallback) && + _deepEquals(failureReason, other.failureReason); } @override @@ -6459,11 +6744,7 @@ class AppLinkResolutionResult { /// Represents an icon from a PWA manifest. class PwaIcon { - PwaIcon({ - required this.src, - this.sizes, - this.type, - }); + PwaIcon({required this.src, this.sizes, this.type}); String src; @@ -6472,15 +6753,12 @@ class PwaIcon { String? type; List _toList() { - return [ - src, - sizes, - type, - ]; + return [src, sizes, type]; } Object encode() { - return _toList(); } + return _toList(); + } static PwaIcon decode(Object result) { result as List; @@ -6500,7 +6778,9 @@ class PwaIcon { if (identical(this, other)) { return true; } - return _deepEquals(src, other.src) && _deepEquals(sizes, other.sizes) && _deepEquals(type, other.type); + return _deepEquals(src, other.src) && + _deepEquals(sizes, other.sizes) && + _deepEquals(type, other.type); } @override @@ -6515,24 +6795,19 @@ class PwaIcon { /// Represents a file entry in share target params. class ShareTargetFiles { - ShareTargetFiles({ - required this.name, - required this.accept, - }); + ShareTargetFiles({required this.name, required this.accept}); String name; List accept; List _toList() { - return [ - name, - accept, - ]; + return [name, accept]; } Object encode() { - return _toList(); } + return _toList(); + } static ShareTargetFiles decode(Object result) { result as List; @@ -6566,12 +6841,7 @@ class ShareTargetFiles { /// Represents share target params. class ShareTargetParams { - ShareTargetParams({ - this.title, - this.text, - this.url, - required this.files, - }); + ShareTargetParams({this.title, this.text, this.url, required this.files}); String? title; @@ -6582,16 +6852,12 @@ class ShareTargetParams { List files; List _toList() { - return [ - title, - text, - url, - files, - ]; + return [title, text, url, files]; } Object encode() { - return _toList(); } + return _toList(); + } static ShareTargetParams decode(Object result) { result as List; @@ -6612,7 +6878,10 @@ class ShareTargetParams { if (identical(this, other)) { return true; } - return _deepEquals(title, other.title) && _deepEquals(text, other.text) && _deepEquals(url, other.url) && _deepEquals(files, other.files); + return _deepEquals(title, other.title) && + _deepEquals(text, other.text) && + _deepEquals(url, other.url) && + _deepEquals(files, other.files); } @override @@ -6627,12 +6896,7 @@ class ShareTargetParams { /// Represents a share target for PWA. class ShareTarget { - ShareTarget({ - required this.action, - this.method, - this.encType, - this.params, - }); + ShareTarget({required this.action, this.method, this.encType, this.params}); String action; @@ -6643,16 +6907,12 @@ class ShareTarget { ShareTargetParams? params; List _toList() { - return [ - action, - method, - encType, - params, - ]; + return [action, method, encType, params]; } Object encode() { - return _toList(); } + return _toList(); + } static ShareTarget decode(Object result) { result as List; @@ -6673,7 +6933,10 @@ class ShareTarget { if (identical(this, other)) { return true; } - return _deepEquals(action, other.action) && _deepEquals(method, other.method) && _deepEquals(encType, other.encType) && _deepEquals(params, other.params); + return _deepEquals(action, other.action) && + _deepEquals(method, other.method) && + _deepEquals(encType, other.encType) && + _deepEquals(params, other.params); } @override @@ -6704,16 +6967,12 @@ class ExternalApplicationResource { String? minVersion; List _toList() { - return [ - platform, - url, - id, - minVersion, - ]; + return [platform, url, id, minVersion]; } Object encode() { - return _toList(); } + return _toList(); + } static ExternalApplicationResource decode(Object result) { result as List; @@ -6728,13 +6987,17 @@ class ExternalApplicationResource { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) { - if (other is! ExternalApplicationResource || other.runtimeType != runtimeType) { + if (other is! ExternalApplicationResource || + other.runtimeType != runtimeType) { return false; } if (identical(this, other)) { return true; } - return _deepEquals(platform, other.platform) && _deepEquals(url, other.url) && _deepEquals(id, other.id) && _deepEquals(minVersion, other.minVersion); + return _deepEquals(platform, other.platform) && + _deepEquals(url, other.url) && + _deepEquals(id, other.id) && + _deepEquals(minVersion, other.minVersion); } @override @@ -6844,7 +7107,8 @@ class PwaManifest { } Object encode() { - return _toList(); } + return _toList(); + } static PwaManifest decode(Object result) { result as List; @@ -6861,7 +7125,8 @@ class PwaManifest { dir: result[9] as String?, lang: result[10] as String?, orientation: result[11] as String?, - relatedApplications: (result[12]! as List).cast(), + relatedApplications: (result[12]! as List) + .cast(), preferRelatedApplications: result[13]! as bool, shareTarget: result[14] as ShareTarget?, currentUrl: result[15]! as String, @@ -6879,7 +7144,27 @@ class PwaManifest { if (identical(this, other)) { return true; } - return _deepEquals(startUrl, other.startUrl) && _deepEquals(name, other.name) && _deepEquals(shortName, other.shortName) && _deepEquals(display, other.display) && _deepEquals(themeColor, other.themeColor) && _deepEquals(backgroundColor, other.backgroundColor) && _deepEquals(scope, other.scope) && _deepEquals(description, other.description) && _deepEquals(icons, other.icons) && _deepEquals(dir, other.dir) && _deepEquals(lang, other.lang) && _deepEquals(orientation, other.orientation) && _deepEquals(relatedApplications, other.relatedApplications) && _deepEquals(preferRelatedApplications, other.preferRelatedApplications) && _deepEquals(shareTarget, other.shareTarget) && _deepEquals(currentUrl, other.currentUrl) && _deepEquals(contextId, other.contextId) && _deepEquals(installLabel, other.installLabel); + return _deepEquals(startUrl, other.startUrl) && + _deepEquals(name, other.name) && + _deepEquals(shortName, other.shortName) && + _deepEquals(display, other.display) && + _deepEquals(themeColor, other.themeColor) && + _deepEquals(backgroundColor, other.backgroundColor) && + _deepEquals(scope, other.scope) && + _deepEquals(description, other.description) && + _deepEquals(icons, other.icons) && + _deepEquals(dir, other.dir) && + _deepEquals(lang, other.lang) && + _deepEquals(orientation, other.orientation) && + _deepEquals(relatedApplications, other.relatedApplications) && + _deepEquals( + preferRelatedApplications, + other.preferRelatedApplications, + ) && + _deepEquals(shareTarget, other.shareTarget) && + _deepEquals(currentUrl, other.currentUrl) && + _deepEquals(contextId, other.contextId) && + _deepEquals(installLabel, other.installLabel); } @override @@ -6922,17 +7207,12 @@ class SandboxCaptureEntry { String status; List _toList() { - return [ - tabId, - captureId, - sourceUrl, - redirectUrl, - status, - ]; + return [tabId, captureId, sourceUrl, redirectUrl, status]; } Object encode() { - return _toList(); } + return _toList(); + } static SandboxCaptureEntry decode(Object result) { result as List; @@ -6954,7 +7234,11 @@ class SandboxCaptureEntry { if (identical(this, other)) { return true; } - return _deepEquals(tabId, other.tabId) && _deepEquals(captureId, other.captureId) && _deepEquals(sourceUrl, other.sourceUrl) && _deepEquals(redirectUrl, other.redirectUrl) && _deepEquals(status, other.status); + return _deepEquals(tabId, other.tabId) && + _deepEquals(captureId, other.captureId) && + _deepEquals(sourceUrl, other.sourceUrl) && + _deepEquals(redirectUrl, other.redirectUrl) && + _deepEquals(status, other.status); } @override @@ -7021,7 +7305,8 @@ class GestureConfig { } Object encode() { - return _toList(); } + return _toList(); + } static GestureConfig decode(Object result) { result as List; @@ -7044,7 +7329,12 @@ class GestureConfig { if (identical(this, other)) { return true; } - return _deepEquals(enabled, other.enabled) && _deepEquals(strokeSize, other.strokeSize) && _deepEquals(timeoutMs, other.timeoutMs) && _deepEquals(maxFingers, other.maxFingers) && _deepEquals(minStrokeIntervalMs, other.minStrokeIntervalMs) && _deepEquals(activeGestureKeys, other.activeGestureKeys); + return _deepEquals(enabled, other.enabled) && + _deepEquals(strokeSize, other.strokeSize) && + _deepEquals(timeoutMs, other.timeoutMs) && + _deepEquals(maxFingers, other.maxFingers) && + _deepEquals(minStrokeIntervalMs, other.minStrokeIntervalMs) && + _deepEquals(activeGestureKeys, other.activeGestureKeys); } @override @@ -7058,10 +7348,7 @@ class GestureConfig { } class PushDistributor { - PushDistributor({ - required this.packageName, - this.label, - }); + PushDistributor({required this.packageName, this.label}); String packageName; @@ -7069,14 +7356,12 @@ class PushDistributor { String? label; List _toList() { - return [ - packageName, - label, - ]; + return [packageName, label]; } Object encode() { - return _toList(); } + return _toList(); + } static PushDistributor decode(Object result) { result as List; @@ -7095,7 +7380,8 @@ class PushDistributor { if (identical(this, other)) { return true; } - return _deepEquals(packageName, other.packageName) && _deepEquals(label, other.label); + return _deepEquals(packageName, other.packageName) && + _deepEquals(label, other.label); } @override @@ -7130,16 +7416,12 @@ class PushStatus { String? lastError; List _toList() { - return [ - status, - current, - available, - lastError, - ]; + return [status, current, available, lastError]; } Object encode() { - return _toList(); } + return _toList(); + } static PushStatus decode(Object result) { result as List; @@ -7160,7 +7442,10 @@ class PushStatus { if (identical(this, other)) { return true; } - return _deepEquals(status, other.status) && _deepEquals(current, other.current) && _deepEquals(available, other.available) && _deepEquals(lastError, other.lastError); + return _deepEquals(status, other.status) && + _deepEquals(current, other.current) && + _deepEquals(available, other.available) && + _deepEquals(lastError, other.lastError); } @override @@ -7174,10 +7459,7 @@ class PushStatus { } class PushSubscription { - PushSubscription({ - required this.scope, - required this.hasEndpoint, - }); + PushSubscription({required this.scope, required this.hasEndpoint}); /// Subscription identifier, which for web push is the site's origin. String scope; @@ -7186,14 +7468,12 @@ class PushSubscription { bool hasEndpoint; List _toList() { - return [ - scope, - hasEndpoint, - ]; + return [scope, hasEndpoint]; } Object encode() { - return _toList(); } + return _toList(); + } static PushSubscription decode(Object result) { result as List; @@ -7212,7 +7492,8 @@ class PushSubscription { if (identical(this, other)) { return true; } - return _deepEquals(scope, other.scope) && _deepEquals(hasEndpoint, other.hasEndpoint); + return _deepEquals(scope, other.scope) && + _deepEquals(hasEndpoint, other.hasEndpoint); } @override @@ -7225,7 +7506,6 @@ class PushSubscription { } } - // ignore: camel_case_types class _PigeonCodecOverflow { _PigeonCodecOverflow({required this.type, required this.wrapped}); @@ -7239,10 +7519,7 @@ class _PigeonCodecOverflow { static _PigeonCodecOverflow decode(Object result) { result as List; - return _PigeonCodecOverflow( - type: result[0]! as int, - wrapped: result[1], - ); + return _PigeonCodecOverflow(type: result[0]! as int, wrapped: result[1]); } Object? unwrap() { @@ -7252,28 +7529,32 @@ class _PigeonCodecOverflow { switch (type) { case 0: - return AppLinkResolutionResult.decode(wrapped!); + return AppLinkPolicySnapshot.decode(wrapped!); case 1: - return PwaIcon.decode(wrapped!); + return AppLinkPromptRequest.decode(wrapped!); case 2: - return ShareTargetFiles.decode(wrapped!); + return AppLinkResolutionResult.decode(wrapped!); case 3: - return ShareTargetParams.decode(wrapped!); + return PwaIcon.decode(wrapped!); case 4: - return ShareTarget.decode(wrapped!); + return ShareTargetFiles.decode(wrapped!); case 5: - return ExternalApplicationResource.decode(wrapped!); + return ShareTargetParams.decode(wrapped!); case 6: - return PwaManifest.decode(wrapped!); + return ShareTarget.decode(wrapped!); case 7: - return SandboxCaptureEntry.decode(wrapped!); + return ExternalApplicationResource.decode(wrapped!); case 8: - return GestureConfig.decode(wrapped!); + return PwaManifest.decode(wrapped!); case 9: - return PushDistributor.decode(wrapped!); + return SandboxCaptureEntry.decode(wrapped!); case 10: - return PushStatus.decode(wrapped!); + return GestureConfig.decode(wrapped!); case 11: + return PushDistributor.decode(wrapped!); + case 12: + return PushStatus.decode(wrapped!); + case 13: return PushSubscription.decode(wrapped!); } return null; @@ -7287,430 +7568,480 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is RestoreLocation) { + } else if (value is RestoreLocation) { buffer.putUint8(129); writeValue(buffer, value.index); - } else if (value is IconType) { + } else if (value is IconType) { buffer.putUint8(130); writeValue(buffer, value.index); - } else if (value is IconSize) { + } else if (value is IconSize) { buffer.putUint8(131); writeValue(buffer, value.index); - } else if (value is IconSource) { + } else if (value is IconSource) { buffer.putUint8(132); writeValue(buffer, value.index); - } else if (value is CookieSameSiteStatus) { + } else if (value is CookieSameSiteStatus) { buffer.putUint8(133); writeValue(buffer, value.index); - } else if (value is VisitType) { + } else if (value is VisitType) { buffer.putUint8(134); writeValue(buffer, value.index); - } else if (value is FrecencyThresholdOption) { + } else if (value is FrecencyThresholdOption) { buffer.putUint8(135); writeValue(buffer, value.index); - } else if (value is DocumentType) { + } else if (value is DocumentType) { buffer.putUint8(136); writeValue(buffer, value.index); - } else if (value is SelectionPattern) { + } else if (value is SelectionPattern) { buffer.putUint8(137); writeValue(buffer, value.index); - } else if (value is WebExtensionActionType) { + } else if (value is WebExtensionActionType) { buffer.putUint8(138); writeValue(buffer, value.index); - } else if (value is AddonDisabledReason) { + } else if (value is AddonDisabledReason) { buffer.putUint8(139); writeValue(buffer, value.index); - } else if (value is AddonIncognito) { + } else if (value is AddonIncognito) { buffer.putUint8(140); writeValue(buffer, value.index); - } else if (value is AddonUpdateStatus) { + } else if (value is AddonUpdateStatus) { buffer.putUint8(141); writeValue(buffer, value.index); - } else if (value is AddonStoreApp) { + } else if (value is AddonStoreApp) { buffer.putUint8(142); writeValue(buffer, value.index); - } else if (value is AddonStorePromoted) { + } else if (value is AddonStorePromoted) { buffer.putUint8(143); writeValue(buffer, value.index); - } else if (value is GeckoSuggestionType) { + } else if (value is GeckoSuggestionType) { buffer.putUint8(144); writeValue(buffer, value.index); - } else if (value is TrackingProtectionPolicy) { + } else if (value is TrackingProtectionPolicy) { buffer.putUint8(145); writeValue(buffer, value.index); - } else if (value is HttpsOnlyMode) { + } else if (value is HttpsOnlyMode) { buffer.putUint8(146); writeValue(buffer, value.index); - } else if (value is QueryParameterStripping) { + } else if (value is QueryParameterStripping) { buffer.putUint8(147); writeValue(buffer, value.index); - } else if (value is BounceTrackingProtectionMode) { + } else if (value is BounceTrackingProtectionMode) { buffer.putUint8(148); writeValue(buffer, value.index); - } else if (value is ColorScheme) { + } else if (value is ColorScheme) { buffer.putUint8(149); writeValue(buffer, value.index); - } else if (value is CookieBannerHandlingMode) { + } else if (value is CookieBannerHandlingMode) { buffer.putUint8(150); writeValue(buffer, value.index); - } else if (value is AppLinksMode) { + } else if (value is AppLinksMode) { buffer.putUint8(151); writeValue(buffer, value.index); - } else if (value is WebContentIsolationStrategy) { + } else if (value is WebContentIsolationStrategy) { buffer.putUint8(152); writeValue(buffer, value.index); - } else if (value is CustomCookiePolicy) { + } else if (value is CustomCookiePolicy) { buffer.putUint8(153); writeValue(buffer, value.index); - } else if (value is TrackingScope) { + } else if (value is TrackingScope) { buffer.putUint8(154); writeValue(buffer, value.index); - } else if (value is DohSettingsMode) { + } else if (value is DohSettingsMode) { buffer.putUint8(155); writeValue(buffer, value.index); - } else if (value is DownloadStatus) { + } else if (value is DownloadStatus) { buffer.putUint8(156); writeValue(buffer, value.index); - } else if (value is LogLevel) { + } else if (value is LogLevel) { buffer.putUint8(157); writeValue(buffer, value.index); - } else if (value is SyncEngineValue) { + } else if (value is SyncEngineValue) { buffer.putUint8(158); writeValue(buffer, value.index); - } else if (value is MlProgressType) { + } else if (value is MlProgressType) { buffer.putUint8(159); writeValue(buffer, value.index); - } else if (value is MlProgressStatus) { + } else if (value is MlProgressStatus) { buffer.putUint8(160); writeValue(buffer, value.index); - } else if (value is ClearDataType) { + } else if (value is ClearDataType) { buffer.putUint8(161); writeValue(buffer, value.index); - } else if (value is GeckoFetchMethod) { + } else if (value is GeckoFetchMethod) { buffer.putUint8(162); writeValue(buffer, value.index); - } else if (value is GeckoFetchRedircet) { + } else if (value is GeckoFetchRedircet) { buffer.putUint8(163); writeValue(buffer, value.index); - } else if (value is GeckoFetchCookiePolicy) { + } else if (value is GeckoFetchCookiePolicy) { buffer.putUint8(164); writeValue(buffer, value.index); - } else if (value is BookmarkNodeType) { + } else if (value is BookmarkNodeType) { buffer.putUint8(165); writeValue(buffer, value.index); - } else if (value is SitePermissionStatus) { + } else if (value is SitePermissionStatus) { buffer.putUint8(166); writeValue(buffer, value.index); - } else if (value is AutoplayStatus) { + } else if (value is AutoplayStatus) { buffer.putUint8(167); writeValue(buffer, value.index); - } else if (value is NativeAppLinkRuleDecision) { + } else if (value is NativeAppLinkRuleDecision) { buffer.putUint8(168); writeValue(buffer, value.index); - } else if (value is AppLinkPromptOwner) { + } else if (value is AppLinkPromptOwner) { buffer.putUint8(169); writeValue(buffer, value.index); - } else if (value is AppLinkDecision) { + } else if (value is AppLinkDecision) { buffer.putUint8(170); writeValue(buffer, value.index); - } else if (value is PushDistributorStatus) { + } else if (value is PushDistributorStatus) { buffer.putUint8(171); writeValue(buffer, value.index); - } else if (value is TranslationOptions) { + } else if (value is TranslationOptions) { buffer.putUint8(172); writeValue(buffer, value.encode()); - } else if (value is TranslationLanguage) { + } else if (value is TranslationLanguage) { buffer.putUint8(173); writeValue(buffer, value.encode()); - } else if (value is TranslationDetectedLanguages) { + } else if (value is TranslationDetectedLanguages) { buffer.putUint8(174); writeValue(buffer, value.encode()); - } else if (value is TranslationPair) { + } else if (value is TranslationPair) { buffer.putUint8(175); writeValue(buffer, value.encode()); - } else if (value is TranslationEngineStateData) { + } else if (value is TranslationEngineStateData) { buffer.putUint8(176); writeValue(buffer, value.encode()); - } else if (value is TabTranslationStateData) { + } else if (value is TabTranslationStateData) { buffer.putUint8(177); writeValue(buffer, value.encode()); - } else if (value is ReaderState) { + } else if (value is ReaderState) { buffer.putUint8(178); writeValue(buffer, value.encode()); - } else if (value is AddTabParams) { + } else if (value is AddTabParams) { buffer.putUint8(179); writeValue(buffer, value.encode()); - } else if (value is LastMediaAccessState) { + } else if (value is LastMediaAccessState) { buffer.putUint8(180); writeValue(buffer, value.encode()); - } else if (value is HistoryMetadataKey) { + } else if (value is HistoryMetadataKey) { buffer.putUint8(181); writeValue(buffer, value.encode()); - } else if (value is PackageCategoryValue) { + } else if (value is PackageCategoryValue) { buffer.putUint8(182); writeValue(buffer, value.encode()); - } else if (value is ExternalPackage) { + } else if (value is ExternalPackage) { buffer.putUint8(183); writeValue(buffer, value.encode()); - } else if (value is LoadUrlFlagsValue) { + } else if (value is LoadUrlFlagsValue) { buffer.putUint8(184); writeValue(buffer, value.encode()); - } else if (value is SourceValue) { + } else if (value is SourceValue) { buffer.putUint8(185); writeValue(buffer, value.encode()); - } else if (value is TabState) { + } else if (value is TabState) { buffer.putUint8(186); writeValue(buffer, value.encode()); - } else if (value is RecoverableTab) { + } else if (value is RecoverableTab) { buffer.putUint8(187); writeValue(buffer, value.encode()); - } else if (value is IconRequest) { + } else if (value is IconRequest) { buffer.putUint8(188); writeValue(buffer, value.encode()); - } else if (value is ResourceSize) { + } else if (value is ResourceSize) { buffer.putUint8(189); writeValue(buffer, value.encode()); - } else if (value is Resource) { + } else if (value is Resource) { buffer.putUint8(190); writeValue(buffer, value.encode()); - } else if (value is IconResult) { + } else if (value is IconResult) { buffer.putUint8(191); writeValue(buffer, value.encode()); - } else if (value is CookiePartitionKey) { + } else if (value is CookiePartitionKey) { buffer.putUint8(192); writeValue(buffer, value.encode()); - } else if (value is Cookie) { + } else if (value is Cookie) { buffer.putUint8(193); writeValue(buffer, value.encode()); - } else if (value is VisitInfo) { + } else if (value is VisitInfo) { buffer.putUint8(194); writeValue(buffer, value.encode()); - } else if (value is HistoryHighlightWeights) { + } else if (value is HistoryHighlightWeights) { buffer.putUint8(195); writeValue(buffer, value.encode()); - } else if (value is HistoryHighlight) { + } else if (value is HistoryHighlight) { buffer.putUint8(196); writeValue(buffer, value.encode()); - } else if (value is TopFrecentSiteInfo) { + } else if (value is TopFrecentSiteInfo) { buffer.putUint8(197); writeValue(buffer, value.encode()); - } else if (value is HistoryMetadata) { + } else if (value is HistoryMetadata) { buffer.putUint8(198); writeValue(buffer, value.encode()); - } else if (value is HistorySuggestion) { + } else if (value is HistorySuggestion) { buffer.putUint8(199); writeValue(buffer, value.encode()); - } else if (value is PageObservation) { + } else if (value is PageObservation) { buffer.putUint8(200); writeValue(buffer, value.encode()); - } else if (value is HistoryItem) { + } else if (value is HistoryItem) { buffer.putUint8(201); writeValue(buffer, value.encode()); - } else if (value is HistoryState) { + } else if (value is HistoryState) { buffer.putUint8(202); writeValue(buffer, value.encode()); - } else if (value is ReaderableState) { + } else if (value is ReaderableState) { buffer.putUint8(203); writeValue(buffer, value.encode()); - } else if (value is SecurityInfoState) { + } else if (value is SecurityInfoState) { buffer.putUint8(204); writeValue(buffer, value.encode()); - } else if (value is TabContentState) { + } else if (value is TabContentState) { buffer.putUint8(205); writeValue(buffer, value.encode()); - } else if (value is FindResultState) { + } else if (value is FindResultState) { buffer.putUint8(206); writeValue(buffer, value.encode()); - } else if (value is CustomSelectionAction) { + } else if (value is CustomSelectionAction) { buffer.putUint8(207); writeValue(buffer, value.encode()); - } else if (value is WebExtensionData) { + } else if (value is WebExtensionData) { buffer.putUint8(208); writeValue(buffer, value.encode()); - } else if (value is AddonInfo) { + } else if (value is AddonInfo) { buffer.putUint8(209); writeValue(buffer, value.encode()); - } else if (value is AddonListingPreview) { + } else if (value is AddonListingPreview) { buffer.putUint8(210); writeValue(buffer, value.encode()); - } else if (value is AddonListing) { + } else if (value is AddonListing) { buffer.putUint8(211); writeValue(buffer, value.encode()); - } else if (value is AddonStoreInfo) { + } else if (value is AddonStoreInfo) { buffer.putUint8(212); writeValue(buffer, value.encode()); - } else if (value is AddonUpdateAttemptInfo) { + } else if (value is AddonUpdateAttemptInfo) { buffer.putUint8(213); writeValue(buffer, value.encode()); - } else if (value is GeckoSuggestion) { + } else if (value is GeckoSuggestion) { buffer.putUint8(214); writeValue(buffer, value.encode()); - } else if (value is TabContent) { + } else if (value is TabContent) { buffer.putUint8(215); writeValue(buffer, value.encode()); - } else if (value is ContentBlocking) { + } else if (value is ContentBlocking) { buffer.putUint8(216); writeValue(buffer, value.encode()); - } else if (value is DohSettings) { + } else if (value is DohSettings) { buffer.putUint8(217); writeValue(buffer, value.encode()); - } else if (value is GeckoEngineSettings) { + } else if (value is GeckoEngineSettings) { buffer.putUint8(218); writeValue(buffer, value.encode()); - } else if (value is AutocompleteResult) { + } else if (value is AutocompleteResult) { buffer.putUint8(219); writeValue(buffer, value.encode()); - } else if (value is UnknownHitResult) { + } else if (value is UnknownHitResult) { buffer.putUint8(220); writeValue(buffer, value.encode()); - } else if (value is ImageHitResult) { + } else if (value is ImageHitResult) { buffer.putUint8(221); writeValue(buffer, value.encode()); - } else if (value is VideoHitResult) { + } else if (value is VideoHitResult) { buffer.putUint8(222); writeValue(buffer, value.encode()); - } else if (value is AudioHitResult) { + } else if (value is AudioHitResult) { buffer.putUint8(223); writeValue(buffer, value.encode()); - } else if (value is ImageSrcHitResult) { + } else if (value is ImageSrcHitResult) { buffer.putUint8(224); writeValue(buffer, value.encode()); - } else if (value is PhoneHitResult) { + } else if (value is PhoneHitResult) { buffer.putUint8(225); writeValue(buffer, value.encode()); - } else if (value is EmailHitResult) { + } else if (value is EmailHitResult) { buffer.putUint8(226); writeValue(buffer, value.encode()); - } else if (value is GeoHitResult) { + } else if (value is GeoHitResult) { buffer.putUint8(227); writeValue(buffer, value.encode()); - } else if (value is DownloadState) { + } else if (value is DownloadState) { buffer.putUint8(228); writeValue(buffer, value.encode()); - } else if (value is ShareInternetResourceState) { + } else if (value is ShareInternetResourceState) { buffer.putUint8(229); writeValue(buffer, value.encode()); - } else if (value is AddonCollection) { + } else if (value is AddonCollection) { buffer.putUint8(230); writeValue(buffer, value.encode()); - } else if (value is SyncEngineStatus) { + } else if (value is SyncEngineStatus) { buffer.putUint8(231); writeValue(buffer, value.encode()); - } else if (value is SyncAccountInfo) { + } else if (value is SyncAccountInfo) { buffer.putUint8(232); writeValue(buffer, value.encode()); - } else if (value is SyncDevice) { + } else if (value is SyncDevice) { buffer.putUint8(233); writeValue(buffer, value.encode()); - } else if (value is SyncIncomingTab) { + } else if (value is SyncIncomingTab) { buffer.putUint8(234); writeValue(buffer, value.encode()); - } else if (value is SyncRemoteTab) { + } else if (value is SyncRemoteTab) { buffer.putUint8(235); writeValue(buffer, value.encode()); - } else if (value is SyncDeviceTabs) { + } else if (value is SyncDeviceTabs) { buffer.putUint8(236); writeValue(buffer, value.encode()); - } else if (value is GeckoPref) { + } else if (value is GeckoPref) { buffer.putUint8(237); writeValue(buffer, value.encode()); - } else if (value is MlProgressData) { + } else if (value is MlProgressData) { buffer.putUint8(238); writeValue(buffer, value.encode()); - } else if (value is GeckoProxySettings) { + } else if (value is GeckoProxySettings) { buffer.putUint8(239); writeValue(buffer, value.encode()); - } else if (value is ContainerSiteAssignment) { + } else if (value is ContainerSiteAssignment) { buffer.putUint8(240); writeValue(buffer, value.encode()); - } else if (value is ProxyLoadError) { + } else if (value is ProxyLoadError) { buffer.putUint8(241); writeValue(buffer, value.encode()); - } else if (value is GeckoHeader) { + } else if (value is GeckoHeader) { buffer.putUint8(242); writeValue(buffer, value.encode()); - } else if (value is GeckoFetchRequest) { + } else if (value is GeckoFetchRequest) { buffer.putUint8(243); writeValue(buffer, value.encode()); - } else if (value is GeckoFetchResponse) { + } else if (value is GeckoFetchResponse) { buffer.putUint8(244); writeValue(buffer, value.encode()); - } else if (value is BookmarkNode) { + } else if (value is BookmarkNode) { buffer.putUint8(245); writeValue(buffer, value.encode()); - } else if (value is BookmarkInfo) { + } else if (value is BookmarkImportNode) { buffer.putUint8(246); writeValue(buffer, value.encode()); - } else if (value is SitePermissions) { + } else if (value is BookmarkInsertTreeResult) { buffer.putUint8(247); writeValue(buffer, value.encode()); - } else if (value is TrackingProtectionException) { + } else if (value is BookmarkInfo) { buffer.putUint8(248); writeValue(buffer, value.encode()); - } else if (value is AppLinkTarget) { + } else if (value is SitePermissions) { buffer.putUint8(249); writeValue(buffer, value.encode()); - } else if (value is ProtectedTargetPattern) { + } else if (value is TrackingProtectionException) { buffer.putUint8(250); writeValue(buffer, value.encode()); - } else if (value is NativeAppLinkRule) { + } else if (value is AppLinkTarget) { buffer.putUint8(251); writeValue(buffer, value.encode()); - } else if (value is NativeContextAppLinkPolicy) { + } else if (value is ProtectedTargetPattern) { buffer.putUint8(252); writeValue(buffer, value.encode()); - } else if (value is AppLinkPolicySnapshot) { + } else if (value is NativeAppLinkRule) { buffer.putUint8(253); writeValue(buffer, value.encode()); - } else if (value is AppLinkPromptRequest) { + } else if (value is NativeContextAppLinkPolicy) { buffer.putUint8(254); writeValue(buffer, value.encode()); - } else if (value is AppLinkResolutionResult) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 0, wrapped: value.encode()); + } else if (value is AppLinkPolicySnapshot) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 0, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is PwaIcon) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 1, wrapped: value.encode()); + } else if (value is AppLinkPromptRequest) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 1, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is ShareTargetFiles) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 2, wrapped: value.encode()); + } else if (value is AppLinkResolutionResult) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 2, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is ShareTargetParams) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 3, wrapped: value.encode()); + } else if (value is PwaIcon) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 3, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is ShareTarget) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 4, wrapped: value.encode()); + } else if (value is ShareTargetFiles) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 4, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is ExternalApplicationResource) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 5, wrapped: value.encode()); + } else if (value is ShareTargetParams) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 5, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is PwaManifest) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 6, wrapped: value.encode()); + } else if (value is ShareTarget) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 6, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is SandboxCaptureEntry) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 7, wrapped: value.encode()); + } else if (value is ExternalApplicationResource) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 7, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is GestureConfig) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 8, wrapped: value.encode()); + } else if (value is PwaManifest) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 8, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is PushDistributor) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 9, wrapped: value.encode()); + } else if (value is SandboxCaptureEntry) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 9, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is PushStatus) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 10, wrapped: value.encode()); + } else if (value is GestureConfig) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 10, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); - } else if (value is PushSubscription) { - final _PigeonCodecOverflow wrap = _PigeonCodecOverflow(type: 11, wrapped: value.encode()); + } else if (value is PushDistributor) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 11, + wrapped: value.encode(), + ); + buffer.putUint8(255); + writeValue(buffer, wrap.encode()); + } else if (value is PushStatus) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 12, + wrapped: value.encode(), + ); + buffer.putUint8(255); + writeValue(buffer, wrap.encode()); + } else if (value is PushSubscription) { + final _PigeonCodecOverflow wrap = _PigeonCodecOverflow( + type: 13, + wrapped: value.encode(), + ); buffer.putUint8(255); writeValue(buffer, wrap.encode()); } else { @@ -7780,7 +8111,9 @@ class _PigeonCodec extends StandardMessageCodec { return value == null ? null : QueryParameterStripping.values[value]; case 148: final value = readValue(buffer) as int?; - return value == null ? null : BounceTrackingProtectionMode.values[value]; + return value == null + ? null + : BounceTrackingProtectionMode.values[value]; case 149: final value = readValue(buffer) as int?; return value == null ? null : ColorScheme.values[value]; @@ -7999,25 +8332,27 @@ class _PigeonCodec extends StandardMessageCodec { case 245: return BookmarkNode.decode(readValue(buffer)!); case 246: - return BookmarkInfo.decode(readValue(buffer)!); + return BookmarkImportNode.decode(readValue(buffer)!); case 247: - return SitePermissions.decode(readValue(buffer)!); + return BookmarkInsertTreeResult.decode(readValue(buffer)!); case 248: - return TrackingProtectionException.decode(readValue(buffer)!); + return BookmarkInfo.decode(readValue(buffer)!); case 249: - return AppLinkTarget.decode(readValue(buffer)!); + return SitePermissions.decode(readValue(buffer)!); case 250: - return ProtectedTargetPattern.decode(readValue(buffer)!); + return TrackingProtectionException.decode(readValue(buffer)!); case 251: - return NativeAppLinkRule.decode(readValue(buffer)!); + return AppLinkTarget.decode(readValue(buffer)!); case 252: - return NativeContextAppLinkPolicy.decode(readValue(buffer)!); + return ProtectedTargetPattern.decode(readValue(buffer)!); case 253: - return AppLinkPolicySnapshot.decode(readValue(buffer)!); + return NativeAppLinkRule.decode(readValue(buffer)!); case 254: - return AppLinkPromptRequest.decode(readValue(buffer)!); + return NativeContextAppLinkPolicy.decode(readValue(buffer)!); case 255: - final _PigeonCodecOverflow wrapper = _PigeonCodecOverflow.decode(readValue(buffer)!); + final _PigeonCodecOverflow wrapper = _PigeonCodecOverflow.decode( + readValue(buffer)!, + ); return wrapper.unwrap(); default: return super.readValueOfType(type, buffer); @@ -8029,9 +8364,13 @@ class GeckoBrowserApi { /// Constructor for [GeckoBrowserApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoBrowserApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoBrowserApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -8039,7 +8378,8 @@ class GeckoBrowserApi { final String pigeonVar_messageChannelSuffix; Future getGeckoVersion() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.getGeckoVersion$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.getGeckoVersion$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8049,34 +8389,55 @@ class GeckoBrowserApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } - Future initialize(String profileFolder, LogLevel logLevel, ContentBlocking contentBlocking, AddonCollection? addonCollection, String? fxaServerOverride, String? syncTokenServerOverride, GeckoEngineSettings? startupSettings, String? startupUBlockFilterListsPref, bool clearStartupUBlockFilterListsPref) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.initialize$pigeonVar_messageChannelSuffix'; + Future initialize( + String profileFolder, + LogLevel logLevel, + ContentBlocking contentBlocking, + AddonCollection? addonCollection, + String? fxaServerOverride, + String? syncTokenServerOverride, + GeckoEngineSettings? startupSettings, + String? startupUBlockFilterListsPref, + bool clearStartupUBlockFilterListsPref, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.initialize$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([profileFolder, logLevel, contentBlocking, addonCollection, fxaServerOverride, syncTokenServerOverride, startupSettings, startupUBlockFilterListsPref, clearStartupUBlockFilterListsPref]); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([ + profileFolder, + logLevel, + contentBlocking, + addonCollection, + fxaServerOverride, + syncTokenServerOverride, + startupSettings, + startupUBlockFilterListsPref, + clearStartupUBlockFilterListsPref, + ]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future showNativeFragment() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.showNativeFragment$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.showNativeFragment$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8086,52 +8447,60 @@ class GeckoBrowserApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } Future onTrimMemory(int level) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.onTrimMemory$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.onTrimMemory$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([level]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [level], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future openInCustomTab({required String url, required bool private, required String? contextId, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.openInCustomTab$pigeonVar_messageChannelSuffix'; + Future openInCustomTab({ + required String url, + required bool private, + required String? contextId, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.openInCustomTab$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url, private, contextId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url, private, contextId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future isDefaultBrowser() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.isDefaultBrowser$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.isDefaultBrowser$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8141,16 +8510,16 @@ class GeckoBrowserApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } Future requestDefaultBrowser() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.requestDefaultBrowser$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.requestDefaultBrowser$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8160,15 +8529,15 @@ class GeckoBrowserApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future shutdown() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.shutdown$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.shutdown$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8178,11 +8547,10 @@ class GeckoBrowserApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -8190,9 +8558,13 @@ class GeckoSyncApi { /// Constructor for [GeckoSyncApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoSyncApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoSyncApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -8200,7 +8572,8 @@ class GeckoSyncApi { final String pigeonVar_messageChannelSuffix; Future getAccountInfo() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.getAccountInfo$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.getAccountInfo$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8210,16 +8583,16 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as SyncAccountInfo; } Future beginAuthentication() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.beginAuthentication$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.beginAuthentication$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8229,33 +8602,35 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future beginPairingAuthentication(String pairingUrl) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.beginPairingAuthentication$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.beginPairingAuthentication$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([pairingUrl]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pairingUrl], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future logout() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.logout$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.logout$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8265,15 +8640,15 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future syncNow() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.syncNow$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.syncNow$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8283,33 +8658,35 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setEngineEnabled(SyncEngineValue engine, bool enabled) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.setEngineEnabled$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.setEngineEnabled$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([engine, enabled]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [engine, enabled], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future> getSyncedTabs() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.getSyncedTabs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.getSyncedTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8319,16 +8696,16 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } Future> getDevices() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.getDevices$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.getDevices$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8338,35 +8715,42 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } - Future sendTabToDevice(String deviceId, String title, String url, bool private) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.sendTabToDevice$pigeonVar_messageChannelSuffix'; + Future sendTabToDevice( + String deviceId, + String title, + String url, + bool private, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.sendTabToDevice$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([deviceId, title, url, private]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [deviceId, title, url, private], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } Future refreshDevices() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.refreshDevices$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.refreshDevices$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8376,15 +8760,15 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future pollDeviceCommands() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.pollDeviceCommands$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.pollDeviceCommands$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8394,15 +8778,15 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future> drainIncomingTabs() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.drainIncomingTabs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.drainIncomingTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8412,16 +8796,16 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } Future getDeviceName() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.getDeviceName$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.getDeviceName$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8431,30 +8815,31 @@ class GeckoSyncApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as String?; } Future setDeviceName(String newName) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.setDeviceName$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncApi.setDeviceName$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([newName]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [newName], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } } @@ -8463,9 +8848,13 @@ class GeckoEngineSettingsApi { /// Constructor for [GeckoEngineSettingsApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoEngineSettingsApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoEngineSettingsApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -8473,99 +8862,110 @@ class GeckoEngineSettingsApi { final String pigeonVar_messageChannelSuffix; Future setDefaultSettings(GeckoEngineSettings settings) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setDefaultSettings$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setDefaultSettings$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([settings]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [settings], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future updateRuntimeSettings(GeckoEngineSettings settings) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.updateRuntimeSettings$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.updateRuntimeSettings$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([settings]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [settings], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setScreenshotProtectionEnabled(bool enabled) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setScreenshotProtectionEnabled$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setScreenshotProtectionEnabled$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([enabled]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enabled], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setPullToRefreshEnabled(bool enabled) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setPullToRefreshEnabled$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setPullToRefreshEnabled$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([enabled]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enabled], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Sets whether to use external download managers for downloads. /// When enabled, downloads are forwarded to third-party apps like ADM, 1DM, AB DM. Future setUseExternalDownloadManager(bool enabled) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setUseExternalDownloadManager$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setUseExternalDownloadManager$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([enabled]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enabled], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future getUseExternalDownloadManager() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.getUseExternalDownloadManager$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.getUseExternalDownloadManager$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8575,11 +8975,10 @@ class GeckoEngineSettingsApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } @@ -8591,22 +8990,27 @@ class GeckoEngineSettingsApi { /// currently open tabs (loaded tabs are reloaded, suspended tabs are updated /// in place). This should only be requested for an explicit user toggle, not /// during startup/replication restore, to avoid clobbering per-tab overrides. - Future setGlobalDesktopMode(bool enable, bool applyToExistingTabs) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setGlobalDesktopMode$pigeonVar_messageChannelSuffix'; + Future setGlobalDesktopMode( + bool enable, + bool applyToExistingTabs, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setGlobalDesktopMode$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([enable, applyToExistingTabs]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enable, applyToExistingTabs], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Sets whether the reader view dark color scheme should be rendered as pure @@ -8614,21 +9018,23 @@ class GeckoEngineSettingsApi { /// Mozilla's reader view extension. Persisted in SharedPreferences so a /// cold-started reader view resolves the right value before Flutter runs. Future setReaderViewPureBlack(bool enabled) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setReaderViewPureBlack$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setReaderViewPureBlack$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([enabled]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enabled], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// The set of Gecko contextual-identity ids ("container" contextIds) whose @@ -8636,21 +9042,23 @@ class GeckoEngineSettingsApi { /// exclude-from-history / "incognito container"). WebLibreHistoryDelegate /// skips the Places write for a visit resolved to one of these containers. Future setExcludedHistoryContextIds(List contextIds) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setExcludedHistoryContextIds$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setExcludedHistoryContextIds$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contextIds]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contextIds], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -8658,269 +9066,332 @@ class GeckoSessionApi { /// Constructor for [GeckoSessionApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoSessionApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoSessionApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); final String pigeonVar_messageChannelSuffix; - Future loadUrl({required String? tabId, required String url, required LoadUrlFlagsValue flags, required Map? additionalHeaders, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.loadUrl$pigeonVar_messageChannelSuffix'; + Future loadUrl({ + required String? tabId, + required String url, + required LoadUrlFlagsValue flags, + required Map? additionalHeaders, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.loadUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, url, flags, additionalHeaders]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, url, flags, additionalHeaders], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future loadData({required String? tabId, required String data, required String mimeType, required String encoding, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.loadData$pigeonVar_messageChannelSuffix'; + Future loadData({ + required String? tabId, + required String data, + required String mimeType, + required String encoding, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.loadData$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, data, mimeType, encoding]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, data, mimeType, encoding], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future reload({required String? tabId, required LoadUrlFlagsValue flags}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.reload$pigeonVar_messageChannelSuffix'; + Future reload({ + required String? tabId, + required LoadUrlFlagsValue flags, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.reload$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, flags]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, flags], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future stopLoading({required String? tabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.stopLoading$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.stopLoading$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future goBack({required String? tabId, required bool userInteraction}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.goBack$pigeonVar_messageChannelSuffix'; + Future goBack({ + required String? tabId, + required bool userInteraction, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.goBack$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, userInteraction]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, userInteraction], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future goForward({required String? tabId, required bool userInteraction}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.goForward$pigeonVar_messageChannelSuffix'; + Future goForward({ + required String? tabId, + required bool userInteraction, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.goForward$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, userInteraction]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, userInteraction], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future goToHistoryIndex({required int index, required String? tabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.goToHistoryIndex$pigeonVar_messageChannelSuffix'; + Future goToHistoryIndex({ + required int index, + required String? tabId, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.goToHistoryIndex$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([index, tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [index, tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future requestDesktopSite({required String? tabId, required bool enable}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.requestDesktopSite$pigeonVar_messageChannelSuffix'; + Future requestDesktopSite({ + required String? tabId, + required bool enable, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.requestDesktopSite$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, enable]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, enable], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future exitFullscreen({required String? tabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.exitFullscreen$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.exitFullscreen$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future saveToPdf({required String? tabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.saveToPdf$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.saveToPdf$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future printContent({required String? tabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.printContent$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.printContent$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future translate({required String? tabId, required String fromLanguage, required String toLanguage, required TranslationOptions? options, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.translate$pigeonVar_messageChannelSuffix'; + Future translate({ + required String? tabId, + required String fromLanguage, + required String toLanguage, + required TranslationOptions? options, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.translate$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, fromLanguage, toLanguage, options]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, fromLanguage, toLanguage, options], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future translateRestore({required String? tabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.translateRestore$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.translateRestore$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future crashRecovery({required List? tabIds}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.crashRecovery$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.crashRecovery$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabIds]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabIds], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future purgeHistory() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.purgeHistory$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.purgeHistory$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -8930,66 +9401,74 @@ class GeckoSessionApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future updateLastAccess({required String? tabId, required int? lastAccess}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.updateLastAccess$pigeonVar_messageChannelSuffix'; + Future updateLastAccess({ + required String? tabId, + required int? lastAccess, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.updateLastAccess$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, lastAccess]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, lastAccess], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future requestScreenshot(bool sendBack) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.requestScreenshot$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.requestScreenshot$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([sendBack]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [sendBack], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as Uint8List?; } Future dispatchKeyEvent({required int keyCode}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.dispatchKeyEvent$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSessionApi.dispatchKeyEvent$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([keyCode]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [keyCode], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -8997,145 +9476,219 @@ class GeckoTabsApi { /// Constructor for [GeckoTabsApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoTabsApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoTabsApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); final String pigeonVar_messageChannelSuffix; - Future syncEvents({required bool onSelectedTabChange, required bool onTabListChange, required bool onRestoreComplete, required bool onTabContentStateChange, required bool onIconChange, required bool onSecurityInfoStateChange, required bool onReaderableStateChange, required bool onHistoryStateChange, required bool onFindResults, required bool onThumbnailChange, required bool onBrowserExtensionsChange, required bool onPageExtensionsChange, required bool onBrowserExtensionIcons, required bool onPageExtensionIcons, required bool onTranslationStateChange, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.syncEvents$pigeonVar_messageChannelSuffix'; + Future syncEvents({ + required bool onSelectedTabChange, + required bool onTabListChange, + required bool onRestoreComplete, + required bool onTabContentStateChange, + required bool onIconChange, + required bool onSecurityInfoStateChange, + required bool onReaderableStateChange, + required bool onHistoryStateChange, + required bool onFindResults, + required bool onThumbnailChange, + required bool onBrowserExtensionsChange, + required bool onPageExtensionsChange, + required bool onBrowserExtensionIcons, + required bool onPageExtensionIcons, + required bool onTranslationStateChange, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.syncEvents$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([onSelectedTabChange, onTabListChange, onRestoreComplete, onTabContentStateChange, onIconChange, onSecurityInfoStateChange, onReaderableStateChange, onHistoryStateChange, onFindResults, onThumbnailChange, onBrowserExtensionsChange, onPageExtensionsChange, onBrowserExtensionIcons, onPageExtensionIcons, onTranslationStateChange]); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([ + onSelectedTabChange, + onTabListChange, + onRestoreComplete, + onTabContentStateChange, + onIconChange, + onSecurityInfoStateChange, + onReaderableStateChange, + onHistoryStateChange, + onFindResults, + onThumbnailChange, + onBrowserExtensionsChange, + onPageExtensionsChange, + onBrowserExtensionIcons, + onPageExtensionIcons, + onTranslationStateChange, + ]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future selectTab({required String tabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.selectTab$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.selectTab$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future removeTab({required String tabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removeTab$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removeTab$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future addTab({required String url, required bool selectTab, required bool startLoading, required String? parentId, required LoadUrlFlagsValue flags, required String? contextId, required SourceValue source, required bool private, required HistoryMetadataKey? historyMetadata, required Map? additionalHeaders, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.addTab$pigeonVar_messageChannelSuffix'; + Future addTab({ + required String url, + required bool selectTab, + required bool startLoading, + required String? parentId, + required LoadUrlFlagsValue flags, + required String? contextId, + required SourceValue source, + required bool private, + required HistoryMetadataKey? historyMetadata, + required Map? additionalHeaders, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.addTab$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url, selectTab, startLoading, parentId, flags, contextId, source, private, historyMetadata, additionalHeaders]); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([ + url, + selectTab, + startLoading, + parentId, + flags, + contextId, + source, + private, + historyMetadata, + additionalHeaders, + ]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } - Future> addMultipleTabs({required List tabs, required String? selectTabId}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.addMultipleTabs$pigeonVar_messageChannelSuffix'; + Future> addMultipleTabs({ + required List tabs, + required String? selectTabId, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.addMultipleTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabs, selectTabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabs, selectTabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } Future removeAllTabs({required bool recoverable}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removeAllTabs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removeAllTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([recoverable]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [recoverable], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future removeTabs({required List ids}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removeTabs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removeTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([ids]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [ids], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future removeNormalTabs() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removeNormalTabs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removeNormalTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -9145,15 +9698,15 @@ class GeckoTabsApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future removePrivateTabs() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removePrivateTabs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.removePrivateTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -9163,15 +9716,15 @@ class GeckoTabsApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future undo() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.undo$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.undo$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -9181,125 +9734,160 @@ class GeckoTabsApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future restoreTabsByList({required List tabs, required String? selectTabId, required RestoreLocation restoreLocation, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.restoreTabsByList$pigeonVar_messageChannelSuffix'; + Future restoreTabsByList({ + required List tabs, + required String? selectTabId, + required RestoreLocation restoreLocation, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.restoreTabsByList$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabs, selectTabId, restoreLocation]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabs, selectTabId, restoreLocation], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Selects an already existing tab with the matching [HistoryMetadataKey] or otherwise /// creates a new tab with the given [url]. - Future selectOrAddTabByHistory({required String url, required HistoryMetadataKey historyMetadata}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.selectOrAddTabByHistory$pigeonVar_messageChannelSuffix'; + Future selectOrAddTabByHistory({ + required String url, + required HistoryMetadataKey historyMetadata, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.selectOrAddTabByHistory$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url, historyMetadata]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url, historyMetadata], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } /// Selects an already existing tab displaying [url] or otherwise creates a new tab. - Future selectOrAddTabByUrl({required String url, required bool private, required SourceValue source, required LoadUrlFlagsValue flags, required bool ignoreFragment, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.selectOrAddTabByUrl$pigeonVar_messageChannelSuffix'; + Future selectOrAddTabByUrl({ + required String url, + required bool private, + required SourceValue source, + required LoadUrlFlagsValue flags, + required bool ignoreFragment, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.selectOrAddTabByUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url, private, source, flags, ignoreFragment]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url, private, source, flags, ignoreFragment], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } - Future duplicateTab({required String? selectTabId, required bool selectNewTab, required String? newContextId, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.duplicateTab$pigeonVar_messageChannelSuffix'; + Future duplicateTab({ + required String? selectTabId, + required bool selectNewTab, + required String? newContextId, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.duplicateTab$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([selectTabId, selectNewTab, newContextId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [selectTabId, selectNewTab, newContextId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } - Future moveTabs({required List tabIds, required String targetTabId, required bool placeAfter, }) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.moveTabs$pigeonVar_messageChannelSuffix'; + Future moveTabs({ + required List tabIds, + required String targetTabId, + required bool placeAfter, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.moveTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabIds, targetTabId, placeAfter]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabIds, targetTabId, placeAfter], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future migratePrivateTabUseCase({required String tabId, required String? alternativeUrl}) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.migratePrivateTabUseCase$pigeonVar_messageChannelSuffix'; + Future migratePrivateTabUseCase({ + required String tabId, + required String? alternativeUrl, + }) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabsApi.migratePrivateTabUseCase$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, alternativeUrl]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, alternativeUrl], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } } @@ -9308,9 +9896,13 @@ class GeckoFindApi { /// Constructor for [GeckoFindApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoFindApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoFindApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -9318,57 +9910,63 @@ class GeckoFindApi { final String pigeonVar_messageChannelSuffix; Future findAll(String? tabId, String text) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoFindApi.findAll$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoFindApi.findAll$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, text]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, text], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future findNext(String? tabId, bool forward) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoFindApi.findNext$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoFindApi.findNext$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, forward]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, forward], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future clearMatches(String? tabId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoFindApi.clearMatches$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoFindApi.clearMatches$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -9376,9 +9974,13 @@ class GeckoIconsApi { /// Constructor for [GeckoIconsApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoIconsApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoIconsApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -9386,21 +9988,23 @@ class GeckoIconsApi { final String pigeonVar_messageChannelSuffix; Future loadIcon(IconRequest request) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoIconsApi.loadIcon$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoIconsApi.loadIcon$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([request]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [request], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as IconResult; } } @@ -9409,9 +10013,13 @@ class GeckoPrefApi { /// Constructor for [GeckoPrefApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoPrefApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoPrefApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -9419,63 +10027,72 @@ class GeckoPrefApi { final String pigeonVar_messageChannelSuffix; Future> getPrefs(List preferenceFilter) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.getPrefs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.getPrefs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([preferenceFilter]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [preferenceFilter], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; - return (pigeonVar_replyValue! as Map).cast(); + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } Future> applyPrefs(Map prefs) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.applyPrefs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.applyPrefs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([prefs]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [prefs], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; - return (pigeonVar_replyValue! as Map).cast(); + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } Future resetPrefs(List preferenceNames) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.resetPrefs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.resetPrefs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([preferenceNames]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [preferenceNames], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future startObserveChanges() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.startObserveChanges$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.startObserveChanges$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -9485,15 +10102,15 @@ class GeckoPrefApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future stopObserveChanges() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.stopObserveChanges$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.stopObserveChanges$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -9503,47 +10120,50 @@ class GeckoPrefApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future registerPrefForObservation(String name) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.registerPrefForObservation$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.registerPrefForObservation$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([name]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [name], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future unregisterPrefForObservation(String name) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.unregisterPrefForObservation$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPrefApi.unregisterPrefForObservation$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([name]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [name], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -9551,9 +10171,13 @@ class GeckoMlApi { /// Constructor for [GeckoMlApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoMlApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoMlApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -9561,45 +10185,52 @@ class GeckoMlApi { final String pigeonVar_messageChannelSuffix; Future predictDocumentTopic(List documents) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoMlApi.predictDocumentTopic$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoMlApi.predictDocumentTopic$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([documents]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [documents], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } - Future> generateDocumentEmbeddings(List documents) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoMlApi.generateDocumentEmbeddings$pigeonVar_messageChannelSuffix'; + Future> generateDocumentEmbeddings( + List documents, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoMlApi.generateDocumentEmbeddings$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([documents]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [documents], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as List; } Future clearMlCache() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoMlApi.clearMlCache$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoMlApi.clearMlCache$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -9609,11 +10240,10 @@ class GeckoMlApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -9621,9 +10251,13 @@ class GeckoBrowserExtensionApi { /// Constructor for [GeckoBrowserExtensionApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoBrowserExtensionApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoBrowserExtensionApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -9631,21 +10265,23 @@ class GeckoBrowserExtensionApi { final String pigeonVar_messageChannelSuffix; Future> getMarkdown(List htmlList) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserExtensionApi.getMarkdown$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserExtensionApi.getMarkdown$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([htmlList]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [htmlList], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } } @@ -9654,9 +10290,13 @@ class GeckoContainerProxyApi { /// Constructor for [GeckoContainerProxyApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoContainerProxyApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoContainerProxyApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -9664,183 +10304,209 @@ class GeckoContainerProxyApi { final String pigeonVar_messageChannelSuffix; Future setProxyPort(int port) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setProxyPort$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setProxyPort$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([port]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [port], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future addContainerProxy(String contextId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.addContainerProxy$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.addContainerProxy$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contextId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contextId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future removeContainerProxy(String contextId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.removeContainerProxy$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.removeContainerProxy$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contextId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contextId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future upsertProxy(GeckoProxySettings proxy) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.upsertProxy$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.upsertProxy$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([proxy]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [proxy], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future removeProxy(String proxyId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.removeProxy$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.removeProxy$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([proxyId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [proxyId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setContainerProxy(String contextId, String proxyId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setContainerProxy$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setContainerProxy$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contextId, proxyId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contextId, proxyId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future setContainerDirectConnection(String contextId, String scopeId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setContainerDirectConnection$pigeonVar_messageChannelSuffix'; + Future setContainerDirectConnection( + String contextId, + String scopeId, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setContainerDirectConnection$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contextId, scopeId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contextId, scopeId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future clearContainerProxy(String contextId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.clearContainerProxy$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.clearContainerProxy$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contextId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contextId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future removeContainerProxyRelation(String contextId, String proxyId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.removeContainerProxyRelation$pigeonVar_messageChannelSuffix'; + Future removeContainerProxyRelation( + String contextId, + String proxyId, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.removeContainerProxyRelation$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contextId, proxyId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contextId, proxyId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setSiteAssignments(Map assignments) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setSiteAssignments$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setSiteAssignments$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([assignments]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [assignments], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Strict-mode enforcement map. Keys are Gecko cookie-store contexts to @@ -9851,25 +10517,28 @@ class GeckoContainerProxyApi { /// equivalence); any other top-level navigation is cancelled and reported /// back with `strict = true`. Future setStrictContexts(Map> contexts) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setStrictContexts$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.setStrictContexts$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contexts]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contexts], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future healthcheck() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.healthcheck$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoContainerProxyApi.healthcheck$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -9879,11 +10548,10 @@ class GeckoContainerProxyApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } } @@ -9892,87 +10560,143 @@ class GeckoCookieApi { /// Constructor for [GeckoCookieApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoCookieApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoCookieApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); final String pigeonVar_messageChannelSuffix; - Future getCookie(String? firstPartyDomain, String name, CookiePartitionKey? partitionKey, String? storeId, String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoCookieApi.getCookie$pigeonVar_messageChannelSuffix'; + Future getCookie( + String? firstPartyDomain, + String name, + CookiePartitionKey? partitionKey, + String? storeId, + String url, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoCookieApi.getCookie$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([firstPartyDomain, name, partitionKey, storeId, url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [firstPartyDomain, name, partitionKey, storeId, url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as Cookie; } - Future> getAllCookies(String? domain, String? firstPartyDomain, String? name, CookiePartitionKey? partitionKey, String? storeId, String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoCookieApi.getAllCookies$pigeonVar_messageChannelSuffix'; + Future> getAllCookies( + String? domain, + String? firstPartyDomain, + String? name, + CookiePartitionKey? partitionKey, + String? storeId, + String url, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoCookieApi.getAllCookies$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([domain, firstPartyDomain, name, partitionKey, storeId, url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [domain, firstPartyDomain, name, partitionKey, storeId, url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } - Future setCookie(String? domain, int? expirationDate, String? firstPartyDomain, bool? httpOnly, String? name, CookiePartitionKey? partitionKey, String? path, CookieSameSiteStatus? sameSite, bool? secure, String? storeId, String url, String? value) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoCookieApi.setCookie$pigeonVar_messageChannelSuffix'; + Future setCookie( + String? domain, + int? expirationDate, + String? firstPartyDomain, + bool? httpOnly, + String? name, + CookiePartitionKey? partitionKey, + String? path, + CookieSameSiteStatus? sameSite, + bool? secure, + String? storeId, + String url, + String? value, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoCookieApi.setCookie$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([domain, expirationDate, firstPartyDomain, httpOnly, name, partitionKey, path, sameSite, secure, storeId, url, value]); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([ + domain, + expirationDate, + firstPartyDomain, + httpOnly, + name, + partitionKey, + path, + sameSite, + secure, + storeId, + url, + value, + ]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future removeCookie(String? firstPartyDomain, String name, CookiePartitionKey? partitionKey, String? storeId, String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoCookieApi.removeCookie$pigeonVar_messageChannelSuffix'; + Future removeCookie( + String? firstPartyDomain, + String name, + CookiePartitionKey? partitionKey, + String? storeId, + String url, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoCookieApi.removeCookie$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([firstPartyDomain, name, partitionKey, storeId, url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [firstPartyDomain, name, partitionKey, storeId, url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -10001,7 +10725,11 @@ abstract class GeckoStateEvents { void onReaderableStateChange(int sequence, String id, ReaderableState state); - void onSecurityInfoStateChange(int sequence, String id, SecurityInfoState state); + void onSecurityInfoStateChange( + int sequence, + String id, + SecurityInfoState state, + ); void onIconChange(int sequence, String id, Uint8List? bytes); @@ -10023,16 +10751,27 @@ abstract class GeckoStateEvents { void onManifestUpdate(int sequence, String tabId, PwaManifest? manifest); - void onTranslationEngineStateChange(int sequence, TranslationEngineStateData state); + void onTranslationEngineStateChange( + int sequence, + TranslationEngineStateData state, + ); void onTabTranslationStateChange(int sequence, TabTranslationStateData state); - static void setUp(GeckoStateEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoStateEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onViewReadyStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onViewReadyStateChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10045,16 +10784,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onEngineReadyStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onEngineReadyStateChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10067,16 +10810,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onIconUpdate$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onIconUpdate$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10090,16 +10837,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTabAdded$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTabAdded$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10112,38 +10863,47 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTabListChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTabListChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; final int arg_sequence = args[0]! as int; - final List arg_tabIds = (args[1]! as List).cast(); + final List arg_tabIds = (args[1]! as List) + .cast(); try { api.onTabListChange(arg_sequence, arg_tabIds); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onSelectedTabChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onSelectedTabChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10156,16 +10916,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onRestoreCompleteChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onRestoreCompleteChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10178,16 +10942,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTabContentStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTabContentStateChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10200,16 +10968,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onHistoryStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onHistoryStateChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10223,16 +10995,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onReaderableStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onReaderableStateChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10246,16 +11022,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onSecurityInfoStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onSecurityInfoStateChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10269,16 +11049,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onIconChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onIconChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10292,16 +11076,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onThumbnailChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onThumbnailChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10315,16 +11103,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onFindResults$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onFindResults$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10332,22 +11124,27 @@ abstract class GeckoStateEvents { final List args = message! as List; final int arg_sequence = args[0]! as int; final String arg_id = args[1]! as String; - final List arg_results = (args[2]! as List).cast(); + final List arg_results = (args[2]! as List) + .cast(); try { api.onFindResults(arg_sequence, arg_id, arg_results); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onLongPress$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onLongPress$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10361,16 +11158,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onPreferenceChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onPreferenceChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10383,38 +11184,47 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onContainerSiteAssignment$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onContainerSiteAssignment$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; final int arg_sequence = args[0]! as int; - final ContainerSiteAssignment arg_details = args[1]! as ContainerSiteAssignment; + final ContainerSiteAssignment arg_details = + args[1]! as ContainerSiteAssignment; try { api.onContainerSiteAssignment(arg_sequence, arg_details); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onProxyLoadError$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onProxyLoadError$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10427,16 +11237,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onMlProgress$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onMlProgress$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10449,16 +11263,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onDownloadStopped$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onDownloadStopped$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10471,16 +11289,20 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onManifestUpdate$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onManifestUpdate$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10494,52 +11316,64 @@ abstract class GeckoStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTranslationEngineStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTranslationEngineStateChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; final int arg_sequence = args[0]! as int; - final TranslationEngineStateData arg_state = args[1]! as TranslationEngineStateData; + final TranslationEngineStateData arg_state = + args[1]! as TranslationEngineStateData; try { api.onTranslationEngineStateChange(arg_sequence, arg_state); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTabTranslationStateChange$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onTabTranslationStateChange$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; final int arg_sequence = args[0]! as int; - final TabTranslationStateData arg_state = args[1]! as TabTranslationStateData; + final TabTranslationStateData arg_state = + args[1]! as TabTranslationStateData; try { api.onTabTranslationStateChange(arg_sequence, arg_state); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -10558,12 +11392,20 @@ abstract class GeckoSyncStateEvents { void onSyncError(int sequence, String? errorMessage); - static void setUp(GeckoSyncStateEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoSyncStateEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncStateEvents.onAuthStateChanged$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncStateEvents.onAuthStateChanged$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10576,16 +11418,20 @@ abstract class GeckoSyncStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncStateEvents.onSyncStarted$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncStateEvents.onSyncStarted$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10597,16 +11443,20 @@ abstract class GeckoSyncStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncStateEvents.onSyncCompleted$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncStateEvents.onSyncCompleted$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10618,16 +11468,20 @@ abstract class GeckoSyncStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncStateEvents.onSyncError$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSyncStateEvents.onSyncError$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10640,8 +11494,10 @@ abstract class GeckoSyncStateEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -10654,12 +11510,20 @@ abstract class GeckoLogging { void onLog(LogLevel level, String message); - static void setUp(GeckoLogging? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoLogging? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoLogging.onLog$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoLogging.onLog$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10672,8 +11536,10 @@ abstract class GeckoLogging { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -10685,9 +11551,13 @@ class ReaderViewEvents { /// Constructor for [ReaderViewEvents]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - ReaderViewEvents({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + ReaderViewEvents({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -10695,25 +11565,28 @@ class ReaderViewEvents { final String pigeonVar_messageChannelSuffix; Future onToggleReaderView(bool enable) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.ReaderViewEvents.onToggleReaderView$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.ReaderViewEvents.onToggleReaderView$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([enable]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enable], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future onAppearanceButtonTap() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.ReaderViewEvents.onAppearanceButtonTap$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.ReaderViewEvents.onAppearanceButtonTap$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -10723,11 +11596,10 @@ class ReaderViewEvents { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -10736,12 +11608,20 @@ abstract class ReaderViewController { void appearanceButtonVisibility(int sequence, bool visible); - static void setUp(ReaderViewController? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + ReaderViewController? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.ReaderViewController.appearanceButtonVisibility$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.ReaderViewController.appearanceButtonVisibility$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10754,8 +11634,10 @@ abstract class ReaderViewController { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -10767,9 +11649,13 @@ class GeckoSelectionActionController { /// Constructor for [GeckoSelectionActionController]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoSelectionActionController({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoSelectionActionController({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -10777,21 +11663,23 @@ class GeckoSelectionActionController { final String pigeonVar_messageChannelSuffix; Future setActions(List actions) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionController.setActions$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionController.setActions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([actions]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [actions], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -10800,12 +11688,20 @@ abstract class GeckoSelectionActionEvents { void performSelectionAction(String id, String selectedText); - static void setUp(GeckoSelectionActionEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoSelectionActionEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionEvents.performSelectionAction$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionEvents.performSelectionAction$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -10818,8 +11714,10 @@ abstract class GeckoSelectionActionEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -10831,9 +11729,13 @@ class GeckoAddonsApi { /// Constructor for [GeckoAddonsApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoAddonsApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoAddonsApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -10841,233 +11743,275 @@ class GeckoAddonsApi { final String pigeonVar_messageChannelSuffix; Future> getAddons(bool allowCache) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getAddons$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getAddons$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([allowCache]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [allowCache], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } Future getAddonById(String addonId, bool allowCache) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getAddonById$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getAddonById$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId, allowCache]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId, allowCache], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as AddonInfo?; } Future getAddonStoreInfo(String addonId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getAddonStoreInfo$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getAddonStoreInfo$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as AddonStoreInfo?; } - Future> searchAddonListings(String query, AddonStoreApp app, int page, int pageSize) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.searchAddonListings$pigeonVar_messageChannelSuffix'; + Future> searchAddonListings( + String query, + AddonStoreApp app, + int page, + int pageSize, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.searchAddonListings$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([query, app, page, pageSize]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [query, app, page, pageSize], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } - Future> getFeaturedAddonListings(AddonStoreApp app, int pageSize) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getFeaturedAddonListings$pigeonVar_messageChannelSuffix'; + Future> getFeaturedAddonListings( + AddonStoreApp app, + int pageSize, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getFeaturedAddonListings$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, pageSize]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [app, pageSize], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } - Future invokeAddonAction(String extensionId, WebExtensionActionType actionType) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.invokeAddonAction$pigeonVar_messageChannelSuffix'; + Future invokeAddonAction( + String extensionId, + WebExtensionActionType actionType, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.invokeAddonAction$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([extensionId, actionType]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [extensionId, actionType], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future enableAddon(String addonId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.enableAddon$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.enableAddon$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as AddonInfo; } Future disableAddon(String addonId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.disableAddon$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.disableAddon$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as AddonInfo; } - Future setAddonAllowedInPrivateBrowsing(String addonId, bool allowed) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.setAddonAllowedInPrivateBrowsing$pigeonVar_messageChannelSuffix'; + Future setAddonAllowedInPrivateBrowsing( + String addonId, + bool allowed, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.setAddonAllowedInPrivateBrowsing$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId, allowed]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId, allowed], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as AddonInfo; } - Future setAddonAutoUpdateEnabledForAddon(String addonId, bool enabled) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.setAddonAutoUpdateEnabledForAddon$pigeonVar_messageChannelSuffix'; + Future setAddonAutoUpdateEnabledForAddon( + String addonId, + bool enabled, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.setAddonAutoUpdateEnabledForAddon$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId, enabled]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId, enabled], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as AddonInfo; } Future uninstallAddon(String addonId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.uninstallAddon$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.uninstallAddon$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future triggerAddonUpdate(String addonId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.triggerAddonUpdate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.triggerAddonUpdate$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as AddonUpdateAttemptInfo?; } Future triggerAllAddonUpdates() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.triggerAllAddonUpdates$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.triggerAllAddonUpdates$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11077,52 +12021,58 @@ class GeckoAddonsApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future getLastAddonUpdateAttempt(String addonId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getLastAddonUpdateAttempt$pigeonVar_messageChannelSuffix'; + Future getLastAddonUpdateAttempt( + String addonId, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.getLastAddonUpdateAttempt$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([addonId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [addonId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as AddonUpdateAttemptInfo?; } Future installAddon(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.installAddon$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.installAddon$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future isAddonAutoUpdateEnabled() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.isAddonAutoUpdateEnabled$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.isAddonAutoUpdateEnabled$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11132,52 +12082,75 @@ class GeckoAddonsApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } Future setAddonAutoUpdateEnabled(bool enabled) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.setAddonAutoUpdateEnabled$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonsApi.setAddonAutoUpdateEnabled$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([enabled]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [enabled], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } abstract class GeckoAddonEvents { static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - void onUpsertWebExtensionAction(int sequence, String extensionId, WebExtensionActionType actionType, WebExtensionData extensionData); + void onUpsertWebExtensionAction( + int sequence, + String extensionId, + WebExtensionActionType actionType, + WebExtensionData extensionData, + ); - void onRemoveWebExtensionAction(int sequence, String extensionId, WebExtensionActionType actionType); + void onRemoveWebExtensionAction( + int sequence, + String extensionId, + WebExtensionActionType actionType, + ); - void onUpdateWebExtensionIcon(int sequence, String extensionId, WebExtensionActionType actionType, Uint8List icon); + void onUpdateWebExtensionIcon( + int sequence, + String extensionId, + WebExtensionActionType actionType, + Uint8List icon, + ); void onWebExtensionPopupRequested(String extensionId, String extensionName); void onOpenAddonSettingsRequested(String addonId); - static void setUp(GeckoAddonEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoAddonEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onUpsertWebExtensionAction$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onUpsertWebExtensionAction$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -11185,23 +12158,34 @@ abstract class GeckoAddonEvents { final List args = message! as List; final int arg_sequence = args[0]! as int; final String arg_extensionId = args[1]! as String; - final WebExtensionActionType arg_actionType = args[2]! as WebExtensionActionType; - final WebExtensionData arg_extensionData = args[3]! as WebExtensionData; + final WebExtensionActionType arg_actionType = + args[2]! as WebExtensionActionType; + final WebExtensionData arg_extensionData = + args[3]! as WebExtensionData; try { - api.onUpsertWebExtensionAction(arg_sequence, arg_extensionId, arg_actionType, arg_extensionData); + api.onUpsertWebExtensionAction( + arg_sequence, + arg_extensionId, + arg_actionType, + arg_extensionData, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onRemoveWebExtensionAction$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onRemoveWebExtensionAction$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -11209,22 +12193,31 @@ abstract class GeckoAddonEvents { final List args = message! as List; final int arg_sequence = args[0]! as int; final String arg_extensionId = args[1]! as String; - final WebExtensionActionType arg_actionType = args[2]! as WebExtensionActionType; + final WebExtensionActionType arg_actionType = + args[2]! as WebExtensionActionType; try { - api.onRemoveWebExtensionAction(arg_sequence, arg_extensionId, arg_actionType); + api.onRemoveWebExtensionAction( + arg_sequence, + arg_extensionId, + arg_actionType, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onUpdateWebExtensionIcon$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onUpdateWebExtensionIcon$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -11232,23 +12225,33 @@ abstract class GeckoAddonEvents { final List args = message! as List; final int arg_sequence = args[0]! as int; final String arg_extensionId = args[1]! as String; - final WebExtensionActionType arg_actionType = args[2]! as WebExtensionActionType; + final WebExtensionActionType arg_actionType = + args[2]! as WebExtensionActionType; final Uint8List arg_icon = args[3]! as Uint8List; try { - api.onUpdateWebExtensionIcon(arg_sequence, arg_extensionId, arg_actionType, arg_icon); + api.onUpdateWebExtensionIcon( + arg_sequence, + arg_extensionId, + arg_actionType, + arg_icon, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onWebExtensionPopupRequested$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onWebExtensionPopupRequested$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -11257,20 +12260,27 @@ abstract class GeckoAddonEvents { final String arg_extensionId = args[0]! as String; final String arg_extensionName = args[1]! as String; try { - api.onWebExtensionPopupRequested(arg_extensionId, arg_extensionName); + api.onWebExtensionPopupRequested( + arg_extensionId, + arg_extensionName, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onOpenAddonSettingsRequested$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAddonEvents.onOpenAddonSettingsRequested$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -11282,8 +12292,10 @@ abstract class GeckoAddonEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -11295,9 +12307,13 @@ class GeckoSuggestionApi { /// Constructor for [GeckoSuggestionApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoSuggestionApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoSuggestionApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -11305,69 +12321,96 @@ class GeckoSuggestionApi { final String pigeonVar_messageChannelSuffix; Future getAutocompleteSuggestion(String query) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSuggestionApi.getAutocompleteSuggestion$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSuggestionApi.getAutocompleteSuggestion$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([query]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [query], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as AutocompleteResult?; } - Future querySuggestions(String text, List providers) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSuggestionApi.querySuggestions$pigeonVar_messageChannelSuffix'; + Future querySuggestions( + String text, + List providers, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSuggestionApi.querySuggestions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([text, providers]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [text, providers], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } abstract class GeckoSuggestionEvents { static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - void onSuggestionResult(int sequence, GeckoSuggestionType suggestionType, List suggestions); + void onSuggestionResult( + int sequence, + GeckoSuggestionType suggestionType, + List suggestions, + ); - static void setUp(GeckoSuggestionEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoSuggestionEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSuggestionEvents.onSuggestionResult$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSuggestionEvents.onSuggestionResult$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; final int arg_sequence = args[0]! as int; - final GeckoSuggestionType arg_suggestionType = args[1]! as GeckoSuggestionType; - final List arg_suggestions = (args[2]! as List).cast(); + final GeckoSuggestionType arg_suggestionType = + args[1]! as GeckoSuggestionType; + final List arg_suggestions = + (args[2]! as List).cast(); try { - api.onSuggestionResult(arg_sequence, arg_suggestionType, arg_suggestions); + api.onSuggestionResult( + arg_sequence, + arg_suggestionType, + arg_suggestions, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -11380,12 +12423,20 @@ abstract class GeckoTabContentEvents { void onContentUpdate(int sequence, TabContent content); - static void setUp(GeckoTabContentEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoTabContentEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabContentEvents.onContentUpdate$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTabContentEvents.onContentUpdate$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -11398,8 +12449,10 @@ abstract class GeckoTabContentEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -11411,9 +12464,13 @@ class GeckoDeleteBrowsingDataController { /// Constructor for [GeckoDeleteBrowsingDataController]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoDeleteBrowsingDataController({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoDeleteBrowsingDataController({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -11421,7 +12478,8 @@ class GeckoDeleteBrowsingDataController { final String pigeonVar_messageChannelSuffix; Future deleteTabs() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteTabs$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteTabs$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11431,15 +12489,15 @@ class GeckoDeleteBrowsingDataController { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future deleteBrowsingHistory() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteBrowsingHistory$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteBrowsingHistory$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11449,15 +12507,15 @@ class GeckoDeleteBrowsingDataController { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future deleteCookiesAndSiteData() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteCookiesAndSiteData$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteCookiesAndSiteData$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11467,15 +12525,15 @@ class GeckoDeleteBrowsingDataController { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future deleteCachedFiles() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteCachedFiles$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteCachedFiles$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11485,15 +12543,15 @@ class GeckoDeleteBrowsingDataController { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future deleteSitePermissions() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteSitePermissions$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteSitePermissions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11503,15 +12561,15 @@ class GeckoDeleteBrowsingDataController { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future deleteDownloads() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteDownloads$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.deleteDownloads$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11521,48 +12579,54 @@ class GeckoDeleteBrowsingDataController { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future clearDataForSessionContext(String contextId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.clearDataForSessionContext$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.clearDataForSessionContext$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([contextId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [contextId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Clear browsing data for a specific host/domain - Future clearDataForHost(String host, List dataTypes) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.clearDataForHost$pigeonVar_messageChannelSuffix'; + Future clearDataForHost( + String host, + List dataTypes, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDeleteBrowsingDataController.clearDataForHost$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([host, dataTypes]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [host, dataTypes], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -11580,12 +12644,20 @@ abstract class GeckoHistoryEvents { /// ([url], [visitTime]) to join back to the Places visit. void onVisitRecorded(String url, int visitTime, String? contextId); - static void setUp(GeckoHistoryEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoHistoryEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryEvents.onVisitRecorded$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryEvents.onVisitRecorded$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -11599,8 +12671,10 @@ abstract class GeckoHistoryEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -11612,163 +12686,197 @@ class GeckoHistoryApi { /// Constructor for [GeckoHistoryApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoHistoryApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoHistoryApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); final String pigeonVar_messageChannelSuffix; - Future> getDetailedVisits(int startMillis, int endMillis, List excludeTypes) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getDetailedVisits$pigeonVar_messageChannelSuffix'; + Future> getDetailedVisits( + int startMillis, + int endMillis, + List excludeTypes, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getDetailedVisits$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([startMillis, endMillis, excludeTypes]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [startMillis, endMillis, excludeTypes], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } - Future> getVisitsPaginated(int offset, int count, List excludeTypes) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getVisitsPaginated$pigeonVar_messageChannelSuffix'; + Future> getVisitsPaginated( + int offset, + int count, + List excludeTypes, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getVisitsPaginated$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([offset, count, excludeTypes]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [offset, count, excludeTypes], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } Future deleteVisit(String url, int timestamp) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteVisit$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteVisit$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url, timestamp]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url, timestamp], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future deleteDownload(String id) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteDownload$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteDownload$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([id]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [id], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future deleteVisitsBetween(int startMillis, int endMillis) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteVisitsBetween$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteVisitsBetween$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([startMillis, endMillis]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [startMillis, endMillis], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future> getHistoryHighlights(HistoryHighlightWeights weights, int limit) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getHistoryHighlights$pigeonVar_messageChannelSuffix'; + Future> getHistoryHighlights( + HistoryHighlightWeights weights, + int limit, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getHistoryHighlights$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([weights, limit]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [weights, limit], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } - Future> getTopFrecentSites(int limit, FrecencyThresholdOption frecencyThreshold) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getTopFrecentSites$pigeonVar_messageChannelSuffix'; + Future> getTopFrecentSites( + int limit, + FrecencyThresholdOption frecencyThreshold, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getTopFrecentSites$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([limit, frecencyThreshold]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [limit, frecencyThreshold], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } /// Returns the most recent [HistoryMetadata] record for [url], or `null` if /// no metadata has been recorded for that URL. Future getLatestHistoryMetadataForUrl(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getLatestHistoryMetadataForUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getLatestHistoryMetadataForUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as HistoryMetadata?; } @@ -11776,191 +12884,227 @@ class GeckoHistoryApi { /// input URL aligned by index; entries are `null` for URLs Places has no /// metadata for. Used by the local search re-rank to collapse N IPC /// roundtrips into one. - Future> getLatestHistoryMetadataForUrls(List urls) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getLatestHistoryMetadataForUrls$pigeonVar_messageChannelSuffix'; + Future> getLatestHistoryMetadataForUrls( + List urls, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getLatestHistoryMetadataForUrls$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([urls]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [urls], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } /// Bulk visited check: returns booleans aligned with [urls] indicating /// whether Places has any visit recorded for each URL. Future> getVisited(List urls) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getVisited$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getVisited$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([urls]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [urls], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } /// Frecency-ranked autocomplete results. Mirrors Places' awesomebar input. - Future> getSuggestions(String query, int limit) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getSuggestions$pigeonVar_messageChannelSuffix'; + Future> getSuggestions( + String query, + int limit, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.getSuggestions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([query, limit]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [query, limit], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } /// Places' built-in metadata text search (matches title / url / searchTerm). /// Useful as a comparison baseline against the local content FTS. - Future> queryHistoryMetadata(String query, int limit) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.queryHistoryMetadata$pigeonVar_messageChannelSuffix'; + Future> queryHistoryMetadata( + String query, + int limit, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.queryHistoryMetadata$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([query, limit]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [query, limit], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } /// Records a title / preview-image observation for [url] without recording /// a visit. Intended for manual flows; the engine middleware records these /// automatically as the user browses. - Future recordObservation(String url, PageObservation observation) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.recordObservation$pigeonVar_messageChannelSuffix'; + Future recordObservation( + String url, + PageObservation observation, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.recordObservation$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url, observation]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url, observation], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Records a view-time observation against the metadata record identified /// by [key]. View time is added to the existing total. - Future noteHistoryMetadataViewTime(HistoryMetadataKey key, int viewTimeMs) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.noteHistoryMetadataViewTime$pigeonVar_messageChannelSuffix'; + Future noteHistoryMetadataViewTime( + HistoryMetadataKey key, + int viewTimeMs, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.noteHistoryMetadataViewTime$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([key, viewTimeMs]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [key, viewTimeMs], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Records a document-type observation against the metadata record /// identified by [key]. - Future noteHistoryMetadataDocumentType(HistoryMetadataKey key, DocumentType documentType) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.noteHistoryMetadataDocumentType$pigeonVar_messageChannelSuffix'; + Future noteHistoryMetadataDocumentType( + HistoryMetadataKey key, + DocumentType documentType, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.noteHistoryMetadataDocumentType$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([key, documentType]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [key, documentType], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Removes all visits for [url]. May propagate to remote devices via Sync. Future deleteVisitsFor(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteVisitsFor$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteVisitsFor$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Removes all visits since [sinceMillis] (inclusive). May propagate to /// remote devices via Sync. Future deleteVisitsSince(int sinceMillis) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteVisitsSince$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteVisitsSince$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([sinceMillis]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [sinceMillis], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Removes all locally stored history. Sync will not remove remote history, /// but it will prevent deleted entries from returning. Future deleteEverything() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteEverything$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteEverything$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -11970,30 +13114,31 @@ class GeckoHistoryApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Prunes history metadata older than [olderThanMillis] (exclusive). Future deleteHistoryMetadataOlderThan(int olderThanMillis) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteHistoryMetadataOlderThan$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoHistoryApi.deleteHistoryMetadataOlderThan$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([olderThanMillis]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [olderThanMillis], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -12001,9 +13146,13 @@ class GeckoDownloadsApi { /// Constructor for [GeckoDownloadsApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoDownloadsApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoDownloadsApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12011,75 +13160,93 @@ class GeckoDownloadsApi { final String pigeonVar_messageChannelSuffix; Future requestDownload(String tabId, DownloadState state) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.requestDownload$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.requestDownload$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, state]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, state], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future copyInternetResource(String tabId, ShareInternetResourceState state) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.copyInternetResource$pigeonVar_messageChannelSuffix'; + Future copyInternetResource( + String tabId, + ShareInternetResourceState state, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.copyInternetResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, state]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, state], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future shareInternetResource(String tabId, ShareInternetResourceState state) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.shareInternetResource$pigeonVar_messageChannelSuffix'; + Future shareInternetResource( + String tabId, + ShareInternetResourceState state, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.shareInternetResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, state]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, state], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future openDownloadedFile(String fileName, String directoryPath, String? contentType) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.openDownloadedFile$pigeonVar_messageChannelSuffix'; + Future openDownloadedFile( + String fileName, + String directoryPath, + String? contentType, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoDownloadsApi.openDownloadedFile$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([fileName, directoryPath, contentType]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [fileName, directoryPath, contentType], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } } @@ -12089,12 +13256,20 @@ abstract class BrowserExtensionEvents { void onFeedRequested(int sequence, String url); - static void setUp(BrowserExtensionEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + BrowserExtensionEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.BrowserExtensionEvents.onFeedRequested$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.BrowserExtensionEvents.onFeedRequested$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -12107,8 +13282,10 @@ abstract class BrowserExtensionEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -12120,9 +13297,13 @@ class GeckoFetchApi { /// Constructor for [GeckoFetchApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoFetchApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoFetchApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12130,21 +13311,23 @@ class GeckoFetchApi { final String pigeonVar_messageChannelSuffix; Future fetch(GeckoFetchRequest request) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoFetchApi.fetch$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoFetchApi.fetch$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([request]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [request], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as GeckoFetchResponse; } } @@ -12162,9 +13345,13 @@ class GeckoViewportApi { /// Constructor for [GeckoViewportApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoViewportApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoViewportApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12181,21 +13368,23 @@ class GeckoViewportApi { /// /// [heightPx] Combined height of top and bottom toolbars in pixels. Future setDynamicToolbarMaxHeight(int heightPx) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoViewportApi.setDynamicToolbarMaxHeight$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoViewportApi.setDynamicToolbarMaxHeight$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([heightPx]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [heightPx], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Sets the vertical clipping offset for the GeckoView content. @@ -12208,21 +13397,23 @@ class GeckoViewportApi { /// /// [clippingPx] The clipping offset in pixels. Negative = bottom clip. Future setVerticalClipping(int clippingPx) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoViewportApi.setVerticalClipping$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoViewportApi.setVerticalClipping$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([clippingPx]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [clippingPx], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -12242,7 +13433,12 @@ abstract class GeckoViewportEvents { /// [heightPx] Keyboard height in pixels (0 when hidden). /// [isVisible] Whether the keyboard is currently visible. /// [isAnimating] Whether the keyboard is currently animating. - void onKeyboardVisibilityChanged(int sequence, int heightPx, bool isVisible, bool isAnimating); + void onKeyboardVisibilityChanged( + int sequence, + int heightPx, + bool isVisible, + bool isAnimating, + ); /// Called when GeckoView scroll-handling eligibility changes. /// @@ -12252,12 +13448,20 @@ abstract class GeckoViewportEvents { /// the page consumed touch input. void onBrowserHandlingScrollChanged(int sequence, bool isHandling); - static void setUp(GeckoViewportEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoViewportEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoViewportEvents.onKeyboardVisibilityChanged$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoViewportEvents.onKeyboardVisibilityChanged$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -12268,20 +13472,29 @@ abstract class GeckoViewportEvents { final bool arg_isVisible = args[2]! as bool; final bool arg_isAnimating = args[3]! as bool; try { - api.onKeyboardVisibilityChanged(arg_sequence, arg_heightPx, arg_isVisible, arg_isAnimating); + api.onKeyboardVisibilityChanged( + arg_sequence, + arg_heightPx, + arg_isVisible, + arg_isAnimating, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoViewportEvents.onBrowserHandlingScrollChanged$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoViewportEvents.onBrowserHandlingScrollChanged$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -12294,8 +13507,10 @@ abstract class GeckoViewportEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -12307,9 +13522,13 @@ class GeckoBookmarksApi { /// Constructor for [GeckoBookmarksApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoBookmarksApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoBookmarksApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12322,21 +13541,23 @@ class GeckoBookmarksApi { /// @param recursive Whether to recurse and obtain all levels of children. /// @return The populated root starting from the guid. Future getTree(String guid, bool recursive) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.getTree$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.getTree$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([guid, recursive]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [guid, recursive], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as BookmarkNode?; } @@ -12345,21 +13566,23 @@ class GeckoBookmarksApi { /// @param guid The bookmark guid to obtain. /// @return The bookmark node or null if it does not exist. Future getBookmark(String guid) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.getBookmark$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.getBookmark$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([guid]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [guid], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as BookmarkNode?; } @@ -12368,21 +13591,23 @@ class GeckoBookmarksApi { /// @param url The URL string. /// @return The list of bookmarks that match the URL Future> getBookmarksWithUrl(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.getBookmarksWithUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.getBookmarksWithUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } @@ -12392,22 +13617,28 @@ class GeckoBookmarksApi { /// @param maxAge Optional parameter used to filter out entries older than this number of milliseconds. /// @param currentTime Optional parameter for current time. Defaults toSystem.currentTimeMillis() /// @return The list of bookmarks that have been recently added up to the limit number of items. - Future> getRecentBookmarks(int limit, int? maxAge, int currentTime) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.getRecentBookmarks$pigeonVar_messageChannelSuffix'; + Future> getRecentBookmarks( + int limit, + int? maxAge, + int currentTime, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.getRecentBookmarks$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([limit, maxAge, currentTime]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [limit, maxAge, currentTime], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } @@ -12417,21 +13648,23 @@ class GeckoBookmarksApi { /// @param limit The maximum number of entries to return. /// @return The list of matching bookmark nodes up to the limit number of items. Future> searchBookmarks(String query, int limit) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.searchBookmarks$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.searchBookmarks$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([query, limit]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [query, limit], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } @@ -12444,22 +13677,29 @@ class GeckoBookmarksApi { /// @param title The title of the bookmark item to add. /// @param position The optional position to add the new node or null to append. /// @return The guid of the newly inserted bookmark item. - Future addItem(String parentGuid, String url, String title, int? position) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.addItem$pigeonVar_messageChannelSuffix'; + Future addItem( + String parentGuid, + String url, + String title, + int? position, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.addItem$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([parentGuid, url, title, position]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [parentGuid, url, title, position], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } @@ -12471,22 +13711,28 @@ class GeckoBookmarksApi { /// @param title The title of the bookmark folder to add. /// @param position The optional position to add the new node or null to append. /// @return The guid of the newly inserted bookmark item. - Future addFolder(String parentGuid, String title, int? position) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.addFolder$pigeonVar_messageChannelSuffix'; + Future addFolder( + String parentGuid, + String title, + int? position, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.addFolder$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([parentGuid, title, position]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [parentGuid, title, position], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } @@ -12497,21 +13743,23 @@ class GeckoBookmarksApi { /// @param guid The guid of the item to update. /// @param info The info to change in the bookmark. Future updateNode(String guid, BookmarkInfo info) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.updateNode$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.updateNode$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([guid, info]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [guid, info], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Deletes a bookmark node and all of its children, if any. @@ -12520,23 +13768,100 @@ class GeckoBookmarksApi { /// /// @return Whether the bookmark existed or not. Future deleteNode(String guid) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.deleteNode$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.deleteNode$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([guid]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [guid], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } + + /// Bulk-inserts [children] underneath [parentGuid], appending them after any + /// nodes the parent already contains. + /// + /// Each top-level folder is handed to the storage layer as a single tree + /// insertion, so importing a large bookmark file costs one platform channel + /// call instead of one per node. Separators are preserved. + /// + /// Timestamps survive in full for everything nested inside a top-level + /// folder. Loose top-level items and separators keep their [dateAdded], but + /// their [lastModified] is set to the time of import: the only storage call + /// that accepts timestamps creates a folder, so nodes landing directly in + /// [parentGuid] have to be moved into place afterwards. + /// + /// Sync behavior: will add the inserted bookmarks to remote devices. + /// + /// Unlike [addItem] and [addFolder] this does *not* emit a + /// `bookmarks.onCreated` extension event per node, since a large import would + /// otherwise flood every installed WebExtension. + /// + /// @param parentGuid The guid of the existing folder to insert underneath. + /// @param children The nodes to insert, in the order they should appear. + /// @return The number of inserted bookmark items and failed top-level nodes. + Future insertTree( + String parentGuid, + List children, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.insertTree$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [parentGuid, children], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as BookmarkInsertTreeResult; + } + + /// Counts the bookmark items contained in the trees rooted at [guids]. + /// + /// Folders and separators are not counted, and a guid that does not exist + /// contributes nothing. Lets the app report how much a destructive action + /// affects without loading the subtrees into Dart. + /// + /// @param guids The guids of the folders to count within. + /// @return The total number of bookmark items across all trees. + Future countBookmarksInTrees(List guids) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBookmarksApi.countBookmarksInTrees$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [guids], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as int; + } } /// API for managing site permissions stored in GeckoView @@ -12544,9 +13869,13 @@ class GeckoSitePermissionsApi { /// Constructor for [GeckoSitePermissionsApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoSitePermissionsApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoSitePermissionsApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12554,61 +13883,73 @@ class GeckoSitePermissionsApi { final String pigeonVar_messageChannelSuffix; /// Get permissions for origin (single source of truth from GeckoView) - Future getSitePermissions(String origin, bool private) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSitePermissionsApi.getSitePermissions$pigeonVar_messageChannelSuffix'; + Future getSitePermissions( + String origin, + bool private, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSitePermissionsApi.getSitePermissions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([origin, private]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [origin, private], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as SitePermissions?; } /// Save/update permissions (persisted by GeckoView) - Future setSitePermissions(SitePermissions permissions, bool private) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSitePermissionsApi.setSitePermissions$pigeonVar_messageChannelSuffix'; + Future setSitePermissions( + SitePermissions permissions, + bool private, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSitePermissionsApi.setSitePermissions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([permissions, private]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [permissions, private], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Delete permissions for origin (removed from GeckoView storage) Future deleteSitePermissions(String origin, bool private) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSitePermissionsApi.deleteSitePermissions$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSitePermissionsApi.deleteSitePermissions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([origin, private]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [origin, private], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -12617,9 +13958,13 @@ class GeckoPublicSuffixListApi { /// Constructor for [GeckoPublicSuffixListApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoPublicSuffixListApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoPublicSuffixListApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12629,21 +13974,23 @@ class GeckoPublicSuffixListApi { /// Get base domain (eTLD+1) from host using Mozilla's Public Suffix List /// Returns the host unchanged if PSL lookup fails Future getPublicSuffixPlusOne(String host) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPublicSuffixListApi.getPublicSuffixPlusOne$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPublicSuffixListApi.getPublicSuffixPlusOne$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([host]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [host], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as String; } } @@ -12657,9 +14004,13 @@ class GeckoTrackingProtectionApi { /// Constructor for [GeckoTrackingProtectionApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoTrackingProtectionApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoTrackingProtectionApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12671,21 +14022,23 @@ class GeckoTrackingProtectionApi { /// Uses callback pattern to match Mozilla Android Components API. /// Returns true if the site is in the exceptions list (ETP disabled). Future containsException(String tabId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.containsException$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.containsException$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } @@ -12694,21 +14047,23 @@ class GeckoTrackingProtectionApi { /// This adds the current tab's URL to the exceptions list. /// ETP will be disabled for this site until the exception is removed. Future addException(String tabId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.addException$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.addException$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Remove tracking protection exception for a tab (enable ETP for this site) @@ -12716,21 +14071,23 @@ class GeckoTrackingProtectionApi { /// This removes the current tab's URL from the exceptions list. /// ETP will be re-enabled for this site. Future removeException(String tabId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.removeException$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.removeException$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Remove a specific exception by URL @@ -12738,28 +14095,31 @@ class GeckoTrackingProtectionApi { /// Alternative to removeException(tabId) for cases where you /// have a URL rather than a tabId. Future removeExceptionByUrl(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.removeExceptionByUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.removeExceptionByUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Fetch all tracking protection exceptions /// /// Returns list of all sites that have exceptions (ETP disabled). Future> fetchExceptions() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.fetchExceptions$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.fetchExceptions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -12769,19 +14129,20 @@ class GeckoTrackingProtectionApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; - return (pigeonVar_replyValue! as List).cast(); + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List) + .cast(); } /// Remove all tracking protection exceptions /// /// This re-enables ETP for all exception sites. Future removeAllExceptions() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.removeAllExceptions$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTrackingProtectionApi.removeAllExceptions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -12791,11 +14152,10 @@ class GeckoTrackingProtectionApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -12808,9 +14168,13 @@ class GeckoAppLinksApi { /// Constructor for [GeckoAppLinksApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoAppLinksApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoAppLinksApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12820,64 +14184,76 @@ class GeckoAppLinksApi { /// Push the complete policy snapshot to native (last-write-wins). Native /// persists it durably to the active profile's prefs record before acking. Future setAppLinkPolicy(AppLinkPolicySnapshot snapshot) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.setAppLinkPolicy$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.setAppLinkPolicy$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([snapshot]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [snapshot], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Non-consuming query of pending prompts for [owner] (§2.6). Surfaces call /// this on attach/resume/rotation and when the availability event fires, and /// render idempotently by requestId. - Future> getPendingAppLinkPrompts(AppLinkPromptOwner owner) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.getPendingAppLinkPrompts$pigeonVar_messageChannelSuffix'; + Future> getPendingAppLinkPrompts( + AppLinkPromptOwner owner, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.getPendingAppLinkPrompts$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([owner]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [owner], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; - return (pigeonVar_replyValue! as List).cast(); + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List) + .cast(); } /// Atomically resolve a pending prompt: validate it still exists and its tab /// is alive, consume it (double-resolve is a no-op), then perform side effects /// after releasing the store lock (§2.6). - Future resolvePendingAppLink(int requestId, AppLinkDecision decision) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.resolvePendingAppLink$pigeonVar_messageChannelSuffix'; + Future resolvePendingAppLink( + int requestId, + AppLinkDecision decision, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.resolvePendingAppLink$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([requestId, decision]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [requestId, decision], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as AppLinkResolutionResult; } @@ -12889,22 +14265,27 @@ class GeckoAppLinksApi { /// /// [includeHttpAppLinks] when true, an app resolving an engine-supported /// (http(s)) URL is surfaced (e.g. the YouTube app for a youtube.com link). - Future resolveAppLink(String url, bool includeHttpAppLinks) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.resolveAppLink$pigeonVar_messageChannelSuffix'; + Future resolveAppLink( + String url, + bool includeHttpAppLinks, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.resolveAppLink$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url, includeHttpAppLinks]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url, includeHttpAppLinks], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); return pigeonVar_replyValue as AppLinkTarget?; } @@ -12914,21 +14295,23 @@ class GeckoAppLinksApi { /// no-app or ActivityNotFoundException/SecurityException; never throws across /// the channel for expected conditions. Future launchAppLink(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.launchAppLink$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinksApi.launchAppLink$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } } @@ -12943,12 +14326,20 @@ abstract class GeckoAppLinkEvents { void onAppLinkPromptAvailable(int sequence, AppLinkPromptOwner owner); - static void setUp(GeckoAppLinkEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoAppLinkEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinkEvents.onAppLinkPromptAvailable$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoAppLinkEvents.onAppLinkPromptAvailable$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -12961,8 +14352,10 @@ abstract class GeckoAppLinkEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -12978,9 +14371,13 @@ class GeckoPwaApi { /// Constructor for [GeckoPwaApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoPwaApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoPwaApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -12998,28 +14395,36 @@ class GeckoPwaApi { /// The [contextId] is the container's contextual identity (optional, null for default container). /// The [overrideAppName] customizes the installed app's displayed name and persists in the saved manifest. /// Returns true if installation was successful. - Future installWebApp(String? tabId, String profileUuid, String? contextId, String? overrideAppName) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPwaApi.installWebApp$pigeonVar_messageChannelSuffix'; + Future installWebApp( + String? tabId, + String profileUuid, + String? contextId, + String? overrideAppName, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPwaApi.installWebApp$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, profileUuid, contextId, overrideAppName]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, profileUuid, contextId, overrideAppName], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } /// Returns a list of all installed PWA manifests. Future> getInstalledWebApps() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPwaApi.getInstalledWebApps$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPwaApi.getInstalledWebApps$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -13029,11 +14434,10 @@ class GeckoPwaApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } @@ -13048,22 +14452,29 @@ class GeckoPwaApi { /// The [contextId] is the container's contextual identity (optional). /// The [overrideShortcutName] allows customizing the shortcut label. /// Returns true if the shortcut was created successfully. - Future installBasicShortcut(String? tabId, String profileUuid, String? contextId, String? overrideShortcutName) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPwaApi.installBasicShortcut$pigeonVar_messageChannelSuffix'; + Future installBasicShortcut( + String? tabId, + String profileUuid, + String? contextId, + String? overrideShortcutName, + ) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPwaApi.installBasicShortcut$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId, profileUuid, contextId, overrideShortcutName]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId, profileUuid, contextId, overrideShortcutName], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as bool; } } @@ -13074,9 +14485,13 @@ class SandboxCaptureApi { /// Constructor for [SandboxCaptureApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - SandboxCaptureApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + SandboxCaptureApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -13087,59 +14502,65 @@ class SandboxCaptureApi { /// Dart has brought up [CaptureServer] and reconciled local artifacts with /// the `capture_tab` rows. Future resetAll(List entries) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureApi.resetAll$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureApi.resetAll$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([entries]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [entries], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Inserts or updates the registry entry for [entry.tabId]. Future mark(SandboxCaptureEntry entry) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureApi.mark$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureApi.mark$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([entry]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [entry], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Removes the registry entry for [tabId]. Future unmark(String tabId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureApi.unmark$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureApi.unmark$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([tabId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [tabId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -13159,14 +14580,27 @@ abstract class SandboxCaptureHostEvents { /// The native middleware has already rewritten the new tab's URL to /// `about:blank`; Dart should register it as sandbox and run the capture /// pipeline for [targetUrl]. - void onSandboxNewTab(int sequence, String parentTabId, String newTabId, String targetUrl); + void onSandboxNewTab( + int sequence, + String parentTabId, + String newTabId, + String targetUrl, + ); - static void setUp(SandboxCaptureHostEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + SandboxCaptureHostEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureHostEvents.onSandboxLinkClick$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureHostEvents.onSandboxLinkClick$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -13176,20 +14610,28 @@ abstract class SandboxCaptureHostEvents { final String arg_parentTabId = args[1]! as String; final String arg_targetUrl = args[2]! as String; try { - api.onSandboxLinkClick(arg_sequence, arg_parentTabId, arg_targetUrl); + api.onSandboxLinkClick( + arg_sequence, + arg_parentTabId, + arg_targetUrl, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureHostEvents.onSandboxNewTab$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.SandboxCaptureHostEvents.onSandboxNewTab$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -13200,12 +14642,19 @@ abstract class SandboxCaptureHostEvents { final String arg_newTabId = args[2]! as String; final String arg_targetUrl = args[3]! as String; try { - api.onSandboxNewTab(arg_sequence, arg_parentTabId, arg_newTabId, arg_targetUrl); + api.onSandboxNewTab( + arg_sequence, + arg_parentTabId, + arg_newTabId, + arg_targetUrl, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -13218,9 +14667,13 @@ class GeckoGestureApi { /// Constructor for [GeckoGestureApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoGestureApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoGestureApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -13228,21 +14681,23 @@ class GeckoGestureApi { final String pigeonVar_messageChannelSuffix; Future setGestureConfig(GestureConfig config) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoGestureApi.setGestureConfig$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoGestureApi.setGestureConfig$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([config]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [config], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -13269,12 +14724,20 @@ abstract class GeckoGestureEvents { /// [sequence] Event sequence number for ordering. void onGestureReset(int sequence); - static void setUp(GeckoGestureEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoGestureEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoGestureEvents.onGestureRecognized$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoGestureEvents.onGestureRecognized$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -13287,16 +14750,20 @@ abstract class GeckoGestureEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoGestureEvents.onGestureProgress$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoGestureEvents.onGestureProgress$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -13309,16 +14776,20 @@ abstract class GeckoGestureEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoGestureEvents.onGestureReset$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoGestureEvents.onGestureReset$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -13330,8 +14801,10 @@ abstract class GeckoGestureEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -13344,9 +14817,13 @@ class GeckoPushApi { /// Constructor for [GeckoPushApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - GeckoPushApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + GeckoPushApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -13354,7 +14831,8 @@ class GeckoPushApi { final String pigeonVar_messageChannelSuffix; Future getPushStatus() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.getPushStatus$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.getPushStatus$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -13364,11 +14842,10 @@ class GeckoPushApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return pigeonVar_replyValue! as PushStatus; } @@ -13377,26 +14854,29 @@ class GeckoPushApi { /// The picker is built in Dart rather than delegated to the connector's own /// dialog, which would save the selection against a non-profile context. Future setDistributor(String packageName) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.setDistributor$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.setDistributor$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([packageName]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [packageName], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Forgets the current distributor. This is the off switch for web push. Future removeDistributor() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.removeDistributor$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.removeDistributor$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -13406,15 +14886,15 @@ class GeckoPushApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future renewRegistration() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.renewRegistration$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.renewRegistration$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -13424,39 +14904,41 @@ class GeckoPushApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Pauses push transport for the current profile before switching profiles. /// Site subscriptions and the chosen distributor are retained for restoration /// when this profile becomes active again. Future suspendForProfileSwitch(String targetProfileId) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.suspendForProfileSwitch$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.suspendForProfileSwitch$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([targetProfileId]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [targetProfileId], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Subscriptions Gecko has created, read from the UnifiedPush store. Read-only: /// there is no app→Gecko channel to revoke a subscription, so removal has to go /// through the site's notification permission instead. Future> getSubscriptions() async { - final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.getSubscriptions$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushApi.getSubscriptions$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -13466,11 +14948,10 @@ class GeckoPushApi { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); return (pigeonVar_replyValue! as List).cast(); } } @@ -13486,12 +14967,20 @@ abstract class GeckoPushEvents { /// [sequence] Event sequence number for ordering. void onPushStatusChanged(int sequence, PushStatus status); - static void setUp(GeckoPushEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { - messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp( + GeckoPushEvents? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushEvents.onPushStatusChanged$messageChannelSuffix', pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.flutter_mozilla_components.GeckoPushEvents.onPushStatusChanged$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { @@ -13504,8 +14993,10 @@ abstract class GeckoPushEvents { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } diff --git a/packages/flutter_mozilla_components/pigeons/gecko.dart b/packages/flutter_mozilla_components/pigeons/gecko.dart index d0a8ed69..bc744745 100644 --- a/packages/flutter_mozilla_components/pigeons/gecko.dart +++ b/packages/flutter_mozilla_components/pigeons/gecko.dart @@ -2467,6 +2467,51 @@ class BookmarkNode { }); } +/// A node of a bookmark tree that is about to be bulk-inserted into storage. +/// +/// Unlike [BookmarkNode] this carries no guids or parent links: the tree is +/// described purely by nesting, and storage assigns guids while inserting. +/// +/// @property type Whether this node is an item, a folder or a separator. +/// @property title The title of the item or folder. Ignored for separators. +/// @property url The URL of the item. Must be non-null for items, ignored otherwise. +/// @property dateAdded Creation timestamp in milliseconds since epoch, or 0 if unknown. +/// @property lastModified Modification timestamp in milliseconds since epoch, or 0 if unknown. +/// @property children Child nodes of a folder, in insertion order. Empty for items and separators. +class BookmarkImportNode { + final BookmarkNodeType type; + final String? title; + final String? url; + final int dateAdded; + final int lastModified; + final List children; + + BookmarkImportNode({ + required this.type, + required this.title, + required this.url, + required this.dateAdded, + required this.lastModified, + required this.children, + }); +} + +/// Outcome of a bulk bookmark tree insertion. +/// +/// @property insertedItemCount The number of bookmark items (not folders or +/// separators) that were inserted. +/// @property failedNodeCount The number of top-level nodes that could not be +/// inserted. Their subtrees are missing entirely. +class BookmarkInsertTreeResult { + final int insertedItemCount; + final int failedNodeCount; + + BookmarkInsertTreeResult({ + required this.insertedItemCount, + required this.failedNodeCount, + }); +} + /// Class for making alterations to any bookmark node class BookmarkInfo { final String? parentGuid; @@ -2639,6 +2684,45 @@ abstract class GeckoBookmarksApi { /// @return Whether the bookmark existed or not. @async bool deleteNode(String guid); + + /// Bulk-inserts [children] underneath [parentGuid], appending them after any + /// nodes the parent already contains. + /// + /// Each top-level folder is handed to the storage layer as a single tree + /// insertion, so importing a large bookmark file costs one platform channel + /// call instead of one per node. Separators are preserved. + /// + /// Timestamps survive in full for everything nested inside a top-level + /// folder. Loose top-level items and separators keep their [dateAdded], but + /// their [lastModified] is set to the time of import: the only storage call + /// that accepts timestamps creates a folder, so nodes landing directly in + /// [parentGuid] have to be moved into place afterwards. + /// + /// Sync behavior: will add the inserted bookmarks to remote devices. + /// + /// Unlike [addItem] and [addFolder] this does *not* emit a + /// `bookmarks.onCreated` extension event per node, since a large import would + /// otherwise flood every installed WebExtension. + /// + /// @param parentGuid The guid of the existing folder to insert underneath. + /// @param children The nodes to insert, in the order they should appear. + /// @return The number of inserted bookmark items and failed top-level nodes. + @async + BookmarkInsertTreeResult insertTree( + String parentGuid, + List children, + ); + + /// Counts the bookmark items contained in the trees rooted at [guids]. + /// + /// Folders and separators are not counted, and a guid that does not exist + /// contributes nothing. Lets the app report how much a destructive action + /// affects without loading the subtrees into Dart. + /// + /// @param guids The guids of the folders to count within. + /// @return The total number of bookmark items across all trees. + @async + int countBookmarksInTrees(List guids); } // ============================================================================= diff --git a/pubspec.lock b/pubspec.lock index 24235c2b..dd571a37 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,14 +25,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.3" - animated_tree_view: - dependency: transitive - description: - name: animated_tree_view - sha256: ed982be7fa2cf51b62bb76e95b6a0f423cde12f1da8745a1da938e82a7baacf2 - url: "https://pub.dev" - source: hosted - version: "2.3.0" ansi_styles: dependency: transitive description: @@ -361,14 +353,6 @@ packages: url: "https://pub.dev" source: hosted version: "8.1.0" - diffutil_dart: - dependency: transitive - description: - name: diffutil_dart - sha256: "5e74883aedf87f3b703cb85e815bdc1ed9208b33501556e4a8a5572af9845c81" - url: "https://pub.dev" - source: hosted - version: "4.0.1" drift: dependency: transitive description: @@ -1481,14 +1465,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0" - scroll_to_index: - dependency: transitive - description: - name: scroll_to_index - sha256: b707546e7500d9f070d63e5acf74fd437ec7eeeb68d3412ef7b0afada0b4f176 - url: "https://pub.dev" - source: hosted - version: "3.0.1" search_client: dependency: transitive description: