From 2ff97e226cda9e9b20162432a73414d6dd7aa779 Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Thu, 18 Sep 2025 12:53:03 +0200 Subject: [PATCH] basic history working --- app/lib/core/routing/routes.browser.dart | 8 + app/lib/core/routing/routes.dart | 1 + app/lib/core/routing/routes.g.dart | 26 +++ .../browser_modules/bottom_app_bar.dart | 7 + .../entities/history_filter_options.dart | 28 +++ .../entities/history_filter_options.g.dart | 80 +++++++ .../features/history/domain/providers.dart | 40 +++- .../features/history/domain/providers.g.dart | 197 +++-------------- .../history/presentation/screens/history.dart | 200 +++++++++++++++++- .../pigeons/Gecko.g.kt | 19 ++ .../lib/src/pigeons/gecko.g.dart | 15 ++ .../pigeons/gecko.dart | 23 ++ 12 files changed, 454 insertions(+), 190 deletions(-) create mode 100644 app/lib/features/geckoview/features/history/domain/entities/history_filter_options.dart create mode 100644 app/lib/features/geckoview/features/history/domain/entities/history_filter_options.g.dart diff --git a/app/lib/core/routing/routes.browser.dart b/app/lib/core/routing/routes.browser.dart index c104b48c..c0fab4d9 100644 --- a/app/lib/core/routing/routes.browser.dart +++ b/app/lib/core/routing/routes.browser.dart @@ -28,6 +28,7 @@ part of 'routes.dart'; path: 'search/:tabType/:searchText', ), TypedGoRoute(name: 'TorProxyRoute', path: 'tor_proxy'), + TypedGoRoute(name: 'HistoryRoute', path: 'history'), TypedGoRoute( name: 'ContextMenuRoute', path: 'context_menu', @@ -178,3 +179,10 @@ class OpenSharedContentRoute extends GoRouteData with _$OpenSharedContentRoute { return DialogPage(builder: (_) => OpenSharedContent(sharedUrl: $extra)); } } + +class HistoryRoute extends GoRouteData with _$HistoryRoute { + @override + Widget build(BuildContext context, GoRouterState state) { + return const HistoryScreen(); + } +} diff --git a/app/lib/core/routing/routes.dart b/app/lib/core/routing/routes.dart index 2214ace5..35faad96 100644 --- a/app/lib/core/routing/routes.dart +++ b/app/lib/core/routing/routes.dart @@ -31,6 +31,7 @@ import 'package:weblibre/features/geckoview/features/browser/presentation/dialog import 'package:weblibre/features/geckoview/features/browser/presentation/screens/browser.dart'; import 'package:weblibre/features/geckoview/features/contextmenu/extensions/hit_result.dart'; import 'package:weblibre/features/geckoview/features/contextmenu/presentation/context_menu_dialog.dart'; +import 'package:weblibre/features/geckoview/features/history/presentation/screens/history.dart'; import 'package:weblibre/features/geckoview/features/search/presentation/screens/search.dart'; import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart'; import 'package:weblibre/features/geckoview/features/tabs/presentation/screens/container_edit.dart'; diff --git a/app/lib/core/routing/routes.g.dart b/app/lib/core/routing/routes.g.dart index 48760524..b1bd1e3e 100644 --- a/app/lib/core/routing/routes.g.dart +++ b/app/lib/core/routing/routes.g.dart @@ -295,6 +295,12 @@ RouteBase get $browserRoute => GoRouteData.$route( factory: _$TorProxyRoute._fromState, ), + GoRouteData.$route( + path: 'history', + name: 'HistoryRoute', + + factory: _$HistoryRoute._fromState, + ), GoRouteData.$route( path: 'context_menu', name: 'ContextMenuRoute', @@ -419,6 +425,26 @@ mixin _$TorProxyRoute on GoRouteData { void replace(BuildContext context) => context.replace(location); } +mixin _$HistoryRoute on GoRouteData { + static HistoryRoute _fromState(GoRouterState state) => HistoryRoute(); + + @override + String get location => GoRouteData.$location('/history'); + + @override + void go(BuildContext context) => context.go(location); + + @override + Future push(BuildContext context) => context.push(location); + + @override + void pushReplacement(BuildContext context) => + context.pushReplacement(location); + + @override + void replace(BuildContext context) => context.replace(location); +} + mixin _$ContextMenuRoute on GoRouteData { static ContextMenuRoute _fromState(GoRouterState state) => ContextMenuRoute(state.extra as String); diff --git a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart index 88dee46c..3e80685a 100644 --- a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart +++ b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart @@ -257,6 +257,13 @@ class BrowserBottomAppBar extends HookConsumerWidget { leadingIcon: const Icon(Icons.settings), child: const Text('Settings'), ), + MenuItemButton( + onPressed: () async { + await HistoryRoute().push(context); + }, + leadingIcon: const Icon(Icons.history), + child: const Text('History'), + ), Consumer( builder: (context, childRef, child) { final browserExtensions = childRef.watch( diff --git a/app/lib/features/geckoview/features/history/domain/entities/history_filter_options.dart b/app/lib/features/geckoview/features/history/domain/entities/history_filter_options.dart new file mode 100644 index 00000000..61f3cfa7 --- /dev/null +++ b/app/lib/features/geckoview/features/history/domain/entities/history_filter_options.dart @@ -0,0 +1,28 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:fast_equatable/fast_equatable.dart'; +import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; + +part 'history_filter_options.g.dart'; + +@CopyWith() +class HistoryFilterOptions with FastEquatable { + final DateTime? start; + final DateTime? end; + final Set visitTypes; + + HistoryFilterOptions({ + required this.start, + required this.end, + required this.visitTypes, + }); + + HistoryFilterOptions.withDefaults() + : this( + start: null, + end: null, + visitTypes: {VisitType.link, VisitType.typed}, + ); + + @override + List get hashParameters => [start, end, visitTypes]; +} diff --git a/app/lib/features/geckoview/features/history/domain/entities/history_filter_options.g.dart b/app/lib/features/geckoview/features/history/domain/entities/history_filter_options.g.dart new file mode 100644 index 00000000..daae825c --- /dev/null +++ b/app/lib/features/geckoview/features/history/domain/entities/history_filter_options.g.dart @@ -0,0 +1,80 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'history_filter_options.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$HistoryFilterOptionsCWProxy { + HistoryFilterOptions start(DateTime? start); + + HistoryFilterOptions end(DateTime? end); + + HistoryFilterOptions visitTypes(Set visitTypes); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `HistoryFilterOptions(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// HistoryFilterOptions(...).copyWith(id: 12, name: "My name") + /// ```` + HistoryFilterOptions call({ + DateTime? start, + DateTime? end, + Set visitTypes, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfHistoryFilterOptions.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfHistoryFilterOptions.copyWith.fieldName(...)` +class _$HistoryFilterOptionsCWProxyImpl + implements _$HistoryFilterOptionsCWProxy { + const _$HistoryFilterOptionsCWProxyImpl(this._value); + + final HistoryFilterOptions _value; + + @override + HistoryFilterOptions start(DateTime? start) => this(start: start); + + @override + HistoryFilterOptions end(DateTime? end) => this(end: end); + + @override + HistoryFilterOptions visitTypes(Set visitTypes) => + this(visitTypes: visitTypes); + + @override + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `HistoryFilterOptions(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// HistoryFilterOptions(...).copyWith(id: 12, name: "My name") + /// ```` + HistoryFilterOptions call({ + Object? start = const $CopyWithPlaceholder(), + Object? end = const $CopyWithPlaceholder(), + Object? visitTypes = const $CopyWithPlaceholder(), + }) { + return HistoryFilterOptions( + start: start == const $CopyWithPlaceholder() + ? _value.start + // ignore: cast_nullable_to_non_nullable + : start as DateTime?, + end: end == const $CopyWithPlaceholder() + ? _value.end + // ignore: cast_nullable_to_non_nullable + : end as DateTime?, + visitTypes: visitTypes == const $CopyWithPlaceholder() + ? _value.visitTypes + // ignore: cast_nullable_to_non_nullable + : visitTypes as Set, + ); + } +} + +extension $HistoryFilterOptionsCopyWith on HistoryFilterOptions { + /// Returns a callable class that can be used as follows: `instanceOfHistoryFilterOptions.copyWith(...)` or like so:`instanceOfHistoryFilterOptions.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$HistoryFilterOptionsCWProxy get copyWith => + _$HistoryFilterOptionsCWProxyImpl(this); +} diff --git a/app/lib/features/geckoview/features/history/domain/providers.dart b/app/lib/features/geckoview/features/history/domain/providers.dart index 0a01ddab..3e481559 100644 --- a/app/lib/features/geckoview/features/history/domain/providers.dart +++ b/app/lib/features/geckoview/features/history/domain/providers.dart @@ -20,16 +20,38 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:riverpod/riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:weblibre/features/geckoview/features/history/domain/entities/history_filter_options.dart'; part 'providers.g.dart'; -@Riverpod() -Future> browsingHistory( - Ref red, { - required DateTime start, - required DateTime end, - required Set types, -}) { - final service = GeckoHistoryService(); - return service.getDetailedVisits(start, end, types); +@Riverpod(keepAlive: true) +class HistoryFilter extends _$HistoryFilter { + void updateVisitType(VisitType type, bool value) { + if (value) { + state = state.copyWith.visitTypes({...state.visitTypes, type}); + } else { + state = state.copyWith.visitTypes({...state.visitTypes}..remove(type)); + } + } + + @override + HistoryFilterOptions build() { + return HistoryFilterOptions.withDefaults(); + } +} + +@Riverpod() +Future> browsingHistory(Ref ref) { + final options = ref.watch(historyFilterProvider); + + final service = GeckoHistoryService(); + return service + .getDetailedVisits( + options.start ?? DateTime(0), + options.end ?? DateTime(9999), + options.visitTypes, + ) + .then( + (visits) => visits..sort((a, b) => b.visitTime.compareTo(a.visitTime)), + ); } diff --git a/app/lib/features/geckoview/features/history/domain/providers.g.dart b/app/lib/features/geckoview/features/history/domain/providers.g.dart index ed2b7655..c2269713 100644 --- a/app/lib/features/geckoview/features/history/domain/providers.g.dart +++ b/app/lib/features/geckoview/features/history/domain/providers.g.dart @@ -6,186 +6,39 @@ part of 'providers.dart'; // RiverpodGenerator // ************************************************************************** -String _$browsingHistoryHash() => r'1f644757c60473f00dd94c9d312647baeaec525a'; - -/// Copied from Dart SDK -class _SystemHash { - _SystemHash._(); - - static int combine(int hash, int value) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + value); - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - // ignore: parameter_assignments - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } -} +String _$browsingHistoryHash() => r'a684c34fc370474a771c5fcc7982a200de2294e5'; /// See also [browsingHistory]. @ProviderFor(browsingHistory) -const browsingHistoryProvider = BrowsingHistoryFamily(); - -/// See also [browsingHistory]. -class BrowsingHistoryFamily extends Family>> { - /// See also [browsingHistory]. - const BrowsingHistoryFamily(); - - /// See also [browsingHistory]. - BrowsingHistoryProvider call({ - required DateTime start, - required DateTime end, - required Set types, - }) { - return BrowsingHistoryProvider(start: start, end: end, types: types); - } - - @override - BrowsingHistoryProvider getProviderOverride( - covariant BrowsingHistoryProvider provider, - ) { - return call( - start: provider.start, - end: provider.end, - types: provider.types, +final browsingHistoryProvider = + AutoDisposeFutureProvider>.internal( + browsingHistory, + name: r'browsingHistoryProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$browsingHistoryHash, + dependencies: null, + allTransitiveDependencies: null, ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'browsingHistoryProvider'; -} - -/// See also [browsingHistory]. -class BrowsingHistoryProvider - extends AutoDisposeFutureProvider> { - /// See also [browsingHistory]. - BrowsingHistoryProvider({ - required DateTime start, - required DateTime end, - required Set types, - }) : this._internal( - (ref) => browsingHistory( - ref as BrowsingHistoryRef, - start: start, - end: end, - types: types, - ), - from: browsingHistoryProvider, - name: r'browsingHistoryProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$browsingHistoryHash, - dependencies: BrowsingHistoryFamily._dependencies, - allTransitiveDependencies: - BrowsingHistoryFamily._allTransitiveDependencies, - start: start, - end: end, - types: types, - ); - - BrowsingHistoryProvider._internal( - super._createNotifier, { - required super.name, - required super.dependencies, - required super.allTransitiveDependencies, - required super.debugGetCreateSourceHash, - required super.from, - required this.start, - required this.end, - required this.types, - }) : super.internal(); - - final DateTime start; - final DateTime end; - final Set types; - - @override - Override overrideWith( - FutureOr> Function(BrowsingHistoryRef provider) create, - ) { - return ProviderOverride( - origin: this, - override: BrowsingHistoryProvider._internal( - (ref) => create(ref as BrowsingHistoryRef), - from: from, - name: null, - dependencies: null, - allTransitiveDependencies: null, - debugGetCreateSourceHash: null, - start: start, - end: end, - types: types, - ), - ); - } - - @override - AutoDisposeFutureProviderElement> createElement() { - return _BrowsingHistoryProviderElement(this); - } - - @override - bool operator ==(Object other) { - return other is BrowsingHistoryProvider && - other.start == start && - other.end == end && - other.types == types; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, start.hashCode); - hash = _SystemHash.combine(hash, end.hashCode); - hash = _SystemHash.combine(hash, types.hashCode); - - return _SystemHash.finish(hash); - } -} @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element -mixin BrowsingHistoryRef on AutoDisposeFutureProviderRef> { - /// The parameter `start` of this provider. - DateTime get start; +typedef BrowsingHistoryRef = AutoDisposeFutureProviderRef>; +String _$historyFilterHash() => r'271d60ce79f96ac49d450f01d21cbfdad684ce53'; - /// The parameter `end` of this provider. - DateTime get end; - - /// The parameter `types` of this provider. - Set get types; -} - -class _BrowsingHistoryProviderElement - extends AutoDisposeFutureProviderElement> - with BrowsingHistoryRef { - _BrowsingHistoryProviderElement(super.provider); - - @override - DateTime get start => (origin as BrowsingHistoryProvider).start; - @override - DateTime get end => (origin as BrowsingHistoryProvider).end; - @override - Set get types => (origin as BrowsingHistoryProvider).types; -} +/// See also [HistoryFilter]. +@ProviderFor(HistoryFilter) +final historyFilterProvider = + NotifierProvider.internal( + HistoryFilter.new, + name: r'historyFilterProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$historyFilterHash, + dependencies: null, + allTransitiveDependencies: null, + ); +typedef _$HistoryFilter = Notifier; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/app/lib/features/geckoview/features/history/presentation/screens/history.dart b/app/lib/features/geckoview/features/history/presentation/screens/history.dart index 93c7e991..23866edc 100644 --- a/app/lib/features/geckoview/features/history/presentation/screens/history.dart +++ b/app/lib/features/geckoview/features/history/presentation/screens/history.dart @@ -1,22 +1,204 @@ +import 'package:collection/collection.dart'; +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:intl/intl.dart' show DateFormat; +import 'package:nullability/nullability.dart'; +import 'package:sliver_tools/sliver_tools.dart'; +import 'package:timeago/timeago.dart' as timeago; import 'package:weblibre/features/geckoview/features/history/domain/providers.dart'; +import 'package:weblibre/presentation/hooks/menu_controller.dart'; +import 'package:weblibre/presentation/widgets/failure_widget.dart'; +import 'package:weblibre/presentation/widgets/url_icon.dart'; + +class Section extends MultiSliver { + static final _datePattern = DateFormat('yMMMMd').addPattern('Hm'); + + Section({ + Key? key, + required BuildContext context, + required String title, + required List items, + }) : super( + key: key, + pushPinnedChildren: true, + children: [ + SliverPinnedHeader( + child: Container( + padding: const EdgeInsets.only(left: 24, top: 8), + color: Theme.of(context).canvasColor, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, style: Theme.of(context).textTheme.bodyLarge), + const Divider(), + ], + ), + ), + ), + SliverList.builder( + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + + return Column( + key: ValueKey(item.hashCode), + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListTile( + leading: UrlIcon([Uri.parse(item.url)], iconSize: 24), + title: item.title.mapNotNull((title) => Text(title)), + subtitle: Text( + item.url, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + Padding( + padding: const EdgeInsets.only(left: 54), + child: Wrap( + spacing: 8.0, + children: [ + Chip( + label: switch (item.visitType) { + VisitType.link => const Text('Followed Link'), + VisitType.typed => const Text('Typed Address'), + VisitType.embed => const Text( + 'Embedded Page Element', + ), + VisitType.redirectPermanent => const Text( + 'Temporary Redirect', + ), + VisitType.redirectTemporary => const Text( + 'Permanent Redirect', + ), + VisitType.download => const Text('Download'), + VisitType.framedLink => const Text('Frame'), + VisitType.reload => const Text('Page Reload'), + VisitType.bookmark => throw UnimplementedError(), + }, + ), + Chip( + label: Text( + _datePattern.format( + DateTime.fromMillisecondsSinceEpoch( + item.visitTime, + ), + ), + ), + ), + ], + ), + ), + ], + ); + }, + ), + ], + ); +} class HistoryScreen extends HookConsumerWidget { const HistoryScreen({super.key}); + @override Widget build(BuildContext context, WidgetRef ref) { - final history = ref.watch( - browsingHistoryProvider( - start: DateTime(0), - end: DateTime.now(), - types: { - VisitType.link, - VisitType.redirectPermanent, - VisitType.redirectTemporary, - VisitType.typed, + final historyFilter = ref.watch(historyFilterProvider); + + final menuController = useMenuController(); + + final historyEntries = ref.watch(browsingHistoryProvider); + + return Scaffold( + appBar: AppBar( + actions: [ + MenuAnchor( + controller: menuController, + menuChildren: [ + ...VisitType.values + .whereNot( + (element) => const {VisitType.bookmark}.contains(element), + ) + .map( + (type) => CheckboxMenuButton( + value: historyFilter.visitTypes.contains(type), + onChanged: (value) { + if (value != null) { + ref + .read(historyFilterProvider.notifier) + .updateVisitType(type, value); + } + }, + child: switch (type) { + VisitType.link => const Text('Followed Links'), + VisitType.typed => const Text('Typed Addresses'), + VisitType.embed => const Text('Embedded Page Elements'), + VisitType.redirectPermanent => const Text( + 'Temporary Redirects', + ), + VisitType.redirectTemporary => const Text( + 'Permanent Redirects', + ), + VisitType.download => const Text('Downloads'), + VisitType.framedLink => const Text('Frames'), + VisitType.reload => const Text('Page Reloads'), + VisitType.bookmark => throw UnimplementedError(), + }, + ), + ), + ], + child: IconButton( + onPressed: () { + if (menuController.isOpen) { + menuController.close(); + } else { + menuController.open(); + } + }, + icon: const Icon(Icons.more_vert), + ), + ), + ], + ), + body: historyEntries.when( + data: (data) { + return RefreshIndicator( + onRefresh: () async { + // ignore: unused_result + await ref.refresh(browsingHistoryProvider.future); + }, + child: HookBuilder( + builder: (context) { + final groups = useMemoized( + () => data.groupListsBy( + (element) => timeago.format( + DateTime.fromMillisecondsSinceEpoch(element.visitTime), + ), + ), + [EquatableValue(data)], + ); + + return CustomScrollView( + slivers: [ + for (final MapEntry(:key, :value) in groups.entries) + Section(context: context, title: key, items: value), + ], + ); + }, + ), + ); }, + error: (error, stackTrace) => Center( + child: FailureWidget( + title: 'Failed to load History', + exception: error, + ), + ), + loading: () => const Center(child: CircularProgressIndicator()), ), ); } 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 7f891028..95862c34 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 @@ -167,14 +167,33 @@ enum class CookieSameSiteStatus(val raw: Int) { } enum class VisitType(val raw: Int) { + /** The user followed a link and got a new toplevel window. */ LINK(0), + /** + * 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(1), + /** The user followed a bookmark to get to the page. */ BOOKMARK(2), + /** + * 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(3), + /** Set when the transition was a permanent redirect. */ REDIRECT_PERMANENT(4), + /** Set when the transition was a temporary redirect. */ REDIRECT_TEMPORARY(5), + /** Set when the transition is a download. */ DOWNLOAD(6), + /** The user followed a link and got a visit in a frame. */ FRAMED_LINK(7), + /** The user reloaded a page. */ RELOAD(8); companion object { 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 e734c3d9..e3d97a0e 100644 --- a/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart +++ b/packages/flutter_mozilla_components/lib/src/pigeons/gecko.g.dart @@ -93,14 +93,29 @@ enum CookieSameSiteStatus { } 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, } diff --git a/packages/flutter_mozilla_components/pigeons/gecko.dart b/packages/flutter_mozilla_components/pigeons/gecko.dart index 6d24ae64..f66a11b4 100644 --- a/packages/flutter_mozilla_components/pigeons/gecko.dart +++ b/packages/flutter_mozilla_components/pigeons/gecko.dart @@ -383,14 +383,37 @@ class Cookie { } 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, }