prepare for multiple apps
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:riverpod/riverpod.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang_data.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang_group.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang_key.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/search_history_entry.dart';
|
||||
import 'package:weblibre/features/bangs/domain/repositories/data.dart';
|
||||
import 'package:weblibre/features/bangs/domain/repositories/sync.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
|
||||
part 'bangs.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
Stream<BangData?> defaultSearchBangData(Ref ref) {
|
||||
final key = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(value) => value.defaultSearchProvider,
|
||||
),
|
||||
);
|
||||
|
||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||
return repository.watchBang(key);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<BangData?> bangData(Ref ref, BangKey key) {
|
||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||
return repository.watchBang(key);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<Map<String, List<String>>> bangCategories(Ref ref) {
|
||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||
return repository.watchCategories();
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<List<BangData>> bangList(
|
||||
Ref ref, {
|
||||
List<String>? triggers,
|
||||
List<BangGroup>? groups,
|
||||
String? domain,
|
||||
({String category, String? subCategory})? categoryFilter,
|
||||
bool? orderMostFrequentFirst,
|
||||
}) {
|
||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||
return repository.watchBangs(
|
||||
triggers: triggers,
|
||||
groups: groups,
|
||||
domain: domain,
|
||||
categoryFilter: categoryFilter,
|
||||
orderMostFrequentFirst: orderMostFrequentFirst,
|
||||
);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<List<BangData>> frequentBangList(Ref ref) {
|
||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||
return repository.watchFrequentBangs();
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<List<SearchHistoryEntry>> searchHistory(Ref ref) {
|
||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||
final maxSearchHistoryEntries = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(s) => s.maxSearchHistoryEntries,
|
||||
),
|
||||
);
|
||||
return repository.watchSearchHistory(limit: maxSearchHistoryEntries);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<DateTime?> lastSyncOfGroup(Ref ref, BangGroup group) {
|
||||
final repository = ref.watch(bangSyncRepositoryProvider.notifier);
|
||||
return repository.watchLastSyncOfGroup(group);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<int> bangCountOfGroup(Ref ref, BangGroup group) {
|
||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||
return repository.watchBangCount(group);
|
||||
}
|
||||
@@ -0,0 +1,496 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'bangs.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(defaultSearchBangData)
|
||||
final defaultSearchBangDataProvider = DefaultSearchBangDataProvider._();
|
||||
|
||||
final class DefaultSearchBangDataProvider
|
||||
extends
|
||||
$FunctionalProvider<AsyncValue<BangData?>, BangData?, Stream<BangData?>>
|
||||
with $FutureModifier<BangData?>, $StreamProvider<BangData?> {
|
||||
DefaultSearchBangDataProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'defaultSearchBangDataProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$defaultSearchBangDataHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<BangData?> $createElement($ProviderPointer pointer) =>
|
||||
$StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<BangData?> create(Ref ref) {
|
||||
return defaultSearchBangData(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$defaultSearchBangDataHash() =>
|
||||
r'5f43b8989219cf3cb2f5ca65df351b6cb100427f';
|
||||
|
||||
@ProviderFor(bangData)
|
||||
final bangDataProvider = BangDataFamily._();
|
||||
|
||||
final class BangDataProvider
|
||||
extends
|
||||
$FunctionalProvider<AsyncValue<BangData?>, BangData?, Stream<BangData?>>
|
||||
with $FutureModifier<BangData?>, $StreamProvider<BangData?> {
|
||||
BangDataProvider._({
|
||||
required BangDataFamily super.from,
|
||||
required BangKey super.argument,
|
||||
}) : super(
|
||||
retry: null,
|
||||
name: r'bangDataProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$bangDataHash();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return r'bangDataProvider'
|
||||
''
|
||||
'($argument)';
|
||||
}
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<BangData?> $createElement($ProviderPointer pointer) =>
|
||||
$StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<BangData?> create(Ref ref) {
|
||||
final argument = this.argument as BangKey;
|
||||
return bangData(ref, argument);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is BangDataProvider && other.argument == argument;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return argument.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
String _$bangDataHash() => r'bd9f5ec8b29aab74620a9b5a4246cb7e3b2fd377';
|
||||
|
||||
final class BangDataFamily extends $Family
|
||||
with $FunctionalFamilyOverride<Stream<BangData?>, BangKey> {
|
||||
BangDataFamily._()
|
||||
: super(
|
||||
retry: null,
|
||||
name: r'bangDataProvider',
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
isAutoDispose: true,
|
||||
);
|
||||
|
||||
BangDataProvider call(BangKey key) =>
|
||||
BangDataProvider._(argument: key, from: this);
|
||||
|
||||
@override
|
||||
String toString() => r'bangDataProvider';
|
||||
}
|
||||
|
||||
@ProviderFor(bangCategories)
|
||||
final bangCategoriesProvider = BangCategoriesProvider._();
|
||||
|
||||
final class BangCategoriesProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
AsyncValue<Map<String, List<String>>>,
|
||||
Map<String, List<String>>,
|
||||
Stream<Map<String, List<String>>>
|
||||
>
|
||||
with
|
||||
$FutureModifier<Map<String, List<String>>>,
|
||||
$StreamProvider<Map<String, List<String>>> {
|
||||
BangCategoriesProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'bangCategoriesProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$bangCategoriesHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<Map<String, List<String>>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<Map<String, List<String>>> create(Ref ref) {
|
||||
return bangCategories(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$bangCategoriesHash() => r'947fcfd2dffcc7f585c6ed7379d319f4fe72293a';
|
||||
|
||||
@ProviderFor(bangList)
|
||||
final bangListProvider = BangListFamily._();
|
||||
|
||||
final class BangListProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
AsyncValue<List<BangData>>,
|
||||
List<BangData>,
|
||||
Stream<List<BangData>>
|
||||
>
|
||||
with $FutureModifier<List<BangData>>, $StreamProvider<List<BangData>> {
|
||||
BangListProvider._({
|
||||
required BangListFamily super.from,
|
||||
required ({
|
||||
List<String>? triggers,
|
||||
List<BangGroup>? groups,
|
||||
String? domain,
|
||||
({String category, String? subCategory})? categoryFilter,
|
||||
bool? orderMostFrequentFirst,
|
||||
})
|
||||
super.argument,
|
||||
}) : super(
|
||||
retry: null,
|
||||
name: r'bangListProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$bangListHash();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return r'bangListProvider'
|
||||
''
|
||||
'$argument';
|
||||
}
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<List<BangData>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<List<BangData>> create(Ref ref) {
|
||||
final argument =
|
||||
this.argument
|
||||
as ({
|
||||
List<String>? triggers,
|
||||
List<BangGroup>? groups,
|
||||
String? domain,
|
||||
({String category, String? subCategory})? categoryFilter,
|
||||
bool? orderMostFrequentFirst,
|
||||
});
|
||||
return bangList(
|
||||
ref,
|
||||
triggers: argument.triggers,
|
||||
groups: argument.groups,
|
||||
domain: argument.domain,
|
||||
categoryFilter: argument.categoryFilter,
|
||||
orderMostFrequentFirst: argument.orderMostFrequentFirst,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is BangListProvider && other.argument == argument;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return argument.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
String _$bangListHash() => r'd1e0bb9fa4f523ce516e075c0d149bf7803ebb2b';
|
||||
|
||||
final class BangListFamily extends $Family
|
||||
with
|
||||
$FunctionalFamilyOverride<
|
||||
Stream<List<BangData>>,
|
||||
({
|
||||
List<String>? triggers,
|
||||
List<BangGroup>? groups,
|
||||
String? domain,
|
||||
({String category, String? subCategory})? categoryFilter,
|
||||
bool? orderMostFrequentFirst,
|
||||
})
|
||||
> {
|
||||
BangListFamily._()
|
||||
: super(
|
||||
retry: null,
|
||||
name: r'bangListProvider',
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
isAutoDispose: true,
|
||||
);
|
||||
|
||||
BangListProvider call({
|
||||
List<String>? triggers,
|
||||
List<BangGroup>? groups,
|
||||
String? domain,
|
||||
({String category, String? subCategory})? categoryFilter,
|
||||
bool? orderMostFrequentFirst,
|
||||
}) => BangListProvider._(
|
||||
argument: (
|
||||
triggers: triggers,
|
||||
groups: groups,
|
||||
domain: domain,
|
||||
categoryFilter: categoryFilter,
|
||||
orderMostFrequentFirst: orderMostFrequentFirst,
|
||||
),
|
||||
from: this,
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() => r'bangListProvider';
|
||||
}
|
||||
|
||||
@ProviderFor(frequentBangList)
|
||||
final frequentBangListProvider = FrequentBangListProvider._();
|
||||
|
||||
final class FrequentBangListProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
AsyncValue<List<BangData>>,
|
||||
List<BangData>,
|
||||
Stream<List<BangData>>
|
||||
>
|
||||
with $FutureModifier<List<BangData>>, $StreamProvider<List<BangData>> {
|
||||
FrequentBangListProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'frequentBangListProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$frequentBangListHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<List<BangData>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<List<BangData>> create(Ref ref) {
|
||||
return frequentBangList(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$frequentBangListHash() => r'2c1ecb7e9416772fc1c32d01d767e1eb4f865975';
|
||||
|
||||
@ProviderFor(searchHistory)
|
||||
final searchHistoryProvider = SearchHistoryProvider._();
|
||||
|
||||
final class SearchHistoryProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
AsyncValue<List<SearchHistoryEntry>>,
|
||||
List<SearchHistoryEntry>,
|
||||
Stream<List<SearchHistoryEntry>>
|
||||
>
|
||||
with
|
||||
$FutureModifier<List<SearchHistoryEntry>>,
|
||||
$StreamProvider<List<SearchHistoryEntry>> {
|
||||
SearchHistoryProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'searchHistoryProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$searchHistoryHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<List<SearchHistoryEntry>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<List<SearchHistoryEntry>> create(Ref ref) {
|
||||
return searchHistory(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$searchHistoryHash() => r'5f9508a6b286bfcd1b641bd429de46ad052a3dfe';
|
||||
|
||||
@ProviderFor(lastSyncOfGroup)
|
||||
final lastSyncOfGroupProvider = LastSyncOfGroupFamily._();
|
||||
|
||||
final class LastSyncOfGroupProvider
|
||||
extends
|
||||
$FunctionalProvider<AsyncValue<DateTime?>, DateTime?, Stream<DateTime?>>
|
||||
with $FutureModifier<DateTime?>, $StreamProvider<DateTime?> {
|
||||
LastSyncOfGroupProvider._({
|
||||
required LastSyncOfGroupFamily super.from,
|
||||
required BangGroup super.argument,
|
||||
}) : super(
|
||||
retry: null,
|
||||
name: r'lastSyncOfGroupProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$lastSyncOfGroupHash();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return r'lastSyncOfGroupProvider'
|
||||
''
|
||||
'($argument)';
|
||||
}
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<DateTime?> $createElement($ProviderPointer pointer) =>
|
||||
$StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<DateTime?> create(Ref ref) {
|
||||
final argument = this.argument as BangGroup;
|
||||
return lastSyncOfGroup(ref, argument);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is LastSyncOfGroupProvider && other.argument == argument;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return argument.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
String _$lastSyncOfGroupHash() => r'23d07f3132ba9bb35a31f74e3a69698d31d4c569';
|
||||
|
||||
final class LastSyncOfGroupFamily extends $Family
|
||||
with $FunctionalFamilyOverride<Stream<DateTime?>, BangGroup> {
|
||||
LastSyncOfGroupFamily._()
|
||||
: super(
|
||||
retry: null,
|
||||
name: r'lastSyncOfGroupProvider',
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
isAutoDispose: true,
|
||||
);
|
||||
|
||||
LastSyncOfGroupProvider call(BangGroup group) =>
|
||||
LastSyncOfGroupProvider._(argument: group, from: this);
|
||||
|
||||
@override
|
||||
String toString() => r'lastSyncOfGroupProvider';
|
||||
}
|
||||
|
||||
@ProviderFor(bangCountOfGroup)
|
||||
final bangCountOfGroupProvider = BangCountOfGroupFamily._();
|
||||
|
||||
final class BangCountOfGroupProvider
|
||||
extends $FunctionalProvider<AsyncValue<int>, int, Stream<int>>
|
||||
with $FutureModifier<int>, $StreamProvider<int> {
|
||||
BangCountOfGroupProvider._({
|
||||
required BangCountOfGroupFamily super.from,
|
||||
required BangGroup super.argument,
|
||||
}) : super(
|
||||
retry: null,
|
||||
name: r'bangCountOfGroupProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$bangCountOfGroupHash();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return r'bangCountOfGroupProvider'
|
||||
''
|
||||
'($argument)';
|
||||
}
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<int> $createElement($ProviderPointer pointer) =>
|
||||
$StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<int> create(Ref ref) {
|
||||
final argument = this.argument as BangGroup;
|
||||
return bangCountOfGroup(ref, argument);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is BangCountOfGroupProvider && other.argument == argument;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return argument.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
String _$bangCountOfGroupHash() => r'211ffcd7f49b637a7953f913dc5eafda344423f3';
|
||||
|
||||
final class BangCountOfGroupFamily extends $Family
|
||||
with $FunctionalFamilyOverride<Stream<int>, BangGroup> {
|
||||
BangCountOfGroupFamily._()
|
||||
: super(
|
||||
retry: null,
|
||||
name: r'bangCountOfGroupProvider',
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
isAutoDispose: true,
|
||||
);
|
||||
|
||||
BangCountOfGroupProvider call(BangGroup group) =>
|
||||
BangCountOfGroupProvider._(argument: group, from: this);
|
||||
|
||||
@override
|
||||
String toString() => r'bangCountOfGroupProvider';
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang_data.dart';
|
||||
import 'package:weblibre/features/bangs/data/providers.dart';
|
||||
import 'package:weblibre/features/bangs/domain/providers/bangs.dart';
|
||||
import 'package:weblibre/features/bangs/domain/repositories/data.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
|
||||
part 'search.g.dart';
|
||||
|
||||
@Riverpod()
|
||||
class BangSearch extends _$BangSearch {
|
||||
late StreamController<List<BangData>> _streamController;
|
||||
|
||||
Future<Uri> triggerBangSearch(BangData bang, String searchQuery) async {
|
||||
final bangDataNotifier = ref.read(bangDataRepositoryProvider.notifier);
|
||||
final settings = ref.read(generalSettingsWithDefaultsProvider);
|
||||
|
||||
await bangDataNotifier.increaseFrequency(bang.toKey());
|
||||
await bangDataNotifier.addSearchEntry(
|
||||
bang.group,
|
||||
bang.trigger,
|
||||
searchQuery,
|
||||
maxEntryCount: settings.maxSearchHistoryEntries,
|
||||
);
|
||||
|
||||
return bang.getTemplateUrl(searchQuery);
|
||||
}
|
||||
|
||||
Future<void> search(String input) async {
|
||||
if (input.isNotEmpty) {
|
||||
await ref.read(bangDatabaseProvider).bangDao.queryBangs(input).get().then(
|
||||
(value) {
|
||||
if (!_streamController.isClosed) {
|
||||
_streamController.add(value);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<List<BangData>> build() {
|
||||
_streamController = StreamController();
|
||||
|
||||
// Emit initial empty list so UI doesn't show loading state
|
||||
_streamController.add([]);
|
||||
|
||||
ref.onDispose(() async {
|
||||
await _streamController.close();
|
||||
});
|
||||
|
||||
return _streamController.stream;
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
class SeamlessBang extends _$SeamlessBang {
|
||||
bool _hasSearch = false;
|
||||
|
||||
void search(String input) {
|
||||
if (input.isNotEmpty) {
|
||||
if (!_hasSearch) {
|
||||
_hasSearch = true;
|
||||
ref.invalidateSelf();
|
||||
}
|
||||
|
||||
//Don't block
|
||||
unawaited(ref.read(bangSearchProvider.notifier).search(input));
|
||||
} else if (_hasSearch) {
|
||||
_hasSearch = false;
|
||||
ref.invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
AsyncValue<List<BangData>> build() {
|
||||
return _hasSearch
|
||||
? ref.watch(bangSearchProvider)
|
||||
: ref.watch(frequentBangListProvider);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'search.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(BangSearch)
|
||||
final bangSearchProvider = BangSearchProvider._();
|
||||
|
||||
final class BangSearchProvider
|
||||
extends $StreamNotifierProvider<BangSearch, List<BangData>> {
|
||||
BangSearchProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'bangSearchProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$bangSearchHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
BangSearch create() => BangSearch();
|
||||
}
|
||||
|
||||
String _$bangSearchHash() => r'feed24edfe703b0697f4a855be9c7359c456b0f2';
|
||||
|
||||
abstract class _$BangSearch extends $StreamNotifier<List<BangData>> {
|
||||
Stream<List<BangData>> build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<AsyncValue<List<BangData>>, List<BangData>>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<AsyncValue<List<BangData>>, List<BangData>>,
|
||||
AsyncValue<List<BangData>>,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(SeamlessBang)
|
||||
final seamlessBangProvider = SeamlessBangProvider._();
|
||||
|
||||
final class SeamlessBangProvider
|
||||
extends $NotifierProvider<SeamlessBang, AsyncValue<List<BangData>>> {
|
||||
SeamlessBangProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'seamlessBangProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$seamlessBangHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
SeamlessBang create() => SeamlessBang();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(AsyncValue<List<BangData>> value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<AsyncValue<List<BangData>>>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$seamlessBangHash() => r'8bd7a2cbe4c302ae08f85167290666a7437f8b9b';
|
||||
|
||||
abstract class _$SeamlessBang extends $Notifier<AsyncValue<List<BangData>>> {
|
||||
AsyncValue<List<BangData>> build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref =
|
||||
this.ref
|
||||
as $Ref<AsyncValue<List<BangData>>, AsyncValue<List<BangData>>>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<
|
||||
AsyncValue<List<BangData>>,
|
||||
AsyncValue<List<BangData>>
|
||||
>,
|
||||
AsyncValue<List<BangData>>,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang_data.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang_group.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang_key.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/search_history_entry.dart';
|
||||
import 'package:weblibre/features/bangs/data/providers.dart';
|
||||
|
||||
part 'data.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class BangDataRepository extends _$BangDataRepository {
|
||||
@override
|
||||
void build() {}
|
||||
|
||||
Stream<BangData?> watchBang(BangKey? key) {
|
||||
if (key != null) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.bangDao
|
||||
.getBangData(key.group, key.trigger)
|
||||
.watchSingleOrNull();
|
||||
} else {
|
||||
return Stream.value(null);
|
||||
}
|
||||
}
|
||||
|
||||
Stream<Map<String, List<String>>> watchCategories() {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.definitionsDrift
|
||||
.categoriesJson()
|
||||
.watchSingle()
|
||||
.map((json) {
|
||||
final decoded = jsonDecode(json) as Map<String, dynamic>;
|
||||
return decoded.map(
|
||||
(key, value) => MapEntry(key, (value as List<dynamic>).cast()),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Stream<int> watchBangCount(BangGroup group) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.bangDao
|
||||
.getBangCount(groups: [group])
|
||||
.watchSingle();
|
||||
}
|
||||
|
||||
Stream<List<BangData>> watchBangs({
|
||||
Iterable<String>? triggers,
|
||||
Iterable<BangGroup>? groups,
|
||||
String? domain,
|
||||
({String category, String? subCategory})? categoryFilter,
|
||||
bool? orderMostFrequentFirst,
|
||||
}) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.bangDao
|
||||
.getBangDataList(
|
||||
triggers: triggers,
|
||||
groups: groups,
|
||||
domain: domain,
|
||||
category: categoryFilter?.category,
|
||||
subCategory: categoryFilter?.subCategory,
|
||||
orderMostFrequentFirst: orderMostFrequentFirst,
|
||||
)
|
||||
.watch();
|
||||
}
|
||||
|
||||
Stream<List<BangData>> watchFrequentBangs({Iterable<BangGroup>? groups}) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.bangDao
|
||||
.getFrequentBangDataList(groups: groups)
|
||||
.watch();
|
||||
}
|
||||
|
||||
Stream<List<SearchHistoryEntry>> watchSearchHistory({required int limit}) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.definitionsDrift
|
||||
.searchHistoryEntries(limit: limit)
|
||||
.watch();
|
||||
}
|
||||
|
||||
Future<void> increaseFrequency(BangKey key) {
|
||||
return ref.read(bangDatabaseProvider).bangDao.increaseBangFrequency(key);
|
||||
}
|
||||
|
||||
Future<void> addSearchEntry(
|
||||
BangGroup group,
|
||||
String trigger,
|
||||
String searchQuery, {
|
||||
required int maxEntryCount,
|
||||
}) async {
|
||||
// Skip capturing history if maxEntryCount is 0
|
||||
if (maxEntryCount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final db = ref.read(bangDatabaseProvider);
|
||||
//Pack in a transaction to bundle rebuilds of watch() queries
|
||||
return db.transaction(() async {
|
||||
await db.bangDao.addSearchEntry(group, trigger, searchQuery);
|
||||
await db.definitionsDrift.evictHistoryEntries(limit: maxEntryCount);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> removeSearchEntry(String searchQuery) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.bangDao
|
||||
.removeSearchEntry(searchQuery);
|
||||
}
|
||||
|
||||
Future<int> resetFrequencies() {
|
||||
return ref.read(bangDatabaseProvider).bangFrequency.deleteAll();
|
||||
}
|
||||
|
||||
Future<int> resetFrequency(String trigger) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.bangFrequency
|
||||
.deleteWhere((t) => t.trigger.equals(trigger));
|
||||
}
|
||||
|
||||
Future<BangData?> getBang(BangKey key) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.bangDao
|
||||
.getBangData(key.group, key.trigger)
|
||||
.getSingleOrNull();
|
||||
}
|
||||
|
||||
Future<void> upsertBang(Bang bang) {
|
||||
return ref.read(bangDatabaseProvider).bangDao.upsertBang(bang);
|
||||
}
|
||||
|
||||
Future<void> deleteBang(BangKey key) {
|
||||
return ref.read(bangDatabaseProvider).syncDao.deleteBangs(key.group, [
|
||||
key.trigger,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'data.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(BangDataRepository)
|
||||
final bangDataRepositoryProvider = BangDataRepositoryProvider._();
|
||||
|
||||
final class BangDataRepositoryProvider
|
||||
extends $NotifierProvider<BangDataRepository, void> {
|
||||
BangDataRepositoryProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'bangDataRepositoryProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$bangDataRepositoryHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
BangDataRepository create() => BangDataRepository();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(void value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<void>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$bangDataRepositoryHash() =>
|
||||
r'c562ef10d75ca6dee13805f84d2491cf2a89aaac';
|
||||
|
||||
abstract class _$BangDataRepository extends $Notifier<void> {
|
||||
void build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<void, void>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<void, void>,
|
||||
void,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:exceptions/exceptions.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:weblibre/features/bangs/data/database/database.dart';
|
||||
import 'package:weblibre/features/bangs/data/models/bang_group.dart';
|
||||
import 'package:weblibre/features/bangs/data/providers.dart';
|
||||
import 'package:weblibre/features/bangs/data/services/data_source.dart';
|
||||
|
||||
part 'sync.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class BangSyncRepository extends _$BangSyncRepository {
|
||||
static Future<Result<void>> _fetchAndSyncRemote({
|
||||
required BangDataSourceService sourceService,
|
||||
required BangDatabase db,
|
||||
required Uri url,
|
||||
required BangGroup group,
|
||||
required Duration? syncInterval,
|
||||
}) async {
|
||||
if (syncInterval != null) {
|
||||
final lastSync = await db.syncDao
|
||||
.getLastSyncOfGroup(group)
|
||||
.getSingleOrNull();
|
||||
|
||||
if (lastSync != null &&
|
||||
DateTime.now().difference(lastSync) < syncInterval) {
|
||||
return Result.success(null);
|
||||
}
|
||||
}
|
||||
|
||||
final result = await sourceService.fetchRemoteBangs(url, group);
|
||||
return result.flatMapAsync((remoteBangs) async {
|
||||
await db.syncDao.syncBangs(
|
||||
group: group,
|
||||
remoteBangs: remoteBangs,
|
||||
syncTime: DateTime.now(),
|
||||
);
|
||||
await db.definitionsDrift.optimizeBangFtsIndex();
|
||||
await db.definitionsDrift.optimizeTriggerFtsIndex();
|
||||
});
|
||||
}
|
||||
|
||||
static Future<Result<void>> _fetchAndSyncBundled({
|
||||
required BangDataSourceService sourceService,
|
||||
required BangDatabase db,
|
||||
required BangGroup group,
|
||||
}) async {
|
||||
if (group.bundled == null) {
|
||||
return Result.failure(
|
||||
const ErrorMessage(source: 'BangSync', message: 'Not bundled'),
|
||||
);
|
||||
}
|
||||
|
||||
if (group.remote == null) {
|
||||
return Result.failure(
|
||||
const ErrorMessage(source: 'BangSync', message: 'No remote source'),
|
||||
);
|
||||
}
|
||||
|
||||
final lastSync = await db.syncDao
|
||||
.getLastSyncOfGroup(group)
|
||||
.getSingleOrNull();
|
||||
|
||||
final sourceDate = await sourceService.getBundledBangDate(
|
||||
'assets/bangs/last_sync.txt',
|
||||
);
|
||||
|
||||
if (lastSync != null &&
|
||||
(sourceDate == lastSync ||
|
||||
sourceDate.difference(lastSync).isNegative)) {
|
||||
return Result.success(null);
|
||||
}
|
||||
|
||||
final result = await sourceService.getBundledBangs(group.bundled!, group);
|
||||
return result.flatMapAsync((remoteBangs) async {
|
||||
await db.syncDao.syncBangs(
|
||||
group: group,
|
||||
remoteBangs: remoteBangs,
|
||||
syncTime: sourceDate,
|
||||
);
|
||||
await db.definitionsDrift.optimizeBangFtsIndex();
|
||||
await db.definitionsDrift.optimizeTriggerFtsIndex();
|
||||
});
|
||||
}
|
||||
|
||||
Future<Result<void>> syncRemoteBangGroup(
|
||||
BangGroup group,
|
||||
Duration? syncInterval,
|
||||
) async {
|
||||
try {
|
||||
return Result.success(
|
||||
await ref
|
||||
.read(bangDatabaseProvider)
|
||||
.computeWithDatabase(
|
||||
connect: BangDatabase.new,
|
||||
computation: (db) async {
|
||||
final ref = ProviderContainer();
|
||||
final result = await _fetchAndSyncRemote(
|
||||
sourceService: ref.read(
|
||||
bangDataSourceServiceProvider.notifier,
|
||||
),
|
||||
db: db,
|
||||
url: Uri.parse(group.remote!),
|
||||
group: group,
|
||||
syncInterval: syncInterval,
|
||||
);
|
||||
|
||||
//Throw if necessary
|
||||
return result.value;
|
||||
},
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
return Result.failure(
|
||||
ErrorMessage(
|
||||
message: "Failed to sync Bangs (${group.name})",
|
||||
source: 'BangSync',
|
||||
details: e,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Result<void>> syncBundledBangGroup(BangGroup group) async {
|
||||
try {
|
||||
final db = ref.read(bangDatabaseProvider);
|
||||
|
||||
final result = await _fetchAndSyncBundled(
|
||||
sourceService: ref.read(bangDataSourceServiceProvider.notifier),
|
||||
db: db,
|
||||
group: group,
|
||||
);
|
||||
|
||||
//Throw if necessary
|
||||
return result;
|
||||
} catch (e) {
|
||||
return Result.failure(
|
||||
ErrorMessage(
|
||||
message: "Failed to sync Bangs (${group.name})",
|
||||
source: 'BangSync',
|
||||
details: e,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Stream<DateTime?> watchLastSyncOfGroup(BangGroup group) {
|
||||
return ref
|
||||
.read(bangDatabaseProvider)
|
||||
.syncDao
|
||||
.getLastSyncOfGroup(group)
|
||||
.watchSingleOrNull();
|
||||
}
|
||||
|
||||
Future<Map<BangGroup, Result<void>>> syncBundledBangGroups({
|
||||
Set<BangGroup>? groups,
|
||||
}) async {
|
||||
//Default to all sources
|
||||
groups ??= BangGroup.values.where((e) => e.bundled != null).toSet();
|
||||
|
||||
//Run isolated operations
|
||||
final futures = groups.map(
|
||||
(source) => syncBundledBangGroup(
|
||||
source,
|
||||
).then((result) => MapEntry(source, result)),
|
||||
);
|
||||
|
||||
return Map.fromEntries(await Future.wait(futures));
|
||||
}
|
||||
|
||||
@override
|
||||
void build() {}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'sync.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(BangSyncRepository)
|
||||
final bangSyncRepositoryProvider = BangSyncRepositoryProvider._();
|
||||
|
||||
final class BangSyncRepositoryProvider
|
||||
extends $NotifierProvider<BangSyncRepository, void> {
|
||||
BangSyncRepositoryProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'bangSyncRepositoryProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$bangSyncRepositoryHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
BangSyncRepository create() => BangSyncRepository();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(void value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<void>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$bangSyncRepositoryHash() =>
|
||||
r'1347dcbd03f6a1a4fa3bbbae5d9302098d260c50';
|
||||
|
||||
abstract class _$BangSyncRepository extends $Notifier<void> {
|
||||
void build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<void, void>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<void, void>,
|
||||
void,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:riverpod/riverpod.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:weblibre/features/bangs/data/providers.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
|
||||
part 'search_history_cleanup.g.dart';
|
||||
|
||||
/// Service that listens to maxSearchHistoryEntries setting changes
|
||||
/// and cleans up search history when the limit is reduced.
|
||||
@Riverpod(keepAlive: true)
|
||||
class SearchHistoryCleanupService extends _$SearchHistoryCleanupService {
|
||||
@override
|
||||
void build() {
|
||||
ref.listen(
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(settings) => settings.maxSearchHistoryEntries,
|
||||
),
|
||||
(previous, next) async {
|
||||
// Only cleanup when limit is reduced (including to 0)
|
||||
if (previous != null && next < previous) {
|
||||
final db = ref.read(bangDatabaseProvider);
|
||||
await db.definitionsDrift.evictHistoryEntries(limit: next);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'search_history_cleanup.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
/// Service that listens to maxSearchHistoryEntries setting changes
|
||||
/// and cleans up search history when the limit is reduced.
|
||||
|
||||
@ProviderFor(SearchHistoryCleanupService)
|
||||
final searchHistoryCleanupServiceProvider =
|
||||
SearchHistoryCleanupServiceProvider._();
|
||||
|
||||
/// Service that listens to maxSearchHistoryEntries setting changes
|
||||
/// and cleans up search history when the limit is reduced.
|
||||
final class SearchHistoryCleanupServiceProvider
|
||||
extends $NotifierProvider<SearchHistoryCleanupService, void> {
|
||||
/// Service that listens to maxSearchHistoryEntries setting changes
|
||||
/// and cleans up search history when the limit is reduced.
|
||||
SearchHistoryCleanupServiceProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'searchHistoryCleanupServiceProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$searchHistoryCleanupServiceHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
SearchHistoryCleanupService create() => SearchHistoryCleanupService();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(void value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<void>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$searchHistoryCleanupServiceHash() =>
|
||||
r'4e84ab50fa2ad55c615bb63a667c95383715570b';
|
||||
|
||||
/// Service that listens to maxSearchHistoryEntries setting changes
|
||||
/// and cleans up search history when the limit is reduced.
|
||||
|
||||
abstract class _$SearchHistoryCleanupService extends $Notifier<void> {
|
||||
void build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<void, void>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<void, void>,
|
||||
void,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user