pretty good

This commit is contained in:
Fabian Freund
2025-02-07 20:45:47 +01:00
parent 025ecaf2e3
commit a12ef8244f
68 changed files with 2359 additions and 1015 deletions
@@ -57,17 +57,6 @@ Stream<List<SearchHistoryEntry>> searchHistory(Ref ref) {
return repository.watchSearchHistory(limit: 3); //TODO: make count dynamic
}
@Riverpod()
Future<BangData> bangDataEnsureIcon(
Ref ref,
BangData bang,
) {
final repository = ref.watch(bangDataRepositoryProvider.notifier);
return repository.ensureIconAvailable(bang).then(
(value) => value.value,
);
}
@Riverpod()
Stream<DateTime?> lastSyncOfGroup(
Ref ref,
@@ -387,138 +387,6 @@ final searchHistoryProvider =
// ignore: unused_element
typedef SearchHistoryRef
= AutoDisposeStreamProviderRef<List<SearchHistoryEntry>>;
String _$bangDataEnsureIconHash() =>
r'423b8e92fd89ec328c2fcc8f9e55365c30633fd2';
/// See also [bangDataEnsureIcon].
@ProviderFor(bangDataEnsureIcon)
const bangDataEnsureIconProvider = BangDataEnsureIconFamily();
/// See also [bangDataEnsureIcon].
class BangDataEnsureIconFamily extends Family<AsyncValue<BangData>> {
/// See also [bangDataEnsureIcon].
const BangDataEnsureIconFamily();
/// See also [bangDataEnsureIcon].
BangDataEnsureIconProvider call(
BangData bang,
) {
return BangDataEnsureIconProvider(
bang,
);
}
@override
BangDataEnsureIconProvider getProviderOverride(
covariant BangDataEnsureIconProvider provider,
) {
return call(
provider.bang,
);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'bangDataEnsureIconProvider';
}
/// See also [bangDataEnsureIcon].
class BangDataEnsureIconProvider extends AutoDisposeFutureProvider<BangData> {
/// See also [bangDataEnsureIcon].
BangDataEnsureIconProvider(
BangData bang,
) : this._internal(
(ref) => bangDataEnsureIcon(
ref as BangDataEnsureIconRef,
bang,
),
from: bangDataEnsureIconProvider,
name: r'bangDataEnsureIconProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$bangDataEnsureIconHash,
dependencies: BangDataEnsureIconFamily._dependencies,
allTransitiveDependencies:
BangDataEnsureIconFamily._allTransitiveDependencies,
bang: bang,
);
BangDataEnsureIconProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.bang,
}) : super.internal();
final BangData bang;
@override
Override overrideWith(
FutureOr<BangData> Function(BangDataEnsureIconRef provider) create,
) {
return ProviderOverride(
origin: this,
override: BangDataEnsureIconProvider._internal(
(ref) => create(ref as BangDataEnsureIconRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
bang: bang,
),
);
}
@override
AutoDisposeFutureProviderElement<BangData> createElement() {
return _BangDataEnsureIconProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is BangDataEnsureIconProvider && other.bang == bang;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, bang.hashCode);
return _SystemHash.finish(hash);
}
}
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin BangDataEnsureIconRef on AutoDisposeFutureProviderRef<BangData> {
/// The parameter `bang` of this provider.
BangData get bang;
}
class _BangDataEnsureIconProviderElement
extends AutoDisposeFutureProviderElement<BangData>
with BangDataEnsureIconRef {
_BangDataEnsureIconProviderElement(super.provider);
@override
BangData get bang => (origin as BangDataEnsureIconProvider).bang;
}
String _$lastSyncOfGroupHash() => r'23d07f3132ba9bb35a31f74e3a69698d31d4c569';
/// See also [lastSyncOfGroup].
@@ -111,26 +111,6 @@ class BangDataRepository extends _$BangDataRepository {
.removeSearchEntry(searchQuery);
}
Future<Result<BangData>> ensureIconAvailable(BangData bang) async {
if (bang.icon != null) {
return Result.success(bang);
}
final url = bang.getUrl('');
final websiteProvider = ref.read(genericWebsiteServiceProvider.notifier);
final cachedIcon = await websiteProvider.getCachedIcon(url);
if (cachedIcon != null) {
return Result.success(bang.copyWith.icon(cachedIcon));
}
return websiteProvider.fetchPageInfo(url).then(
(result) => result
.flatMap((pageInfo) => bang.copyWith.icon(pageInfo.favicon)),
);
}
Future<int> resetFrequencies() {
return ref.read(bangDatabaseProvider).bangFrequency.deleteAll();
}
@@ -7,7 +7,7 @@ part of 'data.dart';
// **************************************************************************
String _$bangDataRepositoryHash() =>
r'2c009519cf02df4d3cbb6768dbe55e9eb696e126';
r'de89d7089ce6a92015bee233f08d920981518793';
/// See also [BangDataRepository].
@ProviderFor(BangDataRepository)
@@ -13,12 +13,13 @@ class BangSearch extends _$BangSearch {
Future<void> search(String input) async {
if (input.isNotEmpty) {
await ref
.read(bangDatabaseProvider)
.bangDao
.queryBangs(input)
.get()
.then(_streamController.add);
await ref.read(bangDatabaseProvider).bangDao.queryBangs(input).get().then(
(value) {
if (!_streamController.isClosed) {
_streamController.add(value);
}
},
);
}
}
@@ -6,7 +6,7 @@ part of 'search.dart';
// RiverpodGenerator
// **************************************************************************
String _$bangSearchHash() => r'632ddd09a1198394884cb5c27a2bde7850c0515b';
String _$bangSearchHash() => r'abf9ff5badf2ecfbcbde148fd2c849beac83bec4';
/// See also [BangSearch].
@ProviderFor(BangSearch)
@@ -3,7 +3,7 @@ import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:lensai/core/routing/routes.dart';
import 'package:lensai/features/bangs/data/models/bang_data.dart';
import 'package:lensai/features/bangs/presentation/widgets/bang_icon.dart';
import 'package:lensai/presentation/widgets/bang_icon.dart';
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
class BangDetails extends HookConsumerWidget {
@@ -38,7 +38,7 @@ class BangDetails extends HookConsumerWidget {
children: [
Row(
children: [
BangIcon(bangData),
UrlIcon(bangData.getUrl(''), iconSize: 34.0),
const SizedBox(width: 12.0),
Expanded(
child: Column(
@@ -1,37 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:lensai/features/bangs/data/models/bang_data.dart';
import 'package:lensai/features/bangs/domain/providers/bangs.dart';
import 'package:skeletonizer/skeletonizer.dart';
class BangIcon extends HookConsumerWidget {
final double iconSize;
final BangData bangData;
const BangIcon(this.bangData, {this.iconSize = 34.0, super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final bangAsync = ref.watch(bangDataEnsureIconProvider(bangData));
final bang = bangAsync.valueOrNull ?? bangData;
return Skeletonizer(
enabled: bangAsync.isLoading,
child: SizedBox.square(
dimension: iconSize,
child: (bang.icon != null)
? RawImage(
image: bang.icon?.image.value,
height: iconSize,
width: iconSize,
fit: BoxFit.fill,
)
: Icon(
MdiIcons.web,
size: iconSize,
),
),
);
}
}
@@ -5,13 +5,13 @@ import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:lensai/features/bangs/data/models/bang_data.dart';
import 'package:lensai/features/bangs/domain/providers/search.dart';
import 'package:lensai/features/bangs/presentation/widgets/bang_icon.dart';
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
import 'package:lensai/features/geckoview/features/browser/domain/providers.dart';
import 'package:lensai/features/search/domain/providers/search_suggestions.dart';
import 'package:lensai/features/search/presentation/widgets/search_field.dart';
import 'package:lensai/features/search/presentation/widgets/search_suggestion_list.dart';
import 'package:lensai/features/geckoview/features/search/domain/providers/search_suggestions.dart';
import 'package:lensai/features/geckoview/features/search/presentation/widgets/search_field.dart';
import 'package:lensai/features/geckoview/features/search/presentation/widgets/search_modules/search_suggestions.dart';
import 'package:lensai/presentation/hooks/listenable_callback.dart';
import 'package:lensai/presentation/widgets/bang_icon.dart';
import 'package:lensai/presentation/widgets/selectable_chips.dart';
class SiteSearch extends HookConsumerWidget {
@@ -70,7 +70,7 @@ class SiteSearch extends HookConsumerWidget {
width: double.maxFinite,
child: SelectableChips(
itemId: (bang) => bang.trigger,
itemAvatar: (bang) => BangIcon(bang, iconSize: 20),
itemAvatar: (bang) => UrlIcon(bang.getUrl(''), iconSize: 20),
itemLabel: (bang) => Text(bang.websiteName),
availableItems: availableBangs,
selectedItem: selectedBang,
@@ -98,9 +98,10 @@ class SiteSearch extends HookConsumerWidget {
SearchField(
textEditingController: searchTextController,
activeBang: activeBang,
onFieldSubmitted: (_) async {
onSubmitted: (_) async {
await submitSearch(searchTextController.text);
},
showSuggestions: false,
),
ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 150),
@@ -111,10 +112,12 @@ class SiteSearch extends HookConsumerWidget {
shrinkWrap: true,
controller: controller,
slivers: [
SearchSuggestionList(
SearchTermSuggestions(
searchTextController: searchTextController,
activeBang: activeBang,
submitSearch: submitSearch,
showHistory: false,
showChips: false,
),
],
);