add separate history download screen
This commit is contained in:
@@ -1143,6 +1143,13 @@ RouteBase get $historyRoute => GoRouteData.$route(
|
||||
path: '/history',
|
||||
name: 'HistoryRoute',
|
||||
factory: $HistoryRoute._fromState,
|
||||
routes: [
|
||||
GoRouteData.$route(
|
||||
path: 'downloads',
|
||||
name: 'HistoryDownloadsRoute',
|
||||
factory: $HistoryDownloadsRoute._fromState,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
mixin $HistoryRoute on GoRouteData {
|
||||
@@ -1165,6 +1172,27 @@ mixin $HistoryRoute on GoRouteData {
|
||||
void replace(BuildContext context) => context.replace(location);
|
||||
}
|
||||
|
||||
mixin $HistoryDownloadsRoute on GoRouteData {
|
||||
static HistoryDownloadsRoute _fromState(GoRouterState state) =>
|
||||
const HistoryDownloadsRoute();
|
||||
|
||||
@override
|
||||
String get location => GoRouteData.$location('/history/downloads');
|
||||
|
||||
@override
|
||||
void go(BuildContext context) => context.go(location);
|
||||
|
||||
@override
|
||||
Future<T?> push<T>(BuildContext context) => context.push<T>(location);
|
||||
|
||||
@override
|
||||
void pushReplacement(BuildContext context) =>
|
||||
context.pushReplacement(location);
|
||||
|
||||
@override
|
||||
void replace(BuildContext context) => context.replace(location);
|
||||
}
|
||||
|
||||
RouteBase get $profileListRoute => GoRouteData.$route(
|
||||
path: '/profiles',
|
||||
name: 'ProfileListRoute',
|
||||
|
||||
@@ -19,7 +19,16 @@
|
||||
*/
|
||||
part of 'routes.dart';
|
||||
|
||||
@TypedGoRoute<HistoryRoute>(name: 'HistoryRoute', path: '/history')
|
||||
@TypedGoRoute<HistoryRoute>(
|
||||
name: 'HistoryRoute',
|
||||
path: '/history',
|
||||
routes: [
|
||||
TypedGoRoute<HistoryDownloadsRoute>(
|
||||
name: 'HistoryDownloadsRoute',
|
||||
path: 'downloads',
|
||||
),
|
||||
],
|
||||
)
|
||||
class HistoryRoute extends GoRouteData with $HistoryRoute {
|
||||
const HistoryRoute();
|
||||
|
||||
@@ -28,3 +37,12 @@ class HistoryRoute extends GoRouteData with $HistoryRoute {
|
||||
return const HistoryScreen();
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryDownloadsRoute extends GoRouteData with $HistoryDownloadsRoute {
|
||||
const HistoryDownloadsRoute();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) {
|
||||
return const HistoryScreen(mode: HistoryScreenMode.downloads);
|
||||
}
|
||||
}
|
||||
|
||||
+14
-5
@@ -54,12 +54,12 @@ class BrowserNavigationDrawer extends HookConsumerWidget {
|
||||
|
||||
return NavigationDrawer(
|
||||
backgroundColor: colorScheme.surface,
|
||||
header: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [_ProfileHeader(), _SyncTile(), const Divider()],
|
||||
),
|
||||
children: [
|
||||
// Profile Header
|
||||
_ProfileHeader(),
|
||||
_SyncTile(),
|
||||
const Divider(),
|
||||
|
||||
// Section 1: Tools & Configuration
|
||||
_ExtensionsSection(),
|
||||
|
||||
@@ -107,6 +107,15 @@ class BrowserNavigationDrawer extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
|
||||
ListTile(
|
||||
leading: const Icon(MdiIcons.fileDownload),
|
||||
title: const Text('Downloads'),
|
||||
onTap: () async {
|
||||
Navigator.of(context).pop();
|
||||
await const HistoryDownloadsRoute().push(context);
|
||||
},
|
||||
),
|
||||
|
||||
ListTile(
|
||||
leading: const Icon(MdiIcons.bookmarkMultiple),
|
||||
title: const Text('Bookmarks'),
|
||||
|
||||
@@ -30,7 +30,7 @@ part 'providers.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
@JsonPersist()
|
||||
class HistoryFilter extends _$HistoryFilter {
|
||||
class HistoryVisitsFilter extends _$HistoryVisitsFilter {
|
||||
void updateVisitType(VisitType type, bool value) {
|
||||
if (value) {
|
||||
state = state.copyWith.visitTypes({...state.visitTypes, type});
|
||||
@@ -51,16 +51,54 @@ class HistoryFilter extends _$HistoryFilter {
|
||||
HistoryFilterOptions build() {
|
||||
persist(
|
||||
ref.watch(riverpodDatabaseStorageProvider),
|
||||
key: 'HistoryFilterOptions',
|
||||
key: 'HistoryVisitsFilterOptions',
|
||||
);
|
||||
|
||||
return stateOrNull ?? HistoryFilterOptions.withDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
@JsonPersist()
|
||||
class HistoryDownloadsFilter extends _$HistoryDownloadsFilter {
|
||||
void reset() {
|
||||
state = HistoryFilterOptions(
|
||||
dateRange: null,
|
||||
visitTypes: const {VisitType.download},
|
||||
);
|
||||
}
|
||||
|
||||
void setDateRange(DateTimeRange<DateTime>? range) {
|
||||
state = state.copyWith.dateRange(range);
|
||||
}
|
||||
|
||||
@override
|
||||
HistoryFilterOptions build() {
|
||||
persist(
|
||||
ref.watch(riverpodDatabaseStorageProvider),
|
||||
key: 'HistoryDownloadsFilterOptions',
|
||||
);
|
||||
|
||||
return stateOrNull ??
|
||||
HistoryFilterOptions(
|
||||
dateRange: null,
|
||||
visitTypes: const {VisitType.download},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Future<List<VisitInfo>> browsingHistory(Ref ref) {
|
||||
final options = ref.watch(historyFilterProvider);
|
||||
final options = ref.watch(historyVisitsFilterProvider);
|
||||
|
||||
return ref
|
||||
.read(historyRepositoryProvider.notifier)
|
||||
.getDetailedVisits(options);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Future<List<VisitInfo>> browsingDownloads(Ref ref) {
|
||||
final options = ref.watch(historyDownloadsFilterProvider);
|
||||
|
||||
return ref
|
||||
.read(historyRepositoryProvider.notifier)
|
||||
|
||||
@@ -9,30 +9,30 @@ part of 'providers.dart';
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(HistoryFilter)
|
||||
@ProviderFor(HistoryVisitsFilter)
|
||||
@JsonPersist()
|
||||
final historyFilterProvider = HistoryFilterProvider._();
|
||||
final historyVisitsFilterProvider = HistoryVisitsFilterProvider._();
|
||||
|
||||
@JsonPersist()
|
||||
final class HistoryFilterProvider
|
||||
extends $NotifierProvider<HistoryFilter, HistoryFilterOptions> {
|
||||
HistoryFilterProvider._()
|
||||
final class HistoryVisitsFilterProvider
|
||||
extends $NotifierProvider<HistoryVisitsFilter, HistoryFilterOptions> {
|
||||
HistoryVisitsFilterProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'historyFilterProvider',
|
||||
name: r'historyVisitsFilterProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$historyFilterHash();
|
||||
String debugGetCreateSourceHash() => _$historyVisitsFilterHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
HistoryFilter create() => HistoryFilter();
|
||||
HistoryVisitsFilter create() => HistoryVisitsFilter();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(HistoryFilterOptions value) {
|
||||
@@ -43,10 +43,69 @@ final class HistoryFilterProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$historyFilterHash() => r'685b92590011ec450ef0c19820e4a6750d26b79d';
|
||||
String _$historyVisitsFilterHash() =>
|
||||
r'a4bf6c41c9180166365084cb7c7981558ac7ad36';
|
||||
|
||||
@JsonPersist()
|
||||
abstract class _$HistoryFilterBase extends $Notifier<HistoryFilterOptions> {
|
||||
abstract class _$HistoryVisitsFilterBase
|
||||
extends $Notifier<HistoryFilterOptions> {
|
||||
HistoryFilterOptions build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<HistoryFilterOptions, HistoryFilterOptions>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<HistoryFilterOptions, HistoryFilterOptions>,
|
||||
HistoryFilterOptions,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(HistoryDownloadsFilter)
|
||||
@JsonPersist()
|
||||
final historyDownloadsFilterProvider = HistoryDownloadsFilterProvider._();
|
||||
|
||||
@JsonPersist()
|
||||
final class HistoryDownloadsFilterProvider
|
||||
extends $NotifierProvider<HistoryDownloadsFilter, HistoryFilterOptions> {
|
||||
HistoryDownloadsFilterProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'historyDownloadsFilterProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$historyDownloadsFilterHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
HistoryDownloadsFilter create() => HistoryDownloadsFilter();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(HistoryFilterOptions value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<HistoryFilterOptions>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$historyDownloadsFilterHash() =>
|
||||
r'b44de5aced7dadba361fddf69b8462ff92252a99';
|
||||
|
||||
@JsonPersist()
|
||||
abstract class _$HistoryDownloadsFilterBase
|
||||
extends $Notifier<HistoryFilterOptions> {
|
||||
HistoryFilterOptions build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
@@ -101,17 +160,88 @@ final class BrowsingHistoryProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$browsingHistoryHash() => r'3b6ee5853387481d7544bc9733741a5519f84f40';
|
||||
String _$browsingHistoryHash() => r'6f26228da28f6f67844551bf430025b161731bb2';
|
||||
|
||||
@ProviderFor(browsingDownloads)
|
||||
final browsingDownloadsProvider = BrowsingDownloadsProvider._();
|
||||
|
||||
final class BrowsingDownloadsProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
AsyncValue<List<VisitInfo>>,
|
||||
List<VisitInfo>,
|
||||
FutureOr<List<VisitInfo>>
|
||||
>
|
||||
with $FutureModifier<List<VisitInfo>>, $FutureProvider<List<VisitInfo>> {
|
||||
BrowsingDownloadsProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'browsingDownloadsProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$browsingDownloadsHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$FutureProviderElement<List<VisitInfo>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $FutureProviderElement(pointer);
|
||||
|
||||
@override
|
||||
FutureOr<List<VisitInfo>> create(Ref ref) {
|
||||
return browsingDownloads(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$browsingDownloadsHash() => r'd05e3c079c6de349ff9e910ca597ad7c78f87a16';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
abstract class _$HistoryFilter extends _$HistoryFilterBase {
|
||||
abstract class _$HistoryVisitsFilter extends _$HistoryVisitsFilterBase {
|
||||
/// The default key used by [persist].
|
||||
String get key {
|
||||
const resolvedKey = "HistoryFilter";
|
||||
const resolvedKey = "HistoryVisitsFilter";
|
||||
return resolvedKey;
|
||||
}
|
||||
|
||||
/// A variant of [persist], for JSON-specific encoding.
|
||||
///
|
||||
/// You can override [key] to customize the key used for storage.
|
||||
PersistResult persist(
|
||||
FutureOr<Storage<String, String>> storage, {
|
||||
String? key,
|
||||
String Function(HistoryFilterOptions state)? encode,
|
||||
HistoryFilterOptions Function(String encoded)? decode,
|
||||
StorageOptions options = const StorageOptions(),
|
||||
}) {
|
||||
return NotifierPersistX(this).persist<String, String>(
|
||||
storage,
|
||||
key: key ?? this.key,
|
||||
encode: encode ?? $jsonCodex.encode,
|
||||
decode:
|
||||
decode ??
|
||||
(encoded) {
|
||||
final e = $jsonCodex.decode(encoded);
|
||||
return HistoryFilterOptions.fromJson(e as Map<String, Object?>);
|
||||
},
|
||||
options: options,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _$HistoryDownloadsFilter extends _$HistoryDownloadsFilterBase {
|
||||
/// The default key used by [persist].
|
||||
String get key {
|
||||
const resolvedKey = "HistoryDownloadsFilter";
|
||||
return resolvedKey;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ class Section extends MultiSliver {
|
||||
required Set<VisitInfo> selectedItems,
|
||||
required void Function(VisitInfo) onTap,
|
||||
required void Function(VisitInfo) onLongPress,
|
||||
required Future<void> Function(VisitInfo) onDelete,
|
||||
}) : super(
|
||||
pushPinnedChildren: true,
|
||||
children: [
|
||||
@@ -103,37 +104,11 @@ class Section extends MultiSliver {
|
||||
),
|
||||
),
|
||||
subtitle: UriBreadcrumb(uri: uri),
|
||||
trailing: Consumer(
|
||||
builder: (context, ref, _) {
|
||||
return IconButton(
|
||||
onPressed: () async {
|
||||
await ref
|
||||
.read(historyRepositoryProvider.notifier)
|
||||
.deleteVisit(item);
|
||||
|
||||
final downloadedFile = item.title.mapNotNull(
|
||||
(title) => File(title),
|
||||
);
|
||||
|
||||
if (await downloadedFile?.exists() == true) {
|
||||
if (context.mounted) {
|
||||
final delete = await showDeleteFileDialog(
|
||||
context,
|
||||
downloadedFile.toString(),
|
||||
);
|
||||
|
||||
if (delete?.delete == true) {
|
||||
await downloadedFile!.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: unused_result
|
||||
await ref.refresh(browsingHistoryProvider.future);
|
||||
},
|
||||
icon: const Icon(MdiIcons.closeCircle),
|
||||
);
|
||||
trailing: IconButton(
|
||||
onPressed: () async {
|
||||
await onDelete(item);
|
||||
},
|
||||
icon: const Icon(MdiIcons.closeCircle),
|
||||
),
|
||||
onTap: () {
|
||||
onTap(item);
|
||||
@@ -196,21 +171,74 @@ class Section extends MultiSliver {
|
||||
);
|
||||
}
|
||||
|
||||
enum HistoryScreenMode { history, downloads }
|
||||
|
||||
class HistoryScreen extends HookConsumerWidget {
|
||||
const HistoryScreen({super.key});
|
||||
const HistoryScreen({super.key, this.mode = HistoryScreenMode.history});
|
||||
|
||||
final HistoryScreenMode mode;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final historyFilter = ref.watch(historyFilterProvider);
|
||||
final isDownloadsMode = mode == HistoryScreenMode.downloads;
|
||||
|
||||
final textFilterEnabled = useState(false);
|
||||
final textFilterController = useTextEditingController();
|
||||
|
||||
final menuController = useMenuController();
|
||||
|
||||
final historyEntries = ref.watch(browsingHistoryProvider);
|
||||
final historyFilter = isDownloadsMode
|
||||
? ref.watch(historyDownloadsFilterProvider)
|
||||
: ref.watch(historyVisitsFilterProvider);
|
||||
final historyEntries = isDownloadsMode
|
||||
? ref.watch(browsingDownloadsProvider)
|
||||
: ref.watch(browsingHistoryProvider);
|
||||
|
||||
final selectedItems = useState(<VisitInfo>{});
|
||||
final defaultDownloadsFilter = HistoryFilterOptions(
|
||||
dateRange: null,
|
||||
visitTypes: const {VisitType.download},
|
||||
);
|
||||
final hasActiveFilter = isDownloadsMode
|
||||
? historyFilter != defaultDownloadsFilter
|
||||
: historyFilter != HistoryFilterOptions.withDefaults();
|
||||
|
||||
Future<void> refreshHistoryEntries() async {
|
||||
if (isDownloadsMode) {
|
||||
// ignore: unused_result
|
||||
await ref.refresh(browsingDownloadsProvider.future);
|
||||
} else {
|
||||
// ignore: unused_result
|
||||
await ref.refresh(browsingHistoryProvider.future);
|
||||
}
|
||||
}
|
||||
|
||||
void setDateRange(DateTimeRange<DateTime>? range) {
|
||||
if (isDownloadsMode) {
|
||||
ref.read(historyDownloadsFilterProvider.notifier).setDateRange(range);
|
||||
} else {
|
||||
ref.read(historyVisitsFilterProvider.notifier).setDateRange(range);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteHistoryItem(VisitInfo item) async {
|
||||
await ref.read(historyRepositoryProvider.notifier).deleteVisit(item);
|
||||
|
||||
final downloadedFile = item.title.mapNotNull((title) => File(title));
|
||||
|
||||
if (await downloadedFile?.exists() == true && context.mounted) {
|
||||
final delete = await showDeleteFileDialog(
|
||||
context,
|
||||
downloadedFile.toString(),
|
||||
);
|
||||
|
||||
if (delete?.delete == true) {
|
||||
await downloadedFile!.delete();
|
||||
}
|
||||
}
|
||||
|
||||
await refreshHistoryEntries();
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
@@ -220,7 +248,9 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.only(top: 12),
|
||||
border: InputBorder.none,
|
||||
hintText: 'Filter history...',
|
||||
hintText: isDownloadsMode
|
||||
? 'Filter downloads...'
|
||||
: 'Filter history...',
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () {
|
||||
@@ -235,7 +265,7 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
),
|
||||
)
|
||||
: selectedItems.value.isEmpty
|
||||
? const Text('History')
|
||||
? Text(isDownloadsMode ? 'Downloads' : 'History')
|
||||
: Text('${selectedItems.value.length} selected'),
|
||||
actions: [
|
||||
if (selectedItems.value.isNotEmpty)
|
||||
@@ -272,8 +302,7 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
selectedItems.value = {};
|
||||
// ignore: unused_result
|
||||
await ref.refresh(browsingHistoryProvider.future);
|
||||
await refreshHistoryEntries();
|
||||
},
|
||||
icon: const Icon(Icons.delete),
|
||||
)
|
||||
@@ -282,11 +311,15 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
onPressed: () async {
|
||||
await showDeleteDataDialog(
|
||||
context,
|
||||
initialSettings: {DeleteBrowsingDataType.history},
|
||||
initialSettings: {
|
||||
if (isDownloadsMode)
|
||||
DeleteBrowsingDataType.downloads
|
||||
else
|
||||
DeleteBrowsingDataType.history,
|
||||
},
|
||||
);
|
||||
|
||||
// ignore: unused_result
|
||||
await ref.refresh(browsingHistoryProvider.future);
|
||||
await refreshHistoryEntries();
|
||||
},
|
||||
icon: const Icon(Icons.delete),
|
||||
),
|
||||
@@ -307,9 +340,7 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
trailingIcon: historyFilter.dateRange.mapNotNull(
|
||||
(_) => IconButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(historyFilterProvider.notifier)
|
||||
.setDateRange(null);
|
||||
setDateRange(null);
|
||||
},
|
||||
icon: const Icon(Icons.clear),
|
||||
),
|
||||
@@ -331,53 +362,52 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
lastDate: DateTime.now(),
|
||||
);
|
||||
|
||||
ref
|
||||
.read(historyFilterProvider.notifier)
|
||||
.setDateRange(
|
||||
range.mapNotNull(
|
||||
(range) => DateTimeRange(
|
||||
start: range.start,
|
||||
//Make sure to include last day fully
|
||||
end: range.end.add(
|
||||
const Duration(days: 1) -
|
||||
const Duration(milliseconds: 1),
|
||||
),
|
||||
),
|
||||
setDateRange(
|
||||
range.mapNotNull(
|
||||
(range) => DateTimeRange(
|
||||
start: range.start,
|
||||
// Make sure to include last day fully.
|
||||
end: range.end.add(
|
||||
const Duration(days: 1) -
|
||||
const Duration(milliseconds: 1),
|
||||
),
|
||||
);
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
...{VisitType.link, VisitType.reload, VisitType.download}.map(
|
||||
(type) => CheckboxMenuButton(
|
||||
closeOnActivate: false,
|
||||
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(
|
||||
'VisitType.bookmark filter not implemented',
|
||||
),
|
||||
},
|
||||
if (!isDownloadsMode) const Divider(),
|
||||
if (!isDownloadsMode)
|
||||
...{VisitType.link, VisitType.reload, VisitType.download}.map(
|
||||
(type) => CheckboxMenuButton(
|
||||
closeOnActivate: false,
|
||||
value: historyFilter.visitTypes.contains(type),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
ref
|
||||
.read(historyVisitsFilterProvider.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(
|
||||
'VisitType.bookmark filter not implemented',
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(MdiIcons.restore),
|
||||
@@ -385,8 +415,11 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
onPressed: () {
|
||||
textFilterController.clear();
|
||||
textFilterEnabled.value = false;
|
||||
|
||||
ref.read(historyFilterProvider.notifier).reset();
|
||||
if (isDownloadsMode) {
|
||||
ref.read(historyDownloadsFilterProvider.notifier).reset();
|
||||
} else {
|
||||
ref.read(historyVisitsFilterProvider.notifier).reset();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -399,8 +432,7 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
}
|
||||
},
|
||||
icon: Badge(
|
||||
isLabelVisible:
|
||||
historyFilter != HistoryFilterOptions.withDefaults(),
|
||||
isLabelVisible: hasActiveFilter,
|
||||
child: const Icon(MdiIcons.filter),
|
||||
),
|
||||
),
|
||||
@@ -413,8 +445,7 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
data: (data) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
// ignore: unused_result
|
||||
await ref.refresh(browsingHistoryProvider.future);
|
||||
await refreshHistoryEntries();
|
||||
},
|
||||
child: HookBuilder(
|
||||
builder: (context) {
|
||||
@@ -464,6 +495,7 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
items: value,
|
||||
selectedItems: selectedItems.value,
|
||||
onLongPress: toggleSelected,
|
||||
onDelete: deleteHistoryItem,
|
||||
onTap: (item) async {
|
||||
if (selectedItems.value.isNotEmpty) {
|
||||
toggleSelected(item);
|
||||
@@ -492,7 +524,9 @@ class HistoryScreen extends HookConsumerWidget {
|
||||
},
|
||||
error: (error, stackTrace) => Center(
|
||||
child: FailureWidget(
|
||||
title: 'Failed to load History',
|
||||
title: isDownloadsMode
|
||||
? 'Failed to load Downloads'
|
||||
: 'Failed to load History',
|
||||
exception: error,
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user