increase min sdk and apply new formatter

This commit is contained in:
Fabian Freund
2025-02-18 15:37:03 +01:00
parent f7885fc829
commit a1ee8bef35
266 changed files with 11329 additions and 10058 deletions
+14 -20
View File
@@ -2,30 +2,24 @@ import 'package:exceptions/exceptions.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:universal_io/io.dart'; import 'package:universal_io/io.dart';
ErrorMessage handleHttpError( ErrorMessage handleHttpError(Exception exception, StackTrace stackTrace) {
Exception exception,
StackTrace stackTrace,
) {
return switch (exception) { return switch (exception) {
SocketException() => const ErrorMessage( SocketException() => const ErrorMessage(
source: 'http', source: 'http',
message: 'Could not contact remote service', message: 'Could not contact remote service',
), ),
HttpException() => const ErrorMessage( HttpException() => const ErrorMessage(
source: 'http', source: 'http',
message: 'Web request returned error', message: 'Web request returned error',
), ),
FormatException() => const ErrorMessage( FormatException() => const ErrorMessage(
source: 'http', source: 'http',
message: 'Bad response format', message: 'Bad response format',
), ),
ClientException() => const ErrorMessage( ClientException() => const ErrorMessage(
source: 'http', source: 'http',
message: 'Could not contact remote service', message: 'Could not contact remote service',
), ),
_ => ErrorMessage.fromException( _ => ErrorMessage.fromException(exception, stackTrace),
exception,
stackTrace,
)
}; };
} }
+8 -6
View File
@@ -29,9 +29,10 @@ String _$embeddingModelHash() => r'40111a5f08b43afe6edd399ff0e6c022b3387265';
final embeddingModelProvider = Provider<OpenAIEmbeddings>.internal( final embeddingModelProvider = Provider<OpenAIEmbeddings>.internal(
embeddingModel, embeddingModel,
name: r'embeddingModelProvider', name: r'embeddingModelProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$embeddingModelHash, ? null
: _$embeddingModelHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -47,9 +48,10 @@ String _$embeddingDimensionsHash() =>
final embeddingDimensionsProvider = Provider<int>.internal( final embeddingDimensionsProvider = Provider<int>.internal(
embeddingDimensions, embeddingDimensions,
name: r'embeddingDimensionsProvider', name: r'embeddingDimensionsProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$embeddingDimensionsHash, ? null
: _$embeddingDimensionsHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
+1 -4
View File
@@ -8,10 +8,7 @@ part 'providers.g.dart';
@Riverpod(keepAlive: true) @Riverpod(keepAlive: true)
GoRouter router(Ref ref) { GoRouter router(Ref ref) {
return GoRouter( return GoRouter(debugLogDiagnostics: true, routes: $appRoutes);
debugLogDiagnostics: true,
routes: $appRoutes,
);
} }
@Riverpod() @Riverpod()
+9 -8
View File
@@ -28,14 +28,15 @@ String _$willAcceptDropHash() => r'97b47784ef9101757602b4408d1f545ef2308830';
@ProviderFor(WillAcceptDrop) @ProviderFor(WillAcceptDrop)
final willAcceptDropProvider = final willAcceptDropProvider =
AutoDisposeNotifierProvider<WillAcceptDrop, DropTargetData?>.internal( AutoDisposeNotifierProvider<WillAcceptDrop, DropTargetData?>.internal(
WillAcceptDrop.new, WillAcceptDrop.new,
name: r'willAcceptDropProvider', name: r'willAcceptDropProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$willAcceptDropHash, ? null
dependencies: null, : _$willAcceptDropHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$WillAcceptDrop = AutoDisposeNotifier<DropTargetData?>; typedef _$WillAcceptDrop = AutoDisposeNotifier<DropTargetData?>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
+10 -10
View File
@@ -27,14 +27,14 @@ class DialogPage<T> extends Page<T> {
@override @override
Route<T> createRoute(BuildContext context) => DialogRoute<T>( Route<T> createRoute(BuildContext context) => DialogRoute<T>(
context: context, context: context,
settings: this, settings: this,
builder: builder, builder: builder,
anchorPoint: anchorPoint, anchorPoint: anchorPoint,
barrierColor: barrierColor, barrierColor: barrierColor,
barrierDismissible: barrierDismissible, barrierDismissible: barrierDismissible,
barrierLabel: barrierLabel, barrierLabel: barrierLabel,
useSafeArea: useSafeArea, useSafeArea: useSafeArea,
themes: themes, themes: themes,
); );
} }
+19 -34
View File
@@ -30,22 +30,10 @@ part 'routes.g.dart';
name: 'BrowserRoute', name: 'BrowserRoute',
path: '/', path: '/',
routes: [ routes: [
TypedGoRoute<WebPageRoute>( TypedGoRoute<WebPageRoute>(name: 'WebPageRoute', path: 'page/:url'),
name: 'WebPageRoute', TypedGoRoute<AboutRoute>(name: 'AboutRoute', path: 'about'),
path: 'page/:url', TypedGoRoute<UserAuthRoute>(name: 'UserAuthRoute', path: 'userAuth'),
), TypedGoRoute<SearchRoute>(name: 'SearchRoute', path: 'search/:searchText'),
TypedGoRoute<AboutRoute>(
name: 'AboutRoute',
path: 'about',
),
TypedGoRoute<UserAuthRoute>(
name: 'UserAuthRoute',
path: 'userAuth',
),
TypedGoRoute<SearchRoute>(
name: 'SearchRoute',
path: 'search/:searchText',
),
TypedGoRoute<BangCategoriesRoute>( TypedGoRoute<BangCategoriesRoute>(
name: 'BangRoute', name: 'BangRoute',
path: 'bangs', path: 'bangs',
@@ -97,10 +85,11 @@ class WebPageRoute extends GoRouteData {
@override @override
Page<void> buildPage(BuildContext context, GoRouterState state) { Page<void> buildPage(BuildContext context, GoRouterState state) {
return DialogPage( return DialogPage(
builder: (_) => WebPageDialog( builder:
url: Uri.parse(url), (_) => WebPageDialog(
precachedInfo: state.extra as WebPageInfo?, url: Uri.parse(url),
), precachedInfo: state.extra as WebPageInfo?,
),
); );
} }
} }
@@ -130,9 +119,10 @@ class SearchRoute extends GoRouteData {
@override @override
Widget build(BuildContext context, GoRouterState state) { Widget build(BuildContext context, GoRouterState state) {
return SearchScreen( return SearchScreen(
initialSearchText: (searchText.isEmpty || searchText == emptySearchText) initialSearchText:
? null (searchText.isEmpty || searchText == emptySearchText)
: searchText, ? null
: searchText,
); );
} }
} }
@@ -181,9 +171,10 @@ class BangSearchRoute extends GoRouteData {
@override @override
Widget build(BuildContext context, GoRouterState state) { Widget build(BuildContext context, GoRouterState state) {
return BangSearchScreen( return BangSearchScreen(
initialSearchText: (searchText.isEmpty || searchText == emptySearchText) initialSearchText:
? null (searchText.isEmpty || searchText == emptySearchText)
: searchText, ? null
: searchText,
); );
} }
} }
@@ -221,10 +212,7 @@ class ContainerCreateRoute extends GoRouteData {
name: 'GeneralSettingsRoute', name: 'GeneralSettingsRoute',
path: 'general', path: 'general',
), ),
TypedGoRoute<BangSettingsRoute>( TypedGoRoute<BangSettingsRoute>(name: 'BangSettingsRoute', path: 'bang'),
name: 'BangSettingsRoute',
path: 'bang',
),
TypedGoRoute<WebEngineSettingsRoute>( TypedGoRoute<WebEngineSettingsRoute>(
name: 'WebEngineSettingsRoute', name: 'WebEngineSettingsRoute',
path: 'web_engine', path: 'web_engine',
@@ -328,10 +316,7 @@ class ChatArchiveDetailRoute extends GoRouteData {
} }
} }
@TypedGoRoute<TorProxyRoute>( @TypedGoRoute<TorProxyRoute>(name: 'TorProxyRoute', path: '/tor_proxy')
name: 'TorProxyRoute',
path: '/tor_proxy',
)
class TorProxyRoute extends GoRouteData { class TorProxyRoute extends GoRouteData {
@override @override
Widget build(BuildContext context, GoRouterState state) { Widget build(BuildContext context, GoRouterState state) {
+150 -189
View File
@@ -7,87 +7,85 @@ part of 'routes.dart';
// ************************************************************************** // **************************************************************************
List<RouteBase> get $appRoutes => [ List<RouteBase> get $appRoutes => [
$browserRoute, $browserRoute,
$settingsRoute, $settingsRoute,
$chatArchiveListRoute, $chatArchiveListRoute,
$torProxyRoute, $torProxyRoute,
]; ];
RouteBase get $browserRoute => GoRouteData.$route( RouteBase get $browserRoute => GoRouteData.$route(
path: '/', path: '/',
name: 'BrowserRoute', name: 'BrowserRoute',
factory: $BrowserRouteExtension._fromState, factory: $BrowserRouteExtension._fromState,
routes: [
GoRouteData.$route(
path: 'page/:url',
name: 'WebPageRoute',
factory: $WebPageRouteExtension._fromState,
),
GoRouteData.$route(
path: 'about',
name: 'AboutRoute',
factory: $AboutRouteExtension._fromState,
),
GoRouteData.$route(
path: 'userAuth',
name: 'UserAuthRoute',
factory: $UserAuthRouteExtension._fromState,
),
GoRouteData.$route(
path: 'search/:searchText',
name: 'SearchRoute',
factory: $SearchRouteExtension._fromState,
),
GoRouteData.$route(
path: 'bangs',
name: 'BangRoute',
factory: $BangCategoriesRouteExtension._fromState,
routes: [ routes: [
GoRouteData.$route(
path: 'page/:url',
name: 'WebPageRoute',
factory: $WebPageRouteExtension._fromState,
),
GoRouteData.$route(
path: 'about',
name: 'AboutRoute',
factory: $AboutRouteExtension._fromState,
),
GoRouteData.$route(
path: 'userAuth',
name: 'UserAuthRoute',
factory: $UserAuthRouteExtension._fromState,
),
GoRouteData.$route( GoRouteData.$route(
path: 'search/:searchText', path: 'search/:searchText',
name: 'SearchRoute', name: 'BangSearchRoute',
factory: $SearchRouteExtension._fromState, factory: $BangSearchRouteExtension._fromState,
), ),
GoRouteData.$route( GoRouteData.$route(
path: 'bangs', path: 'category/:category',
name: 'BangRoute', name: 'BangCategoryRoute',
factory: $BangCategoriesRouteExtension._fromState, factory: $BangCategoryRouteExtension._fromState,
routes: [ routes: [
GoRouteData.$route( GoRouteData.$route(
path: 'search/:searchText', path: ':subCategory',
name: 'BangSearchRoute', name: 'BangSubCategoryRoute',
factory: $BangSearchRouteExtension._fromState, factory: $BangSubCategoryRouteExtension._fromState,
),
GoRouteData.$route(
path: 'category/:category',
name: 'BangCategoryRoute',
factory: $BangCategoryRouteExtension._fromState,
routes: [
GoRouteData.$route(
path: ':subCategory',
name: 'BangSubCategoryRoute',
factory: $BangSubCategoryRouteExtension._fromState,
),
],
),
],
),
GoRouteData.$route(
path: 'containers',
name: 'ContainerListRoute',
factory: $ContainerListRouteExtension._fromState,
routes: [
GoRouteData.$route(
path: 'create',
name: 'ContainerCreateRoute',
factory: $ContainerCreateRouteExtension._fromState,
),
GoRouteData.$route(
path: 'edit',
name: 'ContainerEditRoute',
factory: $ContainerEditRouteExtension._fromState,
), ),
], ],
), ),
], ],
); ),
GoRouteData.$route(
path: 'containers',
name: 'ContainerListRoute',
factory: $ContainerListRouteExtension._fromState,
routes: [
GoRouteData.$route(
path: 'create',
name: 'ContainerCreateRoute',
factory: $ContainerCreateRouteExtension._fromState,
),
GoRouteData.$route(
path: 'edit',
name: 'ContainerEditRoute',
factory: $ContainerEditRouteExtension._fromState,
),
],
),
],
);
extension $BrowserRouteExtension on BrowserRoute { extension $BrowserRouteExtension on BrowserRoute {
static BrowserRoute _fromState(GoRouterState state) => BrowserRoute(); static BrowserRoute _fromState(GoRouterState state) => BrowserRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/');
'/',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -100,13 +98,11 @@ extension $BrowserRouteExtension on BrowserRoute {
} }
extension $WebPageRouteExtension on WebPageRoute { extension $WebPageRouteExtension on WebPageRoute {
static WebPageRoute _fromState(GoRouterState state) => WebPageRoute( static WebPageRoute _fromState(GoRouterState state) =>
url: state.pathParameters['url']!, WebPageRoute(url: state.pathParameters['url']!);
);
String get location => GoRouteData.$location( String get location =>
'/page/${Uri.encodeComponent(url)}', GoRouteData.$location('/page/${Uri.encodeComponent(url)}');
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -121,9 +117,7 @@ extension $WebPageRouteExtension on WebPageRoute {
extension $AboutRouteExtension on AboutRoute { extension $AboutRouteExtension on AboutRoute {
static AboutRoute _fromState(GoRouterState state) => AboutRoute(); static AboutRoute _fromState(GoRouterState state) => AboutRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/about');
'/about',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -138,9 +132,7 @@ extension $AboutRouteExtension on AboutRoute {
extension $UserAuthRouteExtension on UserAuthRoute { extension $UserAuthRouteExtension on UserAuthRoute {
static UserAuthRoute _fromState(GoRouterState state) => UserAuthRoute(); static UserAuthRoute _fromState(GoRouterState state) => UserAuthRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/userAuth');
'/userAuth',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -154,13 +146,12 @@ extension $UserAuthRouteExtension on UserAuthRoute {
extension $SearchRouteExtension on SearchRoute { extension $SearchRouteExtension on SearchRoute {
static SearchRoute _fromState(GoRouterState state) => SearchRoute( static SearchRoute _fromState(GoRouterState state) => SearchRoute(
searchText: searchText:
state.pathParameters['searchText']! ?? SearchRoute.emptySearchText, state.pathParameters['searchText']! ?? SearchRoute.emptySearchText,
); );
String get location => GoRouteData.$location( String get location =>
'/search/${Uri.encodeComponent(searchText)}', GoRouteData.$location('/search/${Uri.encodeComponent(searchText)}');
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -176,9 +167,7 @@ extension $BangCategoriesRouteExtension on BangCategoriesRoute {
static BangCategoriesRoute _fromState(GoRouterState state) => static BangCategoriesRoute _fromState(GoRouterState state) =>
BangCategoriesRoute(); BangCategoriesRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/bangs');
'/bangs',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -192,13 +181,12 @@ extension $BangCategoriesRouteExtension on BangCategoriesRoute {
extension $BangSearchRouteExtension on BangSearchRoute { extension $BangSearchRouteExtension on BangSearchRoute {
static BangSearchRoute _fromState(GoRouterState state) => BangSearchRoute( static BangSearchRoute _fromState(GoRouterState state) => BangSearchRoute(
searchText: state.pathParameters['searchText']! ?? searchText:
BangSearchRoute.emptySearchText, state.pathParameters['searchText']! ?? BangSearchRoute.emptySearchText,
); );
String get location => GoRouteData.$location( String get location =>
'/bangs/search/${Uri.encodeComponent(searchText)}', GoRouteData.$location('/bangs/search/${Uri.encodeComponent(searchText)}');
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -211,13 +199,11 @@ extension $BangSearchRouteExtension on BangSearchRoute {
} }
extension $BangCategoryRouteExtension on BangCategoryRoute { extension $BangCategoryRouteExtension on BangCategoryRoute {
static BangCategoryRoute _fromState(GoRouterState state) => BangCategoryRoute( static BangCategoryRoute _fromState(GoRouterState state) =>
category: state.pathParameters['category']!, BangCategoryRoute(category: state.pathParameters['category']!);
);
String get location => GoRouteData.$location( String get location =>
'/bangs/category/${Uri.encodeComponent(category)}', GoRouteData.$location('/bangs/category/${Uri.encodeComponent(category)}');
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -237,8 +223,8 @@ extension $BangSubCategoryRouteExtension on BangSubCategoryRoute {
); );
String get location => GoRouteData.$location( String get location => GoRouteData.$location(
'/bangs/category/${Uri.encodeComponent(category)}/${Uri.encodeComponent(subCategory)}', '/bangs/category/${Uri.encodeComponent(category)}/${Uri.encodeComponent(subCategory)}',
); );
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -254,9 +240,7 @@ extension $ContainerListRouteExtension on ContainerListRoute {
static ContainerListRoute _fromState(GoRouterState state) => static ContainerListRoute _fromState(GoRouterState state) =>
ContainerListRoute(); ContainerListRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/containers');
'/containers',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -272,9 +256,7 @@ extension $ContainerCreateRouteExtension on ContainerCreateRoute {
static ContainerCreateRoute _fromState(GoRouterState state) => static ContainerCreateRoute _fromState(GoRouterState state) =>
ContainerCreateRoute(); ContainerCreateRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/containers/create');
'/containers/create',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -290,9 +272,7 @@ extension $ContainerEditRouteExtension on ContainerEditRoute {
static ContainerEditRoute _fromState(GoRouterState state) => static ContainerEditRoute _fromState(GoRouterState state) =>
ContainerEditRoute(); ContainerEditRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/containers/edit');
'/containers/edit',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -305,48 +285,46 @@ extension $ContainerEditRouteExtension on ContainerEditRoute {
} }
RouteBase get $settingsRoute => GoRouteData.$route( RouteBase get $settingsRoute => GoRouteData.$route(
path: '/settings', path: '/settings',
name: 'SettingsRoute', name: 'SettingsRoute',
factory: $SettingsRouteExtension._fromState, factory: $SettingsRouteExtension._fromState,
routes: [
GoRouteData.$route(
path: 'general',
name: 'GeneralSettingsRoute',
factory: $GeneralSettingsRouteExtension._fromState,
),
GoRouteData.$route(
path: 'bang',
name: 'BangSettingsRoute',
factory: $BangSettingsRouteExtension._fromState,
),
GoRouteData.$route(
path: 'web_engine',
name: 'WebEngineSettingsRoute',
factory: $WebEngineSettingsRouteExtension._fromState,
routes: [ routes: [
GoRouteData.$route( GoRouteData.$route(
path: 'general', path: 'hardening',
name: 'GeneralSettingsRoute', name: 'WebEngineHardeningRoute',
factory: $GeneralSettingsRouteExtension._fromState, factory: $WebEngineHardeningRouteExtension._fromState,
),
GoRouteData.$route(
path: 'bang',
name: 'BangSettingsRoute',
factory: $BangSettingsRouteExtension._fromState,
),
GoRouteData.$route(
path: 'web_engine',
name: 'WebEngineSettingsRoute',
factory: $WebEngineSettingsRouteExtension._fromState,
routes: [ routes: [
GoRouteData.$route( GoRouteData.$route(
path: 'hardening', path: 'group/:group',
name: 'WebEngineHardeningRoute', name: 'WebEngineHardeningGroupRoute',
factory: $WebEngineHardeningRouteExtension._fromState, factory: $WebEngineHardeningGroupRouteExtension._fromState,
routes: [
GoRouteData.$route(
path: 'group/:group',
name: 'WebEngineHardeningGroupRoute',
factory: $WebEngineHardeningGroupRouteExtension._fromState,
),
],
), ),
], ],
), ),
], ],
); ),
],
);
extension $SettingsRouteExtension on SettingsRoute { extension $SettingsRouteExtension on SettingsRoute {
static SettingsRoute _fromState(GoRouterState state) => SettingsRoute(); static SettingsRoute _fromState(GoRouterState state) => SettingsRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/settings');
'/settings',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -362,9 +340,7 @@ extension $GeneralSettingsRouteExtension on GeneralSettingsRoute {
static GeneralSettingsRoute _fromState(GoRouterState state) => static GeneralSettingsRoute _fromState(GoRouterState state) =>
GeneralSettingsRoute(); GeneralSettingsRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/settings/general');
'/settings/general',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -380,9 +356,7 @@ extension $BangSettingsRouteExtension on BangSettingsRoute {
static BangSettingsRoute _fromState(GoRouterState state) => static BangSettingsRoute _fromState(GoRouterState state) =>
BangSettingsRoute(); BangSettingsRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/settings/bang');
'/settings/bang',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -398,9 +372,7 @@ extension $WebEngineSettingsRouteExtension on WebEngineSettingsRoute {
static WebEngineSettingsRoute _fromState(GoRouterState state) => static WebEngineSettingsRoute _fromState(GoRouterState state) =>
WebEngineSettingsRoute(); WebEngineSettingsRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/settings/web_engine');
'/settings/web_engine',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -416,9 +388,8 @@ extension $WebEngineHardeningRouteExtension on WebEngineHardeningRoute {
static WebEngineHardeningRoute _fromState(GoRouterState state) => static WebEngineHardeningRoute _fromState(GoRouterState state) =>
WebEngineHardeningRoute(); WebEngineHardeningRoute();
String get location => GoRouteData.$location( String get location =>
'/settings/web_engine/hardening', GoRouteData.$location('/settings/web_engine/hardening');
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -433,13 +404,11 @@ extension $WebEngineHardeningRouteExtension on WebEngineHardeningRoute {
extension $WebEngineHardeningGroupRouteExtension extension $WebEngineHardeningGroupRouteExtension
on WebEngineHardeningGroupRoute { on WebEngineHardeningGroupRoute {
static WebEngineHardeningGroupRoute _fromState(GoRouterState state) => static WebEngineHardeningGroupRoute _fromState(GoRouterState state) =>
WebEngineHardeningGroupRoute( WebEngineHardeningGroupRoute(group: state.pathParameters['group']!);
group: state.pathParameters['group']!,
);
String get location => GoRouteData.$location( String get location => GoRouteData.$location(
'/settings/web_engine/hardening/group/${Uri.encodeComponent(group)}', '/settings/web_engine/hardening/group/${Uri.encodeComponent(group)}',
); );
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -452,30 +421,28 @@ extension $WebEngineHardeningGroupRouteExtension
} }
RouteBase get $chatArchiveListRoute => GoRouteData.$route( RouteBase get $chatArchiveListRoute => GoRouteData.$route(
path: '/chat_archive', path: '/chat_archive',
name: 'ChatArchiveListRoute', name: 'ChatArchiveListRoute',
factory: $ChatArchiveListRouteExtension._fromState, factory: $ChatArchiveListRouteExtension._fromState,
routes: [ routes: [
GoRouteData.$route( GoRouteData.$route(
path: 'search', path: 'search',
name: 'ChatArchiveSearchRoute', name: 'ChatArchiveSearchRoute',
factory: $ChatArchiveSearchRouteExtension._fromState, factory: $ChatArchiveSearchRouteExtension._fromState,
), ),
GoRouteData.$route( GoRouteData.$route(
path: 'detail/:fileName', path: 'detail/:fileName',
name: 'ChatArchiveDetailRoute', name: 'ChatArchiveDetailRoute',
factory: $ChatArchiveDetailRouteExtension._fromState, factory: $ChatArchiveDetailRouteExtension._fromState,
), ),
], ],
); );
extension $ChatArchiveListRouteExtension on ChatArchiveListRoute { extension $ChatArchiveListRouteExtension on ChatArchiveListRoute {
static ChatArchiveListRoute _fromState(GoRouterState state) => static ChatArchiveListRoute _fromState(GoRouterState state) =>
ChatArchiveListRoute(); ChatArchiveListRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/chat_archive');
'/chat_archive',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -491,9 +458,7 @@ extension $ChatArchiveSearchRouteExtension on ChatArchiveSearchRoute {
static ChatArchiveSearchRoute _fromState(GoRouterState state) => static ChatArchiveSearchRoute _fromState(GoRouterState state) =>
ChatArchiveSearchRoute(); ChatArchiveSearchRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/chat_archive/search');
'/chat_archive/search',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -507,13 +472,11 @@ extension $ChatArchiveSearchRouteExtension on ChatArchiveSearchRoute {
extension $ChatArchiveDetailRouteExtension on ChatArchiveDetailRoute { extension $ChatArchiveDetailRouteExtension on ChatArchiveDetailRoute {
static ChatArchiveDetailRoute _fromState(GoRouterState state) => static ChatArchiveDetailRoute _fromState(GoRouterState state) =>
ChatArchiveDetailRoute( ChatArchiveDetailRoute(fileName: state.pathParameters['fileName']!);
fileName: state.pathParameters['fileName']!,
);
String get location => GoRouteData.$location( String get location => GoRouteData.$location(
'/chat_archive/detail/${Uri.encodeComponent(fileName)}', '/chat_archive/detail/${Uri.encodeComponent(fileName)}',
); );
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
@@ -526,17 +489,15 @@ extension $ChatArchiveDetailRouteExtension on ChatArchiveDetailRoute {
} }
RouteBase get $torProxyRoute => GoRouteData.$route( RouteBase get $torProxyRoute => GoRouteData.$route(
path: '/tor_proxy', path: '/tor_proxy',
name: 'TorProxyRoute', name: 'TorProxyRoute',
factory: $TorProxyRouteExtension._fromState, factory: $TorProxyRouteExtension._fromState,
); );
extension $TorProxyRouteExtension on TorProxyRoute { extension $TorProxyRouteExtension on TorProxyRoute {
static TorProxyRoute _fromState(GoRouterState state) => TorProxyRoute(); static TorProxyRoute _fromState(GoRouterState state) => TorProxyRoute();
String get location => GoRouteData.$location( String get location => GoRouteData.$location('/tor_proxy');
'/tor_proxy',
);
void go(BuildContext context) => context.go(location); void go(BuildContext context) => context.go(location);
+5 -8
View File
@@ -5,17 +5,14 @@ class EquatableCollection<T> with FastEquatable {
final bool immutable; final bool immutable;
EquatableCollection(this.collection, {required this.immutable}) EquatableCollection(this.collection, {required this.immutable})
: assert( : assert(
collection is Map || collection is Iterable || collection == null, collection is Map || collection is Iterable || collection == null,
'Collection type not supported', 'Collection type not supported',
); );
@override @override
bool get cacheHash => immutable; bool get cacheHash => immutable;
@override @override
List<Object?> get hashParameters => [ List<Object?> get hashParameters => [collection, immutable];
collection,
immutable,
];
} }
+1 -5
View File
@@ -12,9 +12,5 @@ class WebPageInfo {
bool get isPageInfoComplete => bool get isPageInfoComplete =>
(title?.isNotEmpty ?? false) && favicon != null; (title?.isNotEmpty ?? false) && favicon != null;
WebPageInfo({ WebPageInfo({required this.url, this.title, this.favicon});
required this.url,
this.title,
this.favicon,
});
} }
+16 -18
View File
@@ -19,11 +19,7 @@ abstract class _$WebPageInfoCWProxy {
/// ```dart /// ```dart
/// WebPageInfo(...).copyWith(id: 12, name: "My name") /// WebPageInfo(...).copyWith(id: 12, name: "My name")
/// ```` /// ````
WebPageInfo call({ WebPageInfo call({Uri url, String? title, BrowserIcon? favicon});
Uri url,
String? title,
BrowserIcon? favicon,
});
} }
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfWebPageInfo.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfWebPageInfo.copyWith.fieldName(...)` /// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfWebPageInfo.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfWebPageInfo.copyWith.fieldName(...)`
@@ -42,7 +38,6 @@ class _$WebPageInfoCWProxyImpl implements _$WebPageInfoCWProxy {
WebPageInfo favicon(BrowserIcon? favicon) => this(favicon: favicon); WebPageInfo favicon(BrowserIcon? favicon) => this(favicon: favicon);
@override @override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `WebPageInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `WebPageInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
/// ///
/// Usage /// Usage
@@ -55,18 +50,21 @@ class _$WebPageInfoCWProxyImpl implements _$WebPageInfoCWProxy {
Object? favicon = const $CopyWithPlaceholder(), Object? favicon = const $CopyWithPlaceholder(),
}) { }) {
return WebPageInfo( return WebPageInfo(
url: url == const $CopyWithPlaceholder() url:
? _value.url url == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.url
: url as Uri, // ignore: cast_nullable_to_non_nullable
title: title == const $CopyWithPlaceholder() : url as Uri,
? _value.title title:
// ignore: cast_nullable_to_non_nullable title == const $CopyWithPlaceholder()
: title as String?, ? _value.title
favicon: favicon == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.favicon : title as String?,
// ignore: cast_nullable_to_non_nullable favicon:
: favicon as BrowserIcon?, favicon == const $CopyWithPlaceholder()
? _value.favicon
// ignore: cast_nullable_to_non_nullable
: favicon as BrowserIcon?,
); );
} }
} }
+1 -4
View File
@@ -6,10 +6,7 @@ class EquatableImage {
final Image value; final Image value;
final int? _imageHash; final int? _imageHash;
EquatableImage( EquatableImage(this.value, {required int? hash}) : _imageHash = hash;
this.value, {
required int? hash,
}) : _imageHash = hash;
static Future<EquatableImage> calculate(Image image) async { static Future<EquatableImage> calculate(Image image) async {
final imageHash = await image.calculateHash(); final imageHash = await image.calculateHash();
+16 -18
View File
@@ -18,25 +18,21 @@ class AppInitializationService extends _$AppInitializationService {
Future<void> _initPackageInfo() { Future<void> _initPackageInfo() {
//Ensure Package info is loaded //Ensure Package info is loaded
state = Result.success( state = Result.success((
( initialized: false,
initialized: false, stage: 'Loading Package Info...',
stage: 'Loading Package Info...', errors: List.empty(),
errors: List.empty(), ));
),
);
return ref.read(packageInfoProvider.future); return ref.read(packageInfoProvider.future);
} }
Future<Map<BangGroup, Result<void>>> _initBangs() { Future<Map<BangGroup, Result<void>>> _initBangs() {
state = Result.success( state = Result.success((
( initialized: false,
initialized: false, stage: 'Synchronizing Bangs...',
stage: 'Synchronizing Bangs...', errors: List.empty(),
errors: List.empty(), ));
),
);
return ref return ref
.read(bangSyncRepositoryProvider.notifier) .read(bangSyncRepositoryProvider.notifier)
@@ -60,9 +56,11 @@ class AppInitializationService extends _$AppInitializationService {
@override @override
Result<({bool initialized, String? stage, List<ErrorMessage> errors})> Result<({bool initialized, String? stage, List<ErrorMessage> errors})>
build() { build() {
return Result.success( return Result.success((
(initialized: false, stage: null, errors: List.empty()), initialized: false,
); stage: null,
errors: List.empty(),
));
} }
} }
@@ -12,23 +12,22 @@ String _$appInitializationServiceHash() =>
/// See also [AppInitializationService]. /// See also [AppInitializationService].
@ProviderFor(AppInitializationService) @ProviderFor(AppInitializationService)
final appInitializationServiceProvider = NotifierProvider< final appInitializationServiceProvider = NotifierProvider<
AppInitializationService, AppInitializationService,
Result< Result<({bool initialized, String? stage, List<ErrorMessage> errors})>
({ >.internal(
bool initialized,
String? stage,
List<ErrorMessage> errors
})>>.internal(
AppInitializationService.new, AppInitializationService.new,
name: r'appInitializationServiceProvider', name: r'appInitializationServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$appInitializationServiceHash, ? null
: _$appInitializationServiceHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
typedef _$AppInitializationService = Notifier< typedef _$AppInitializationService =
Result<({bool initialized, String? stage, List<ErrorMessage> errors})>>; Notifier<
Result<({bool initialized, String? stage, List<ErrorMessage> errors})>
>;
// ignore_for_file: type=lint // 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 // 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
+36 -41
View File
@@ -65,8 +65,8 @@ class GenericWebsiteService extends _$GenericWebsiteService {
final LRUCache<String, BrowserIcon> _browserIconCache; final LRUCache<String, BrowserIcon> _browserIconCache;
GenericWebsiteService() GenericWebsiteService()
: _iconsService = GeckoIconService(), : _iconsService = GeckoIconService(),
_browserIconCache = LRUCache(50); _browserIconCache = LRUCache(50);
@override @override
void build() { void build() {
@@ -89,9 +89,10 @@ class GenericWebsiteService extends _$GenericWebsiteService {
url: resource['url'] as String, url: resource['url'] as String,
type: resource['type'] as IconType, type: resource['type'] as IconType,
mimeType: resource['mimeType'] as String?, mimeType: resource['mimeType'] as String?,
sizes: (resource['sizes'] as List<List<int>>) sizes:
.map((s) => ResourceSize(height: s[0], width: s[1])) (resource['sizes'] as List<List<int>>)
.toList(), .map((s) => ResourceSize(height: s[0], width: s[1]))
.toList(),
maskable: resource['maskable'] as bool, maskable: resource['maskable'] as bool,
); );
} }
@@ -187,45 +188,39 @@ class GenericWebsiteService extends _$GenericWebsiteService {
} }
Future<Result<WebPageInfo>> fetchPageInfo(Uri url) async { Future<Result<WebPageInfo>> fetchPageInfo(Uri url) async {
return Result.fromAsync( return Result.fromAsync(() async {
() async { final response = await _client
final response = .get(url)
await _client.get(url).timeout(const Duration(seconds: 10)); .timeout(const Duration(seconds: 10));
final result = await compute( final result = await compute((args) async {
(args) async { final document = html_parser.parse(args[0]);
final document = html_parser.parse(args[0]); final baseUri = Uri.parse(args[1]);
final baseUri = Uri.parse(args[1]);
final title = document.querySelector('title')?.text; final title = document.querySelector('title')?.text;
final resources = _extractIcons(baseUri, document); final resources = _extractIcons(baseUri, document);
return { return {
'title': title, 'title': title,
'resources': resources.map(_serializeResource).toList(), 'resources': resources.map(_serializeResource).toList(),
}; };
}, }, [response.body, url.toString()]);
[response.body, url.toString()],
);
final resources = (result['resources']! as List<Map<String, dynamic>>) final resources =
.map(_deserializeResource) (result['resources']! as List<Map<String, dynamic>>)
.toList(); .map(_deserializeResource)
.toList();
final favicon = await getCachedIcon(url) ?? final favicon =
await loadIcon( await getCachedIcon(url) ??
url: url, await loadIcon(url: url, resources: resources);
resources: resources,
);
return WebPageInfo( return WebPageInfo(
url: url, url: url,
title: result['title'] as String?, title: result['title'] as String?,
favicon: favicon, favicon: favicon,
); );
}, }, exceptionHandler: handleHttpError);
exceptionHandler: handleHttpError,
);
} }
Future<BrowserIcon?> getCachedIcon(Uri url) async { Future<BrowserIcon?> getCachedIcon(Uri url) async {
@@ -281,9 +276,9 @@ class GenericWebsiteService extends _$GenericWebsiteService {
return cachedIcon; return cachedIcon;
} }
return fetchPageInfo(url).then( return fetchPageInfo(
(result) => result.flatMap((pageInfo) => pageInfo.favicon!).value, url,
); ).then((result) => result.flatMap((pageInfo) => pageInfo.favicon!).value);
} }
// Future<Uri?> tryUpgradeToHttps(Uri httpUri) async { // Future<Uri?> tryUpgradeToHttps(Uri httpUri) async {
@@ -13,14 +13,15 @@ String _$genericWebsiteServiceHash() =>
@ProviderFor(GenericWebsiteService) @ProviderFor(GenericWebsiteService)
final genericWebsiteServiceProvider = final genericWebsiteServiceProvider =
NotifierProvider<GenericWebsiteService, void>.internal( NotifierProvider<GenericWebsiteService, void>.internal(
GenericWebsiteService.new, GenericWebsiteService.new,
name: r'genericWebsiteServiceProvider', name: r'genericWebsiteServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$genericWebsiteServiceHash, ? null
dependencies: null, : _$genericWebsiteServiceHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$GenericWebsiteService = Notifier<void>; typedef _$GenericWebsiteService = Notifier<void>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -12,13 +12,12 @@ FutureOr<bool> widgetPinnable(Ref ref) async {
} }
@Riverpod() @Riverpod()
Raw<Stream<ReceivedParameter>> appWidgetLaunchStream( Raw<Stream<ReceivedParameter>> appWidgetLaunchStream(Ref ref) {
Ref ref,
) {
// ignore: discarded_futures // ignore: discarded_futures
final initialStream = HomeWidget.initiallyLaunchedFromHomeWidget().asStream(); final initialStream = HomeWidget.initiallyLaunchedFromHomeWidget().asStream();
return ConcatStream([initialStream, HomeWidget.widgetClicked]) return ConcatStream([
.whereNotNull() initialStream,
.map((uri) => ReceivedParameter(null, uri.host)); HomeWidget.widgetClicked,
]).whereNotNull().map((uri) => ReceivedParameter(null, uri.host));
} }
@@ -13,9 +13,10 @@ String _$widgetPinnableHash() => r'f91041f0f051ad0f00dd765cafea5571ca8c8088';
final widgetPinnableProvider = FutureProvider<bool>.internal( final widgetPinnableProvider = FutureProvider<bool>.internal(
widgetPinnable, widgetPinnable,
name: r'widgetPinnableProvider', name: r'widgetPinnableProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$widgetPinnableHash, ? null
: _$widgetPinnableHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -30,18 +31,19 @@ String _$appWidgetLaunchStreamHash() =>
@ProviderFor(appWidgetLaunchStream) @ProviderFor(appWidgetLaunchStream)
final appWidgetLaunchStreamProvider = final appWidgetLaunchStreamProvider =
AutoDisposeProvider<Raw<Stream<ReceivedParameter>>>.internal( AutoDisposeProvider<Raw<Stream<ReceivedParameter>>>.internal(
appWidgetLaunchStream, appWidgetLaunchStream,
name: r'appWidgetLaunchStreamProvider', name: r'appWidgetLaunchStreamProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$appWidgetLaunchStreamHash, ? null
dependencies: null, : _$appWidgetLaunchStreamHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead') @Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element // ignore: unused_element
typedef AppWidgetLaunchStreamRef typedef AppWidgetLaunchStreamRef =
= AutoDisposeProviderRef<Raw<Stream<ReceivedParameter>>>; AutoDisposeProviderRef<Raw<Stream<ReceivedParameter>>>;
// ignore_for_file: type=lint // 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 // 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
@@ -95,13 +95,9 @@ class BangDao extends DatabaseAccessor<BangDatabase> with _$BangDaoMixin {
final ftsQuery = db.buildFtsQuery(searchString); final ftsQuery = db.buildFtsQuery(searchString);
if (ftsQuery.isNotEmpty) { if (ftsQuery.isNotEmpty) {
return db.queryBangs( return db.queryBangs(query: ftsQuery);
query: ftsQuery,
);
} else { } else {
return db.queryBangsBasic( return db.queryBangsBasic(query: db.buildLikeQuery(searchString));
query: db.buildLikeQuery(searchString),
);
} }
} }
@@ -9,19 +9,17 @@ class SyncDao extends DatabaseAccessor<BangDatabase> with _$SyncDaoMixin {
SyncDao(super.db); SyncDao(super.db);
SingleOrNullSelectable<DateTime?> lastSyncOfGroup(BangGroup group) { SingleOrNullSelectable<DateTime?> lastSyncOfGroup(BangGroup group) {
final query = selectOnly(db.bangSync) final query =
..addColumns([db.bangSync.lastSync]) selectOnly(db.bangSync)
..where(db.bangSync.group.equalsValue(group)); ..addColumns([db.bangSync.lastSync])
..where(db.bangSync.group.equalsValue(group));
return query.map((row) => row.read(db.bangSync.lastSync)); return query.map((row) => row.read(db.bangSync.lastSync));
} }
Future<void> upsertLastSyncOfGroup(BangGroup group, DateTime lastSync) { Future<void> upsertLastSyncOfGroup(BangGroup group, DateTime lastSync) {
return db.bangSync.insertOne( return db.bangSync.insertOne(
BangSyncCompanion.insert( BangSyncCompanion.insert(group: Value(group), lastSync: lastSync),
group: Value(group),
lastSync: lastSync,
),
onConflict: DoUpdate( onConflict: DoUpdate(
(old) => BangSyncCompanion.custom(lastSync: Variable(lastSync)), (old) => BangSyncCompanion.custom(lastSync: Variable(lastSync)),
), ),
@@ -33,11 +31,9 @@ class SyncDao extends DatabaseAccessor<BangDatabase> with _$SyncDaoMixin {
} }
Future<void> replaceBangs(Iterable<Bang> bangs) { Future<void> replaceBangs(Iterable<Bang> bangs) {
return batch( return batch((batch) {
(batch) { batch.replaceAll(db.bang, bangs);
batch.replaceAll(db.bang, bangs); });
},
);
} }
Future<int> deleteBangs(Iterable<String> triggers) { Future<int> deleteBangs(Iterable<String> triggers) {
@@ -50,36 +46,34 @@ class SyncDao extends DatabaseAccessor<BangDatabase> with _$SyncDaoMixin {
required Iterable<Bang> remoteBangs, required Iterable<Bang> remoteBangs,
required DateTime syncTime, required DateTime syncTime,
}) async { }) async {
final remoteBangMap = final remoteBangMap = Map.fromEntries(
Map.fromEntries(remoteBangs.map((e) => MapEntry(e.trigger, e))); remoteBangs.map((e) => MapEntry(e.trigger, e)),
final localBangMap = );
await db.bangDao.getBangList(groups: [group]).get().then( final localBangMap = await db.bangDao
(bangs) => .getBangList(groups: [group])
Map.fromEntries(bangs.map((e) => MapEntry(e.trigger, e))), .get()
); .then(
(bangs) => Map.fromEntries(bangs.map((e) => MapEntry(e.trigger, e))),
);
final remoteBangTriggers = remoteBangMap.keys.toSet(); final remoteBangTriggers = remoteBangMap.keys.toSet();
final localBangTriggers = localBangMap.keys.toSet(); final localBangTriggers = localBangMap.keys.toSet();
final removedBangs = localBangTriggers.difference(remoteBangTriggers); final removedBangs = localBangTriggers.difference(remoteBangTriggers);
final addedBangs = remoteBangTriggers.difference(localBangTriggers).map( final addedBangs = remoteBangTriggers
(e) => remoteBangMap[e]!, .difference(localBangTriggers)
); .map((e) => remoteBangMap[e]!);
final changedBangs = remoteBangTriggers final changedBangs = remoteBangTriggers
.intersection(localBangTriggers) .intersection(localBangTriggers)
.where((e) => remoteBangMap[e] != localBangMap[e]) .where((e) => remoteBangMap[e] != localBangMap[e])
.map( .map((e) => remoteBangMap[e]!);
(e) => remoteBangMap[e]!,
);
await db.transaction( await db.transaction(() async {
() async { await deleteBangs(removedBangs);
await deleteBangs(removedBangs); await insertBangs(addedBangs);
await insertBangs(addedBangs); await replaceBangs(changedBangs);
await replaceBangs(changedBangs); await upsertLastSyncOfGroup(group, syncTime);
await upsertLastSyncOfGroup(group, syncTime); });
},
);
} }
} }
@@ -9,10 +9,7 @@ import 'package:lensai/features/search/domain/fts_tokenizer.dart';
part 'database.g.dart'; part 'database.g.dart';
@DriftDatabase( @DriftDatabase(include: {'database.drift'}, daos: [BangDao, SyncDao])
include: {'database.drift'},
daos: [BangDao, SyncDao],
)
class BangDatabase extends _$BangDatabase with PrefixQueryBuilderMixin { class BangDatabase extends _$BangDatabase with PrefixQueryBuilderMixin {
@override @override
final int schemaVersion = 1; final int schemaVersion = 1;
@@ -24,10 +21,10 @@ class BangDatabase extends _$BangDatabase with PrefixQueryBuilderMixin {
@override @override
MigrationStrategy get migration => MigrationStrategy( MigrationStrategy get migration => MigrationStrategy(
beforeOpen: (details) async { beforeOpen: (details) async {
await customStatement('PRAGMA foreign_keys = ON;'); await customStatement('PRAGMA foreign_keys = ON;');
}, },
); );
BangDatabase(super.e); BangDatabase(super.e);
} }
File diff suppressed because it is too large Load Diff
+20 -19
View File
@@ -8,9 +8,7 @@ import 'package:lensai/features/bangs/data/database/database.dart'
part 'bang.g.dart'; part 'bang.g.dart';
enum BangGroup { enum BangGroup {
general( general('https://raw.githubusercontent.com/FaFre/bangs/main/data/bangs.json'),
'https://raw.githubusercontent.com/FaFre/bangs/main/data/bangs.json',
),
assistant( assistant(
'https://raw.githubusercontent.com/FaFre/bangs/main/data/assistant_bangs.json', 'https://raw.githubusercontent.com/FaFre/bangs/main/data/assistant_bangs.json',
), ),
@@ -90,16 +88,19 @@ class Bang with FastEquatable implements Insertable<Bang> {
} }
Uri getUrl(String? query) { Uri getUrl(String? query) {
final url = (query != null) final url =
? urlTemplate.replaceAll(_templateQueryPlaceholder, formatQuery(query)) (query != null)
: urlTemplate; ? urlTemplate.replaceAll(
_templateQueryPlaceholder,
formatQuery(query),
)
: urlTemplate;
var template = Uri.parse(url); var template = Uri.parse(url);
if (!template.hasScheme || template.origin.isEmpty) { if (!template.hasScheme || template.origin.isEmpty) {
template = Uri.https(domain).replace( template = Uri.https(
path: template.path, domain,
query: template.query, ).replace(path: template.path, query: template.query);
);
} }
return template; return template;
@@ -133,15 +134,15 @@ class Bang with FastEquatable implements Insertable<Bang> {
@override @override
List<Object?> get hashParameters => [ List<Object?> get hashParameters => [
group, group,
websiteName, websiteName,
domain, domain,
trigger, trigger,
urlTemplate, urlTemplate,
category, category,
subCategory, subCategory,
format, format,
]; ];
@override @override
Map<String, Expression<Object>> toColumns(bool nullToAbsent) { Map<String, Expression<Object>> toColumns(bool nullToAbsent) {
+57 -49
View File
@@ -72,7 +72,6 @@ class _$BangCWProxyImpl implements _$BangCWProxy {
Bang format(Set<BangFormat>? format) => this(format: format); Bang format(Set<BangFormat>? format) => this(format: format);
@override @override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Bang(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Bang(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
/// ///
/// Usage /// Usage
@@ -90,38 +89,46 @@ class _$BangCWProxyImpl implements _$BangCWProxy {
Object? format = const $CopyWithPlaceholder(), Object? format = const $CopyWithPlaceholder(),
}) { }) {
return Bang( return Bang(
websiteName: websiteName == const $CopyWithPlaceholder() websiteName:
? _value.websiteName websiteName == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.websiteName
: websiteName as String, // ignore: cast_nullable_to_non_nullable
domain: domain == const $CopyWithPlaceholder() : websiteName as String,
? _value.domain domain:
// ignore: cast_nullable_to_non_nullable domain == const $CopyWithPlaceholder()
: domain as String, ? _value.domain
trigger: trigger == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.trigger : domain as String,
// ignore: cast_nullable_to_non_nullable trigger:
: trigger as String, trigger == const $CopyWithPlaceholder()
urlTemplate: urlTemplate == const $CopyWithPlaceholder() ? _value.trigger
? _value.urlTemplate // ignore: cast_nullable_to_non_nullable
// ignore: cast_nullable_to_non_nullable : trigger as String,
: urlTemplate as String, urlTemplate:
group: group == const $CopyWithPlaceholder() urlTemplate == const $CopyWithPlaceholder()
? _value.group ? _value.urlTemplate
// ignore: cast_nullable_to_non_nullable // ignore: cast_nullable_to_non_nullable
: group as BangGroup?, : urlTemplate as String,
category: category == const $CopyWithPlaceholder() group:
? _value.category group == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.group
: category as String?, // ignore: cast_nullable_to_non_nullable
subCategory: subCategory == const $CopyWithPlaceholder() : group as BangGroup?,
? _value.subCategory category:
// ignore: cast_nullable_to_non_nullable category == const $CopyWithPlaceholder()
: subCategory as String?, ? _value.category
format: format == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.format : category as String?,
// ignore: cast_nullable_to_non_nullable subCategory:
: format as Set<BangFormat>?, subCategory == const $CopyWithPlaceholder()
? _value.subCategory
// ignore: cast_nullable_to_non_nullable
: subCategory as String?,
format:
format == const $CopyWithPlaceholder()
? _value.format
// ignore: cast_nullable_to_non_nullable
: format as Set<BangFormat>?,
); );
} }
} }
@@ -137,26 +144,27 @@ extension $BangCopyWith on Bang {
// ************************************************************************** // **************************************************************************
Bang _$BangFromJson(Map<String, dynamic> json) => Bang( Bang _$BangFromJson(Map<String, dynamic> json) => Bang(
websiteName: json['s'] as String, websiteName: json['s'] as String,
domain: json['d'] as String, domain: json['d'] as String,
trigger: json['t'] as String, trigger: json['t'] as String,
urlTemplate: json['u'] as String, urlTemplate: json['u'] as String,
category: json['c'] as String?, category: json['c'] as String?,
subCategory: json['sc'] as String?, subCategory: json['sc'] as String?,
format: (json['fmt'] as List<dynamic>?) format:
(json['fmt'] as List<dynamic>?)
?.map((e) => $enumDecode(_$BangFormatEnumMap, e)) ?.map((e) => $enumDecode(_$BangFormatEnumMap, e))
.toSet(), .toSet(),
); );
Map<String, dynamic> _$BangToJson(Bang instance) => <String, dynamic>{ Map<String, dynamic> _$BangToJson(Bang instance) => <String, dynamic>{
's': instance.websiteName, 's': instance.websiteName,
'd': instance.domain, 'd': instance.domain,
't': instance.trigger, 't': instance.trigger,
'u': instance.urlTemplate, 'u': instance.urlTemplate,
'c': instance.category, 'c': instance.category,
'sc': instance.subCategory, 'sc': instance.subCategory,
'fmt': instance.format?.map((e) => _$BangFormatEnumMap[e]!).toList(), 'fmt': instance.format?.map((e) => _$BangFormatEnumMap[e]!).toList(),
}; };
const _$BangFormatEnumMap = { const _$BangFormatEnumMap = {
BangFormat.openBasePath: 'open_base_path', BangFormat.openBasePath: 'open_base_path',
@@ -29,9 +29,9 @@ class BangData extends Bang {
@override @override
List<Object?> get hashParameters => [ List<Object?> get hashParameters => [
...super.hashParameters, ...super.hashParameters,
frequency, frequency,
lastUsed, lastUsed,
icon, icon,
]; ];
} }
@@ -84,7 +84,6 @@ class _$BangDataCWProxyImpl implements _$BangDataCWProxy {
BangData icon(BrowserIcon? icon) => this(icon: icon); BangData icon(BrowserIcon? icon) => this(icon: icon);
@override @override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `BangData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `BangData(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
/// ///
/// Usage /// Usage
@@ -104,46 +103,56 @@ class _$BangDataCWProxyImpl implements _$BangDataCWProxy {
Object? icon = const $CopyWithPlaceholder(), Object? icon = const $CopyWithPlaceholder(),
}) { }) {
return BangData( return BangData(
websiteName: websiteName == const $CopyWithPlaceholder() websiteName:
? _value.websiteName websiteName == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.websiteName
: websiteName as String, // ignore: cast_nullable_to_non_nullable
domain: domain == const $CopyWithPlaceholder() : websiteName as String,
? _value.domain domain:
// ignore: cast_nullable_to_non_nullable domain == const $CopyWithPlaceholder()
: domain as String, ? _value.domain
trigger: trigger == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.trigger : domain as String,
// ignore: cast_nullable_to_non_nullable trigger:
: trigger as String, trigger == const $CopyWithPlaceholder()
urlTemplate: urlTemplate == const $CopyWithPlaceholder() ? _value.trigger
? _value.urlTemplate // ignore: cast_nullable_to_non_nullable
// ignore: cast_nullable_to_non_nullable : trigger as String,
: urlTemplate as String, urlTemplate:
category: category == const $CopyWithPlaceholder() urlTemplate == const $CopyWithPlaceholder()
? _value.category ? _value.urlTemplate
// ignore: cast_nullable_to_non_nullable // ignore: cast_nullable_to_non_nullable
: category as String?, : urlTemplate as String,
subCategory: subCategory == const $CopyWithPlaceholder() category:
? _value.subCategory category == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.category
: subCategory as String?, // ignore: cast_nullable_to_non_nullable
format: format == const $CopyWithPlaceholder() : category as String?,
? _value.format subCategory:
// ignore: cast_nullable_to_non_nullable subCategory == const $CopyWithPlaceholder()
: format as Set<BangFormat>?, ? _value.subCategory
frequency: frequency == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.frequency : subCategory as String?,
// ignore: cast_nullable_to_non_nullable format:
: frequency as int?, format == const $CopyWithPlaceholder()
lastUsed: lastUsed == const $CopyWithPlaceholder() ? _value.format
? _value.lastUsed // ignore: cast_nullable_to_non_nullable
// ignore: cast_nullable_to_non_nullable : format as Set<BangFormat>?,
: lastUsed as DateTime?, frequency:
icon: icon == const $CopyWithPlaceholder() frequency == const $CopyWithPlaceholder()
? _value.icon ? _value.frequency
// ignore: cast_nullable_to_non_nullable // ignore: cast_nullable_to_non_nullable
: icon as BrowserIcon?, : frequency as int?,
lastUsed:
lastUsed == const $CopyWithPlaceholder()
? _value.lastUsed
// ignore: cast_nullable_to_non_nullable
: lastUsed as DateTime?,
icon:
icon == const $CopyWithPlaceholder()
? _value.icon
// ignore: cast_nullable_to_non_nullable
: icon as BrowserIcon?,
); );
} }
} }
@@ -15,9 +15,5 @@ class SearchHistoryEntry with FastEquatable {
bool get cacheHash => true; bool get cacheHash => true;
@override @override
List<Object?> get hashParameters => [ List<Object?> get hashParameters => [searchQuery, trigger, searchDate];
searchQuery,
trigger,
searchDate,
];
} }
@@ -19,25 +19,22 @@ class BangSourceService extends _$BangSourceService {
} }
Future<Result<List<Bang>>> getBangs(Uri url, BangGroup? group) async { Future<Result<List<Bang>>> getBangs(Uri url, BangGroup? group) async {
return Result.fromAsync( return Result.fromAsync(() async {
() async { final response = await _client.get(url);
final response = await _client.get(url); return await compute((args) => jsonDecode(utf8.decode(args[0])) as List, [
return await compute( response.bodyBytes,
(args) => jsonDecode(utf8.decode(args[0])) as List, ]).then(
[response.bodyBytes], (json) =>
).then( json.map((e) {
(json) => json.map((e) { var bang = Bang.fromJson(e as Map<String, dynamic>);
var bang = Bang.fromJson(e as Map<String, dynamic>);
if (group != null) { if (group != null) {
bang = bang.copyWith.group(group); bang = bang.copyWith.group(group);
} }
return bang; return bang;
}).toList(), }).toList(),
); );
}, }, exceptionHandler: handleHttpError);
exceptionHandler: handleHttpError,
);
} }
} }
@@ -12,14 +12,15 @@ String _$bangSourceServiceHash() => r'2f734d563fa20de306a72013526ef1f72f910fe1';
@ProviderFor(BangSourceService) @ProviderFor(BangSourceService)
final bangSourceServiceProvider = final bangSourceServiceProvider =
AutoDisposeNotifierProvider<BangSourceService, void>.internal( AutoDisposeNotifierProvider<BangSourceService, void>.internal(
BangSourceService.new, BangSourceService.new,
name: r'bangSourceServiceProvider', name: r'bangSourceServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$bangSourceServiceHash, ? null
dependencies: null, : _$bangSourceServiceHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$BangSourceService = AutoDisposeNotifier<void>; typedef _$BangSourceService = AutoDisposeNotifier<void>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -34,7 +34,8 @@ Stream<List<BangData>> bangDataList(
String? domain, String? domain,
({String category, String? subCategory})? categoryFilter, ({String category, String? subCategory})? categoryFilter,
bool? orderMostFrequentFirst, bool? orderMostFrequentFirst,
})? filter, })?
filter,
}) { }) {
final repository = ref.watch(bangDataRepositoryProvider.notifier); final repository = ref.watch(bangDataRepositoryProvider.notifier);
return repository.watchBangs( return repository.watchBangs(
@@ -58,19 +59,13 @@ Stream<List<SearchHistoryEntry>> searchHistory(Ref ref) {
} }
@Riverpod() @Riverpod()
Stream<DateTime?> lastSyncOfGroup( Stream<DateTime?> lastSyncOfGroup(Ref ref, BangGroup group) {
Ref ref,
BangGroup group,
) {
final repository = ref.watch(bangSyncRepositoryProvider.notifier); final repository = ref.watch(bangSyncRepositoryProvider.notifier);
return repository.watchLastSyncOfGroup(group); return repository.watchLastSyncOfGroup(group);
} }
@Riverpod() @Riverpod()
Stream<int> bangCountOfGroup( Stream<int> bangCountOfGroup(Ref ref, BangGroup group) {
Ref ref,
BangGroup group,
) {
final repository = ref.watch(bangDataRepositoryProvider.notifier); final repository = ref.watch(bangDataRepositoryProvider.notifier);
return repository.watchBangCount(group); return repository.watchBangCount(group);
} }
@@ -39,21 +39,13 @@ class BangDataFamily extends Family<AsyncValue<BangData?>> {
const BangDataFamily(); const BangDataFamily();
/// See also [bangData]. /// See also [bangData].
BangDataProvider call( BangDataProvider call(String? trigger) {
String? trigger, return BangDataProvider(trigger);
) {
return BangDataProvider(
trigger,
);
} }
@override @override
BangDataProvider getProviderOverride( BangDataProvider getProviderOverride(covariant BangDataProvider provider) {
covariant BangDataProvider provider, return call(provider.trigger);
) {
return call(
provider.trigger,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -74,23 +66,19 @@ class BangDataFamily extends Family<AsyncValue<BangData?>> {
/// See also [bangData]. /// See also [bangData].
class BangDataProvider extends AutoDisposeStreamProvider<BangData?> { class BangDataProvider extends AutoDisposeStreamProvider<BangData?> {
/// See also [bangData]. /// See also [bangData].
BangDataProvider( BangDataProvider(String? trigger)
String? trigger, : this._internal(
) : this._internal( (ref) => bangData(ref as BangDataRef, trigger),
(ref) => bangData( from: bangDataProvider,
ref as BangDataRef, name: r'bangDataProvider',
trigger, debugGetCreateSourceHash:
), const bool.fromEnvironment('dart.vm.product')
from: bangDataProvider, ? null
name: r'bangDataProvider', : _$bangDataHash,
debugGetCreateSourceHash: dependencies: BangDataFamily._dependencies,
const bool.fromEnvironment('dart.vm.product') allTransitiveDependencies: BangDataFamily._allTransitiveDependencies,
? null trigger: trigger,
: _$bangDataHash, );
dependencies: BangDataFamily._dependencies,
allTransitiveDependencies: BangDataFamily._allTransitiveDependencies,
trigger: trigger,
);
BangDataProvider._internal( BangDataProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -149,7 +137,8 @@ mixin BangDataRef on AutoDisposeStreamProviderRef<BangData?> {
} }
class _BangDataProviderElement class _BangDataProviderElement
extends AutoDisposeStreamProviderElement<BangData?> with BangDataRef { extends AutoDisposeStreamProviderElement<BangData?>
with BangDataRef {
_BangDataProviderElement(super.provider); _BangDataProviderElement(super.provider);
@override @override
@@ -164,9 +153,10 @@ String _$defaultSearchBangDataHash() =>
final defaultSearchBangDataProvider = StreamProvider<BangData?>.internal( final defaultSearchBangDataProvider = StreamProvider<BangData?>.internal(
defaultSearchBangData, defaultSearchBangData,
name: r'defaultSearchBangDataProvider', name: r'defaultSearchBangDataProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$defaultSearchBangDataHash, ? null
: _$defaultSearchBangDataHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -180,19 +170,20 @@ String _$bangCategoriesHash() => r'947fcfd2dffcc7f585c6ed7379d319f4fe72293a';
@ProviderFor(bangCategories) @ProviderFor(bangCategories)
final bangCategoriesProvider = final bangCategoriesProvider =
AutoDisposeStreamProvider<Map<String, List<String>>>.internal( AutoDisposeStreamProvider<Map<String, List<String>>>.internal(
bangCategories, bangCategories,
name: r'bangCategoriesProvider', name: r'bangCategoriesProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$bangCategoriesHash, ? null
dependencies: null, : _$bangCategoriesHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead') @Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element // ignore: unused_element
typedef BangCategoriesRef typedef BangCategoriesRef =
= AutoDisposeStreamProviderRef<Map<String, List<String>>>; AutoDisposeStreamProviderRef<Map<String, List<String>>>;
String _$bangDataListHash() => r'cd034fdf046b156ac452edd0857ac054ab477917'; String _$bangDataListHash() => r'cd034fdf046b156ac452edd0857ac054ab477917';
/// See also [bangDataList]. /// See also [bangDataList].
@@ -210,21 +201,18 @@ class BangDataListFamily extends Family<AsyncValue<List<BangData>>> {
({String category, String? subCategory})? categoryFilter, ({String category, String? subCategory})? categoryFilter,
String? domain, String? domain,
Iterable<BangGroup>? groups, Iterable<BangGroup>? groups,
bool? orderMostFrequentFirst bool? orderMostFrequentFirst,
})? filter, })?
filter,
}) { }) {
return BangDataListProvider( return BangDataListProvider(filter: filter);
filter: filter,
);
} }
@override @override
BangDataListProvider getProviderOverride( BangDataListProvider getProviderOverride(
covariant BangDataListProvider provider, covariant BangDataListProvider provider,
) { ) {
return call( return call(filter: provider.filter);
filter: provider.filter,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -250,24 +238,22 @@ class BangDataListProvider extends AutoDisposeStreamProvider<List<BangData>> {
({String category, String? subCategory})? categoryFilter, ({String category, String? subCategory})? categoryFilter,
String? domain, String? domain,
Iterable<BangGroup>? groups, Iterable<BangGroup>? groups,
bool? orderMostFrequentFirst bool? orderMostFrequentFirst,
})? filter, })?
filter,
}) : this._internal( }) : this._internal(
(ref) => bangDataList( (ref) => bangDataList(ref as BangDataListRef, filter: filter),
ref as BangDataListRef, from: bangDataListProvider,
filter: filter, name: r'bangDataListProvider',
), debugGetCreateSourceHash:
from: bangDataListProvider, const bool.fromEnvironment('dart.vm.product')
name: r'bangDataListProvider', ? null
debugGetCreateSourceHash: : _$bangDataListHash,
const bool.fromEnvironment('dart.vm.product') dependencies: BangDataListFamily._dependencies,
? null allTransitiveDependencies:
: _$bangDataListHash, BangDataListFamily._allTransitiveDependencies,
dependencies: BangDataListFamily._dependencies, filter: filter,
allTransitiveDependencies: );
BangDataListFamily._allTransitiveDependencies,
filter: filter,
);
BangDataListProvider._internal( BangDataListProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -283,8 +269,9 @@ class BangDataListProvider extends AutoDisposeStreamProvider<List<BangData>> {
({String category, String? subCategory})? categoryFilter, ({String category, String? subCategory})? categoryFilter,
String? domain, String? domain,
Iterable<BangGroup>? groups, Iterable<BangGroup>? groups,
bool? orderMostFrequentFirst bool? orderMostFrequentFirst,
})? filter; })?
filter;
@override @override
Override overrideWith( Override overrideWith(
@@ -331,8 +318,9 @@ mixin BangDataListRef on AutoDisposeStreamProviderRef<List<BangData>> {
({String category, String? subCategory})? categoryFilter, ({String category, String? subCategory})? categoryFilter,
String? domain, String? domain,
Iterable<BangGroup>? groups, Iterable<BangGroup>? groups,
bool? orderMostFrequentFirst bool? orderMostFrequentFirst,
})? get filter; })?
get filter;
} }
class _BangDataListProviderElement class _BangDataListProviderElement
@@ -345,8 +333,9 @@ class _BangDataListProviderElement
({String category, String? subCategory})? categoryFilter, ({String category, String? subCategory})? categoryFilter,
String? domain, String? domain,
Iterable<BangGroup>? groups, Iterable<BangGroup>? groups,
bool? orderMostFrequentFirst bool? orderMostFrequentFirst,
})? get filter => (origin as BangDataListProvider).filter; })?
get filter => (origin as BangDataListProvider).filter;
} }
String _$frequentBangDataListHash() => String _$frequentBangDataListHash() =>
@@ -356,14 +345,15 @@ String _$frequentBangDataListHash() =>
@ProviderFor(frequentBangDataList) @ProviderFor(frequentBangDataList)
final frequentBangDataListProvider = final frequentBangDataListProvider =
AutoDisposeStreamProvider<List<BangData>>.internal( AutoDisposeStreamProvider<List<BangData>>.internal(
frequentBangDataList, frequentBangDataList,
name: r'frequentBangDataListProvider', name: r'frequentBangDataListProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$frequentBangDataListHash, ? null
dependencies: null, : _$frequentBangDataListHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead') @Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element // ignore: unused_element
@@ -374,19 +364,20 @@ String _$searchHistoryHash() => r'7b97798729643de8e44fd8024cdc02f35124b08b';
@ProviderFor(searchHistory) @ProviderFor(searchHistory)
final searchHistoryProvider = final searchHistoryProvider =
AutoDisposeStreamProvider<List<SearchHistoryEntry>>.internal( AutoDisposeStreamProvider<List<SearchHistoryEntry>>.internal(
searchHistory, searchHistory,
name: r'searchHistoryProvider', name: r'searchHistoryProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$searchHistoryHash, ? null
dependencies: null, : _$searchHistoryHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead') @Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element // ignore: unused_element
typedef SearchHistoryRef typedef SearchHistoryRef =
= AutoDisposeStreamProviderRef<List<SearchHistoryEntry>>; AutoDisposeStreamProviderRef<List<SearchHistoryEntry>>;
String _$lastSyncOfGroupHash() => r'23d07f3132ba9bb35a31f74e3a69698d31d4c569'; String _$lastSyncOfGroupHash() => r'23d07f3132ba9bb35a31f74e3a69698d31d4c569';
/// See also [lastSyncOfGroup]. /// See also [lastSyncOfGroup].
@@ -399,21 +390,15 @@ class LastSyncOfGroupFamily extends Family<AsyncValue<DateTime?>> {
const LastSyncOfGroupFamily(); const LastSyncOfGroupFamily();
/// See also [lastSyncOfGroup]. /// See also [lastSyncOfGroup].
LastSyncOfGroupProvider call( LastSyncOfGroupProvider call(BangGroup group) {
BangGroup group, return LastSyncOfGroupProvider(group);
) {
return LastSyncOfGroupProvider(
group,
);
} }
@override @override
LastSyncOfGroupProvider getProviderOverride( LastSyncOfGroupProvider getProviderOverride(
covariant LastSyncOfGroupProvider provider, covariant LastSyncOfGroupProvider provider,
) { ) {
return call( return call(provider.group);
provider.group,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -434,24 +419,20 @@ class LastSyncOfGroupFamily extends Family<AsyncValue<DateTime?>> {
/// See also [lastSyncOfGroup]. /// See also [lastSyncOfGroup].
class LastSyncOfGroupProvider extends AutoDisposeStreamProvider<DateTime?> { class LastSyncOfGroupProvider extends AutoDisposeStreamProvider<DateTime?> {
/// See also [lastSyncOfGroup]. /// See also [lastSyncOfGroup].
LastSyncOfGroupProvider( LastSyncOfGroupProvider(BangGroup group)
BangGroup group, : this._internal(
) : this._internal( (ref) => lastSyncOfGroup(ref as LastSyncOfGroupRef, group),
(ref) => lastSyncOfGroup( from: lastSyncOfGroupProvider,
ref as LastSyncOfGroupRef, name: r'lastSyncOfGroupProvider',
group, debugGetCreateSourceHash:
), const bool.fromEnvironment('dart.vm.product')
from: lastSyncOfGroupProvider, ? null
name: r'lastSyncOfGroupProvider', : _$lastSyncOfGroupHash,
debugGetCreateSourceHash: dependencies: LastSyncOfGroupFamily._dependencies,
const bool.fromEnvironment('dart.vm.product') allTransitiveDependencies:
? null LastSyncOfGroupFamily._allTransitiveDependencies,
: _$lastSyncOfGroupHash, group: group,
dependencies: LastSyncOfGroupFamily._dependencies, );
allTransitiveDependencies:
LastSyncOfGroupFamily._allTransitiveDependencies,
group: group,
);
LastSyncOfGroupProvider._internal( LastSyncOfGroupProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -530,21 +511,15 @@ class BangCountOfGroupFamily extends Family<AsyncValue<int>> {
const BangCountOfGroupFamily(); const BangCountOfGroupFamily();
/// See also [bangCountOfGroup]. /// See also [bangCountOfGroup].
BangCountOfGroupProvider call( BangCountOfGroupProvider call(BangGroup group) {
BangGroup group, return BangCountOfGroupProvider(group);
) {
return BangCountOfGroupProvider(
group,
);
} }
@override @override
BangCountOfGroupProvider getProviderOverride( BangCountOfGroupProvider getProviderOverride(
covariant BangCountOfGroupProvider provider, covariant BangCountOfGroupProvider provider,
) { ) {
return call( return call(provider.group);
provider.group,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -565,24 +540,20 @@ class BangCountOfGroupFamily extends Family<AsyncValue<int>> {
/// See also [bangCountOfGroup]. /// See also [bangCountOfGroup].
class BangCountOfGroupProvider extends AutoDisposeStreamProvider<int> { class BangCountOfGroupProvider extends AutoDisposeStreamProvider<int> {
/// See also [bangCountOfGroup]. /// See also [bangCountOfGroup].
BangCountOfGroupProvider( BangCountOfGroupProvider(BangGroup group)
BangGroup group, : this._internal(
) : this._internal( (ref) => bangCountOfGroup(ref as BangCountOfGroupRef, group),
(ref) => bangCountOfGroup( from: bangCountOfGroupProvider,
ref as BangCountOfGroupRef, name: r'bangCountOfGroupProvider',
group, debugGetCreateSourceHash:
), const bool.fromEnvironment('dart.vm.product')
from: bangCountOfGroupProvider, ? null
name: r'bangCountOfGroupProvider', : _$bangCountOfGroupHash,
debugGetCreateSourceHash: dependencies: BangCountOfGroupFamily._dependencies,
const bool.fromEnvironment('dart.vm.product') allTransitiveDependencies:
? null BangCountOfGroupFamily._allTransitiveDependencies,
: _$bangCountOfGroupHash, group: group,
dependencies: BangCountOfGroupFamily._dependencies, );
allTransitiveDependencies:
BangCountOfGroupFamily._allTransitiveDependencies,
group: group,
);
BangCountOfGroupProvider._internal( BangCountOfGroupProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -641,11 +612,13 @@ mixin BangCountOfGroupRef on AutoDisposeStreamProviderRef<int> {
} }
class _BangCountOfGroupProviderElement class _BangCountOfGroupProviderElement
extends AutoDisposeStreamProviderElement<int> with BangCountOfGroupRef { extends AutoDisposeStreamProviderElement<int>
with BangCountOfGroupRef {
_BangCountOfGroupProviderElement(super.provider); _BangCountOfGroupProviderElement(super.provider);
@override @override
BangGroup get group => (origin as BangCountOfGroupProvider).group; BangGroup get group => (origin as BangCountOfGroupProvider).group;
} }
// ignore_for_file: type=lint // 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 // 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
@@ -39,24 +39,15 @@ class TriggerBangSearchFamily extends Family<AsyncValue<Uri>> {
const TriggerBangSearchFamily(); const TriggerBangSearchFamily();
/// See also [triggerBangSearch]. /// See also [triggerBangSearch].
TriggerBangSearchProvider call( TriggerBangSearchProvider call(BangData bang, String searchQuery) {
BangData bang, return TriggerBangSearchProvider(bang, searchQuery);
String searchQuery,
) {
return TriggerBangSearchProvider(
bang,
searchQuery,
);
} }
@override @override
TriggerBangSearchProvider getProviderOverride( TriggerBangSearchProvider getProviderOverride(
covariant TriggerBangSearchProvider provider, covariant TriggerBangSearchProvider provider,
) { ) {
return call( return call(provider.bang, provider.searchQuery);
provider.bang,
provider.searchQuery,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -77,27 +68,22 @@ class TriggerBangSearchFamily extends Family<AsyncValue<Uri>> {
/// See also [triggerBangSearch]. /// See also [triggerBangSearch].
class TriggerBangSearchProvider extends AutoDisposeFutureProvider<Uri> { class TriggerBangSearchProvider extends AutoDisposeFutureProvider<Uri> {
/// See also [triggerBangSearch]. /// See also [triggerBangSearch].
TriggerBangSearchProvider( TriggerBangSearchProvider(BangData bang, String searchQuery)
BangData bang, : this._internal(
String searchQuery, (ref) =>
) : this._internal( triggerBangSearch(ref as TriggerBangSearchRef, bang, searchQuery),
(ref) => triggerBangSearch( from: triggerBangSearchProvider,
ref as TriggerBangSearchRef, name: r'triggerBangSearchProvider',
bang, debugGetCreateSourceHash:
searchQuery, const bool.fromEnvironment('dart.vm.product')
), ? null
from: triggerBangSearchProvider, : _$triggerBangSearchHash,
name: r'triggerBangSearchProvider', dependencies: TriggerBangSearchFamily._dependencies,
debugGetCreateSourceHash: allTransitiveDependencies:
const bool.fromEnvironment('dart.vm.product') TriggerBangSearchFamily._allTransitiveDependencies,
? null bang: bang,
: _$triggerBangSearchHash, searchQuery: searchQuery,
dependencies: TriggerBangSearchFamily._dependencies, );
allTransitiveDependencies:
TriggerBangSearchFamily._allTransitiveDependencies,
bang: bang,
searchQuery: searchQuery,
);
TriggerBangSearchProvider._internal( TriggerBangSearchProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -165,7 +151,8 @@ mixin TriggerBangSearchRef on AutoDisposeFutureProviderRef<Uri> {
} }
class _TriggerBangSearchProviderElement class _TriggerBangSearchProviderElement
extends AutoDisposeFutureProviderElement<Uri> with TriggerBangSearchRef { extends AutoDisposeFutureProviderElement<Uri>
with TriggerBangSearchRef {
_TriggerBangSearchProviderElement(super.provider); _TriggerBangSearchProviderElement(super.provider);
@override @override
@@ -173,5 +160,6 @@ class _TriggerBangSearchProviderElement
@override @override
String get searchQuery => (origin as TriggerBangSearchProvider).searchQuery; String get searchQuery => (origin as TriggerBangSearchProvider).searchQuery;
} }
// ignore_for_file: type=lint // 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 // 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
@@ -27,11 +27,9 @@ class BangDataRepository extends _$BangDataRepository {
} }
Stream<Map<String, List<String>>> watchCategories() { Stream<Map<String, List<String>>> watchCategories() {
return ref return ref.read(bangDatabaseProvider).categoriesJson().watchSingle().map((
.read(bangDatabaseProvider) json,
.categoriesJson() ) {
.watchSingle()
.map((json) {
final decoded = jsonDecode(json) as Map<String, dynamic>; final decoded = jsonDecode(json) as Map<String, dynamic>;
return decoded.map( return decoded.map(
(key, value) => MapEntry(key, (value as List<dynamic>).cast()), (key, value) => MapEntry(key, (value as List<dynamic>).cast()),
@@ -43,7 +41,8 @@ class BangDataRepository extends _$BangDataRepository {
return ref return ref
.read(bangDatabaseProvider) .read(bangDatabaseProvider)
.bangDao .bangDao
.getBangCount(groups: [group]).watchSingle(); .getBangCount(groups: [group])
.watchSingle();
} }
Stream<List<BangData>> watchBangs({ Stream<List<BangData>> watchBangs({
@@ -94,12 +93,10 @@ class BangDataRepository extends _$BangDataRepository {
}) { }) {
final db = ref.read(bangDatabaseProvider); final db = ref.read(bangDatabaseProvider);
//Pack in a transaction to bundle rebuilds of watch() queries //Pack in a transaction to bundle rebuilds of watch() queries
return db.transaction( return db.transaction(() async {
() async { await db.bangDao.addSearchEntry(trigger, searchQuery);
await db.bangDao.addSearchEntry(trigger, searchQuery); await db.evictHistoryEntries(limit: maxEntryCount);
await db.evictHistoryEntries(limit: maxEntryCount); });
},
);
} }
Future<void> removeSearchEntry(String searchQuery) { Future<void> removeSearchEntry(String searchQuery) {
@@ -13,14 +13,15 @@ String _$bangDataRepositoryHash() =>
@ProviderFor(BangDataRepository) @ProviderFor(BangDataRepository)
final bangDataRepositoryProvider = final bangDataRepositoryProvider =
NotifierProvider<BangDataRepository, void>.internal( NotifierProvider<BangDataRepository, void>.internal(
BangDataRepository.new, BangDataRepository.new,
name: r'bangDataRepositoryProvider', name: r'bangDataRepositoryProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$bangDataRepositoryHash, ? null
dependencies: null, : _$bangDataRepositoryHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$BangDataRepository = Notifier<void>; typedef _$BangDataRepository = Notifier<void>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -12,13 +12,15 @@ String _$bangSearchHash() => r'abf9ff5badf2ecfbcbde148fd2c849beac83bec4';
@ProviderFor(BangSearch) @ProviderFor(BangSearch)
final bangSearchProvider = final bangSearchProvider =
AutoDisposeStreamNotifierProvider<BangSearch, List<BangData>>.internal( AutoDisposeStreamNotifierProvider<BangSearch, List<BangData>>.internal(
BangSearch.new, BangSearch.new,
name: r'bangSearchProvider', name: r'bangSearchProvider',
debugGetCreateSourceHash: debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') ? null : _$bangSearchHash, const bool.fromEnvironment('dart.vm.product')
dependencies: null, ? null
allTransitiveDependencies: null, : _$bangSearchHash,
); dependencies: null,
allTransitiveDependencies: null,
);
typedef _$BangSearch = AutoDisposeStreamNotifier<List<BangData>>; typedef _$BangSearch = AutoDisposeStreamNotifier<List<BangData>>;
String _$seamlessBangProviderHash() => String _$seamlessBangProviderHash() =>
@@ -27,17 +29,20 @@ String _$seamlessBangProviderHash() =>
/// See also [SeamlessBangProvider]. /// See also [SeamlessBangProvider].
@ProviderFor(SeamlessBangProvider) @ProviderFor(SeamlessBangProvider)
final seamlessBangProviderProvider = AutoDisposeNotifierProvider< final seamlessBangProviderProvider = AutoDisposeNotifierProvider<
SeamlessBangProvider, AsyncValue<List<BangData>>>.internal( SeamlessBangProvider,
AsyncValue<List<BangData>>
>.internal(
SeamlessBangProvider.new, SeamlessBangProvider.new,
name: r'seamlessBangProviderProvider', name: r'seamlessBangProviderProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$seamlessBangProviderHash, ? null
: _$seamlessBangProviderHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
typedef _$SeamlessBangProvider typedef _$SeamlessBangProvider =
= AutoDisposeNotifier<AsyncValue<List<BangData>>>; AutoDisposeNotifier<AsyncValue<List<BangData>>>;
// ignore_for_file: type=lint // 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 // 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
@@ -29,16 +29,14 @@ class BangSyncRepository extends _$BangSyncRepository {
} }
final result = await sourceService.getBangs(url, group); final result = await sourceService.getBangs(url, group);
return result.flatMapAsync( return result.flatMapAsync((remoteBangs) async {
(remoteBangs) async { await db.syncDao.syncBangs(
await db.syncDao.syncBangs( group: group,
group: group, remoteBangs: remoteBangs,
remoteBangs: remoteBangs, syncTime: DateTime.now(),
syncTime: DateTime.now(), );
); await db.optimizeFtsIndex();
await db.optimizeFtsIndex(); });
},
);
} }
Future<Result<void>> syncBangGroup( Future<Result<void>> syncBangGroup(
@@ -47,7 +45,9 @@ class BangSyncRepository extends _$BangSyncRepository {
) async { ) async {
try { try {
return Result.success( return Result.success(
await ref.read(bangDatabaseProvider).computeWithDatabase( await ref
.read(bangDatabaseProvider)
.computeWithDatabase(
connect: BangDatabase.new, connect: BangDatabase.new,
computation: (db) async { computation: (db) async {
final ref = ProviderContainer(); final ref = ProviderContainer();
@@ -92,8 +92,10 @@ class BangSyncRepository extends _$BangSyncRepository {
//Run isolated operations //Run isolated operations
final futures = groups.map( final futures = groups.map(
(source) => syncBangGroup(source, syncInterval) (source) => syncBangGroup(
.then((result) => MapEntry(source, result)), source,
syncInterval,
).then((result) => MapEntry(source, result)),
); );
return Map.fromEntries(await Future.wait(futures)); return Map.fromEntries(await Future.wait(futures));
@@ -13,14 +13,15 @@ String _$bangSyncRepositoryHash() =>
@ProviderFor(BangSyncRepository) @ProviderFor(BangSyncRepository)
final bangSyncRepositoryProvider = final bangSyncRepositoryProvider =
NotifierProvider<BangSyncRepository, void>.internal( NotifierProvider<BangSyncRepository, void>.internal(
BangSyncRepository.new, BangSyncRepository.new,
name: r'bangSyncRepositoryProvider', name: r'bangSyncRepositoryProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$bangSyncRepositoryHash, ? null
dependencies: null, : _$bangSyncRepositoryHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$BangSyncRepository = Notifier<void>; typedef _$BangSyncRepository = Notifier<void>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -45,38 +45,43 @@ class BangCategoriesScreen extends HookConsumerWidget {
expanded.value = {...expanded.value}..remove(key); expanded.value = {...expanded.value}..remove(key);
} }
}, },
children: categories.entries children:
.map( categories.entries
(category) => ExpansionPanel( .map(
canTapOnHeader: true, (category) => ExpansionPanel(
isExpanded: expanded.value.contains(category.key), canTapOnHeader: true,
headerBuilder: (context, isExpanded) => ListTile( isExpanded: expanded.value.contains(
title: Text(category.key), category.key,
), ),
body: Padding( headerBuilder:
padding: const EdgeInsets.only(left: 16.0), (context, isExpanded) =>
child: Column( ListTile(title: Text(category.key)),
mainAxisSize: MainAxisSize.min, body: Padding(
children: category.value padding: const EdgeInsets.only(left: 16.0),
.map( child: Column(
(subCategory) => ListTile( mainAxisSize: MainAxisSize.min,
title: Text(subCategory), children:
onTap: () async { category.value
await context.push( .map(
BangSubCategoryRoute( (subCategory) => ListTile(
category: category.key, title: Text(subCategory),
subCategory: subCategory, onTap: () async {
).location, await context.push(
); BangSubCategoryRoute(
}, category: category.key,
), subCategory:
) subCategory,
.toList(), ).location,
);
},
),
)
.toList(),
),
),
), ),
), )
), .toList(),
)
.toList(),
); );
}, },
), ),
@@ -84,12 +89,13 @@ class BangCategoriesScreen extends HookConsumerWidget {
}, },
); );
}, },
error: (error, stackTrace) => Center( error:
child: FailureWidget( (error, stackTrace) => Center(
title: 'Failed to load Bang Categories', child: FailureWidget(
exception: error, title: 'Failed to load Bang Categories',
), exception: error,
), ),
),
loading: () => const Center(child: CircularProgressIndicator()), loading: () => const Center(child: CircularProgressIndicator()),
), ),
); );
@@ -35,9 +35,7 @@ class BangListScreen extends HookConsumerWidget {
return Scaffold( return Scaffold(
body: CustomScrollView( body: CustomScrollView(
slivers: [ slivers: [
SliverAppBar.medium( SliverAppBar.medium(title: Text('$category: $subCategory')),
title: Text('$category: $subCategory'),
),
bangsAsync.when( bangsAsync.when(
data: (bangs) { data: (bangs) {
return SliverList.builder( return SliverList.builder(
@@ -53,10 +51,10 @@ class BangListScreen extends HookConsumerWidget {
if (ref.read(bottomSheetControllerProvider) if (ref.read(bottomSheetControllerProvider)
is! CreateTabSheet) { is! CreateTabSheet) {
ref.read(bottomSheetControllerProvider.notifier).show( ref
CreateTabSheet( .read(bottomSheetControllerProvider.notifier)
preferredTool: KagiTool.search, .show(
), CreateTabSheet(preferredTool: KagiTool.search),
); );
} }
@@ -66,17 +64,19 @@ class BangListScreen extends HookConsumerWidget {
}, },
); );
}, },
error: (error, stackTrace) => SliverToBoxAdapter( error:
child: Center( (error, stackTrace) => SliverToBoxAdapter(
child: FailureWidget( child: Center(
title: 'Failed to load Bangs', child: FailureWidget(
exception: error, title: 'Failed to load Bangs',
exception: error,
),
),
),
loading:
() => const SliverToBoxAdapter(
child: Center(child: CircularProgressIndicator()),
), ),
),
),
loading: () => const SliverToBoxAdapter(
child: Center(child: CircularProgressIndicator()),
),
), ),
], ],
), ),
@@ -22,8 +22,9 @@ class BangSearchScreen extends HookConsumerWidget {
final resultsAsync = ref.watch(bangSearchProvider); final resultsAsync = ref.watch(bangSearchProvider);
final incognitoEnabled = ref.watch(incognitoModeEnabledProvider); final incognitoEnabled = ref.watch(incognitoModeEnabledProvider);
final textEditingController = final textEditingController = useTextEditingController(
useTextEditingController(text: initialSearchText); text: initialSearchText,
);
useListenableCallback(textEditingController, () async { useListenableCallback(textEditingController, () async {
unawaited( unawaited(
@@ -57,42 +58,44 @@ class BangSearchScreen extends HookConsumerWidget {
), ),
body: resultsAsync.when( body: resultsAsync.when(
skipLoadingOnReload: true, skipLoadingOnReload: true,
data: (bangs) => FadingScroll( data:
fadingSize: 25, (bangs) => FadingScroll(
builder: (context, controller) { fadingSize: 25,
return ListView.builder( builder: (context, controller) {
controller: controller, return ListView.builder(
itemCount: bangs.length, controller: controller,
itemBuilder: (context, index) { itemCount: bangs.length,
final bang = bangs[index]; itemBuilder: (context, index) {
return BangDetails( final bang = bangs[index];
bang, return BangDetails(
onTap: () { bang,
ref onTap: () {
.read(selectedBangTriggerProvider().notifier) ref
.setTrigger(bang.trigger); .read(selectedBangTriggerProvider().notifier)
.setTrigger(bang.trigger);
// if (ref.read(bottomSheetControllerProvider) // if (ref.read(bottomSheetControllerProvider)
// is! CreateTabSheet) { // is! CreateTabSheet) {
// ref.read(bottomSheetControllerProvider.notifier).show( // ref.read(bottomSheetControllerProvider.notifier).show(
// CreateTabSheet(preferredTool: KagiTool.search), // CreateTabSheet(preferredTool: KagiTool.search),
// ); // );
// } // }
// context.go(BrowserRoute().location); // context.go(BrowserRoute().location);
context.pop(); context.pop();
},
);
}, },
); );
}, },
); ),
}, error:
), (error, stackTrace) => Center(
error: (error, stackTrace) => Center( child: FailureWidget(
child: FailureWidget( title: 'Bang Search failed',
title: 'Bang Search failed', exception: error,
exception: error, ),
), ),
),
loading: () => const SizedBox.shrink(), loading: () => const SizedBox.shrink(),
), ),
); );
@@ -63,8 +63,9 @@ class BangDetails extends HookConsumerWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
FilledButton.tonalIcon( FilledButton.tonalIcon(
style: style: const ButtonStyle(
const ButtonStyle(visualDensity: VisualDensity.compact), visualDensity: VisualDensity.compact,
),
onPressed: () async { onPressed: () async {
final url = Uri.parse(bangData.getUrl('').origin); final url = Uri.parse(bangData.getUrl('').origin);
@@ -79,9 +80,7 @@ class BangDetails extends HookConsumerWidget {
label: Text(bangData.domain), label: Text(bangData.domain),
icon: const Icon(Icons.open_in_new), icon: const Icon(Icons.open_in_new),
), ),
const SizedBox( const SizedBox(width: 8),
width: 8,
),
Expanded( Expanded(
child: Text( child: Text(
'!${bangData.trigger}', '!${bangData.trigger}',
@@ -30,14 +30,11 @@ class SiteSearch extends HookConsumerWidget {
final searchTextController = useTextEditingController(); final searchTextController = useTextEditingController();
useListenableCallback( useListenableCallback(searchTextController, () async {
searchTextController, ref
() async { .read(searchSuggestionsProvider().notifier)
ref .addQuery(searchTextController.text);
.read(searchSuggestionsProvider().notifier) });
.addQuery(searchTextController.text);
},
);
final selectedBang = ref.watch(selectedBangDataProvider(domain: domain)); final selectedBang = ref.watch(selectedBangDataProvider(domain: domain));
@@ -73,15 +70,11 @@ class SiteSearch extends HookConsumerWidget {
selectedItem: selectedBang, selectedItem: selectedBang,
onSelected: (bang) { onSelected: (bang) {
ref ref
.read( .read(selectedBangTriggerProvider(domain: domain).notifier)
selectedBangTriggerProvider(domain: domain).notifier,
)
.setTrigger(bang.trigger); .setTrigger(bang.trigger);
}, },
onDeleted: (bang) { onDeleted: (bang) {
if (ref.read( if (ref.read(selectedBangTriggerProvider(domain: domain)) ==
selectedBangTriggerProvider(domain: domain),
) ==
bang.trigger) { bang.trigger) {
ref ref
.read( .read(
@@ -13,9 +13,7 @@ class MessagesDao extends DatabaseAccessor<ChatDatabase>
MessagesDao(super.db); MessagesDao(super.db);
Selectable<int> messageCount({required String chatId}) { Selectable<int> messageCount({required String chatId}) {
return db.chatMessage.count( return db.chatMessage.count(where: (row) => row.chatId.equals(chatId));
where: (row) => row.chatId.equals(chatId),
);
} }
Selectable<ChatMessageData> chatMessages({required String chatId}) { Selectable<ChatMessageData> chatMessages({required String chatId}) {
@@ -29,9 +27,9 @@ class MessagesDao extends DatabaseAccessor<ChatDatabase>
db.chatMessage.select()..where((row) => row.messageId.equals(messageId)), db.chatMessage.select()..where((row) => row.messageId.equals(messageId)),
); );
return db.selectExpressions([existsExpression]).map( return db
(row) => row.read(existsExpression)!, .selectExpressions([existsExpression])
); .map((row) => row.read(existsExpression)!);
} }
SingleOrNullSelectable<int> messageIndex({ SingleOrNullSelectable<int> messageIndex({
@@ -52,39 +50,39 @@ class MessagesDao extends DatabaseAccessor<ChatDatabase>
return null; return null;
} }
return db.transaction( return db.transaction(() async {
() async { final String orderKey;
final String orderKey; if (index != null) {
if (index != null) { if (index <= 0) {
if (index <= 0) { orderKey =
orderKey = await db.leadingOrderKey(bucket: 0, chatId: chatId).getSingle();
await db.leadingOrderKey(bucket: 0, chatId: chatId).getSingle();
} else {
orderKey = await db
.orderKeyBeforeIndex(chatId: chatId, rowIdx: index + 1)
.getSingle();
}
} else { } else {
orderKey = orderKey =
await db.trailingOrderKey(bucket: 0, chatId: chatId).getSingle(); await db
.orderKeyBeforeIndex(chatId: chatId, rowIdx: index + 1)
.getSingle();
} }
} else {
orderKey =
await db.trailingOrderKey(bucket: 0, chatId: chatId).getSingle();
}
await db.chatMessage.insertOne( await db.chatMessage.insertOne(
ChatMessageCompanion.insert( ChatMessageCompanion.insert(
messageId: message.id, messageId: message.id,
chatId: chatId, chatId: chatId,
orderKey: orderKey, orderKey: orderKey,
messageJson: jsonEncode(message.toJson()), messageJson: jsonEncode(message.toJson()),
), ),
); );
final rowIdx = await db final rowIdx =
.messageIndex(chatId: chatId, messageId: message.id) await db
.getSingle(); .messageIndex(chatId: chatId, messageId: message.id)
.getSingle();
return rowIdx - 1; return rowIdx - 1;
}, });
);
} }
Future<int> removeMessage({required String messageId}) { Future<int> removeMessage({required String messageId}) {
@@ -98,10 +96,10 @@ class MessagesDao extends DatabaseAccessor<ChatDatabase>
return (db.chatMessage.update() return (db.chatMessage.update()
..where((row) => row.messageId.equals(messageId))) ..where((row) => row.messageId.equals(messageId)))
.write( .write(
ChatMessageCompanion( ChatMessageCompanion(
messageJson: Value(jsonEncode(message.toJson())), messageJson: Value(jsonEncode(message.toJson())),
), ),
); );
} }
Future<int> deleteChatMessages({required String chatId}) { Future<int> deleteChatMessages({required String chatId}) {
@@ -120,21 +118,19 @@ class MessagesDao extends DatabaseAccessor<ChatDatabase>
await db.leadingOrderKey(bucket: 0, chatId: chatId).getSingle(); await db.leadingOrderKey(bucket: 0, chatId: chatId).getSingle();
await db.chatMessage.insertAll( await db.chatMessage.insertAll(
messages.map( messages.map((message) {
(message) { final insertable = ChatMessageCompanion.insert(
final insertable = ChatMessageCompanion.insert( messageId: message.id,
messageId: message.id, chatId: chatId,
chatId: chatId, messageJson: jsonEncode(message.toJson()),
messageJson: jsonEncode(message.toJson()), orderKey: currentOrderKey,
orderKey: currentOrderKey, // timestamp: DateTime.now(),
// timestamp: DateTime.now(), );
);
currentOrderKey = LexoRank.parse(currentOrderKey).genPrev().value; currentOrderKey = LexoRank.parse(currentOrderKey).genPrev().value;
return insertable; return insertable;
}, }),
),
); );
}); });
} }
@@ -10,9 +10,10 @@ class MetadataDao extends DatabaseAccessor<ChatDatabase>
MetadataDao(super.db); MetadataDao(super.db);
SingleOrNullSelectable<ChatMetadata> chatMetadata(String chatId) { SingleOrNullSelectable<ChatMetadata> chatMetadata(String chatId) {
final statement = db.chatData.selectOnly() final statement =
..addColumns([db.chatData.metadata]) db.chatData.selectOnly()
..where(db.chatData.chatId.equals(chatId)); ..addColumns([db.chatData.metadata])
..where(db.chatData.chatId.equals(chatId));
return statement.map((row) => row.readWithConverter(db.chatData.metadata)!); return statement.map((row) => row.readWithConverter(db.chatData.metadata)!);
} }
@@ -9,16 +9,22 @@ class ChatData extends Table with TableInfo<ChatData, ChatDataData> {
final String? _alias; final String? _alias;
ChatData(this.attachedDatabase, [this._alias]); ChatData(this.attachedDatabase, [this._alias]);
late final GeneratedColumn<String> chatId = GeneratedColumn<String>( late final GeneratedColumn<String> chatId = GeneratedColumn<String>(
'chat_id', aliasedName, false, 'chat_id',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: 'PRIMARY KEY NOT NULL'); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'PRIMARY KEY NOT NULL',
);
late final GeneratedColumnWithTypeConverter<ChatMetadata, String> metadata = late final GeneratedColumnWithTypeConverter<ChatMetadata, String> metadata =
GeneratedColumn<String>('metadata', aliasedName, false, GeneratedColumn<String>(
type: DriftSqlType.string, 'metadata',
requiredDuringInsert: true, aliasedName,
$customConstraints: 'NOT NULL') false,
.withConverter<ChatMetadata>(ChatData.$convertermetadata); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL',
).withConverter<ChatMetadata>(ChatData.$convertermetadata);
@override @override
List<GeneratedColumn> get $columns => [chatId, metadata]; List<GeneratedColumn> get $columns => [chatId, metadata];
@override @override
@@ -32,10 +38,17 @@ class ChatData extends Table with TableInfo<ChatData, ChatDataData> {
ChatDataData map(Map<String, dynamic> data, {String? tablePrefix}) { ChatDataData map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return ChatDataData( return ChatDataData(
chatId: attachedDatabase.typeMapping chatId:
.read(DriftSqlType.string, data['${effectivePrefix}chat_id'])!, attachedDatabase.typeMapping.read(
metadata: ChatData.$convertermetadata.fromSql(attachedDatabase.typeMapping DriftSqlType.string,
.read(DriftSqlType.string, data['${effectivePrefix}metadata'])!), data['${effectivePrefix}chat_id'],
)!,
metadata: ChatData.$convertermetadata.fromSql(
attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}metadata'],
)!,
),
); );
} }
@@ -59,14 +72,17 @@ class ChatDataData extends DataClass implements Insertable<ChatDataData> {
final map = <String, Expression>{}; final map = <String, Expression>{};
map['chat_id'] = Variable<String>(chatId); map['chat_id'] = Variable<String>(chatId);
{ {
map['metadata'] = map['metadata'] = Variable<String>(
Variable<String>(ChatData.$convertermetadata.toSql(metadata)); ChatData.$convertermetadata.toSql(metadata),
);
} }
return map; return map;
} }
factory ChatDataData.fromJson(Map<String, dynamic> json, factory ChatDataData.fromJson(
{ValueSerializer? serializer}) { Map<String, dynamic> json, {
ValueSerializer? serializer,
}) {
serializer ??= driftRuntimeOptions.defaultSerializer; serializer ??= driftRuntimeOptions.defaultSerializer;
return ChatDataData( return ChatDataData(
chatId: serializer.fromJson<String>(json['chat_id']), chatId: serializer.fromJson<String>(json['chat_id']),
@@ -126,8 +142,8 @@ class ChatDataCompanion extends UpdateCompanion<ChatDataData> {
required String chatId, required String chatId,
required ChatMetadata metadata, required ChatMetadata metadata,
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : chatId = Value(chatId), }) : chatId = Value(chatId),
metadata = Value(metadata); metadata = Value(metadata);
static Insertable<ChatDataData> custom({ static Insertable<ChatDataData> custom({
Expression<String>? chatId, Expression<String>? chatId,
Expression<String>? metadata, Expression<String>? metadata,
@@ -140,10 +156,11 @@ class ChatDataCompanion extends UpdateCompanion<ChatDataData> {
}); });
} }
ChatDataCompanion copyWith( ChatDataCompanion copyWith({
{Value<String>? chatId, Value<String>? chatId,
Value<ChatMetadata>? metadata, Value<ChatMetadata>? metadata,
Value<int>? rowid}) { Value<int>? rowid,
}) {
return ChatDataCompanion( return ChatDataCompanion(
chatId: chatId ?? this.chatId, chatId: chatId ?? this.chatId,
metadata: metadata ?? this.metadata, metadata: metadata ?? this.metadata,
@@ -158,8 +175,9 @@ class ChatDataCompanion extends UpdateCompanion<ChatDataData> {
map['chat_id'] = Variable<String>(chatId.value); map['chat_id'] = Variable<String>(chatId.value);
} }
if (metadata.present) { if (metadata.present) {
map['metadata'] = map['metadata'] = Variable<String>(
Variable<String>(ChatData.$convertermetadata.toSql(metadata.value)); ChatData.$convertermetadata.toSql(metadata.value),
);
} }
if (rowid.present) { if (rowid.present) {
map['rowid'] = Variable<int>(rowid.value); map['rowid'] = Variable<int>(rowid.value);
@@ -184,28 +202,44 @@ class ChatMessage extends Table with TableInfo<ChatMessage, ChatMessageData> {
final String? _alias; final String? _alias;
ChatMessage(this.attachedDatabase, [this._alias]); ChatMessage(this.attachedDatabase, [this._alias]);
late final GeneratedColumn<String> messageId = GeneratedColumn<String>( late final GeneratedColumn<String> messageId = GeneratedColumn<String>(
'message_id', aliasedName, false, 'message_id',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: 'PRIMARY KEY NOT NULL'); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'PRIMARY KEY NOT NULL',
);
late final GeneratedColumn<String> chatId = GeneratedColumn<String>( late final GeneratedColumn<String> chatId = GeneratedColumn<String>(
'chat_id', aliasedName, false, 'chat_id',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: 'NOT NULL'); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL',
);
late final GeneratedColumn<String> orderKey = GeneratedColumn<String>( late final GeneratedColumn<String> orderKey = GeneratedColumn<String>(
'order_key', aliasedName, false, 'order_key',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: 'NOT NULL'); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL',
);
late final GeneratedColumn<String> messageJson = GeneratedColumn<String>( late final GeneratedColumn<String> messageJson = GeneratedColumn<String>(
'message_json', aliasedName, false, 'message_json',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: 'NOT NULL'); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL',
);
@override @override
List<GeneratedColumn> get $columns => List<GeneratedColumn> get $columns => [
[messageId, chatId, orderKey, messageJson]; messageId,
chatId,
orderKey,
messageJson,
];
@override @override
String get aliasedName => _alias ?? actualTableName; String get aliasedName => _alias ?? actualTableName;
@override @override
@@ -217,14 +251,26 @@ class ChatMessage extends Table with TableInfo<ChatMessage, ChatMessageData> {
ChatMessageData map(Map<String, dynamic> data, {String? tablePrefix}) { ChatMessageData map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return ChatMessageData( return ChatMessageData(
messageId: attachedDatabase.typeMapping messageId:
.read(DriftSqlType.string, data['${effectivePrefix}message_id'])!, attachedDatabase.typeMapping.read(
chatId: attachedDatabase.typeMapping DriftSqlType.string,
.read(DriftSqlType.string, data['${effectivePrefix}chat_id'])!, data['${effectivePrefix}message_id'],
orderKey: attachedDatabase.typeMapping )!,
.read(DriftSqlType.string, data['${effectivePrefix}order_key'])!, chatId:
messageJson: attachedDatabase.typeMapping attachedDatabase.typeMapping.read(
.read(DriftSqlType.string, data['${effectivePrefix}message_json'])!, DriftSqlType.string,
data['${effectivePrefix}chat_id'],
)!,
orderKey:
attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}order_key'],
)!,
messageJson:
attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}message_json'],
)!,
); );
} }
@@ -242,11 +288,12 @@ class ChatMessageData extends DataClass implements Insertable<ChatMessageData> {
final String chatId; final String chatId;
final String orderKey; final String orderKey;
final String messageJson; final String messageJson;
const ChatMessageData( const ChatMessageData({
{required this.messageId, required this.messageId,
required this.chatId, required this.chatId,
required this.orderKey, required this.orderKey,
required this.messageJson}); required this.messageJson,
});
@override @override
Map<String, Expression> toColumns(bool nullToAbsent) { Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{}; final map = <String, Expression>{};
@@ -257,8 +304,10 @@ class ChatMessageData extends DataClass implements Insertable<ChatMessageData> {
return map; return map;
} }
factory ChatMessageData.fromJson(Map<String, dynamic> json, factory ChatMessageData.fromJson(
{ValueSerializer? serializer}) { Map<String, dynamic> json, {
ValueSerializer? serializer,
}) {
serializer ??= driftRuntimeOptions.defaultSerializer; serializer ??= driftRuntimeOptions.defaultSerializer;
return ChatMessageData( return ChatMessageData(
messageId: serializer.fromJson<String>(json['message_id']), messageId: serializer.fromJson<String>(json['message_id']),
@@ -278,17 +327,17 @@ class ChatMessageData extends DataClass implements Insertable<ChatMessageData> {
}; };
} }
ChatMessageData copyWith( ChatMessageData copyWith({
{String? messageId, String? messageId,
String? chatId, String? chatId,
String? orderKey, String? orderKey,
String? messageJson}) => String? messageJson,
ChatMessageData( }) => ChatMessageData(
messageId: messageId ?? this.messageId, messageId: messageId ?? this.messageId,
chatId: chatId ?? this.chatId, chatId: chatId ?? this.chatId,
orderKey: orderKey ?? this.orderKey, orderKey: orderKey ?? this.orderKey,
messageJson: messageJson ?? this.messageJson, messageJson: messageJson ?? this.messageJson,
); );
ChatMessageData copyWithCompanion(ChatMessageCompanion data) { ChatMessageData copyWithCompanion(ChatMessageCompanion data) {
return ChatMessageData( return ChatMessageData(
messageId: data.messageId.present ? data.messageId.value : this.messageId, messageId: data.messageId.present ? data.messageId.value : this.messageId,
@@ -341,10 +390,10 @@ class ChatMessageCompanion extends UpdateCompanion<ChatMessageData> {
required String orderKey, required String orderKey,
required String messageJson, required String messageJson,
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : messageId = Value(messageId), }) : messageId = Value(messageId),
chatId = Value(chatId), chatId = Value(chatId),
orderKey = Value(orderKey), orderKey = Value(orderKey),
messageJson = Value(messageJson); messageJson = Value(messageJson);
static Insertable<ChatMessageData> custom({ static Insertable<ChatMessageData> custom({
Expression<String>? messageId, Expression<String>? messageId,
Expression<String>? chatId, Expression<String>? chatId,
@@ -361,12 +410,13 @@ class ChatMessageCompanion extends UpdateCompanion<ChatMessageData> {
}); });
} }
ChatMessageCompanion copyWith( ChatMessageCompanion copyWith({
{Value<String>? messageId, Value<String>? messageId,
Value<String>? chatId, Value<String>? chatId,
Value<String>? orderKey, Value<String>? orderKey,
Value<String>? messageJson, Value<String>? messageJson,
Value<int>? rowid}) { Value<int>? rowid,
}) {
return ChatMessageCompanion( return ChatMessageCompanion(
messageId: messageId ?? this.messageId, messageId: messageId ?? this.messageId,
chatId: chatId ?? this.chatId, chatId: chatId ?? this.chatId,
@@ -415,80 +465,79 @@ abstract class _$ChatDatabase extends GeneratedDatabase {
$ChatDatabaseManager get managers => $ChatDatabaseManager(this); $ChatDatabaseManager get managers => $ChatDatabaseManager(this);
late final ChatData chatData = ChatData(this); late final ChatData chatData = ChatData(this);
late final ChatMessage chatMessage = ChatMessage(this); late final ChatMessage chatMessage = ChatMessage(this);
late final Index groupOrderIdx = Index('group_order_idx', late final Index groupOrderIdx = Index(
'CREATE UNIQUE INDEX group_order_idx ON chat_message (chat_id, order_key)'); 'group_order_idx',
'CREATE UNIQUE INDEX group_order_idx ON chat_message (chat_id, order_key)',
);
late final MessagesDao messagesDao = MessagesDao(this as ChatDatabase); late final MessagesDao messagesDao = MessagesDao(this as ChatDatabase);
late final MetadataDao metadataDao = MetadataDao(this as ChatDatabase); late final MetadataDao metadataDao = MetadataDao(this as ChatDatabase);
Selectable<String> leadingOrderKey( Selectable<String> leadingOrderKey({
{required int bucket, required String chatId}) { required int bucket,
required String chatId,
}) {
return customSelect( return customSelect(
'SELECT lexo_rank_previous(?1, (SELECT order_key FROM chat_message WHERE chat_id = ?2 ORDER BY order_key LIMIT 1)) AS _c0', 'SELECT lexo_rank_previous(?1, (SELECT order_key FROM chat_message WHERE chat_id = ?2 ORDER BY order_key LIMIT 1)) AS _c0',
variables: [ variables: [Variable<int>(bucket), Variable<String>(chatId)],
Variable<int>(bucket), readsFrom: {chatMessage},
Variable<String>(chatId) ).map((QueryRow row) => row.read<String>('_c0'));
],
readsFrom: {
chatMessage,
}).map((QueryRow row) => row.read<String>('_c0'));
} }
Selectable<String> trailingOrderKey( Selectable<String> trailingOrderKey({
{required int bucket, required String chatId}) { required int bucket,
required String chatId,
}) {
return customSelect( return customSelect(
'SELECT lexo_rank_next(?1, (SELECT order_key FROM chat_message WHERE chat_id = ?2 ORDER BY order_key DESC LIMIT 1)) AS _c0', 'SELECT lexo_rank_next(?1, (SELECT order_key FROM chat_message WHERE chat_id = ?2 ORDER BY order_key DESC LIMIT 1)) AS _c0',
variables: [ variables: [Variable<int>(bucket), Variable<String>(chatId)],
Variable<int>(bucket), readsFrom: {chatMessage},
Variable<String>(chatId) ).map((QueryRow row) => row.read<String>('_c0'));
],
readsFrom: {
chatMessage,
}).map((QueryRow row) => row.read<String>('_c0'));
} }
Selectable<String> orderKeyBeforeIndex( Selectable<String> orderKeyBeforeIndex({
{required String chatId, required int rowIdx}) { required String chatId,
required int rowIdx,
}) {
return customSelect( return customSelect(
'WITH ordered_table AS (SELECT message_id, order_key, LEAD(order_key)OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS next_order_key, ROW_NUMBER()OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS row_idx, COUNT(*)OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS total_rows FROM chat_message WHERE chat_id = ?1) SELECT lexo_rank_reorder_after(order_key, next_order_key) AS _c0 FROM ordered_table WHERE row_idx = MIN(?2, total_rows)', 'WITH ordered_table AS (SELECT message_id, order_key, LEAD(order_key)OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS next_order_key, ROW_NUMBER()OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS row_idx, COUNT(*)OVER (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS total_rows FROM chat_message WHERE chat_id = ?1) SELECT lexo_rank_reorder_after(order_key, next_order_key) AS _c0 FROM ordered_table WHERE row_idx = MIN(?2, total_rows)',
variables: [ variables: [Variable<String>(chatId), Variable<int>(rowIdx)],
Variable<String>(chatId), readsFrom: {chatMessage},
Variable<int>(rowIdx) ).map((QueryRow row) => row.read<String>('_c0'));
],
readsFrom: {
chatMessage,
}).map((QueryRow row) => row.read<String>('_c0'));
} }
Selectable<int> messageIndex( Selectable<int> messageIndex({
{required String chatId, required String messageId}) { required String chatId,
required String messageId,
}) {
return customSelect( return customSelect(
'WITH ordered_table AS (SELECT message_id, ROW_NUMBER()OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS row_idx FROM chat_message WHERE chat_id = ?1) SELECT row_idx FROM ordered_table WHERE message_id = ?2', 'WITH ordered_table AS (SELECT message_id, ROW_NUMBER()OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS row_idx FROM chat_message WHERE chat_id = ?1) SELECT row_idx FROM ordered_table WHERE message_id = ?2',
variables: [ variables: [Variable<String>(chatId), Variable<String>(messageId)],
Variable<String>(chatId), readsFrom: {chatMessage},
Variable<String>(messageId) ).map((QueryRow row) => row.read<int>('row_idx'));
],
readsFrom: {
chatMessage,
}).map((QueryRow row) => row.read<int>('row_idx'));
} }
@override @override
Iterable<TableInfo<Table, Object?>> get allTables => Iterable<TableInfo<Table, Object?>> get allTables =>
allSchemaEntities.whereType<TableInfo<Table, Object?>>(); allSchemaEntities.whereType<TableInfo<Table, Object?>>();
@override @override
List<DatabaseSchemaEntity> get allSchemaEntities => List<DatabaseSchemaEntity> get allSchemaEntities => [
[chatData, chatMessage, groupOrderIdx]; chatData,
chatMessage,
groupOrderIdx,
];
} }
typedef $ChatDataCreateCompanionBuilder = ChatDataCompanion Function({ typedef $ChatDataCreateCompanionBuilder =
required String chatId, ChatDataCompanion Function({
required ChatMetadata metadata, required String chatId,
Value<int> rowid, required ChatMetadata metadata,
}); Value<int> rowid,
typedef $ChatDataUpdateCompanionBuilder = ChatDataCompanion Function({ });
Value<String> chatId, typedef $ChatDataUpdateCompanionBuilder =
Value<ChatMetadata> metadata, ChatDataCompanion Function({
Value<int> rowid, Value<String> chatId,
}); Value<ChatMetadata> metadata,
Value<int> rowid,
});
class $ChatDataFilterComposer extends Composer<_$ChatDatabase, ChatData> { class $ChatDataFilterComposer extends Composer<_$ChatDatabase, ChatData> {
$ChatDataFilterComposer({ $ChatDataFilterComposer({
@@ -499,12 +548,15 @@ class $ChatDataFilterComposer extends Composer<_$ChatDatabase, ChatData> {
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnFilters<String> get chatId => $composableBuilder( ColumnFilters<String> get chatId => $composableBuilder(
column: $table.chatId, builder: (column) => ColumnFilters(column)); column: $table.chatId,
builder: (column) => ColumnFilters(column),
);
ColumnWithTypeConverterFilters<ChatMetadata, ChatMetadata, String> ColumnWithTypeConverterFilters<ChatMetadata, ChatMetadata, String>
get metadata => $composableBuilder( get metadata => $composableBuilder(
column: $table.metadata, column: $table.metadata,
builder: (column) => ColumnWithTypeConverterFilters(column)); builder: (column) => ColumnWithTypeConverterFilters(column),
);
} }
class $ChatDataOrderingComposer extends Composer<_$ChatDatabase, ChatData> { class $ChatDataOrderingComposer extends Composer<_$ChatDatabase, ChatData> {
@@ -516,10 +568,14 @@ class $ChatDataOrderingComposer extends Composer<_$ChatDatabase, ChatData> {
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnOrderings<String> get chatId => $composableBuilder( ColumnOrderings<String> get chatId => $composableBuilder(
column: $table.chatId, builder: (column) => ColumnOrderings(column)); column: $table.chatId,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get metadata => $composableBuilder( ColumnOrderings<String> get metadata => $composableBuilder(
column: $table.metadata, builder: (column) => ColumnOrderings(column)); column: $table.metadata,
builder: (column) => ColumnOrderings(column),
);
} }
class $ChatDataAnnotationComposer extends Composer<_$ChatDatabase, ChatData> { class $ChatDataAnnotationComposer extends Composer<_$ChatDatabase, ChatData> {
@@ -537,81 +593,100 @@ class $ChatDataAnnotationComposer extends Composer<_$ChatDatabase, ChatData> {
$composableBuilder(column: $table.metadata, builder: (column) => column); $composableBuilder(column: $table.metadata, builder: (column) => column);
} }
class $ChatDataTableManager extends RootTableManager< class $ChatDataTableManager
_$ChatDatabase, extends
ChatData, RootTableManager<
ChatDataData, _$ChatDatabase,
$ChatDataFilterComposer, ChatData,
$ChatDataOrderingComposer, ChatDataData,
$ChatDataAnnotationComposer, $ChatDataFilterComposer,
$ChatDataCreateCompanionBuilder, $ChatDataOrderingComposer,
$ChatDataUpdateCompanionBuilder, $ChatDataAnnotationComposer,
(ChatDataData, BaseReferences<_$ChatDatabase, ChatData, ChatDataData>), $ChatDataCreateCompanionBuilder,
ChatDataData, $ChatDataUpdateCompanionBuilder,
PrefetchHooks Function()> { (
ChatDataData,
BaseReferences<_$ChatDatabase, ChatData, ChatDataData>,
),
ChatDataData,
PrefetchHooks Function()
> {
$ChatDataTableManager(_$ChatDatabase db, ChatData table) $ChatDataTableManager(_$ChatDatabase db, ChatData table)
: super(TableManagerState( : super(
TableManagerState(
db: db, db: db,
table: table, table: table,
createFilteringComposer: () => createFilteringComposer:
$ChatDataFilterComposer($db: db, $table: table), () => $ChatDataFilterComposer($db: db, $table: table),
createOrderingComposer: () => createOrderingComposer:
$ChatDataOrderingComposer($db: db, $table: table), () => $ChatDataOrderingComposer($db: db, $table: table),
createComputedFieldComposer: () => createComputedFieldComposer:
$ChatDataAnnotationComposer($db: db, $table: table), () => $ChatDataAnnotationComposer($db: db, $table: table),
updateCompanionCallback: ({ updateCompanionCallback:
Value<String> chatId = const Value.absent(), ({
Value<ChatMetadata> metadata = const Value.absent(), Value<String> chatId = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<ChatMetadata> metadata = const Value.absent(),
}) => Value<int> rowid = const Value.absent(),
ChatDataCompanion( }) => ChatDataCompanion(
chatId: chatId, chatId: chatId,
metadata: metadata, metadata: metadata,
rowid: rowid, rowid: rowid,
), ),
createCompanionCallback: ({ createCompanionCallback:
required String chatId, ({
required ChatMetadata metadata, required String chatId,
Value<int> rowid = const Value.absent(), required ChatMetadata metadata,
}) => Value<int> rowid = const Value.absent(),
ChatDataCompanion.insert( }) => ChatDataCompanion.insert(
chatId: chatId, chatId: chatId,
metadata: metadata, metadata: metadata,
rowid: rowid, rowid: rowid,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper:
.map((e) => (e.readTable(table), BaseReferences(db, table, e))) (p0) =>
.toList(), p0
.map(
(e) => (
e.readTable(table),
BaseReferences(db, table, e),
),
)
.toList(),
prefetchHooksCallback: null, prefetchHooksCallback: null,
)); ),
);
} }
typedef $ChatDataProcessedTableManager = ProcessedTableManager< typedef $ChatDataProcessedTableManager =
_$ChatDatabase, ProcessedTableManager<
ChatData, _$ChatDatabase,
ChatDataData, ChatData,
$ChatDataFilterComposer, ChatDataData,
$ChatDataOrderingComposer, $ChatDataFilterComposer,
$ChatDataAnnotationComposer, $ChatDataOrderingComposer,
$ChatDataCreateCompanionBuilder, $ChatDataAnnotationComposer,
$ChatDataUpdateCompanionBuilder, $ChatDataCreateCompanionBuilder,
(ChatDataData, BaseReferences<_$ChatDatabase, ChatData, ChatDataData>), $ChatDataUpdateCompanionBuilder,
ChatDataData, (ChatDataData, BaseReferences<_$ChatDatabase, ChatData, ChatDataData>),
PrefetchHooks Function()>; ChatDataData,
typedef $ChatMessageCreateCompanionBuilder = ChatMessageCompanion Function({ PrefetchHooks Function()
required String messageId, >;
required String chatId, typedef $ChatMessageCreateCompanionBuilder =
required String orderKey, ChatMessageCompanion Function({
required String messageJson, required String messageId,
Value<int> rowid, required String chatId,
}); required String orderKey,
typedef $ChatMessageUpdateCompanionBuilder = ChatMessageCompanion Function({ required String messageJson,
Value<String> messageId, Value<int> rowid,
Value<String> chatId, });
Value<String> orderKey, typedef $ChatMessageUpdateCompanionBuilder =
Value<String> messageJson, ChatMessageCompanion Function({
Value<int> rowid, Value<String> messageId,
}); Value<String> chatId,
Value<String> orderKey,
Value<String> messageJson,
Value<int> rowid,
});
class $ChatMessageFilterComposer extends Composer<_$ChatDatabase, ChatMessage> { class $ChatMessageFilterComposer extends Composer<_$ChatDatabase, ChatMessage> {
$ChatMessageFilterComposer({ $ChatMessageFilterComposer({
@@ -622,16 +697,24 @@ class $ChatMessageFilterComposer extends Composer<_$ChatDatabase, ChatMessage> {
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnFilters<String> get messageId => $composableBuilder( ColumnFilters<String> get messageId => $composableBuilder(
column: $table.messageId, builder: (column) => ColumnFilters(column)); column: $table.messageId,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get chatId => $composableBuilder( ColumnFilters<String> get chatId => $composableBuilder(
column: $table.chatId, builder: (column) => ColumnFilters(column)); column: $table.chatId,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get orderKey => $composableBuilder( ColumnFilters<String> get orderKey => $composableBuilder(
column: $table.orderKey, builder: (column) => ColumnFilters(column)); column: $table.orderKey,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get messageJson => $composableBuilder( ColumnFilters<String> get messageJson => $composableBuilder(
column: $table.messageJson, builder: (column) => ColumnFilters(column)); column: $table.messageJson,
builder: (column) => ColumnFilters(column),
);
} }
class $ChatMessageOrderingComposer class $ChatMessageOrderingComposer
@@ -644,16 +727,24 @@ class $ChatMessageOrderingComposer
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnOrderings<String> get messageId => $composableBuilder( ColumnOrderings<String> get messageId => $composableBuilder(
column: $table.messageId, builder: (column) => ColumnOrderings(column)); column: $table.messageId,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get chatId => $composableBuilder( ColumnOrderings<String> get chatId => $composableBuilder(
column: $table.chatId, builder: (column) => ColumnOrderings(column)); column: $table.chatId,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get orderKey => $composableBuilder( ColumnOrderings<String> get orderKey => $composableBuilder(
column: $table.orderKey, builder: (column) => ColumnOrderings(column)); column: $table.orderKey,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get messageJson => $composableBuilder( ColumnOrderings<String> get messageJson => $composableBuilder(
column: $table.messageJson, builder: (column) => ColumnOrderings(column)); column: $table.messageJson,
builder: (column) => ColumnOrderings(column),
);
} }
class $ChatMessageAnnotationComposer class $ChatMessageAnnotationComposer
@@ -675,84 +766,100 @@ class $ChatMessageAnnotationComposer
$composableBuilder(column: $table.orderKey, builder: (column) => column); $composableBuilder(column: $table.orderKey, builder: (column) => column);
GeneratedColumn<String> get messageJson => $composableBuilder( GeneratedColumn<String> get messageJson => $composableBuilder(
column: $table.messageJson, builder: (column) => column); column: $table.messageJson,
builder: (column) => column,
);
} }
class $ChatMessageTableManager extends RootTableManager< class $ChatMessageTableManager
_$ChatDatabase, extends
ChatMessage, RootTableManager<
ChatMessageData, _$ChatDatabase,
$ChatMessageFilterComposer, ChatMessage,
$ChatMessageOrderingComposer, ChatMessageData,
$ChatMessageAnnotationComposer, $ChatMessageFilterComposer,
$ChatMessageCreateCompanionBuilder, $ChatMessageOrderingComposer,
$ChatMessageUpdateCompanionBuilder, $ChatMessageAnnotationComposer,
( $ChatMessageCreateCompanionBuilder,
ChatMessageData, $ChatMessageUpdateCompanionBuilder,
BaseReferences<_$ChatDatabase, ChatMessage, ChatMessageData> (
), ChatMessageData,
ChatMessageData, BaseReferences<_$ChatDatabase, ChatMessage, ChatMessageData>,
PrefetchHooks Function()> { ),
ChatMessageData,
PrefetchHooks Function()
> {
$ChatMessageTableManager(_$ChatDatabase db, ChatMessage table) $ChatMessageTableManager(_$ChatDatabase db, ChatMessage table)
: super(TableManagerState( : super(
TableManagerState(
db: db, db: db,
table: table, table: table,
createFilteringComposer: () => createFilteringComposer:
$ChatMessageFilterComposer($db: db, $table: table), () => $ChatMessageFilterComposer($db: db, $table: table),
createOrderingComposer: () => createOrderingComposer:
$ChatMessageOrderingComposer($db: db, $table: table), () => $ChatMessageOrderingComposer($db: db, $table: table),
createComputedFieldComposer: () => createComputedFieldComposer:
$ChatMessageAnnotationComposer($db: db, $table: table), () => $ChatMessageAnnotationComposer($db: db, $table: table),
updateCompanionCallback: ({ updateCompanionCallback:
Value<String> messageId = const Value.absent(), ({
Value<String> chatId = const Value.absent(), Value<String> messageId = const Value.absent(),
Value<String> orderKey = const Value.absent(), Value<String> chatId = const Value.absent(),
Value<String> messageJson = const Value.absent(), Value<String> orderKey = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<String> messageJson = const Value.absent(),
}) => Value<int> rowid = const Value.absent(),
ChatMessageCompanion( }) => ChatMessageCompanion(
messageId: messageId, messageId: messageId,
chatId: chatId, chatId: chatId,
orderKey: orderKey, orderKey: orderKey,
messageJson: messageJson, messageJson: messageJson,
rowid: rowid, rowid: rowid,
), ),
createCompanionCallback: ({ createCompanionCallback:
required String messageId, ({
required String chatId, required String messageId,
required String orderKey, required String chatId,
required String messageJson, required String orderKey,
Value<int> rowid = const Value.absent(), required String messageJson,
}) => Value<int> rowid = const Value.absent(),
ChatMessageCompanion.insert( }) => ChatMessageCompanion.insert(
messageId: messageId, messageId: messageId,
chatId: chatId, chatId: chatId,
orderKey: orderKey, orderKey: orderKey,
messageJson: messageJson, messageJson: messageJson,
rowid: rowid, rowid: rowid,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper:
.map((e) => (e.readTable(table), BaseReferences(db, table, e))) (p0) =>
.toList(), p0
.map(
(e) => (
e.readTable(table),
BaseReferences(db, table, e),
),
)
.toList(),
prefetchHooksCallback: null, prefetchHooksCallback: null,
)); ),
);
} }
typedef $ChatMessageProcessedTableManager = ProcessedTableManager< typedef $ChatMessageProcessedTableManager =
_$ChatDatabase, ProcessedTableManager<
ChatMessage, _$ChatDatabase,
ChatMessageData, ChatMessage,
$ChatMessageFilterComposer,
$ChatMessageOrderingComposer,
$ChatMessageAnnotationComposer,
$ChatMessageCreateCompanionBuilder,
$ChatMessageUpdateCompanionBuilder,
(
ChatMessageData, ChatMessageData,
BaseReferences<_$ChatDatabase, ChatMessage, ChatMessageData> $ChatMessageFilterComposer,
), $ChatMessageOrderingComposer,
ChatMessageData, $ChatMessageAnnotationComposer,
PrefetchHooks Function()>; $ChatMessageCreateCompanionBuilder,
$ChatMessageUpdateCompanionBuilder,
(
ChatMessageData,
BaseReferences<_$ChatDatabase, ChatMessage, ChatMessageData>,
),
ChatMessageData,
PrefetchHooks Function()
>;
class $ChatDatabaseManager { class $ChatDatabaseManager {
final _$ChatDatabase _db; final _$ChatDatabase _db;
@@ -7,9 +7,9 @@ part of 'chat_metadata.dart';
// ************************************************************************** // **************************************************************************
ChatMetadata _$ChatMetadataFromJson(Map<String, dynamic> json) => ChatMetadata( ChatMetadata _$ChatMetadataFromJson(Map<String, dynamic> json) => ChatMetadata(
mainDocumentId: json['mainDocumentId'] as String?, mainDocumentId: json['mainDocumentId'] as String?,
contextId: json['contextId'] as String?, contextId: json['contextId'] as String?,
); );
Map<String, dynamic> _$ChatMetadataToJson(ChatMetadata instance) => Map<String, dynamic> _$ChatMetadataToJson(ChatMetadata instance) =>
<String, dynamic>{ <String, dynamic>{
@@ -59,44 +59,46 @@ class ChatMemory implements BaseMemory {
Future<MemoryVariables> loadMemoryVariables([ Future<MemoryVariables> loadMemoryVariables([
MemoryInputValues values = const {}, MemoryInputValues values = const {},
]) async { ]) async {
final messages = _controller.messages final messages =
.whereNot( _controller.messages
(message) => message.metadata?['hideFromModelChatHistory'] == true, .whereNot(
) (message) =>
.map( message.metadata?['hideFromModelChatHistory'] == true,
(message) => switch (message) { )
TextMessage( .map(
authorId: final authorId, (message) => switch (message) {
text: final text, TextMessage(
metadata: final metadata, authorId: final authorId,
) => text: final text,
() { metadata: final metadata,
if (authorId == MessageAuthor.system.user.id) { ) =>
return SystemChatMessage(content: text); () {
} if (authorId == MessageAuthor.system.user.id) {
if (authorId == MessageAuthor.human.user.id) { return SystemChatMessage(content: text);
return HumanChatMessage( }
content: ChatMessageContent.text(text), if (authorId == MessageAuthor.human.user.id) {
); return HumanChatMessage(
} content: ChatMessageContent.text(text),
if (authorId == MessageAuthor.ai.user.id) { );
final toolsRaw = metadata?['toolCalls']; }
if (toolsRaw is String) { if (authorId == MessageAuthor.ai.user.id) {
return AIChatMessage( final toolsRaw = metadata?['toolCalls'];
content: text, if (toolsRaw is String) {
toolCalls: _deserializeToolCalls(toolsRaw), return AIChatMessage(
); content: text,
} toolCalls: _deserializeToolCalls(toolsRaw),
return AIChatMessage(content: text); );
} }
throw UnimplementedError(); return AIChatMessage(content: text);
}(), }
ImageMessage() => throw UnimplementedError(), throw UnimplementedError();
CustomMessage() => throw UnimplementedError(), }(),
UnsupportedMessage() => throw UnimplementedError() ImageMessage() => throw UnimplementedError(),
}, CustomMessage() => throw UnimplementedError(),
) UnsupportedMessage() => throw UnimplementedError(),
.toList(); },
)
.toList();
int currentBufferLength = await llm.countTokens(PromptValue.chat(messages)); int currentBufferLength = await llm.countTokens(PromptValue.chat(messages));
// Prune buffer if it exceeds max token limit // Prune buffer if it exceeds max token limit
@@ -124,16 +126,17 @@ class ChatMemory implements BaseMemory {
List<AIChatMessageToolCall> _deserializeToolCalls(String toolsRaw) { List<AIChatMessageToolCall> _deserializeToolCalls(String toolsRaw) {
final decoded = jsonDecode(toolsRaw) as List<dynamic>; final decoded = jsonDecode(toolsRaw) as List<dynamic>;
final tools = decoded final tools =
.map( decoded
(tool) => AIChatMessageToolCall( .map(
id: tool['id'] as String, (tool) => AIChatMessageToolCall(
name: tool['name'] as String, id: tool['id'] as String,
arguments: tool['arguments'] as Map<String, dynamic>, name: tool['name'] as String,
argumentsRaw: tool['argumentsRaw'] as String, arguments: tool['arguments'] as Map<String, dynamic>,
), argumentsRaw: tool['argumentsRaw'] as String,
) ),
.toList(); )
.toList();
return tools; return tools;
} }
@@ -17,30 +17,26 @@ class DriftChatController implements ChatController {
late final BehaviorSubject<Map<String, Message>> _intermediateMessages; late final BehaviorSubject<Map<String, Message>> _intermediateMessages;
DriftChatController(this._dao, {required this.chatId}) { DriftChatController(this._dao, {required this.chatId}) {
final chatMessagesStream = _dao final chatMessagesStream =
.chatMessages(chatId: chatId) _dao
.map( .chatMessages(chatId: chatId)
(data) => Message.fromJson( .map(
jsonDecode(data.messageJson) as Map<String, dynamic>, (data) => Message.fromJson(
), jsonDecode(data.messageJson) as Map<String, dynamic>,
) ),
.watch(); )
.watch();
_intermediateMessages = BehaviorSubject.seeded({}); _intermediateMessages = BehaviorSubject.seeded({});
_mergedMessagesStream = Rx.combineLatest2( _mergedMessagesStream =
chatMessagesStream, Rx.combineLatest2(chatMessagesStream, _intermediateMessages, (a, b) {
_intermediateMessages, if (a.isNotEmpty && b.isNotEmpty) {
(a, b) { return [for (final message in a) b[message.id] ?? message];
if (a.isNotEmpty && b.isNotEmpty) { }
return [
for (final message in a) b[message.id] ?? message,
];
}
return a; return a;
}, }).shareValue();
).shareValue();
//Set initial messages //Set initial messages
unawaited( unawaited(
@@ -80,9 +76,10 @@ class DriftChatController implements ChatController {
@override @override
Future<void> remove(Message message) async { Future<void> remove(Message message) async {
final index = await _dao final index =
.messageIndex(chatId: chatId, messageId: message.id) await _dao
.getSingleOrNull(); .messageIndex(chatId: chatId, messageId: message.id)
.getSingleOrNull();
if (index != null) { if (index != null) {
await _dao.removeMessage(messageId: message.id); await _dao.removeMessage(messageId: message.id);
@@ -39,21 +39,15 @@ class ChatControllerFamily extends Family<DriftChatController> {
const ChatControllerFamily(); const ChatControllerFamily();
/// See also [chatController]. /// See also [chatController].
ChatControllerProvider call( ChatControllerProvider call(String chatId) {
String chatId, return ChatControllerProvider(chatId);
) {
return ChatControllerProvider(
chatId,
);
} }
@override @override
ChatControllerProvider getProviderOverride( ChatControllerProvider getProviderOverride(
covariant ChatControllerProvider provider, covariant ChatControllerProvider provider,
) { ) {
return call( return call(provider.chatId);
provider.chatId,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -74,24 +68,20 @@ class ChatControllerFamily extends Family<DriftChatController> {
/// See also [chatController]. /// See also [chatController].
class ChatControllerProvider extends AutoDisposeProvider<DriftChatController> { class ChatControllerProvider extends AutoDisposeProvider<DriftChatController> {
/// See also [chatController]. /// See also [chatController].
ChatControllerProvider( ChatControllerProvider(String chatId)
String chatId, : this._internal(
) : this._internal( (ref) => chatController(ref as ChatControllerRef, chatId),
(ref) => chatController( from: chatControllerProvider,
ref as ChatControllerRef, name: r'chatControllerProvider',
chatId, debugGetCreateSourceHash:
), const bool.fromEnvironment('dart.vm.product')
from: chatControllerProvider, ? null
name: r'chatControllerProvider', : _$chatControllerHash,
debugGetCreateSourceHash: dependencies: ChatControllerFamily._dependencies,
const bool.fromEnvironment('dart.vm.product') allTransitiveDependencies:
? null ChatControllerFamily._allTransitiveDependencies,
: _$chatControllerHash, chatId: chatId,
dependencies: ChatControllerFamily._dependencies, );
allTransitiveDependencies:
ChatControllerFamily._allTransitiveDependencies,
chatId: chatId,
);
ChatControllerProvider._internal( ChatControllerProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -170,21 +160,15 @@ class ChatMetadataFamily extends Family<AsyncValue<ChatMetadata?>> {
const ChatMetadataFamily(); const ChatMetadataFamily();
/// See also [chatMetadata]. /// See also [chatMetadata].
ChatMetadataProvider call( ChatMetadataProvider call(String chatId) {
String chatId, return ChatMetadataProvider(chatId);
) {
return ChatMetadataProvider(
chatId,
);
} }
@override @override
ChatMetadataProvider getProviderOverride( ChatMetadataProvider getProviderOverride(
covariant ChatMetadataProvider provider, covariant ChatMetadataProvider provider,
) { ) {
return call( return call(provider.chatId);
provider.chatId,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -205,24 +189,20 @@ class ChatMetadataFamily extends Family<AsyncValue<ChatMetadata?>> {
/// See also [chatMetadata]. /// See also [chatMetadata].
class ChatMetadataProvider extends AutoDisposeStreamProvider<ChatMetadata?> { class ChatMetadataProvider extends AutoDisposeStreamProvider<ChatMetadata?> {
/// See also [chatMetadata]. /// See also [chatMetadata].
ChatMetadataProvider( ChatMetadataProvider(String chatId)
String chatId, : this._internal(
) : this._internal( (ref) => chatMetadata(ref as ChatMetadataRef, chatId),
(ref) => chatMetadata( from: chatMetadataProvider,
ref as ChatMetadataRef, name: r'chatMetadataProvider',
chatId, debugGetCreateSourceHash:
), const bool.fromEnvironment('dart.vm.product')
from: chatMetadataProvider, ? null
name: r'chatMetadataProvider', : _$chatMetadataHash,
debugGetCreateSourceHash: dependencies: ChatMetadataFamily._dependencies,
const bool.fromEnvironment('dart.vm.product') allTransitiveDependencies:
? null ChatMetadataFamily._allTransitiveDependencies,
: _$chatMetadataHash, chatId: chatId,
dependencies: ChatMetadataFamily._dependencies, );
allTransitiveDependencies:
ChatMetadataFamily._allTransitiveDependencies,
chatId: chatId,
);
ChatMetadataProvider._internal( ChatMetadataProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -288,5 +268,6 @@ class _ChatMetadataProviderElement
@override @override
String get chatId => (origin as ChatMetadataProvider).chatId; String get chatId => (origin as ChatMetadataProvider).chatId;
} }
// ignore_for_file: type=lint // 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 // 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
@@ -31,9 +31,7 @@ class ChatMessageRepository extends _$ChatMessageRepository {
id: uuid.v4(), id: uuid.v4(),
authorId: author.user.id, authorId: author.user.id,
createdAt: DateTime.now().toUtc(), createdAt: DateTime.now().toUtc(),
metadata: { metadata: {'type': 'typing'},
'type': 'typing',
},
), ),
); );
@@ -65,12 +63,13 @@ class ChatMessageRepository extends _$ChatMessageRepository {
createdAt: DateTime.now().toUtc(), createdAt: DateTime.now().toUtc(),
text: content, text: content,
isOnlyEmoji: isOnlyEmoji(content), isOnlyEmoji: isOnlyEmoji(content),
metadata: (hideFromModelChatHistory || (toolCalls?.isNotEmpty ?? false)) metadata:
? { (hideFromModelChatHistory || (toolCalls?.isNotEmpty ?? false))
'toolCalls': toolCalls?.map((tool) => tool.toMap()).toList(), ? {
if (hideFromModelChatHistory) 'hideFromModelChatHistory': true, 'toolCalls': toolCalls?.map((tool) => tool.toMap()).toList(),
} if (hideFromModelChatHistory) 'hideFromModelChatHistory': true,
: null, }
: null,
); );
return Result.fromAsync(() async { return Result.fromAsync(() async {
@@ -34,9 +34,7 @@ abstract class _$ChatMessageRepository
extends BuildlessAutoDisposeNotifier<void> { extends BuildlessAutoDisposeNotifier<void> {
late final String chatId; late final String chatId;
void build( void build(String chatId);
String chatId,
);
} }
/// See also [ChatMessageRepository]. /// See also [ChatMessageRepository].
@@ -49,21 +47,15 @@ class ChatMessageRepositoryFamily extends Family<void> {
const ChatMessageRepositoryFamily(); const ChatMessageRepositoryFamily();
/// See also [ChatMessageRepository]. /// See also [ChatMessageRepository].
ChatMessageRepositoryProvider call( ChatMessageRepositoryProvider call(String chatId) {
String chatId, return ChatMessageRepositoryProvider(chatId);
) {
return ChatMessageRepositoryProvider(
chatId,
);
} }
@override @override
ChatMessageRepositoryProvider getProviderOverride( ChatMessageRepositoryProvider getProviderOverride(
covariant ChatMessageRepositoryProvider provider, covariant ChatMessageRepositoryProvider provider,
) { ) {
return call( return call(provider.chatId);
provider.chatId,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -85,21 +77,20 @@ class ChatMessageRepositoryFamily extends Family<void> {
class ChatMessageRepositoryProvider class ChatMessageRepositoryProvider
extends AutoDisposeNotifierProviderImpl<ChatMessageRepository, void> { extends AutoDisposeNotifierProviderImpl<ChatMessageRepository, void> {
/// See also [ChatMessageRepository]. /// See also [ChatMessageRepository].
ChatMessageRepositoryProvider( ChatMessageRepositoryProvider(String chatId)
String chatId, : this._internal(
) : this._internal( () => ChatMessageRepository()..chatId = chatId,
() => ChatMessageRepository()..chatId = chatId, from: chatMessageRepositoryProvider,
from: chatMessageRepositoryProvider, name: r'chatMessageRepositoryProvider',
name: r'chatMessageRepositoryProvider', debugGetCreateSourceHash:
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
const bool.fromEnvironment('dart.vm.product') ? null
? null : _$chatMessageRepositoryHash,
: _$chatMessageRepositoryHash, dependencies: ChatMessageRepositoryFamily._dependencies,
dependencies: ChatMessageRepositoryFamily._dependencies, allTransitiveDependencies:
allTransitiveDependencies: ChatMessageRepositoryFamily._allTransitiveDependencies,
ChatMessageRepositoryFamily._allTransitiveDependencies, chatId: chatId,
chatId: chatId, );
);
ChatMessageRepositoryProvider._internal( ChatMessageRepositoryProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -114,12 +105,8 @@ class ChatMessageRepositoryProvider
final String chatId; final String chatId;
@override @override
void runNotifierBuild( void runNotifierBuild(covariant ChatMessageRepository notifier) {
covariant ChatMessageRepository notifier, return notifier.build(chatId);
) {
return notifier.build(
chatId,
);
} }
@override @override
@@ -140,7 +127,7 @@ class ChatMessageRepositoryProvider
@override @override
AutoDisposeNotifierProviderElement<ChatMessageRepository, void> AutoDisposeNotifierProviderElement<ChatMessageRepository, void>
createElement() { createElement() {
return _ChatMessageRepositoryProviderElement(this); return _ChatMessageRepositoryProviderElement(this);
} }
@@ -173,5 +160,6 @@ class _ChatMessageRepositoryProviderElement
@override @override
String get chatId => (origin as ChatMessageRepositoryProvider).chatId; String get chatId => (origin as ChatMessageRepositoryProvider).chatId;
} }
// ignore_for_file: type=lint // 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 // 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
@@ -34,9 +34,7 @@ abstract class _$ChatMetadataRepository
extends BuildlessAutoDisposeNotifier<void> { extends BuildlessAutoDisposeNotifier<void> {
late final String chatId; late final String chatId;
void build( void build(String chatId);
String chatId,
);
} }
/// See also [ChatMetadataRepository]. /// See also [ChatMetadataRepository].
@@ -49,21 +47,15 @@ class ChatMetadataRepositoryFamily extends Family<void> {
const ChatMetadataRepositoryFamily(); const ChatMetadataRepositoryFamily();
/// See also [ChatMetadataRepository]. /// See also [ChatMetadataRepository].
ChatMetadataRepositoryProvider call( ChatMetadataRepositoryProvider call(String chatId) {
String chatId, return ChatMetadataRepositoryProvider(chatId);
) {
return ChatMetadataRepositoryProvider(
chatId,
);
} }
@override @override
ChatMetadataRepositoryProvider getProviderOverride( ChatMetadataRepositoryProvider getProviderOverride(
covariant ChatMetadataRepositoryProvider provider, covariant ChatMetadataRepositoryProvider provider,
) { ) {
return call( return call(provider.chatId);
provider.chatId,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -85,21 +77,20 @@ class ChatMetadataRepositoryFamily extends Family<void> {
class ChatMetadataRepositoryProvider class ChatMetadataRepositoryProvider
extends AutoDisposeNotifierProviderImpl<ChatMetadataRepository, void> { extends AutoDisposeNotifierProviderImpl<ChatMetadataRepository, void> {
/// See also [ChatMetadataRepository]. /// See also [ChatMetadataRepository].
ChatMetadataRepositoryProvider( ChatMetadataRepositoryProvider(String chatId)
String chatId, : this._internal(
) : this._internal( () => ChatMetadataRepository()..chatId = chatId,
() => ChatMetadataRepository()..chatId = chatId, from: chatMetadataRepositoryProvider,
from: chatMetadataRepositoryProvider, name: r'chatMetadataRepositoryProvider',
name: r'chatMetadataRepositoryProvider', debugGetCreateSourceHash:
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
const bool.fromEnvironment('dart.vm.product') ? null
? null : _$chatMetadataRepositoryHash,
: _$chatMetadataRepositoryHash, dependencies: ChatMetadataRepositoryFamily._dependencies,
dependencies: ChatMetadataRepositoryFamily._dependencies, allTransitiveDependencies:
allTransitiveDependencies: ChatMetadataRepositoryFamily._allTransitiveDependencies,
ChatMetadataRepositoryFamily._allTransitiveDependencies, chatId: chatId,
chatId: chatId, );
);
ChatMetadataRepositoryProvider._internal( ChatMetadataRepositoryProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -114,12 +105,8 @@ class ChatMetadataRepositoryProvider
final String chatId; final String chatId;
@override @override
void runNotifierBuild( void runNotifierBuild(covariant ChatMetadataRepository notifier) {
covariant ChatMetadataRepository notifier, return notifier.build(chatId);
) {
return notifier.build(
chatId,
);
} }
@override @override
@@ -140,7 +127,7 @@ class ChatMetadataRepositoryProvider
@override @override
AutoDisposeNotifierProviderElement<ChatMetadataRepository, void> AutoDisposeNotifierProviderElement<ChatMetadataRepository, void>
createElement() { createElement() {
return _ChatMetadataRepositoryProviderElement(this); return _ChatMetadataRepositoryProviderElement(this);
} }
@@ -173,5 +160,6 @@ class _ChatMetadataRepositoryProviderElement
@override @override
String get chatId => (origin as ChatMetadataRepositoryProvider).chatId; String get chatId => (origin as ChatMetadataRepositoryProvider).chatId;
} }
// ignore_for_file: type=lint // 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 // 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
@@ -24,9 +24,7 @@ class SearchDao extends DatabaseAccessor<ChatSearchDatabase>
return db.chat.insertOne( return db.chat.insertOne(
chat, chat,
onConflict: DoUpdate( onConflict: DoUpdate(
(old) => ChatCompanion.custom( (old) => ChatCompanion.custom(content: Variable(chat.content.value)),
content: Variable(chat.content.value),
),
), ),
); );
} }
@@ -4,10 +4,7 @@ import 'package:lensai/features/search/domain/fts_tokenizer.dart';
part 'database.g.dart'; part 'database.g.dart';
@DriftDatabase( @DriftDatabase(include: {'database.drift'}, daos: [SearchDao])
include: {'database.drift'},
daos: [SearchDao],
)
class ChatSearchDatabase extends _$ChatSearchDatabase class ChatSearchDatabase extends _$ChatSearchDatabase
with TrigramQueryBuilderMixin { with TrigramQueryBuilderMixin {
@override @override
@@ -9,20 +9,29 @@ class Chat extends Table with TableInfo<Chat, ChatData> {
final String? _alias; final String? _alias;
Chat(this.attachedDatabase, [this._alias]); Chat(this.attachedDatabase, [this._alias]);
late final GeneratedColumn<String> fileName = GeneratedColumn<String>( late final GeneratedColumn<String> fileName = GeneratedColumn<String>(
'file_name', aliasedName, false, 'file_name',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: 'PRIMARY KEY NOT NULL'); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'PRIMARY KEY NOT NULL',
);
late final GeneratedColumn<String> title = GeneratedColumn<String>( late final GeneratedColumn<String> title = GeneratedColumn<String>(
'title', aliasedName, false, 'title',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: 'NOT NULL'); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL',
);
late final GeneratedColumn<String> content = GeneratedColumn<String>( late final GeneratedColumn<String> content = GeneratedColumn<String>(
'content', aliasedName, false, 'content',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: 'NOT NULL'); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: 'NOT NULL',
);
@override @override
List<GeneratedColumn> get $columns => [fileName, title, content]; List<GeneratedColumn> get $columns => [fileName, title, content];
@override @override
@@ -36,12 +45,21 @@ class Chat extends Table with TableInfo<Chat, ChatData> {
ChatData map(Map<String, dynamic> data, {String? tablePrefix}) { ChatData map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return ChatData( return ChatData(
fileName: attachedDatabase.typeMapping fileName:
.read(DriftSqlType.string, data['${effectivePrefix}file_name'])!, attachedDatabase.typeMapping.read(
title: attachedDatabase.typeMapping DriftSqlType.string,
.read(DriftSqlType.string, data['${effectivePrefix}title'])!, data['${effectivePrefix}file_name'],
content: attachedDatabase.typeMapping )!,
.read(DriftSqlType.string, data['${effectivePrefix}content'])!, title:
attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}title'],
)!,
content:
attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}content'],
)!,
); );
} }
@@ -58,8 +76,11 @@ class ChatData extends DataClass implements Insertable<ChatData> {
final String fileName; final String fileName;
final String title; final String title;
final String content; final String content;
const ChatData( const ChatData({
{required this.fileName, required this.title, required this.content}); required this.fileName,
required this.title,
required this.content,
});
@override @override
Map<String, Expression> toColumns(bool nullToAbsent) { Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{}; final map = <String, Expression>{};
@@ -69,8 +90,10 @@ class ChatData extends DataClass implements Insertable<ChatData> {
return map; return map;
} }
factory ChatData.fromJson(Map<String, dynamic> json, factory ChatData.fromJson(
{ValueSerializer? serializer}) { Map<String, dynamic> json, {
ValueSerializer? serializer,
}) {
serializer ??= driftRuntimeOptions.defaultSerializer; serializer ??= driftRuntimeOptions.defaultSerializer;
return ChatData( return ChatData(
fileName: serializer.fromJson<String>(json['file_name']), fileName: serializer.fromJson<String>(json['file_name']),
@@ -139,9 +162,9 @@ class ChatCompanion extends UpdateCompanion<ChatData> {
required String title, required String title,
required String content, required String content,
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : fileName = Value(fileName), }) : fileName = Value(fileName),
title = Value(title), title = Value(title),
content = Value(content); content = Value(content);
static Insertable<ChatData> custom({ static Insertable<ChatData> custom({
Expression<String>? fileName, Expression<String>? fileName,
Expression<String>? title, Expression<String>? title,
@@ -156,11 +179,12 @@ class ChatCompanion extends UpdateCompanion<ChatData> {
}); });
} }
ChatCompanion copyWith( ChatCompanion copyWith({
{Value<String>? fileName, Value<String>? fileName,
Value<String>? title, Value<String>? title,
Value<String>? content, Value<String>? content,
Value<int>? rowid}) { Value<int>? rowid,
}) {
return ChatCompanion( return ChatCompanion(
fileName: fileName ?? this.fileName, fileName: fileName ?? this.fileName,
title: title ?? this.title, title: title ?? this.title,
@@ -206,15 +230,21 @@ class ChatFts extends Table
final String? _alias; final String? _alias;
ChatFts(this.attachedDatabase, [this._alias]); ChatFts(this.attachedDatabase, [this._alias]);
late final GeneratedColumn<String> title = GeneratedColumn<String>( late final GeneratedColumn<String> title = GeneratedColumn<String>(
'title', aliasedName, false, 'title',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: ''); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: '',
);
late final GeneratedColumn<String> content = GeneratedColumn<String>( late final GeneratedColumn<String> content = GeneratedColumn<String>(
'content', aliasedName, false, 'content',
type: DriftSqlType.string, aliasedName,
requiredDuringInsert: true, false,
$customConstraints: ''); type: DriftSqlType.string,
requiredDuringInsert: true,
$customConstraints: '',
);
@override @override
List<GeneratedColumn> get $columns => [title, content]; List<GeneratedColumn> get $columns => [title, content];
@override @override
@@ -228,10 +258,16 @@ class ChatFts extends Table
ChatFt map(Map<String, dynamic> data, {String? tablePrefix}) { ChatFt map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return ChatFt( return ChatFt(
title: attachedDatabase.typeMapping title:
.read(DriftSqlType.string, data['${effectivePrefix}title'])!, attachedDatabase.typeMapping.read(
content: attachedDatabase.typeMapping DriftSqlType.string,
.read(DriftSqlType.string, data['${effectivePrefix}content'])!, data['${effectivePrefix}title'],
)!,
content:
attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}content'],
)!,
); );
} }
@@ -259,8 +295,10 @@ class ChatFt extends DataClass implements Insertable<ChatFt> {
return map; return map;
} }
factory ChatFt.fromJson(Map<String, dynamic> json, factory ChatFt.fromJson(
{ValueSerializer? serializer}) { Map<String, dynamic> json, {
ValueSerializer? serializer,
}) {
serializer ??= driftRuntimeOptions.defaultSerializer; serializer ??= driftRuntimeOptions.defaultSerializer;
return ChatFt( return ChatFt(
title: serializer.fromJson<String>(json['title']), title: serializer.fromJson<String>(json['title']),
@@ -276,10 +314,8 @@ class ChatFt extends DataClass implements Insertable<ChatFt> {
}; };
} }
ChatFt copyWith({String? title, String? content}) => ChatFt( ChatFt copyWith({String? title, String? content}) =>
title: title ?? this.title, ChatFt(title: title ?? this.title, content: content ?? this.content);
content: content ?? this.content,
);
ChatFt copyWithCompanion(ChatFtsCompanion data) { ChatFt copyWithCompanion(ChatFtsCompanion data) {
return ChatFt( return ChatFt(
title: data.title.present ? data.title.value : this.title, title: data.title.present ? data.title.value : this.title,
@@ -319,8 +355,8 @@ class ChatFtsCompanion extends UpdateCompanion<ChatFt> {
required String title, required String title,
required String content, required String content,
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : title = Value(title), }) : title = Value(title),
content = Value(content); content = Value(content);
static Insertable<ChatFt> custom({ static Insertable<ChatFt> custom({
Expression<String>? title, Expression<String>? title,
Expression<String>? content, Expression<String>? content,
@@ -333,8 +369,11 @@ class ChatFtsCompanion extends UpdateCompanion<ChatFt> {
}); });
} }
ChatFtsCompanion copyWith( ChatFtsCompanion copyWith({
{Value<String>? title, Value<String>? content, Value<int>? rowid}) { Value<String>? title,
Value<String>? content,
Value<int>? rowid,
}) {
return ChatFtsCompanion( return ChatFtsCompanion(
title: title ?? this.title, title: title ?? this.title,
content: content ?? this.content, content: content ?? this.content,
@@ -374,86 +413,95 @@ abstract class _$ChatSearchDatabase extends GeneratedDatabase {
late final Chat chat = Chat(this); late final Chat chat = Chat(this);
late final ChatFts chatFts = ChatFts(this); late final ChatFts chatFts = ChatFts(this);
late final Trigger chatAfterInsert = Trigger( late final Trigger chatAfterInsert = Trigger(
'CREATE TRIGGER chat_after_insert AFTER INSERT ON chat BEGIN INSERT INTO chat_fts ("rowid", title, content) VALUES (new."rowid", new.title, new.content);END', 'CREATE TRIGGER chat_after_insert AFTER INSERT ON chat BEGIN INSERT INTO chat_fts ("rowid", title, content) VALUES (new."rowid", new.title, new.content);END',
'chat_after_insert'); 'chat_after_insert',
);
late final Trigger chatAfterDelete = Trigger( late final Trigger chatAfterDelete = Trigger(
'CREATE TRIGGER chat_after_delete AFTER DELETE ON chat BEGIN INSERT INTO chat_fts (chat_fts, "rowid", title, content) VALUES (\'delete\', old."rowid", old.title, old.content);END', 'CREATE TRIGGER chat_after_delete AFTER DELETE ON chat BEGIN INSERT INTO chat_fts (chat_fts, "rowid", title, content) VALUES (\'delete\', old."rowid", old.title, old.content);END',
'chat_after_delete'); 'chat_after_delete',
);
late final Trigger chatAfterUpdate = Trigger( late final Trigger chatAfterUpdate = Trigger(
'CREATE TRIGGER chat_after_update AFTER UPDATE ON chat BEGIN INSERT INTO chat_fts (chat_fts, "rowid", title, content) VALUES (\'delete\', old."rowid", old.title, old.content);INSERT INTO chat_fts ("rowid", title, content) VALUES (new."rowid", new.title, new.content);END', 'CREATE TRIGGER chat_after_update AFTER UPDATE ON chat BEGIN INSERT INTO chat_fts (chat_fts, "rowid", title, content) VALUES (\'delete\', old."rowid", old.title, old.content);INSERT INTO chat_fts ("rowid", title, content) VALUES (new."rowid", new.title, new.content);END',
'chat_after_update'); 'chat_after_update',
);
late final SearchDao searchDao = SearchDao(this as ChatSearchDatabase); late final SearchDao searchDao = SearchDao(this as ChatSearchDatabase);
Selectable<ChatQueryResult> chatQuery( Selectable<ChatQueryResult> chatQuery({
{required String beforeMatch, required String beforeMatch,
required String afterMatch, required String afterMatch,
required String ellipsis, required String ellipsis,
required int snippetLength, required int snippetLength,
required String query}) { required String query,
}) {
return customSelect( return customSelect(
'SELECT c.file_name, highlight(chat_fts, 0, ?1, ?2) AS title, snippet(chat_fts, 1, ?1, ?2, ?3, ?4) AS content_snippet FROM chat_fts(?5)AS fts INNER JOIN chat AS c ON c."rowid" = fts."rowid" ORDER BY RANK', 'SELECT c.file_name, highlight(chat_fts, 0, ?1, ?2) AS title, snippet(chat_fts, 1, ?1, ?2, ?3, ?4) AS content_snippet FROM chat_fts(?5)AS fts INNER JOIN chat AS c ON c."rowid" = fts."rowid" ORDER BY RANK',
variables: [ variables: [
Variable<String>(beforeMatch), Variable<String>(beforeMatch),
Variable<String>(afterMatch), Variable<String>(afterMatch),
Variable<String>(ellipsis), Variable<String>(ellipsis),
Variable<int>(snippetLength), Variable<int>(snippetLength),
Variable<String>(query) Variable<String>(query),
], ],
readsFrom: { readsFrom: {chat, chatFts},
chat, ).map(
chatFts, (QueryRow row) => ChatQueryResult(
}).map((QueryRow row) => ChatQueryResult( fileName: row.read<String>('file_name'),
fileName: row.read<String>('file_name'), title: row.readNullable<String>('title'),
title: row.readNullable<String>('title'), contentSnippet: row.readNullable<String>('content_snippet'),
contentSnippet: row.readNullable<String>('content_snippet'), ),
)); );
} }
@override @override
Iterable<TableInfo<Table, Object?>> get allTables => Iterable<TableInfo<Table, Object?>> get allTables =>
allSchemaEntities.whereType<TableInfo<Table, Object?>>(); allSchemaEntities.whereType<TableInfo<Table, Object?>>();
@override @override
List<DatabaseSchemaEntity> get allSchemaEntities => List<DatabaseSchemaEntity> get allSchemaEntities => [
[chat, chatFts, chatAfterInsert, chatAfterDelete, chatAfterUpdate]; chat,
chatFts,
chatAfterInsert,
chatAfterDelete,
chatAfterUpdate,
];
@override @override
StreamQueryUpdateRules get streamUpdateRules => const StreamQueryUpdateRules( StreamQueryUpdateRules get streamUpdateRules => const StreamQueryUpdateRules([
[ WritePropagation(
WritePropagation( on: TableUpdateQuery.onTableName(
on: TableUpdateQuery.onTableName('chat', 'chat',
limitUpdateKind: UpdateKind.insert), limitUpdateKind: UpdateKind.insert,
result: [ ),
TableUpdate('chat_fts', kind: UpdateKind.insert), result: [TableUpdate('chat_fts', kind: UpdateKind.insert)],
], ),
), WritePropagation(
WritePropagation( on: TableUpdateQuery.onTableName(
on: TableUpdateQuery.onTableName('chat', 'chat',
limitUpdateKind: UpdateKind.delete), limitUpdateKind: UpdateKind.delete,
result: [ ),
TableUpdate('chat_fts', kind: UpdateKind.insert), result: [TableUpdate('chat_fts', kind: UpdateKind.insert)],
], ),
), WritePropagation(
WritePropagation( on: TableUpdateQuery.onTableName(
on: TableUpdateQuery.onTableName('chat', 'chat',
limitUpdateKind: UpdateKind.update), limitUpdateKind: UpdateKind.update,
result: [ ),
TableUpdate('chat_fts', kind: UpdateKind.insert), result: [TableUpdate('chat_fts', kind: UpdateKind.insert)],
], ),
), ]);
],
);
} }
typedef $ChatCreateCompanionBuilder = ChatCompanion Function({ typedef $ChatCreateCompanionBuilder =
required String fileName, ChatCompanion Function({
required String title, required String fileName,
required String content, required String title,
Value<int> rowid, required String content,
}); Value<int> rowid,
typedef $ChatUpdateCompanionBuilder = ChatCompanion Function({ });
Value<String> fileName, typedef $ChatUpdateCompanionBuilder =
Value<String> title, ChatCompanion Function({
Value<String> content, Value<String> fileName,
Value<int> rowid, Value<String> title,
}); Value<String> content,
Value<int> rowid,
});
class $ChatFilterComposer extends Composer<_$ChatSearchDatabase, Chat> { class $ChatFilterComposer extends Composer<_$ChatSearchDatabase, Chat> {
$ChatFilterComposer({ $ChatFilterComposer({
@@ -464,13 +512,19 @@ class $ChatFilterComposer extends Composer<_$ChatSearchDatabase, Chat> {
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnFilters<String> get fileName => $composableBuilder( ColumnFilters<String> get fileName => $composableBuilder(
column: $table.fileName, builder: (column) => ColumnFilters(column)); column: $table.fileName,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get title => $composableBuilder( ColumnFilters<String> get title => $composableBuilder(
column: $table.title, builder: (column) => ColumnFilters(column)); column: $table.title,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get content => $composableBuilder( ColumnFilters<String> get content => $composableBuilder(
column: $table.content, builder: (column) => ColumnFilters(column)); column: $table.content,
builder: (column) => ColumnFilters(column),
);
} }
class $ChatOrderingComposer extends Composer<_$ChatSearchDatabase, Chat> { class $ChatOrderingComposer extends Composer<_$ChatSearchDatabase, Chat> {
@@ -482,13 +536,19 @@ class $ChatOrderingComposer extends Composer<_$ChatSearchDatabase, Chat> {
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnOrderings<String> get fileName => $composableBuilder( ColumnOrderings<String> get fileName => $composableBuilder(
column: $table.fileName, builder: (column) => ColumnOrderings(column)); column: $table.fileName,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get title => $composableBuilder( ColumnOrderings<String> get title => $composableBuilder(
column: $table.title, builder: (column) => ColumnOrderings(column)); column: $table.title,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get content => $composableBuilder( ColumnOrderings<String> get content => $composableBuilder(
column: $table.content, builder: (column) => ColumnOrderings(column)); column: $table.content,
builder: (column) => ColumnOrderings(column),
);
} }
class $ChatAnnotationComposer extends Composer<_$ChatSearchDatabase, Chat> { class $ChatAnnotationComposer extends Composer<_$ChatSearchDatabase, Chat> {
@@ -509,81 +569,97 @@ class $ChatAnnotationComposer extends Composer<_$ChatSearchDatabase, Chat> {
$composableBuilder(column: $table.content, builder: (column) => column); $composableBuilder(column: $table.content, builder: (column) => column);
} }
class $ChatTableManager extends RootTableManager< class $ChatTableManager
_$ChatSearchDatabase, extends
Chat, RootTableManager<
ChatData, _$ChatSearchDatabase,
$ChatFilterComposer, Chat,
$ChatOrderingComposer, ChatData,
$ChatAnnotationComposer, $ChatFilterComposer,
$ChatCreateCompanionBuilder, $ChatOrderingComposer,
$ChatUpdateCompanionBuilder, $ChatAnnotationComposer,
(ChatData, BaseReferences<_$ChatSearchDatabase, Chat, ChatData>), $ChatCreateCompanionBuilder,
ChatData, $ChatUpdateCompanionBuilder,
PrefetchHooks Function()> { (ChatData, BaseReferences<_$ChatSearchDatabase, Chat, ChatData>),
ChatData,
PrefetchHooks Function()
> {
$ChatTableManager(_$ChatSearchDatabase db, Chat table) $ChatTableManager(_$ChatSearchDatabase db, Chat table)
: super(TableManagerState( : super(
TableManagerState(
db: db, db: db,
table: table, table: table,
createFilteringComposer: () => createFilteringComposer:
$ChatFilterComposer($db: db, $table: table), () => $ChatFilterComposer($db: db, $table: table),
createOrderingComposer: () => createOrderingComposer:
$ChatOrderingComposer($db: db, $table: table), () => $ChatOrderingComposer($db: db, $table: table),
createComputedFieldComposer: () => createComputedFieldComposer:
$ChatAnnotationComposer($db: db, $table: table), () => $ChatAnnotationComposer($db: db, $table: table),
updateCompanionCallback: ({ updateCompanionCallback:
Value<String> fileName = const Value.absent(), ({
Value<String> title = const Value.absent(), Value<String> fileName = const Value.absent(),
Value<String> content = const Value.absent(), Value<String> title = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<String> content = const Value.absent(),
}) => Value<int> rowid = const Value.absent(),
ChatCompanion( }) => ChatCompanion(
fileName: fileName, fileName: fileName,
title: title, title: title,
content: content, content: content,
rowid: rowid, rowid: rowid,
), ),
createCompanionCallback: ({ createCompanionCallback:
required String fileName, ({
required String title, required String fileName,
required String content, required String title,
Value<int> rowid = const Value.absent(), required String content,
}) => Value<int> rowid = const Value.absent(),
ChatCompanion.insert( }) => ChatCompanion.insert(
fileName: fileName, fileName: fileName,
title: title, title: title,
content: content, content: content,
rowid: rowid, rowid: rowid,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper:
.map((e) => (e.readTable(table), BaseReferences(db, table, e))) (p0) =>
.toList(), p0
.map(
(e) => (
e.readTable(table),
BaseReferences(db, table, e),
),
)
.toList(),
prefetchHooksCallback: null, prefetchHooksCallback: null,
)); ),
);
} }
typedef $ChatProcessedTableManager = ProcessedTableManager< typedef $ChatProcessedTableManager =
_$ChatSearchDatabase, ProcessedTableManager<
Chat, _$ChatSearchDatabase,
ChatData, Chat,
$ChatFilterComposer, ChatData,
$ChatOrderingComposer, $ChatFilterComposer,
$ChatAnnotationComposer, $ChatOrderingComposer,
$ChatCreateCompanionBuilder, $ChatAnnotationComposer,
$ChatUpdateCompanionBuilder, $ChatCreateCompanionBuilder,
(ChatData, BaseReferences<_$ChatSearchDatabase, Chat, ChatData>), $ChatUpdateCompanionBuilder,
ChatData, (ChatData, BaseReferences<_$ChatSearchDatabase, Chat, ChatData>),
PrefetchHooks Function()>; ChatData,
typedef $ChatFtsCreateCompanionBuilder = ChatFtsCompanion Function({ PrefetchHooks Function()
required String title, >;
required String content, typedef $ChatFtsCreateCompanionBuilder =
Value<int> rowid, ChatFtsCompanion Function({
}); required String title,
typedef $ChatFtsUpdateCompanionBuilder = ChatFtsCompanion Function({ required String content,
Value<String> title, Value<int> rowid,
Value<String> content, });
Value<int> rowid, typedef $ChatFtsUpdateCompanionBuilder =
}); ChatFtsCompanion Function({
Value<String> title,
Value<String> content,
Value<int> rowid,
});
class $ChatFtsFilterComposer extends Composer<_$ChatSearchDatabase, ChatFts> { class $ChatFtsFilterComposer extends Composer<_$ChatSearchDatabase, ChatFts> {
$ChatFtsFilterComposer({ $ChatFtsFilterComposer({
@@ -594,10 +670,14 @@ class $ChatFtsFilterComposer extends Composer<_$ChatSearchDatabase, ChatFts> {
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnFilters<String> get title => $composableBuilder( ColumnFilters<String> get title => $composableBuilder(
column: $table.title, builder: (column) => ColumnFilters(column)); column: $table.title,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get content => $composableBuilder( ColumnFilters<String> get content => $composableBuilder(
column: $table.content, builder: (column) => ColumnFilters(column)); column: $table.content,
builder: (column) => ColumnFilters(column),
);
} }
class $ChatFtsOrderingComposer extends Composer<_$ChatSearchDatabase, ChatFts> { class $ChatFtsOrderingComposer extends Composer<_$ChatSearchDatabase, ChatFts> {
@@ -609,10 +689,14 @@ class $ChatFtsOrderingComposer extends Composer<_$ChatSearchDatabase, ChatFts> {
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnOrderings<String> get title => $composableBuilder( ColumnOrderings<String> get title => $composableBuilder(
column: $table.title, builder: (column) => ColumnOrderings(column)); column: $table.title,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get content => $composableBuilder( ColumnOrderings<String> get content => $composableBuilder(
column: $table.content, builder: (column) => ColumnOrderings(column)); column: $table.content,
builder: (column) => ColumnOrderings(column),
);
} }
class $ChatFtsAnnotationComposer class $ChatFtsAnnotationComposer
@@ -631,67 +715,81 @@ class $ChatFtsAnnotationComposer
$composableBuilder(column: $table.content, builder: (column) => column); $composableBuilder(column: $table.content, builder: (column) => column);
} }
class $ChatFtsTableManager extends RootTableManager< class $ChatFtsTableManager
_$ChatSearchDatabase, extends
ChatFts, RootTableManager<
ChatFt, _$ChatSearchDatabase,
$ChatFtsFilterComposer, ChatFts,
$ChatFtsOrderingComposer, ChatFt,
$ChatFtsAnnotationComposer, $ChatFtsFilterComposer,
$ChatFtsCreateCompanionBuilder, $ChatFtsOrderingComposer,
$ChatFtsUpdateCompanionBuilder, $ChatFtsAnnotationComposer,
(ChatFt, BaseReferences<_$ChatSearchDatabase, ChatFts, ChatFt>), $ChatFtsCreateCompanionBuilder,
ChatFt, $ChatFtsUpdateCompanionBuilder,
PrefetchHooks Function()> { (ChatFt, BaseReferences<_$ChatSearchDatabase, ChatFts, ChatFt>),
ChatFt,
PrefetchHooks Function()
> {
$ChatFtsTableManager(_$ChatSearchDatabase db, ChatFts table) $ChatFtsTableManager(_$ChatSearchDatabase db, ChatFts table)
: super(TableManagerState( : super(
TableManagerState(
db: db, db: db,
table: table, table: table,
createFilteringComposer: () => createFilteringComposer:
$ChatFtsFilterComposer($db: db, $table: table), () => $ChatFtsFilterComposer($db: db, $table: table),
createOrderingComposer: () => createOrderingComposer:
$ChatFtsOrderingComposer($db: db, $table: table), () => $ChatFtsOrderingComposer($db: db, $table: table),
createComputedFieldComposer: () => createComputedFieldComposer:
$ChatFtsAnnotationComposer($db: db, $table: table), () => $ChatFtsAnnotationComposer($db: db, $table: table),
updateCompanionCallback: ({ updateCompanionCallback:
Value<String> title = const Value.absent(), ({
Value<String> content = const Value.absent(), Value<String> title = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<String> content = const Value.absent(),
}) => Value<int> rowid = const Value.absent(),
ChatFtsCompanion( }) => ChatFtsCompanion(
title: title, title: title,
content: content, content: content,
rowid: rowid, rowid: rowid,
), ),
createCompanionCallback: ({ createCompanionCallback:
required String title, ({
required String content, required String title,
Value<int> rowid = const Value.absent(), required String content,
}) => Value<int> rowid = const Value.absent(),
ChatFtsCompanion.insert( }) => ChatFtsCompanion.insert(
title: title, title: title,
content: content, content: content,
rowid: rowid, rowid: rowid,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper:
.map((e) => (e.readTable(table), BaseReferences(db, table, e))) (p0) =>
.toList(), p0
.map(
(e) => (
e.readTable(table),
BaseReferences(db, table, e),
),
)
.toList(),
prefetchHooksCallback: null, prefetchHooksCallback: null,
)); ),
);
} }
typedef $ChatFtsProcessedTableManager = ProcessedTableManager< typedef $ChatFtsProcessedTableManager =
_$ChatSearchDatabase, ProcessedTableManager<
ChatFts, _$ChatSearchDatabase,
ChatFt, ChatFts,
$ChatFtsFilterComposer, ChatFt,
$ChatFtsOrderingComposer, $ChatFtsFilterComposer,
$ChatFtsAnnotationComposer, $ChatFtsOrderingComposer,
$ChatFtsCreateCompanionBuilder, $ChatFtsAnnotationComposer,
$ChatFtsUpdateCompanionBuilder, $ChatFtsCreateCompanionBuilder,
(ChatFt, BaseReferences<_$ChatSearchDatabase, ChatFts, ChatFt>), $ChatFtsUpdateCompanionBuilder,
ChatFt, (ChatFt, BaseReferences<_$ChatSearchDatabase, ChatFts, ChatFt>),
PrefetchHooks Function()>; ChatFt,
PrefetchHooks Function()
>;
class $ChatSearchDatabaseManager { class $ChatSearchDatabaseManager {
final _$ChatSearchDatabase _db; final _$ChatSearchDatabase _db;
@@ -704,9 +802,5 @@ class ChatQueryResult {
final String fileName; final String fileName;
final String? title; final String? title;
final String? contentSnippet; final String? contentSnippet;
ChatQueryResult({ ChatQueryResult({required this.fileName, this.title, this.contentSnippet});
required this.fileName,
this.title,
this.contentSnippet,
});
} }
@@ -13,14 +13,15 @@ String _$chatSearchDatabaseHash() =>
@ProviderFor(chatSearchDatabase) @ProviderFor(chatSearchDatabase)
final chatSearchDatabaseProvider = final chatSearchDatabaseProvider =
AutoDisposeProvider<ChatSearchDatabase>.internal( AutoDisposeProvider<ChatSearchDatabase>.internal(
chatSearchDatabase, chatSearchDatabase,
name: r'chatSearchDatabaseProvider', name: r'chatSearchDatabaseProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$chatSearchDatabaseHash, ? null
dependencies: null, : _$chatSearchDatabaseHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead') @Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element // ignore: unused_element
@@ -11,19 +11,21 @@ class ChatArchiveFileService extends _$ChatArchiveFileService {
final Future<Directory> _archiveDirectoryFuture; final Future<Directory> _archiveDirectoryFuture;
ChatArchiveFileService() ChatArchiveFileService()
: _archiveDirectoryFuture = : _archiveDirectoryFuture = path_provider
path_provider.getApplicationDocumentsDirectory().then( .getApplicationDocumentsDirectory()
(documentDirectory) => Directory( .then(
path.join(documentDirectory.path, 'archive', 'chat'), (documentDirectory) => Directory(
).create(recursive: true), path.join(documentDirectory.path, 'archive', 'chat'),
); ).create(recursive: true),
);
Future<List<FileSystemEntity>> list() { Future<List<FileSystemEntity>> list() {
return _archiveDirectoryFuture.then( return _archiveDirectoryFuture.then(
(value) => value (value) =>
.list() value
.where((file) => path.extension(file.path) == '.md') .list()
.toList(), .where((file) => path.extension(file.path) == '.md')
.toList(),
); );
} }
@@ -56,8 +58,9 @@ class ChatArchiveFileService extends _$ChatArchiveFileService {
Stream<WatchEvent> _directoryStream() async* { Stream<WatchEvent> _directoryStream() async* {
final watcher = DirectoryWatcher( final watcher = DirectoryWatcher(
await _archiveDirectoryFuture await _archiveDirectoryFuture.then(
.then((archiveDirectory) => archiveDirectory.absolute.path), (archiveDirectory) => archiveDirectory.absolute.path,
),
); );
yield* watcher.events.where((event) => path.extension(event.path) == '.md'); yield* watcher.events.where((event) => path.extension(event.path) == '.md');
@@ -12,12 +12,15 @@ String _$chatArchiveFileServiceHash() =>
/// See also [ChatArchiveFileService]. /// See also [ChatArchiveFileService].
@ProviderFor(ChatArchiveFileService) @ProviderFor(ChatArchiveFileService)
final chatArchiveFileServiceProvider = AutoDisposeNotifierProvider< final chatArchiveFileServiceProvider = AutoDisposeNotifierProvider<
ChatArchiveFileService, Raw<Stream<WatchEvent>>>.internal( ChatArchiveFileService,
Raw<Stream<WatchEvent>>
>.internal(
ChatArchiveFileService.new, ChatArchiveFileService.new,
name: r'chatArchiveFileServiceProvider', name: r'chatArchiveFileServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$chatArchiveFileServiceHash, ? null
: _$chatArchiveFileServiceHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -21,8 +21,9 @@ class ChatArchiveRepository extends _$ChatArchiveRepository {
} }
Future<Result<void>> archiveChat(String fileName, Uri url) async { Future<Result<void>> archiveChat(String fileName, Uri url) async {
final contentsResult = final contentsResult = await ref
await ref.read(kagiChatServiceProvider.notifier).downloadChat(url); .read(kagiChatServiceProvider.notifier)
.downloadChat(url);
return contentsResult.flatMapAsync( return contentsResult.flatMapAsync(
(contents) => ref (contents) => ref
@@ -37,14 +38,15 @@ class ChatArchiveRepository extends _$ChatArchiveRepository {
); );
return contentsResult.fold( return contentsResult.fold(
(value) => (value == null) (value) =>
? Result.failure( (value == null)
ErrorMessage( ? Result.failure(
source: 'Chat Archive', ErrorMessage(
message: 'Chat $fileName not found', source: 'Chat Archive',
), message: 'Chat $fileName not found',
) ),
: Result.success(value), )
: Result.success(value),
onFailure: Result.failure, onFailure: Result.failure,
); );
} }
@@ -55,17 +57,16 @@ class ChatArchiveRepository extends _$ChatArchiveRepository {
yield* ConcatStream([ yield* ConcatStream([
listArchivedChats().asStream(), listArchivedChats().asStream(),
fileRepository.asyncMap( fileRepository.asyncMap((_) => listArchivedChats()),
(_) => listArchivedChats(),
),
]); ]);
} }
} }
@Riverpod() @Riverpod()
Future<String> readArchivedChat(Ref ref, String fileName) async { Future<String> readArchivedChat(Ref ref, String fileName) async {
final result = final result = await ref
await ref.read(chatArchiveRepositoryProvider.notifier).readChat(fileName); .read(chatArchiveRepositoryProvider.notifier)
.readChat(fileName);
return result.value; return result.value;
} }
@@ -39,21 +39,15 @@ class ReadArchivedChatFamily extends Family<AsyncValue<String>> {
const ReadArchivedChatFamily(); const ReadArchivedChatFamily();
/// See also [readArchivedChat]. /// See also [readArchivedChat].
ReadArchivedChatProvider call( ReadArchivedChatProvider call(String fileName) {
String fileName, return ReadArchivedChatProvider(fileName);
) {
return ReadArchivedChatProvider(
fileName,
);
} }
@override @override
ReadArchivedChatProvider getProviderOverride( ReadArchivedChatProvider getProviderOverride(
covariant ReadArchivedChatProvider provider, covariant ReadArchivedChatProvider provider,
) { ) {
return call( return call(provider.fileName);
provider.fileName,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -74,24 +68,20 @@ class ReadArchivedChatFamily extends Family<AsyncValue<String>> {
/// See also [readArchivedChat]. /// See also [readArchivedChat].
class ReadArchivedChatProvider extends AutoDisposeFutureProvider<String> { class ReadArchivedChatProvider extends AutoDisposeFutureProvider<String> {
/// See also [readArchivedChat]. /// See also [readArchivedChat].
ReadArchivedChatProvider( ReadArchivedChatProvider(String fileName)
String fileName, : this._internal(
) : this._internal( (ref) => readArchivedChat(ref as ReadArchivedChatRef, fileName),
(ref) => readArchivedChat( from: readArchivedChatProvider,
ref as ReadArchivedChatRef, name: r'readArchivedChatProvider',
fileName, debugGetCreateSourceHash:
), const bool.fromEnvironment('dart.vm.product')
from: readArchivedChatProvider, ? null
name: r'readArchivedChatProvider', : _$readArchivedChatHash,
debugGetCreateSourceHash: dependencies: ReadArchivedChatFamily._dependencies,
const bool.fromEnvironment('dart.vm.product') allTransitiveDependencies:
? null ReadArchivedChatFamily._allTransitiveDependencies,
: _$readArchivedChatHash, fileName: fileName,
dependencies: ReadArchivedChatFamily._dependencies, );
allTransitiveDependencies:
ReadArchivedChatFamily._allTransitiveDependencies,
fileName: fileName,
);
ReadArchivedChatProvider._internal( ReadArchivedChatProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -150,7 +140,8 @@ mixin ReadArchivedChatRef on AutoDisposeFutureProviderRef<String> {
} }
class _ReadArchivedChatProviderElement class _ReadArchivedChatProviderElement
extends AutoDisposeFutureProviderElement<String> with ReadArchivedChatRef { extends AutoDisposeFutureProviderElement<String>
with ReadArchivedChatRef {
_ReadArchivedChatProviderElement(super.provider); _ReadArchivedChatProviderElement(super.provider);
@override @override
@@ -163,12 +154,15 @@ String _$chatArchiveRepositoryHash() =>
/// See also [ChatArchiveRepository]. /// See also [ChatArchiveRepository].
@ProviderFor(ChatArchiveRepository) @ProviderFor(ChatArchiveRepository)
final chatArchiveRepositoryProvider = AutoDisposeStreamNotifierProvider< final chatArchiveRepositoryProvider = AutoDisposeStreamNotifierProvider<
ChatArchiveRepository, List<ChatEntity>>.internal( ChatArchiveRepository,
List<ChatEntity>
>.internal(
ChatArchiveRepository.new, ChatArchiveRepository.new,
name: r'chatArchiveRepositoryProvider', name: r'chatArchiveRepositoryProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$chatArchiveRepositoryHash, ? null
: _$chatArchiveRepositoryHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -74,13 +74,11 @@ class ChatArchiveSearchRepository extends _$ChatArchiveSearchRepository {
ellipsis: ellipsis, ellipsis: ellipsis,
) )
.get() .get()
.then( .then((value) {
(value) { if (!_streamController.isClosed) {
if (!_streamController.isClosed) { _streamController.add(value);
_streamController.add(value); }
} });
},
);
} }
} }
@@ -96,23 +94,24 @@ class ChatArchiveSearchRepository extends _$ChatArchiveSearchRepository {
await searchDatabase.searchDao.indexChats(await _availableChats()); await searchDatabase.searchDao.indexChats(await _availableChats());
_populatedCompleter.complete(); _populatedCompleter.complete();
final changeStreamSubscription = final changeStreamSubscription = ref
ref.watch(chatArchiveFileServiceProvider).listen((event) async { .watch(chatArchiveFileServiceProvider)
final chat = ChatEntity.fromFileName(path.basename(event.path)); .listen((event) async {
final chat = ChatEntity.fromFileName(path.basename(event.path));
switch (event.type) { switch (event.type) {
case ChangeType.ADD: case ChangeType.ADD:
case ChangeType.MODIFY: case ChangeType.MODIFY:
if (chat.name != null) { if (chat.name != null) {
final companion = await _readChat(chat); final companion = await _readChat(chat);
if (companion != null) { if (companion != null) {
await searchDatabase.searchDao.upsertChat(companion); await searchDatabase.searchDao.upsertChat(companion);
} }
}
case ChangeType.REMOVE:
await searchDatabase.searchDao.deleteChat(chat.fileName);
} }
case ChangeType.REMOVE: });
await searchDatabase.searchDao.deleteChat(chat.fileName);
}
});
ref.onDispose(() async { ref.onDispose(() async {
await changeStreamSubscription.cancel(); await changeStreamSubscription.cancel();
@@ -12,17 +12,20 @@ String _$chatArchiveSearchRepositoryHash() =>
/// See also [ChatArchiveSearchRepository]. /// See also [ChatArchiveSearchRepository].
@ProviderFor(ChatArchiveSearchRepository) @ProviderFor(ChatArchiveSearchRepository)
final chatArchiveSearchRepositoryProvider = AutoDisposeStreamNotifierProvider< final chatArchiveSearchRepositoryProvider = AutoDisposeStreamNotifierProvider<
ChatArchiveSearchRepository, List<ChatQueryResult>>.internal( ChatArchiveSearchRepository,
List<ChatQueryResult>
>.internal(
ChatArchiveSearchRepository.new, ChatArchiveSearchRepository.new,
name: r'chatArchiveSearchRepositoryProvider', name: r'chatArchiveSearchRepositoryProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$chatArchiveSearchRepositoryHash, ? null
: _$chatArchiveSearchRepositoryHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
typedef _$ChatArchiveSearchRepository typedef _$ChatArchiveSearchRepository =
= AutoDisposeStreamNotifier<List<ChatQueryResult>>; AutoDisposeStreamNotifier<List<ChatQueryResult>>;
// ignore_for_file: type=lint // 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 // 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
@@ -62,9 +62,7 @@ class ChatArchiveDetailScreen extends HookConsumerWidget {
onPressed: () async { onPressed: () async {
if (chatAsync.valueOrNull != null) { if (chatAsync.valueOrNull != null) {
await Clipboard.setData( await Clipboard.setData(
ClipboardData( ClipboardData(text: chatAsync.valueOrNull!),
text: chatAsync.valueOrNull!,
),
); );
} }
}, },
@@ -94,23 +92,24 @@ class ChatArchiveDetailScreen extends HookConsumerWidget {
enabled: chatAsync.isLoading, enabled: chatAsync.isLoading,
justifyMultiLineText: false, justifyMultiLineText: false,
child: chatAsync.when( child: chatAsync.when(
data: (data) => Markdown( data:
data: data, (data) => Markdown(
selectable: true, data: data,
onTapLink: (text, href, title) async { selectable: true,
if (href != null) { onTapLink: (text, href, title) async {
if (Uri.parse(href) case final Uri url) { if (href != null) {
await ref if (Uri.parse(href) case final Uri url) {
.read(tabRepositoryProvider.notifier) await ref
.addTab(url: url); .read(tabRepositoryProvider.notifier)
.addTab(url: url);
if (context.mounted) { if (context.mounted) {
context.go(BrowserRoute().location); context.go(BrowserRoute().location);
}
}
} }
} },
} ),
},
),
error: (error, stackTrace) { error: (error, stackTrace) {
return FailureWidget( return FailureWidget(
title: 'Could not load chat', title: 'Could not load chat',
@@ -118,9 +117,7 @@ class ChatArchiveDetailScreen extends HookConsumerWidget {
onRetry: () => ref.refresh(readArchivedChatProvider(fileName)), onRetry: () => ref.refresh(readArchivedChatProvider(fileName)),
); );
}, },
loading: () => const Bone.multiText( loading: () => const Bone.multiText(lines: 15),
lines: 15,
),
), ),
), ),
); );
@@ -48,8 +48,9 @@ class ChatArchiveListScreen extends HookConsumerWidget {
), ),
onTap: () async { onTap: () async {
await context.push( await context.push(
ChatArchiveDetailRoute(fileName: chat.fileName) ChatArchiveDetailRoute(
.location, fileName: chat.fileName,
).location,
); );
}, },
); );
@@ -65,13 +66,15 @@ class ChatArchiveListScreen extends HookConsumerWidget {
onRetry: () => ref.refresh(chatArchiveRepositoryProvider), onRetry: () => ref.refresh(chatArchiveRepositoryProvider),
); );
}, },
loading: () => ListView.builder( loading:
itemCount: 3, () => ListView.builder(
itemBuilder: (context, index) => const ListTile( itemCount: 3,
title: Bone.text(), itemBuilder:
subtitle: Bone.text(), (context, index) => const ListTile(
), title: Bone.text(),
), subtitle: Bone.text(),
),
),
), ),
), ),
); );
@@ -56,58 +56,58 @@ class ChatArchiveSearchScreen extends HookConsumerWidget {
), ),
body: resultsAsync.when( body: resultsAsync.when(
skipLoadingOnReload: true, skipLoadingOnReload: true,
data: (chats) => FadingScroll( data:
fadingSize: 25, (chats) => FadingScroll(
builder: (context, controller) { fadingSize: 25,
return ListView.builder( builder: (context, controller) {
controller: controller, return ListView.builder(
itemCount: chats.length, controller: controller,
itemBuilder: (context, index) { itemCount: chats.length,
final chat = chats[index]; itemBuilder: (context, index) {
final chatEntity = ChatEntity.fromFileName(chat.fileName); final chat = chats[index];
final chatEntity = ChatEntity.fromFileName(chat.fileName);
return Card( return Card(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
child: InkWell( child: InkWell(
onTap: () async { onTap: () async {
await context.push( await context.push(
ChatArchiveDetailRoute(fileName: chat.fileName) ChatArchiveDetailRoute(
.location, fileName: chat.fileName,
); ).location,
}, );
child: Padding( },
padding: const EdgeInsets.all(16.0), child: Padding(
child: Column( padding: const EdgeInsets.all(16.0),
mainAxisSize: MainAxisSize.min, child: Column(
crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min,
children: [ crossAxisAlignment: CrossAxisAlignment.start,
MarkdownBody( children: [
data: '## ${chat.title}', MarkdownBody(data: '## ${chat.title}'),
if (chatEntity.dateTime != null)
Text(
chatEntity.dateTime!
.formatWithMinutePrecision(),
),
const SizedBox(height: 8.0),
if (chat.contentSnippet != null)
MarkdownBody(data: chat.contentSnippet!),
],
), ),
if (chatEntity.dateTime != null) ),
Text(
chatEntity.dateTime!.formatWithMinutePrecision(),
),
const SizedBox(height: 8.0),
if (chat.contentSnippet != null)
MarkdownBody(
data: chat.contentSnippet!,
),
],
), ),
), );
), },
); );
}, },
); ),
}, error:
), (error, stackTrace) => Center(
error: (error, stackTrace) => Center( child: FailureWidget(
child: FailureWidget( title: 'Chat Search failed',
title: 'Chat Search failed', exception: error,
exception: error, ),
), ),
),
loading: () => const SizedBox.shrink(), loading: () => const SizedBox.shrink(),
), ),
); );
@@ -42,7 +42,8 @@ class BottomSheetExtend extends _$BottomSheetExtend {
await _extentStreamController.close(); await _extentStreamController.close();
}); });
return _extentStreamController.stream return _extentStreamController.stream.sampleTime(
.sampleTime(const Duration(milliseconds: 50)); const Duration(milliseconds: 50),
);
} }
} }
@@ -13,14 +13,15 @@ String _$bottomSheetControllerHash() =>
@ProviderFor(BottomSheetController) @ProviderFor(BottomSheetController)
final bottomSheetControllerProvider = final bottomSheetControllerProvider =
AutoDisposeNotifierProvider<BottomSheetController, Sheet?>.internal( AutoDisposeNotifierProvider<BottomSheetController, Sheet?>.internal(
BottomSheetController.new, BottomSheetController.new,
name: r'bottomSheetControllerProvider', name: r'bottomSheetControllerProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$bottomSheetControllerHash, ? null
dependencies: null, : _$bottomSheetControllerHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$BottomSheetController = AutoDisposeNotifier<Sheet?>; typedef _$BottomSheetController = AutoDisposeNotifier<Sheet?>;
String _$bottomSheetExtendHash() => r'7e11b9047c15bdeb4dfcb488a8573daadb64e25c'; String _$bottomSheetExtendHash() => r'7e11b9047c15bdeb4dfcb488a8573daadb64e25c';
@@ -29,14 +30,15 @@ String _$bottomSheetExtendHash() => r'7e11b9047c15bdeb4dfcb488a8573daadb64e25c';
@ProviderFor(BottomSheetExtend) @ProviderFor(BottomSheetExtend)
final bottomSheetExtendProvider = final bottomSheetExtendProvider =
StreamNotifierProvider<BottomSheetExtend, double>.internal( StreamNotifierProvider<BottomSheetExtend, double>.internal(
BottomSheetExtend.new, BottomSheetExtend.new,
name: r'bottomSheetExtendProvider', name: r'bottomSheetExtendProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$bottomSheetExtendHash, ? null
dependencies: null, : _$bottomSheetExtendHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$BottomSheetExtend = StreamNotifier<double>; typedef _$BottomSheetExtend = StreamNotifier<double>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -13,14 +13,15 @@ String _$overlayDialogControllerHash() =>
@ProviderFor(OverlayDialogController) @ProviderFor(OverlayDialogController)
final overlayDialogControllerProvider = final overlayDialogControllerProvider =
AutoDisposeNotifierProvider<OverlayDialogController, Widget?>.internal( AutoDisposeNotifierProvider<OverlayDialogController, Widget?>.internal(
OverlayDialogController.new, OverlayDialogController.new,
name: r'overlayDialogControllerProvider', name: r'overlayDialogControllerProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$overlayDialogControllerHash, ? null
dependencies: null, : _$overlayDialogControllerHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$OverlayDialogController = AutoDisposeNotifier<Widget?>; typedef _$OverlayDialogController = AutoDisposeNotifier<Widget?>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -18,8 +18,9 @@ class BrowserIcon with FastEquatable {
required Color? dominantColor, required Color? dominantColor,
required IconSource source, required IconSource source,
}) async { }) async {
final image = final image = await tryDecodeImage(
await tryDecodeImage(bytes).then((image) => image!.toEquatable()); bytes,
).then((image) => image!.toEquatable());
return BrowserIcon( return BrowserIcon(
image: image, image: image,
@@ -38,9 +39,5 @@ class BrowserIcon with FastEquatable {
bool get cacheHash => true; bool get cacheHash => true;
@override @override
List<Object?> get hashParameters => [ List<Object?> get hashParameters => [image, dominantColor, source];
image,
dominantColor,
source,
];
} }
@@ -12,17 +12,17 @@ class FindResultState with FastEquatable {
}); });
factory FindResultState.$default() => FindResultState( factory FindResultState.$default() => FindResultState(
activeMatchOrdinal: -1, activeMatchOrdinal: -1,
numberOfMatches: 0, numberOfMatches: 0,
isDoneCounting: false, isDoneCounting: false,
); );
@override @override
List<Object?> get hashParameters => [ List<Object?> get hashParameters => [
activeMatchOrdinal, activeMatchOrdinal,
numberOfMatches, numberOfMatches,
isDoneCounting, isDoneCounting,
]; ];
@override @override
bool get cacheHash => true; bool get cacheHash => true;
@@ -28,16 +28,20 @@ class HistoryState with FastEquatable {
}); });
factory HistoryState.$default() => HistoryState( factory HistoryState.$default() => HistoryState(
items: const [], items: const [],
currentIndex: 0, currentIndex: 0,
canGoBack: false, canGoBack: false,
canGoForward: false, canGoForward: false,
); );
@override @override
bool get cacheHash => true; bool get cacheHash => true;
@override @override
List<Object?> get hashParameters => List<Object?> get hashParameters => [
[items, currentIndex, canGoBack, canGoForward]; items,
currentIndex,
canGoBack,
canGoForward,
];
} }
@@ -5,15 +5,10 @@ class ReaderableState with FastEquatable {
final bool active; final bool active;
ReaderableState({ ReaderableState({required this.readerable, required this.active});
required this.readerable,
required this.active,
});
factory ReaderableState.$default() => ReaderableState( factory ReaderableState.$default() =>
readerable: false, ReaderableState(readerable: false, active: false);
active: false,
);
@override @override
bool get cacheHash => true; bool get cacheHash => true;
@@ -11,11 +11,8 @@ class SecurityState with FastEquatable {
required this.issuer, required this.issuer,
}); });
factory SecurityState.$default() => SecurityState( factory SecurityState.$default() =>
secure: false, SecurityState(secure: false, host: "", issuer: "");
host: "",
issuer: "",
);
@override @override
bool get cacheHash => true; bool get cacheHash => true;
@@ -26,12 +26,12 @@ class TabState extends WebPageInfo with FastEquatable {
@override @override
BrowserIcon? get favicon => icon.mapNotNull( BrowserIcon? get favicon => icon.mapNotNull(
(icon) => BrowserIcon( (icon) => BrowserIcon(
image: icon, image: icon,
dominantColor: null, dominantColor: null,
source: IconSource.memory, source: IconSource.memory,
), ),
); );
final EquatableImage? thumbnail; final EquatableImage? thumbnail;
@@ -64,40 +64,40 @@ class TabState extends WebPageInfo with FastEquatable {
}) : super(title: title); }) : super(title: title);
factory TabState.$default(String tabId) => TabState( factory TabState.$default(String tabId) => TabState(
id: tabId, id: tabId,
contextId: null, contextId: null,
url: Uri.parse('about:blank'), url: Uri.parse('about:blank'),
title: "", title: "",
icon: null, icon: null,
thumbnail: null, thumbnail: null,
progress: 0, progress: 0,
isPrivate: false, isPrivate: false,
isFullScreen: false, isFullScreen: false,
isLoading: false, isLoading: false,
securityInfoState: SecurityState.$default(), securityInfoState: SecurityState.$default(),
historyState: HistoryState.$default(), historyState: HistoryState.$default(),
readerableState: ReaderableState.$default(), readerableState: ReaderableState.$default(),
findResultState: FindResultState.$default(), findResultState: FindResultState.$default(),
); );
@override @override
bool get cacheHash => true; bool get cacheHash => true;
@override @override
List<Object?> get hashParameters => [ List<Object?> get hashParameters => [
id, id,
contextId, contextId,
url, url,
title, title,
icon, icon,
thumbnail, thumbnail,
progress, progress,
isPrivate, isPrivate,
isFullScreen, isFullScreen,
isLoading, isLoading,
securityInfoState, securityInfoState,
historyState, historyState,
readerableState, readerableState,
findResultState, findResultState,
]; ];
} }
@@ -106,7 +106,6 @@ class _$TabStateCWProxyImpl implements _$TabStateCWProxy {
this(findResultState: findResultState); this(findResultState: findResultState);
@override @override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TabState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `TabState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
/// ///
/// Usage /// Usage
@@ -130,58 +129,71 @@ class _$TabStateCWProxyImpl implements _$TabStateCWProxy {
}) { }) {
return TabState( return TabState(
id: _value.id, id: _value.id,
contextId: contextId == const $CopyWithPlaceholder() contextId:
? _value.contextId contextId == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.contextId
: contextId as String?, // ignore: cast_nullable_to_non_nullable
url: url == const $CopyWithPlaceholder() : contextId as String?,
? _value.url url:
// ignore: cast_nullable_to_non_nullable url == const $CopyWithPlaceholder()
: url as Uri, ? _value.url
title: title == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.title : url as Uri,
// ignore: cast_nullable_to_non_nullable title:
: title as String, title == const $CopyWithPlaceholder()
icon: icon == const $CopyWithPlaceholder() ? _value.title
? _value.icon // ignore: cast_nullable_to_non_nullable
// ignore: cast_nullable_to_non_nullable : title as String,
: icon as EquatableImage?, icon:
thumbnail: thumbnail == const $CopyWithPlaceholder() icon == const $CopyWithPlaceholder()
? _value.thumbnail ? _value.icon
// ignore: cast_nullable_to_non_nullable // ignore: cast_nullable_to_non_nullable
: thumbnail as EquatableImage?, : icon as EquatableImage?,
progress: progress == const $CopyWithPlaceholder() thumbnail:
? _value.progress thumbnail == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.thumbnail
: progress as int, // ignore: cast_nullable_to_non_nullable
isPrivate: isPrivate == const $CopyWithPlaceholder() : thumbnail as EquatableImage?,
? _value.isPrivate progress:
// ignore: cast_nullable_to_non_nullable progress == const $CopyWithPlaceholder()
: isPrivate as bool, ? _value.progress
isFullScreen: isFullScreen == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.isFullScreen : progress as int,
// ignore: cast_nullable_to_non_nullable isPrivate:
: isFullScreen as bool, isPrivate == const $CopyWithPlaceholder()
isLoading: isLoading == const $CopyWithPlaceholder() ? _value.isPrivate
? _value.isLoading // ignore: cast_nullable_to_non_nullable
// ignore: cast_nullable_to_non_nullable : isPrivate as bool,
: isLoading as bool, isFullScreen:
securityInfoState: securityInfoState == const $CopyWithPlaceholder() isFullScreen == const $CopyWithPlaceholder()
? _value.securityInfoState ? _value.isFullScreen
// ignore: cast_nullable_to_non_nullable // ignore: cast_nullable_to_non_nullable
: securityInfoState as SecurityState, : isFullScreen as bool,
historyState: historyState == const $CopyWithPlaceholder() isLoading:
? _value.historyState isLoading == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.isLoading
: historyState as HistoryState, // ignore: cast_nullable_to_non_nullable
readerableState: readerableState == const $CopyWithPlaceholder() : isLoading as bool,
? _value.readerableState securityInfoState:
// ignore: cast_nullable_to_non_nullable securityInfoState == const $CopyWithPlaceholder()
: readerableState as ReaderableState, ? _value.securityInfoState
findResultState: findResultState == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.findResultState : securityInfoState as SecurityState,
// ignore: cast_nullable_to_non_nullable historyState:
: findResultState as FindResultState, historyState == const $CopyWithPlaceholder()
? _value.historyState
// ignore: cast_nullable_to_non_nullable
: historyState as HistoryState,
readerableState:
readerableState == const $CopyWithPlaceholder()
? _value.readerableState
// ignore: cast_nullable_to_non_nullable
: readerableState as ReaderableState,
findResultState:
findResultState == const $CopyWithPlaceholder()
? _value.findResultState
// ignore: cast_nullable_to_non_nullable
: findResultState as FindResultState,
); );
} }
} }
@@ -33,12 +33,12 @@ class WebExtensionState with FastEquatable {
@override @override
List<Object?> get hashParameters => [ List<Object?> get hashParameters => [
extensionId, extensionId,
title, title,
enabled, enabled,
badgeText, badgeText,
badgeTextColor, badgeTextColor,
badgeBackgroundColor, badgeBackgroundColor,
icon, icon,
]; ];
} }
@@ -69,7 +69,6 @@ class _$WebExtensionStateCWProxyImpl implements _$WebExtensionStateCWProxy {
WebExtensionState icon(EquatableImage? icon) => this(icon: icon); WebExtensionState icon(EquatableImage? icon) => this(icon: icon);
@override @override
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `WebExtensionState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `WebExtensionState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
/// ///
/// Usage /// Usage
@@ -86,34 +85,41 @@ class _$WebExtensionStateCWProxyImpl implements _$WebExtensionStateCWProxy {
Object? icon = const $CopyWithPlaceholder(), Object? icon = const $CopyWithPlaceholder(),
}) { }) {
return WebExtensionState( return WebExtensionState(
extensionId: extensionId == const $CopyWithPlaceholder() extensionId:
? _value.extensionId extensionId == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.extensionId
: extensionId as String, // ignore: cast_nullable_to_non_nullable
enabled: enabled == const $CopyWithPlaceholder() : extensionId as String,
? _value.enabled enabled:
// ignore: cast_nullable_to_non_nullable enabled == const $CopyWithPlaceholder()
: enabled as bool, ? _value.enabled
title: title == const $CopyWithPlaceholder() // ignore: cast_nullable_to_non_nullable
? _value.title : enabled as bool,
// ignore: cast_nullable_to_non_nullable title:
: title as String?, title == const $CopyWithPlaceholder()
badgeText: badgeText == const $CopyWithPlaceholder() ? _value.title
? _value.badgeText // ignore: cast_nullable_to_non_nullable
// ignore: cast_nullable_to_non_nullable : title as String?,
: badgeText as String?, badgeText:
badgeTextColor: badgeTextColor == const $CopyWithPlaceholder() badgeText == const $CopyWithPlaceholder()
? _value.badgeTextColor ? _value.badgeText
// ignore: cast_nullable_to_non_nullable // ignore: cast_nullable_to_non_nullable
: badgeTextColor as Color?, : badgeText as String?,
badgeBackgroundColor: badgeBackgroundColor == const $CopyWithPlaceholder() badgeTextColor:
? _value.badgeBackgroundColor badgeTextColor == const $CopyWithPlaceholder()
// ignore: cast_nullable_to_non_nullable ? _value.badgeTextColor
: badgeBackgroundColor as Color?, // ignore: cast_nullable_to_non_nullable
icon: icon == const $CopyWithPlaceholder() : badgeTextColor as Color?,
? _value.icon badgeBackgroundColor:
// ignore: cast_nullable_to_non_nullable badgeBackgroundColor == const $CopyWithPlaceholder()
: icon as EquatableImage?, ? _value.badgeBackgroundColor
// ignore: cast_nullable_to_non_nullable
: badgeBackgroundColor as Color?,
icon:
icon == const $CopyWithPlaceholder()
? _value.icon
// ignore: cast_nullable_to_non_nullable
: icon as EquatableImage?,
); );
} }
} }
@@ -13,16 +13,15 @@ import 'package:url_launcher/url_launcher.dart';
part 'providers.g.dart'; part 'providers.g.dart';
@Riverpod(keepAlive: true) @Riverpod(keepAlive: true)
GeckoSelectionActionService selectionActionService( GeckoSelectionActionService selectionActionService(Ref ref) {
Ref ref,
) {
final service = GeckoSelectionActionService.setUp(); final service = GeckoSelectionActionService.setUp();
unawaited( unawaited(
service.setActions([ service.setActions([
SearchAction((text) async { SearchAction((text) async {
final defaultSearchBang = final defaultSearchBang = await ref.read(
await ref.read(defaultSearchBangDataProvider.future); defaultSearchBangDataProvider.future,
);
if (defaultSearchBang != null) { if (defaultSearchBang != null) {
await ref await ref
@@ -33,14 +32,14 @@ GeckoSelectionActionService selectionActionService(
} }
}), }),
PrivateSearchAction((text) async { PrivateSearchAction((text) async {
final defaultSearchBang = final defaultSearchBang = await ref.read(
await ref.read(defaultSearchBangDataProvider.future); defaultSearchBangDataProvider.future,
);
if (defaultSearchBang != null) { if (defaultSearchBang != null) {
await ref.read(tabRepositoryProvider.notifier).addTab( await ref
url: defaultSearchBang.getUrl(text), .read(tabRepositoryProvider.notifier)
private: true, .addTab(url: defaultSearchBang.getUrl(text), private: true);
);
} else { } else {
logger.e('No default search bang found'); logger.e('No default search bang found');
} }
@@ -132,12 +131,13 @@ class EngineReadyState extends _$EngineReadyState {
eventService.engineReadyStateEvents eventService.engineReadyStateEvents
.firstWhere((value) => value == true) .firstWhere((value) => value == true)
.timeout( .timeout(
const Duration(seconds: 5), const Duration(seconds: 5),
onTimeout: () { onTimeout: () {
logger.w('Waiting for engine ready state timed out'); logger.w('Waiting for engine ready state timed out');
return true; return true;
}, },
).whenComplete(() => state = true), )
.whenComplete(() => state = true),
); );
} }
@@ -13,14 +13,15 @@ String _$selectionActionServiceHash() =>
@ProviderFor(selectionActionService) @ProviderFor(selectionActionService)
final selectionActionServiceProvider = final selectionActionServiceProvider =
Provider<GeckoSelectionActionService>.internal( Provider<GeckoSelectionActionService>.internal(
selectionActionService, selectionActionService,
name: r'selectionActionServiceProvider', name: r'selectionActionServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$selectionActionServiceHash, ? null
dependencies: null, : _$selectionActionServiceHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead') @Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element // ignore: unused_element
@@ -64,9 +65,10 @@ String _$tabContentServiceHash() => r'd9a991add907ecc138c62790883e59d8e9aa9266';
final tabContentServiceProvider = Provider<GeckoTabContentService>.internal( final tabContentServiceProvider = Provider<GeckoTabContentService>.internal(
tabContentService, tabContentService,
name: r'tabContentServiceProvider', name: r'tabContentServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$tabContentServiceHash, ? null
: _$tabContentServiceHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -81,14 +83,15 @@ String _$engineSuggestionsServiceHash() =>
@ProviderFor(engineSuggestionsService) @ProviderFor(engineSuggestionsService)
final engineSuggestionsServiceProvider = final engineSuggestionsServiceProvider =
Provider<GeckoSuggestionsService>.internal( Provider<GeckoSuggestionsService>.internal(
engineSuggestionsService, engineSuggestionsService,
name: r'engineSuggestionsServiceProvider', name: r'engineSuggestionsServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$engineSuggestionsServiceHash, ? null
dependencies: null, : _$engineSuggestionsServiceHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead') @Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element // ignore: unused_element
@@ -100,14 +103,15 @@ String _$selectedTabSessionNotifierHash() =>
@ProviderFor(selectedTabSessionNotifier) @ProviderFor(selectedTabSessionNotifier)
final selectedTabSessionNotifierProvider = final selectedTabSessionNotifierProvider =
AutoDisposeProvider<Raw<TabSession>>.internal( AutoDisposeProvider<Raw<TabSession>>.internal(
selectedTabSessionNotifier, selectedTabSessionNotifier,
name: r'selectedTabSessionNotifierProvider', name: r'selectedTabSessionNotifierProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$selectedTabSessionNotifierHash, ? null
dependencies: null, : _$selectedTabSessionNotifierHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead') @Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element // ignore: unused_element
@@ -118,14 +122,15 @@ String _$engineReadyStateHash() => r'c682333e2e07cf0635aa7ae793a2088ca648c950';
@ProviderFor(EngineReadyState) @ProviderFor(EngineReadyState)
final engineReadyStateProvider = final engineReadyStateProvider =
NotifierProvider<EngineReadyState, bool>.internal( NotifierProvider<EngineReadyState, bool>.internal(
EngineReadyState.new, EngineReadyState.new,
name: r'engineReadyStateProvider', name: r'engineReadyStateProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$engineReadyStateHash, ? null
dependencies: null, : _$engineReadyStateHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$EngineReadyState = Notifier<bool>; typedef _$EngineReadyState = Notifier<bool>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -12,21 +12,18 @@ class SelectedTab extends _$SelectedTab {
String? build() { String? build() {
final eventSerivce = ref.watch(eventServiceProvider); final eventSerivce = ref.watch(eventServiceProvider);
ref.listen( ref.listen(fireImmediately: true, engineReadyStateProvider, (
fireImmediately: true, previous,
engineReadyStateProvider, next,
(previous, next) async { ) async {
if (next) { if (next) {
await GeckoTabService().syncEvents(onSelectedTabChange: true); await GeckoTabService().syncEvents(onSelectedTabChange: true);
} }
}, });
);
final selectedTabSub = eventSerivce.selectedTabEvents.listen( final selectedTabSub = eventSerivce.selectedTabEvents.listen((tabId) async {
(tabId) async { state = tabId;
state = tabId; });
},
);
ref.onDispose(() { ref.onDispose(() {
unawaited(selectedTabSub.cancel()); unawaited(selectedTabSub.cancel());
@@ -13,23 +13,20 @@ class TabList extends _$TabList {
List<String> build() { List<String> build() {
final eventService = ref.watch(eventServiceProvider); final eventService = ref.watch(eventServiceProvider);
ref.listen( ref.listen(fireImmediately: true, engineReadyStateProvider, (
fireImmediately: true, previous,
engineReadyStateProvider, next,
(previous, next) async { ) async {
if (next) { if (next) {
await GeckoTabService().syncEvents(onTabListChange: true); await GeckoTabService().syncEvents(onTabListChange: true);
} }
}, });
);
final tabListSub = eventService.tabListEvents.listen( final tabListSub = eventService.tabListEvents.listen((tabs) async {
(tabs) async { if (!const DeepCollectionEquality().equals(state, tabs)) {
if (!const DeepCollectionEquality().equals(state, tabs)) { state = tabs;
state = tabs; }
} });
},
);
ref.onDispose(() { ref.onDispose(() {
unawaited(tabListSub.cancel()); unawaited(tabListSub.cancel());
@@ -43,8 +43,9 @@ class TabSession extends _$TabSession {
@override @override
void build({required String? tabId}) { void build({required String? tabId}) {
_sessionService = (tabId != null) _sessionService =
? GeckoSessionService(tabId: tabId) (tabId != null)
: GeckoSessionService.forActiveTab(); ? GeckoSessionService(tabId: tabId)
: GeckoSessionService.forActiveTab();
} }
} }
@@ -32,9 +32,7 @@ class _SystemHash {
abstract class _$TabSession extends BuildlessAutoDisposeNotifier<void> { abstract class _$TabSession extends BuildlessAutoDisposeNotifier<void> {
late final String? tabId; late final String? tabId;
void build({ void build({required String? tabId});
required String? tabId,
});
} }
/// See also [TabSession]. /// See also [TabSession].
@@ -47,21 +45,15 @@ class TabSessionFamily extends Family<void> {
const TabSessionFamily(); const TabSessionFamily();
/// See also [TabSession]. /// See also [TabSession].
TabSessionProvider call({ TabSessionProvider call({required String? tabId}) {
required String? tabId, return TabSessionProvider(tabId: tabId);
}) {
return TabSessionProvider(
tabId: tabId,
);
} }
@override @override
TabSessionProvider getProviderOverride( TabSessionProvider getProviderOverride(
covariant TabSessionProvider provider, covariant TabSessionProvider provider,
) { ) {
return call( return call(tabId: provider.tabId);
tabId: provider.tabId,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -83,21 +75,19 @@ class TabSessionFamily extends Family<void> {
class TabSessionProvider class TabSessionProvider
extends AutoDisposeNotifierProviderImpl<TabSession, void> { extends AutoDisposeNotifierProviderImpl<TabSession, void> {
/// See also [TabSession]. /// See also [TabSession].
TabSessionProvider({ TabSessionProvider({required String? tabId})
required String? tabId, : this._internal(
}) : this._internal( () => TabSession()..tabId = tabId,
() => TabSession()..tabId = tabId, from: tabSessionProvider,
from: tabSessionProvider, name: r'tabSessionProvider',
name: r'tabSessionProvider', debugGetCreateSourceHash:
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
const bool.fromEnvironment('dart.vm.product') ? null
? null : _$tabSessionHash,
: _$tabSessionHash, dependencies: TabSessionFamily._dependencies,
dependencies: TabSessionFamily._dependencies, allTransitiveDependencies: TabSessionFamily._allTransitiveDependencies,
allTransitiveDependencies: tabId: tabId,
TabSessionFamily._allTransitiveDependencies, );
tabId: tabId,
);
TabSessionProvider._internal( TabSessionProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -112,12 +102,8 @@ class TabSessionProvider
final String? tabId; final String? tabId;
@override @override
void runNotifierBuild( void runNotifierBuild(covariant TabSession notifier) {
covariant TabSession notifier, return notifier.build(tabId: tabId);
) {
return notifier.build(
tabId: tabId,
);
} }
@override @override
@@ -170,5 +156,6 @@ class _TabSessionProviderElement
@override @override
String? get tabId => (origin as TabSessionProvider).tabId; String? get tabId => (origin as TabSessionProvider).tabId;
} }
// ignore_for_file: type=lint // 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 // 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
@@ -24,12 +24,14 @@ class TabStates extends _$TabStates {
void _onTabContentStateChange(TabContentState contentState) { void _onTabContentStateChange(TabContentState contentState) {
final current = final current =
state[contentState.id] ?? TabState.$default(contentState.id); state[contentState.id] ?? TabState.$default(contentState.id);
state = {...state}..[contentState.id] = current.copyWith( state = {...state}
..[contentState.id] = current.copyWith(
contextId: contentState.contextId, contextId: contentState.contextId,
url: Uri.parse(contentState.url), url: Uri.parse(contentState.url),
title: (contentState.title.isNotEmpty) title:
? contentState.title (contentState.title.isNotEmpty)
: current.title, ? contentState.title
: current.title,
progress: contentState.progress, progress: contentState.progress,
isPrivate: contentState.isPrivate, isPrivate: contentState.isPrivate,
isFullScreen: contentState.isFullScreen, isFullScreen: contentState.isFullScreen,
@@ -65,7 +67,8 @@ class TabStates extends _$TabStates {
final SecurityInfoEvent(:tabId, :securityInfo) = event; final SecurityInfoEvent(:tabId, :securityInfo) = event;
final current = state[tabId] ?? TabState.$default(tabId); final current = state[tabId] ?? TabState.$default(tabId);
state = {...state}..[tabId] = current.copyWith.securityInfoState( state = {...state}
..[tabId] = current.copyWith.securityInfoState(
SecurityState( SecurityState(
secure: securityInfo.secure, secure: securityInfo.secure,
host: securityInfo.host, host: securityInfo.host,
@@ -78,14 +81,18 @@ class TabStates extends _$TabStates {
final HistoryEvent(:tabId, :history) = event; final HistoryEvent(:tabId, :history) = event;
final current = state[tabId] ?? TabState.$default(tabId); final current = state[tabId] ?? TabState.$default(tabId);
state = {...state}..[tabId] = current.copyWith.historyState( state = {...state}
..[tabId] = current.copyWith.historyState(
HistoryState( HistoryState(
items: history.items.nonNulls items:
.map( history.items.nonNulls
(item) => .map(
HistoryItem(url: Uri.parse(item.url), title: item.title), (item) => HistoryItem(
) url: Uri.parse(item.url),
.toList(), title: item.title,
),
)
.toList(),
currentIndex: history.currentIndex, currentIndex: history.currentIndex,
canGoBack: history.canGoBack, canGoBack: history.canGoBack,
canGoForward: history.canGoForward, canGoForward: history.canGoForward,
@@ -97,7 +104,8 @@ class TabStates extends _$TabStates {
final ReaderableEvent(:tabId, :readerable) = event; final ReaderableEvent(:tabId, :readerable) = event;
final current = state[tabId] ?? TabState.$default(tabId); final current = state[tabId] ?? TabState.$default(tabId);
state = {...state}..[tabId] = current.copyWith.readerableState( state = {...state}
..[tabId] = current.copyWith.readerableState(
ReaderableState( ReaderableState(
readerable: readerable.readerable, readerable: readerable.readerable,
active: readerable.active, active: readerable.active,
@@ -112,7 +120,8 @@ class TabStates extends _$TabStates {
final result = results.last; final result = results.last;
final current = state[tabId] ?? TabState.$default(tabId); final current = state[tabId] ?? TabState.$default(tabId);
state = {...state}..[tabId] = current.copyWith.findResultState( state = {...state}
..[tabId] = current.copyWith.findResultState(
FindResultState( FindResultState(
activeMatchOrdinal: result.activeMatchOrdinal, activeMatchOrdinal: result.activeMatchOrdinal,
numberOfMatches: result.numberOfMatches, numberOfMatches: result.numberOfMatches,
@@ -127,59 +136,44 @@ class TabStates extends _$TabStates {
final eventService = ref.watch(eventServiceProvider); final eventService = ref.watch(eventServiceProvider);
final subscriptions = [ final subscriptions = [
eventService.tabContentEvents.listen( eventService.tabContentEvents.listen((event) async {
(event) async { await _lock.synchronized(() => _onTabContentStateChange(event));
await _lock.synchronized(() => _onTabContentStateChange(event)); }),
}, eventService.iconChangeEvents.listen((event) async {
), await _lock.synchronized(() => _onIconChange(event));
eventService.iconChangeEvents.listen( }),
(event) async { eventService.thumbnailEvents.listen((event) async {
await _lock.synchronized(() => _onIconChange(event)); await _lock.synchronized(() => _onThumbnailChange(event));
}, }),
), eventService.securityInfoEvents.listen((event) async {
eventService.thumbnailEvents.listen( await _lock.synchronized(() => _onSecurityInfoStateChange(event));
(event) async { }),
await _lock.synchronized(() => _onThumbnailChange(event)); eventService.historyEvents.listen((event) async {
}, await _lock.synchronized(() => _onHistoryStateChange(event));
), }),
eventService.securityInfoEvents.listen( eventService.readerableEvents.listen((event) async {
(event) async { await _lock.synchronized(() => _onReaderableStateChange(event));
await _lock.synchronized(() => _onSecurityInfoStateChange(event)); }),
}, eventService.findResultsEvent.listen((event) async {
), await _lock.synchronized(() => _onFindResultsChange(event));
eventService.historyEvents.listen( }),
(event) async {
await _lock.synchronized(() => _onHistoryStateChange(event));
},
),
eventService.readerableEvents.listen(
(event) async {
await _lock.synchronized(() => _onReaderableStateChange(event));
},
),
eventService.findResultsEvent.listen(
(event) async {
await _lock.synchronized(() => _onFindResultsChange(event));
},
),
]; ];
ref.listen( ref.listen(fireImmediately: true, engineReadyStateProvider, (
fireImmediately: true, previous,
engineReadyStateProvider, next,
(previous, next) async { ) async {
if (next) { if (next) {
await GeckoTabService().syncEvents( await GeckoTabService().syncEvents(
onTabContentStateChange: true, onTabContentStateChange: true,
onIconChange: true, onIconChange: true,
onThumbnailChange: true, onThumbnailChange: true,
onSecurityInfoStateChange: true, onSecurityInfoStateChange: true,
onHistoryStateChange: true, onHistoryStateChange: true,
onFindResults: true, onFindResults: true,
); );
} }
}, });
);
ref.onDispose(() { ref.onDispose(() {
for (final sub in subscriptions) { for (final sub in subscriptions) {
@@ -197,9 +191,7 @@ TabState? tabState(Ref ref, String? tabId) {
return null; return null;
} }
return ref.watch( return ref.watch(tabStatesProvider.select((tabs) => tabs[tabId]));
tabStatesProvider.select((tabs) => tabs[tabId]),
);
} }
@Riverpod() @Riverpod()
@@ -39,21 +39,13 @@ class TabStateFamily extends Family<TabState?> {
const TabStateFamily(); const TabStateFamily();
/// See also [tabState]. /// See also [tabState].
TabStateProvider call( TabStateProvider call(String? tabId) {
String? tabId, return TabStateProvider(tabId);
) {
return TabStateProvider(
tabId,
);
} }
@override @override
TabStateProvider getProviderOverride( TabStateProvider getProviderOverride(covariant TabStateProvider provider) {
covariant TabStateProvider provider, return call(provider.tabId);
) {
return call(
provider.tabId,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -74,23 +66,19 @@ class TabStateFamily extends Family<TabState?> {
/// See also [tabState]. /// See also [tabState].
class TabStateProvider extends AutoDisposeProvider<TabState?> { class TabStateProvider extends AutoDisposeProvider<TabState?> {
/// See also [tabState]. /// See also [tabState].
TabStateProvider( TabStateProvider(String? tabId)
String? tabId, : this._internal(
) : this._internal( (ref) => tabState(ref as TabStateRef, tabId),
(ref) => tabState( from: tabStateProvider,
ref as TabStateRef, name: r'tabStateProvider',
tabId, debugGetCreateSourceHash:
), const bool.fromEnvironment('dart.vm.product')
from: tabStateProvider, ? null
name: r'tabStateProvider', : _$tabStateHash,
debugGetCreateSourceHash: dependencies: TabStateFamily._dependencies,
const bool.fromEnvironment('dart.vm.product') allTransitiveDependencies: TabStateFamily._allTransitiveDependencies,
? null tabId: tabId,
: _$tabStateHash, );
dependencies: TabStateFamily._dependencies,
allTransitiveDependencies: TabStateFamily._allTransitiveDependencies,
tabId: tabId,
);
TabStateProvider._internal( TabStateProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -105,9 +93,7 @@ class TabStateProvider extends AutoDisposeProvider<TabState?> {
final String? tabId; final String? tabId;
@override @override
Override overrideWith( Override overrideWith(TabState? Function(TabStateRef provider) create) {
TabState? Function(TabStateRef provider) create,
) {
return ProviderOverride( return ProviderOverride(
origin: this, origin: this,
override: TabStateProvider._internal( override: TabStateProvider._internal(
@@ -163,9 +149,10 @@ String _$selectedTabStateHash() => r'dbd36af7af286bd9d079f30e8e11bbda23bf7728';
final selectedTabStateProvider = AutoDisposeProvider<TabState?>.internal( final selectedTabStateProvider = AutoDisposeProvider<TabState?>.internal(
selectedTabState, selectedTabState,
name: r'selectedTabStateProvider', name: r'selectedTabStateProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$selectedTabStateHash, ? null
: _$selectedTabStateHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -179,13 +166,15 @@ String _$tabStatesHash() => r'296d85ec016b22236b5830fce6b01cda81fbc02d';
@ProviderFor(TabStates) @ProviderFor(TabStates)
final tabStatesProvider = final tabStatesProvider =
NotifierProvider<TabStates, Map<String, TabState>>.internal( NotifierProvider<TabStates, Map<String, TabState>>.internal(
TabStates.new, TabStates.new,
name: r'tabStatesProvider', name: r'tabStatesProvider',
debugGetCreateSourceHash: debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') ? null : _$tabStatesHash, const bool.fromEnvironment('dart.vm.product')
dependencies: null, ? null
allTransitiveDependencies: null, : _$tabStatesHash,
); dependencies: null,
allTransitiveDependencies: null,
);
typedef _$TabStates = Notifier<Map<String, TabState>>; typedef _$TabStates = Notifier<Map<String, TabState>>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -23,21 +23,25 @@ class WebExtensionsState extends _$WebExtensionsState {
final ExtensionDataEvent(:extensionId, :data) = event; final ExtensionDataEvent(:extensionId, :data) = event;
if (data != null) { if (data != null) {
final current = state[extensionId] ?? final current =
state[extensionId] ??
WebExtensionState( WebExtensionState(
extensionId: extensionId, extensionId: extensionId,
icon: _imageCache[extensionId], icon: _imageCache[extensionId],
enabled: false, enabled: false,
); );
state = {...state}..[extensionId] = current.copyWith( state = {...state}
..[extensionId] = current.copyWith(
title: data.title, title: data.title,
enabled: data.enabled ?? current.enabled, enabled: data.enabled ?? current.enabled,
badgeText: data.badgeText, badgeText: data.badgeText,
badgeTextColor: badgeTextColor: data.badgeTextColor.mapNotNull(
data.badgeTextColor.mapNotNull((color) => Color(color)), (color) => Color(color),
badgeBackgroundColor: ),
data.badgeBackgroundColor.mapNotNull((color) => Color(color)), badgeBackgroundColor: data.badgeBackgroundColor.mapNotNull(
(color) => Color(color),
),
); );
} else { } else {
if (state.containsKey(extensionId)) { if (state.containsKey(extensionId)) {
@@ -49,16 +53,17 @@ class WebExtensionsState extends _$WebExtensionsState {
Future<void> _onIconChange(ExtensionIconEvent event) async { Future<void> _onIconChange(ExtensionIconEvent event) async {
final ExtensionIconEvent(:extensionId, :bytes) = event; final ExtensionIconEvent(:extensionId, :bytes) = event;
final image = final image = await tryDecodeImage(
await tryDecodeImage(bytes).then((image) async => image?.toEquatable()); bytes,
).then((image) async => image?.toEquatable());
if (image != null) { if (image != null) {
if (_imageCache[extensionId] != image) { if (_imageCache[extensionId] != image) {
_imageCache[extensionId] = image; _imageCache[extensionId] = image;
if (state.containsKey(extensionId)) { if (state.containsKey(extensionId)) {
state = {...state}..[extensionId] = state = {...state}
state[extensionId]!.copyWith.icon(image); ..[extensionId] = state[extensionId]!.copyWith.icon(image);
} }
} }
} }
@@ -70,29 +75,21 @@ class WebExtensionsState extends _$WebExtensionsState {
final subscriptions = switch (actionType) { final subscriptions = switch (actionType) {
WebExtensionActionType.browser => [ WebExtensionActionType.browser => [
addonService.browserExtensionStream.listen( addonService.browserExtensionStream.listen((event) async {
(event) async { await _lock.synchronized(() => _onExtensionUpdate(event));
await _lock.synchronized(() => _onExtensionUpdate(event)); }),
}, addonService.browserIconStream.listen((event) async {
), await _lock.synchronized(() => _onIconChange(event));
addonService.browserIconStream.listen( }),
(event) async { ],
await _lock.synchronized(() => _onIconChange(event));
},
),
],
WebExtensionActionType.page => [ WebExtensionActionType.page => [
addonService.pageExtensionStream.listen( addonService.pageExtensionStream.listen((event) async {
(event) async { await _lock.synchronized(() => _onExtensionUpdate(event));
await _lock.synchronized(() => _onExtensionUpdate(event)); }),
}, addonService.pageIconStream.listen((event) async {
), await _lock.synchronized(() => _onIconChange(event));
addonService.pageIconStream.listen( }),
(event) async { ],
await _lock.synchronized(() => _onIconChange(event));
},
),
],
}; };
ref.onDispose(() { ref.onDispose(() {
@@ -34,9 +34,7 @@ abstract class _$WebExtensionsState
extends BuildlessNotifier<Map<String, WebExtensionState>> { extends BuildlessNotifier<Map<String, WebExtensionState>> {
late final WebExtensionActionType actionType; late final WebExtensionActionType actionType;
Map<String, WebExtensionState> build( Map<String, WebExtensionState> build(WebExtensionActionType actionType);
WebExtensionActionType actionType,
);
} }
/// See also [WebExtensionsState]. /// See also [WebExtensionsState].
@@ -49,21 +47,15 @@ class WebExtensionsStateFamily extends Family<Map<String, WebExtensionState>> {
const WebExtensionsStateFamily(); const WebExtensionsStateFamily();
/// See also [WebExtensionsState]. /// See also [WebExtensionsState].
WebExtensionsStateProvider call( WebExtensionsStateProvider call(WebExtensionActionType actionType) {
WebExtensionActionType actionType, return WebExtensionsStateProvider(actionType);
) {
return WebExtensionsStateProvider(
actionType,
);
} }
@override @override
WebExtensionsStateProvider getProviderOverride( WebExtensionsStateProvider getProviderOverride(
covariant WebExtensionsStateProvider provider, covariant WebExtensionsStateProvider provider,
) { ) {
return call( return call(provider.actionType);
provider.actionType,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -82,24 +74,27 @@ class WebExtensionsStateFamily extends Family<Map<String, WebExtensionState>> {
} }
/// See also [WebExtensionsState]. /// See also [WebExtensionsState].
class WebExtensionsStateProvider extends NotifierProviderImpl< class WebExtensionsStateProvider
WebExtensionsState, Map<String, WebExtensionState>> { extends
NotifierProviderImpl<
WebExtensionsState,
Map<String, WebExtensionState>
> {
/// See also [WebExtensionsState]. /// See also [WebExtensionsState].
WebExtensionsStateProvider( WebExtensionsStateProvider(WebExtensionActionType actionType)
WebExtensionActionType actionType, : this._internal(
) : this._internal( () => WebExtensionsState()..actionType = actionType,
() => WebExtensionsState()..actionType = actionType, from: webExtensionsStateProvider,
from: webExtensionsStateProvider, name: r'webExtensionsStateProvider',
name: r'webExtensionsStateProvider', debugGetCreateSourceHash:
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
const bool.fromEnvironment('dart.vm.product') ? null
? null : _$webExtensionsStateHash,
: _$webExtensionsStateHash, dependencies: WebExtensionsStateFamily._dependencies,
dependencies: WebExtensionsStateFamily._dependencies, allTransitiveDependencies:
allTransitiveDependencies: WebExtensionsStateFamily._allTransitiveDependencies,
WebExtensionsStateFamily._allTransitiveDependencies, actionType: actionType,
actionType: actionType, );
);
WebExtensionsStateProvider._internal( WebExtensionsStateProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -117,9 +112,7 @@ class WebExtensionsStateProvider extends NotifierProviderImpl<
Map<String, WebExtensionState> runNotifierBuild( Map<String, WebExtensionState> runNotifierBuild(
covariant WebExtensionsState notifier, covariant WebExtensionsState notifier,
) { ) {
return notifier.build( return notifier.build(actionType);
actionType,
);
} }
@override @override
@@ -140,7 +133,7 @@ class WebExtensionsStateProvider extends NotifierProviderImpl<
@override @override
NotifierProviderElement<WebExtensionsState, Map<String, WebExtensionState>> NotifierProviderElement<WebExtensionsState, Map<String, WebExtensionState>>
createElement() { createElement() {
return _WebExtensionsStateProviderElement(this); return _WebExtensionsStateProviderElement(this);
} }
@@ -167,14 +160,19 @@ mixin WebExtensionsStateRef
WebExtensionActionType get actionType; WebExtensionActionType get actionType;
} }
class _WebExtensionsStateProviderElement extends NotifierProviderElement< class _WebExtensionsStateProviderElement
WebExtensionsState, extends
Map<String, WebExtensionState>> with WebExtensionsStateRef { NotifierProviderElement<
WebExtensionsState,
Map<String, WebExtensionState>
>
with WebExtensionsStateRef {
_WebExtensionsStateProviderElement(super.provider); _WebExtensionsStateProviderElement(super.provider);
@override @override
WebExtensionActionType get actionType => WebExtensionActionType get actionType =>
(origin as WebExtensionsStateProvider).actionType; (origin as WebExtensionsStateProvider).actionType;
} }
// ignore_for_file: type=lint // 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 // 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
@@ -98,16 +98,17 @@ class TabRepository extends _$TabRepository {
final db = ref.watch(tabDatabaseProvider); final db = ref.watch(tabDatabaseProvider);
final tabAddedSub = eventSerivce.tabAddedStream.listen( final tabAddedSub = eventSerivce.tabAddedStream.listen((tabId) async {
(tabId) async { final containerId = ref.read(selectedContainerProvider);
final containerId = ref.read(selectedContainerProvider); await db.tabDao.upsertUnassignedTab(
await db.tabDao tabId,
.upsertUnassignedTab(tabId, containerId: Value(containerId)); containerId: Value(containerId),
}, );
); });
final tabContentSub = final tabContentSub = tabContentService.tabContentStream.listen((
tabContentService.tabContentStream.listen((content) async { content,
) async {
await db.tabDao.updateTabContent( await db.tabDao.updateTabContent(
content.tabId, content.tabId,
isProbablyReaderable: content.isProbablyReaderable, isProbablyReaderable: content.isProbablyReaderable,
@@ -118,42 +119,33 @@ class TabRepository extends _$TabRepository {
); );
}); });
ref.listen( ref.listen(selectedTabProvider, (previous, tabId) async {
selectedTabProvider, if (tabId != null) {
(previous, tabId) async { await db.tabDao.touchTab(tabId, timestamp: DateTime.now());
if (tabId != null) { }
await db.tabDao.touchTab(tabId, timestamp: DateTime.now()); });
}
},
);
ref.listen( ref.listen(tabListProvider, (previous, next) async {
tabListProvider, //Only sync tabs if there has been a previous value or is not empty
(previous, next) async { final syncTabs = next.isNotEmpty || (previous?.isNotEmpty ?? false);
//Only sync tabs if there has been a previous value or is not empty
final syncTabs = next.isNotEmpty || (previous?.isNotEmpty ?? false);
if (syncTabs) { if (syncTabs) {
await db.tabDao.syncTabs(retainTabIds: next); await db.tabDao.syncTabs(retainTabIds: next);
} }
}, });
);
ref.listen( ref.listen(tabStatesProvider, (previous, next) async {
tabStatesProvider, //Since state changes occure pretty often and our map always contains
(previous, next) async { //the latest state, we cache the value before starting debouncing and
//Since state changes occure pretty often and our map always contains //later diff to that, to avoid frequent database writes
//the latest state, we cache the value before starting debouncing and if (!tabStateDebouncer.isDebouncing) {
//later diff to that, to avoid frequent database writes debounceStartValue = previous;
if (!tabStateDebouncer.isDebouncing) { }
debounceStartValue = previous;
}
tabStateDebouncer.eventOccured(() async { tabStateDebouncer.eventOccured(() async {
await db.tabDao.updateTabs(debounceStartValue, next); await db.tabDao.updateTabs(debounceStartValue, next);
}); });
}, });
);
ref.onDispose(() { ref.onDispose(() {
tabStateDebouncer.dispose(); tabStateDebouncer.dispose();
@@ -13,9 +13,10 @@ String _$tabRepositoryHash() => r'85af29fa18ea5a4a67fbffbb9478c801dafddac2';
final tabRepositoryProvider = NotifierProvider<TabRepository, void>.internal( final tabRepositoryProvider = NotifierProvider<TabRepository, void>.internal(
TabRepository.new, TabRepository.new,
name: r'tabRepositoryProvider', name: r'tabRepositoryProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$tabRepositoryHash, ? null
: _$tabRepositoryHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -40,15 +40,16 @@ class SelectedBangData extends _$SelectedBangData {
@override @override
BangData? build({String? domain}) { BangData? build({String? domain}) {
final repository = ref.watch(bangDataRepositoryProvider.notifier); final repository = ref.watch(bangDataRepositoryProvider.notifier);
final selectedBangTrigger = final selectedBangTrigger = ref.watch(
ref.watch(selectedBangTriggerProvider(domain: domain)); selectedBangTriggerProvider(domain: domain),
final subscription = repository.watchBang(selectedBangTrigger).listen(
(value) {
state = value;
},
); );
final subscription = repository.watchBang(selectedBangTrigger).listen((
value,
) {
state = value;
});
ref.onDispose(() { ref.onDispose(() {
unawaited(subscription.cancel()); unawaited(subscription.cancel());
}); });
@@ -111,8 +112,9 @@ EquatableCollection<List<String>> availableTabIds(
ContainerFilter containerFilter, ContainerFilter containerFilter,
) { ) {
final containerTabs = ref.watch( final containerTabs = ref.watch(
containerTabIdsProvider(containerFilter) containerTabIdsProvider(
.select((value) => value.valueOrNull), containerFilter,
).select((value) => value.valueOrNull),
); );
final tabList = ref.watch(tabListProvider); final tabList = ref.watch(tabListProvider);
@@ -130,13 +132,10 @@ EquatableCollection<Map<String, TabState>> availableTabStates(
final availableTabs = ref.watch(availableTabIdsProvider(containerFilter)); final availableTabs = ref.watch(availableTabIdsProvider(containerFilter));
final tabStates = ref.watch(tabStatesProvider); final tabStates = ref.watch(tabStatesProvider);
return EquatableCollection( return EquatableCollection({
{ for (final tabId in availableTabs.collection)
for (final tabId in availableTabs.collection) if (tabStates.containsKey(tabId)) tabId: tabStates[tabId]!,
if (tabStates.containsKey(tabId)) tabId: tabStates[tabId]!, }, immutable: true);
},
immutable: true,
);
} }
@Riverpod() @Riverpod()
@@ -145,16 +144,17 @@ EquatableCollection<List<String>> seamlessFilteredTabIds(
TabSearchPartition searchPartition, TabSearchPartition searchPartition,
ContainerFilter containerFilter, ContainerFilter containerFilter,
) { ) {
final tabSearchResults = ref final tabSearchResults =
.watch( ref
tabSearchRepositoryProvider(searchPartition).select( .watch(
(value) => EquatableCollection( tabSearchRepositoryProvider(searchPartition).select(
value.valueOrNull?.map((tab) => tab.id).toList(), (value) => EquatableCollection(
immutable: true, value.valueOrNull?.map((tab) => tab.id).toList(),
), immutable: true,
), ),
) ),
.collection; )
.collection;
final availableTabs = ref.watch(availableTabIdsProvider(containerFilter)); final availableTabs = ref.watch(availableTabIdsProvider(containerFilter));
@@ -176,19 +176,19 @@ EquatableCollection<List<TabPreview>> seamlessFilteredTabPreviews(
TabSearchPartition searchPartition, TabSearchPartition searchPartition,
ContainerFilter containerFilter, ContainerFilter containerFilter,
) { ) {
final tabSearchResults = ref final tabSearchResults =
.watch( ref
tabSearchRepositoryProvider(searchPartition).select( .watch(
(value) => EquatableCollection( tabSearchRepositoryProvider(searchPartition).select(
value.valueOrNull, (value) =>
immutable: true, EquatableCollection(value.valueOrNull, immutable: true),
), ),
), )
) .collection;
.collection;
final availableTabStates = final availableTabStates = ref.watch(
ref.watch(availableTabStatesProvider(containerFilter)); availableTabStatesProvider(containerFilter),
);
if (tabSearchResults == null) { if (tabSearchResults == null) {
return EquatableCollection( return EquatableCollection(
@@ -216,7 +216,8 @@ EquatableCollection<List<TabPreview>> seamlessFilteredTabPreviews(
id: tab.id, id: tab.id,
title: tab.title ?? availableTabStates.collection[tab.id]!.title, title: tab.title ?? availableTabStates.collection[tab.id]!.title,
icon: null, icon: null,
url: tab.cleanUrl.mapNotNull(Uri.tryParse) ?? url:
tab.cleanUrl.mapNotNull(Uri.tryParse) ??
availableTabStates.collection[tab.id]!.url, availableTabStates.collection[tab.id]!.url,
highlightedUrl: tab.url, highlightedUrl: tab.url,
content: tab.extractedContent ?? tab.fullContent, content: tab.extractedContent ?? tab.fullContent,
@@ -39,21 +39,15 @@ class AvailableTabIdsFamily extends Family<EquatableCollection<List<String>>> {
const AvailableTabIdsFamily(); const AvailableTabIdsFamily();
/// See also [availableTabIds]. /// See also [availableTabIds].
AvailableTabIdsProvider call( AvailableTabIdsProvider call(ContainerFilter containerFilter) {
ContainerFilter containerFilter, return AvailableTabIdsProvider(containerFilter);
) {
return AvailableTabIdsProvider(
containerFilter,
);
} }
@override @override
AvailableTabIdsProvider getProviderOverride( AvailableTabIdsProvider getProviderOverride(
covariant AvailableTabIdsProvider provider, covariant AvailableTabIdsProvider provider,
) { ) {
return call( return call(provider.containerFilter);
provider.containerFilter,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -75,24 +69,20 @@ class AvailableTabIdsFamily extends Family<EquatableCollection<List<String>>> {
class AvailableTabIdsProvider class AvailableTabIdsProvider
extends AutoDisposeProvider<EquatableCollection<List<String>>> { extends AutoDisposeProvider<EquatableCollection<List<String>>> {
/// See also [availableTabIds]. /// See also [availableTabIds].
AvailableTabIdsProvider( AvailableTabIdsProvider(ContainerFilter containerFilter)
ContainerFilter containerFilter, : this._internal(
) : this._internal( (ref) => availableTabIds(ref as AvailableTabIdsRef, containerFilter),
(ref) => availableTabIds( from: availableTabIdsProvider,
ref as AvailableTabIdsRef, name: r'availableTabIdsProvider',
containerFilter, debugGetCreateSourceHash:
), const bool.fromEnvironment('dart.vm.product')
from: availableTabIdsProvider, ? null
name: r'availableTabIdsProvider', : _$availableTabIdsHash,
debugGetCreateSourceHash: dependencies: AvailableTabIdsFamily._dependencies,
const bool.fromEnvironment('dart.vm.product') allTransitiveDependencies:
? null AvailableTabIdsFamily._allTransitiveDependencies,
: _$availableTabIdsHash, containerFilter: containerFilter,
dependencies: AvailableTabIdsFamily._dependencies, );
allTransitiveDependencies:
AvailableTabIdsFamily._allTransitiveDependencies,
containerFilter: containerFilter,
);
AvailableTabIdsProvider._internal( AvailableTabIdsProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -109,7 +99,7 @@ class AvailableTabIdsProvider
@override @override
Override overrideWith( Override overrideWith(
EquatableCollection<List<String>> Function(AvailableTabIdsRef provider) EquatableCollection<List<String>> Function(AvailableTabIdsRef provider)
create, create,
) { ) {
return ProviderOverride( return ProviderOverride(
origin: this, origin: this,
@@ -127,7 +117,7 @@ class AvailableTabIdsProvider
@override @override
AutoDisposeProviderElement<EquatableCollection<List<String>>> AutoDisposeProviderElement<EquatableCollection<List<String>>>
createElement() { createElement() {
return _AvailableTabIdsProviderElement(this); return _AvailableTabIdsProviderElement(this);
} }
@@ -178,21 +168,15 @@ class AvailableTabStatesFamily
const AvailableTabStatesFamily(); const AvailableTabStatesFamily();
/// See also [availableTabStates]. /// See also [availableTabStates].
AvailableTabStatesProvider call( AvailableTabStatesProvider call(ContainerFilter containerFilter) {
ContainerFilter containerFilter, return AvailableTabStatesProvider(containerFilter);
) {
return AvailableTabStatesProvider(
containerFilter,
);
} }
@override @override
AvailableTabStatesProvider getProviderOverride( AvailableTabStatesProvider getProviderOverride(
covariant AvailableTabStatesProvider provider, covariant AvailableTabStatesProvider provider,
) { ) {
return call( return call(provider.containerFilter);
provider.containerFilter,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -214,24 +198,21 @@ class AvailableTabStatesFamily
class AvailableTabStatesProvider class AvailableTabStatesProvider
extends AutoDisposeProvider<EquatableCollection<Map<String, TabState>>> { extends AutoDisposeProvider<EquatableCollection<Map<String, TabState>>> {
/// See also [availableTabStates]. /// See also [availableTabStates].
AvailableTabStatesProvider( AvailableTabStatesProvider(ContainerFilter containerFilter)
ContainerFilter containerFilter, : this._internal(
) : this._internal( (ref) =>
(ref) => availableTabStates( availableTabStates(ref as AvailableTabStatesRef, containerFilter),
ref as AvailableTabStatesRef, from: availableTabStatesProvider,
containerFilter, name: r'availableTabStatesProvider',
), debugGetCreateSourceHash:
from: availableTabStatesProvider, const bool.fromEnvironment('dart.vm.product')
name: r'availableTabStatesProvider', ? null
debugGetCreateSourceHash: : _$availableTabStatesHash,
const bool.fromEnvironment('dart.vm.product') dependencies: AvailableTabStatesFamily._dependencies,
? null allTransitiveDependencies:
: _$availableTabStatesHash, AvailableTabStatesFamily._allTransitiveDependencies,
dependencies: AvailableTabStatesFamily._dependencies, containerFilter: containerFilter,
allTransitiveDependencies: );
AvailableTabStatesFamily._allTransitiveDependencies,
containerFilter: containerFilter,
);
AvailableTabStatesProvider._internal( AvailableTabStatesProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -248,8 +229,9 @@ class AvailableTabStatesProvider
@override @override
Override overrideWith( Override overrideWith(
EquatableCollection<Map<String, TabState>> Function( EquatableCollection<Map<String, TabState>> Function(
AvailableTabStatesRef provider) AvailableTabStatesRef provider,
create, )
create,
) { ) {
return ProviderOverride( return ProviderOverride(
origin: this, origin: this,
@@ -267,7 +249,7 @@ class AvailableTabStatesProvider
@override @override
AutoDisposeProviderElement<EquatableCollection<Map<String, TabState>>> AutoDisposeProviderElement<EquatableCollection<Map<String, TabState>>>
createElement() { createElement() {
return _AvailableTabStatesProviderElement(this); return _AvailableTabStatesProviderElement(this);
} }
@@ -294,8 +276,10 @@ mixin AvailableTabStatesRef
ContainerFilter get containerFilter; ContainerFilter get containerFilter;
} }
class _AvailableTabStatesProviderElement extends AutoDisposeProviderElement< class _AvailableTabStatesProviderElement
EquatableCollection<Map<String, TabState>>> with AvailableTabStatesRef { extends
AutoDisposeProviderElement<EquatableCollection<Map<String, TabState>>>
with AvailableTabStatesRef {
_AvailableTabStatesProviderElement(super.provider); _AvailableTabStatesProviderElement(super.provider);
@override @override
@@ -321,20 +305,14 @@ class SeamlessFilteredTabIdsFamily
TabSearchPartition searchPartition, TabSearchPartition searchPartition,
ContainerFilter containerFilter, ContainerFilter containerFilter,
) { ) {
return SeamlessFilteredTabIdsProvider( return SeamlessFilteredTabIdsProvider(searchPartition, containerFilter);
searchPartition,
containerFilter,
);
} }
@override @override
SeamlessFilteredTabIdsProvider getProviderOverride( SeamlessFilteredTabIdsProvider getProviderOverride(
covariant SeamlessFilteredTabIdsProvider provider, covariant SeamlessFilteredTabIdsProvider provider,
) { ) {
return call( return call(provider.searchPartition, provider.containerFilter);
provider.searchPartition,
provider.containerFilter,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -360,23 +338,23 @@ class SeamlessFilteredTabIdsProvider
TabSearchPartition searchPartition, TabSearchPartition searchPartition,
ContainerFilter containerFilter, ContainerFilter containerFilter,
) : this._internal( ) : this._internal(
(ref) => seamlessFilteredTabIds( (ref) => seamlessFilteredTabIds(
ref as SeamlessFilteredTabIdsRef, ref as SeamlessFilteredTabIdsRef,
searchPartition, searchPartition,
containerFilter, containerFilter,
), ),
from: seamlessFilteredTabIdsProvider, from: seamlessFilteredTabIdsProvider,
name: r'seamlessFilteredTabIdsProvider', name: r'seamlessFilteredTabIdsProvider',
debugGetCreateSourceHash: debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') const bool.fromEnvironment('dart.vm.product')
? null ? null
: _$seamlessFilteredTabIdsHash, : _$seamlessFilteredTabIdsHash,
dependencies: SeamlessFilteredTabIdsFamily._dependencies, dependencies: SeamlessFilteredTabIdsFamily._dependencies,
allTransitiveDependencies: allTransitiveDependencies:
SeamlessFilteredTabIdsFamily._allTransitiveDependencies, SeamlessFilteredTabIdsFamily._allTransitiveDependencies,
searchPartition: searchPartition, searchPartition: searchPartition,
containerFilter: containerFilter, containerFilter: containerFilter,
); );
SeamlessFilteredTabIdsProvider._internal( SeamlessFilteredTabIdsProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -395,8 +373,9 @@ class SeamlessFilteredTabIdsProvider
@override @override
Override overrideWith( Override overrideWith(
EquatableCollection<List<String>> Function( EquatableCollection<List<String>> Function(
SeamlessFilteredTabIdsRef provider) SeamlessFilteredTabIdsRef provider,
create, )
create,
) { ) {
return ProviderOverride( return ProviderOverride(
origin: this, origin: this,
@@ -415,7 +394,7 @@ class SeamlessFilteredTabIdsProvider
@override @override
AutoDisposeProviderElement<EquatableCollection<List<String>>> AutoDisposeProviderElement<EquatableCollection<List<String>>>
createElement() { createElement() {
return _SeamlessFilteredTabIdsProviderElement(this); return _SeamlessFilteredTabIdsProviderElement(this);
} }
@@ -488,10 +467,7 @@ class SeamlessFilteredTabPreviewsFamily
SeamlessFilteredTabPreviewsProvider getProviderOverride( SeamlessFilteredTabPreviewsProvider getProviderOverride(
covariant SeamlessFilteredTabPreviewsProvider provider, covariant SeamlessFilteredTabPreviewsProvider provider,
) { ) {
return call( return call(provider.searchPartition, provider.containerFilter);
provider.searchPartition,
provider.containerFilter,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -517,23 +493,23 @@ class SeamlessFilteredTabPreviewsProvider
TabSearchPartition searchPartition, TabSearchPartition searchPartition,
ContainerFilter containerFilter, ContainerFilter containerFilter,
) : this._internal( ) : this._internal(
(ref) => seamlessFilteredTabPreviews( (ref) => seamlessFilteredTabPreviews(
ref as SeamlessFilteredTabPreviewsRef, ref as SeamlessFilteredTabPreviewsRef,
searchPartition, searchPartition,
containerFilter, containerFilter,
), ),
from: seamlessFilteredTabPreviewsProvider, from: seamlessFilteredTabPreviewsProvider,
name: r'seamlessFilteredTabPreviewsProvider', name: r'seamlessFilteredTabPreviewsProvider',
debugGetCreateSourceHash: debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product') const bool.fromEnvironment('dart.vm.product')
? null ? null
: _$seamlessFilteredTabPreviewsHash, : _$seamlessFilteredTabPreviewsHash,
dependencies: SeamlessFilteredTabPreviewsFamily._dependencies, dependencies: SeamlessFilteredTabPreviewsFamily._dependencies,
allTransitiveDependencies: allTransitiveDependencies:
SeamlessFilteredTabPreviewsFamily._allTransitiveDependencies, SeamlessFilteredTabPreviewsFamily._allTransitiveDependencies,
searchPartition: searchPartition, searchPartition: searchPartition,
containerFilter: containerFilter, containerFilter: containerFilter,
); );
SeamlessFilteredTabPreviewsProvider._internal( SeamlessFilteredTabPreviewsProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -552,8 +528,9 @@ class SeamlessFilteredTabPreviewsProvider
@override @override
Override overrideWith( Override overrideWith(
EquatableCollection<List<TabPreview>> Function( EquatableCollection<List<TabPreview>> Function(
SeamlessFilteredTabPreviewsRef provider) SeamlessFilteredTabPreviewsRef provider,
create, )
create,
) { ) {
return ProviderOverride( return ProviderOverride(
origin: this, origin: this,
@@ -572,7 +549,7 @@ class SeamlessFilteredTabPreviewsProvider
@override @override
AutoDisposeProviderElement<EquatableCollection<List<TabPreview>>> AutoDisposeProviderElement<EquatableCollection<List<TabPreview>>>
createElement() { createElement() {
return _SeamlessFilteredTabPreviewsProviderElement(this); return _SeamlessFilteredTabPreviewsProviderElement(this);
} }
@@ -623,9 +600,7 @@ String _$selectedBangTriggerHash() =>
abstract class _$SelectedBangTrigger extends BuildlessNotifier<String?> { abstract class _$SelectedBangTrigger extends BuildlessNotifier<String?> {
late final String? domain; late final String? domain;
String? build({ String? build({String? domain});
String? domain,
});
} }
/// See also [SelectedBangTrigger]. /// See also [SelectedBangTrigger].
@@ -638,21 +613,15 @@ class SelectedBangTriggerFamily extends Family<String?> {
const SelectedBangTriggerFamily(); const SelectedBangTriggerFamily();
/// See also [SelectedBangTrigger]. /// See also [SelectedBangTrigger].
SelectedBangTriggerProvider call({ SelectedBangTriggerProvider call({String? domain}) {
String? domain, return SelectedBangTriggerProvider(domain: domain);
}) {
return SelectedBangTriggerProvider(
domain: domain,
);
} }
@override @override
SelectedBangTriggerProvider getProviderOverride( SelectedBangTriggerProvider getProviderOverride(
covariant SelectedBangTriggerProvider provider, covariant SelectedBangTriggerProvider provider,
) { ) {
return call( return call(domain: provider.domain);
domain: provider.domain,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -674,21 +643,20 @@ class SelectedBangTriggerFamily extends Family<String?> {
class SelectedBangTriggerProvider class SelectedBangTriggerProvider
extends NotifierProviderImpl<SelectedBangTrigger, String?> { extends NotifierProviderImpl<SelectedBangTrigger, String?> {
/// See also [SelectedBangTrigger]. /// See also [SelectedBangTrigger].
SelectedBangTriggerProvider({ SelectedBangTriggerProvider({String? domain})
String? domain, : this._internal(
}) : this._internal( () => SelectedBangTrigger()..domain = domain,
() => SelectedBangTrigger()..domain = domain, from: selectedBangTriggerProvider,
from: selectedBangTriggerProvider, name: r'selectedBangTriggerProvider',
name: r'selectedBangTriggerProvider', debugGetCreateSourceHash:
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
const bool.fromEnvironment('dart.vm.product') ? null
? null : _$selectedBangTriggerHash,
: _$selectedBangTriggerHash, dependencies: SelectedBangTriggerFamily._dependencies,
dependencies: SelectedBangTriggerFamily._dependencies, allTransitiveDependencies:
allTransitiveDependencies: SelectedBangTriggerFamily._allTransitiveDependencies,
SelectedBangTriggerFamily._allTransitiveDependencies, domain: domain,
domain: domain, );
);
SelectedBangTriggerProvider._internal( SelectedBangTriggerProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -703,12 +671,8 @@ class SelectedBangTriggerProvider
final String? domain; final String? domain;
@override @override
String? runNotifierBuild( String? runNotifierBuild(covariant SelectedBangTrigger notifier) {
covariant SelectedBangTrigger notifier, return notifier.build(domain: domain);
) {
return notifier.build(
domain: domain,
);
} }
@override @override
@@ -768,9 +732,7 @@ abstract class _$SelectedBangData
extends BuildlessAutoDisposeNotifier<BangData?> { extends BuildlessAutoDisposeNotifier<BangData?> {
late final String? domain; late final String? domain;
BangData? build({ BangData? build({String? domain});
String? domain,
});
} }
/// See also [SelectedBangData]. /// See also [SelectedBangData].
@@ -783,21 +745,15 @@ class SelectedBangDataFamily extends Family<BangData?> {
const SelectedBangDataFamily(); const SelectedBangDataFamily();
/// See also [SelectedBangData]. /// See also [SelectedBangData].
SelectedBangDataProvider call({ SelectedBangDataProvider call({String? domain}) {
String? domain, return SelectedBangDataProvider(domain: domain);
}) {
return SelectedBangDataProvider(
domain: domain,
);
} }
@override @override
SelectedBangDataProvider getProviderOverride( SelectedBangDataProvider getProviderOverride(
covariant SelectedBangDataProvider provider, covariant SelectedBangDataProvider provider,
) { ) {
return call( return call(domain: provider.domain);
domain: provider.domain,
);
} }
static const Iterable<ProviderOrFamily>? _dependencies = null; static const Iterable<ProviderOrFamily>? _dependencies = null;
@@ -819,21 +775,20 @@ class SelectedBangDataFamily extends Family<BangData?> {
class SelectedBangDataProvider class SelectedBangDataProvider
extends AutoDisposeNotifierProviderImpl<SelectedBangData, BangData?> { extends AutoDisposeNotifierProviderImpl<SelectedBangData, BangData?> {
/// See also [SelectedBangData]. /// See also [SelectedBangData].
SelectedBangDataProvider({ SelectedBangDataProvider({String? domain})
String? domain, : this._internal(
}) : this._internal( () => SelectedBangData()..domain = domain,
() => SelectedBangData()..domain = domain, from: selectedBangDataProvider,
from: selectedBangDataProvider, name: r'selectedBangDataProvider',
name: r'selectedBangDataProvider', debugGetCreateSourceHash:
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
const bool.fromEnvironment('dart.vm.product') ? null
? null : _$selectedBangDataHash,
: _$selectedBangDataHash, dependencies: SelectedBangDataFamily._dependencies,
dependencies: SelectedBangDataFamily._dependencies, allTransitiveDependencies:
allTransitiveDependencies: SelectedBangDataFamily._allTransitiveDependencies,
SelectedBangDataFamily._allTransitiveDependencies, domain: domain,
domain: domain, );
);
SelectedBangDataProvider._internal( SelectedBangDataProvider._internal(
super._createNotifier, { super._createNotifier, {
@@ -848,12 +803,8 @@ class SelectedBangDataProvider
final String? domain; final String? domain;
@override @override
BangData? runNotifierBuild( BangData? runNotifierBuild(covariant SelectedBangData notifier) {
covariant SelectedBangData notifier, return notifier.build(domain: domain);
) {
return notifier.build(
domain: domain,
);
} }
@override @override
@@ -874,7 +825,7 @@ class SelectedBangDataProvider
@override @override
AutoDisposeNotifierProviderElement<SelectedBangData, BangData?> AutoDisposeNotifierProviderElement<SelectedBangData, BangData?>
createElement() { createElement() {
return _SelectedBangDataProviderElement(this); return _SelectedBangDataProviderElement(this);
} }
@@ -915,14 +866,15 @@ String _$lastUsedAssistantModeHash() =>
@ProviderFor(LastUsedAssistantMode) @ProviderFor(LastUsedAssistantMode)
final lastUsedAssistantModeProvider = final lastUsedAssistantModeProvider =
NotifierProvider<LastUsedAssistantMode, AssistantMode>.internal( NotifierProvider<LastUsedAssistantMode, AssistantMode>.internal(
LastUsedAssistantMode.new, LastUsedAssistantMode.new,
name: r'lastUsedAssistantModeProvider', name: r'lastUsedAssistantModeProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$lastUsedAssistantModeHash, ? null
dependencies: null, : _$lastUsedAssistantModeHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$LastUsedAssistantMode = Notifier<AssistantMode>; typedef _$LastUsedAssistantMode = Notifier<AssistantMode>;
String _$activeResearchVariantHash() => String _$activeResearchVariantHash() =>
@@ -932,14 +884,15 @@ String _$activeResearchVariantHash() =>
@ProviderFor(ActiveResearchVariant) @ProviderFor(ActiveResearchVariant)
final activeResearchVariantProvider = final activeResearchVariantProvider =
NotifierProvider<ActiveResearchVariant, ResearchVariant>.internal( NotifierProvider<ActiveResearchVariant, ResearchVariant>.internal(
ActiveResearchVariant.new, ActiveResearchVariant.new,
name: r'activeResearchVariantProvider', name: r'activeResearchVariantProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$activeResearchVariantHash, ? null
dependencies: null, : _$activeResearchVariantHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$ActiveResearchVariant = Notifier<ResearchVariant>; typedef _$ActiveResearchVariant = Notifier<ResearchVariant>;
String _$activeChatModelHash() => r'675f406af8b4aa92699d59e37b5805a81d03a799'; String _$activeChatModelHash() => r'675f406af8b4aa92699d59e37b5805a81d03a799';
@@ -948,14 +901,15 @@ String _$activeChatModelHash() => r'675f406af8b4aa92699d59e37b5805a81d03a799';
@ProviderFor(ActiveChatModel) @ProviderFor(ActiveChatModel)
final activeChatModelProvider = final activeChatModelProvider =
NotifierProvider<ActiveChatModel, ChatModel>.internal( NotifierProvider<ActiveChatModel, ChatModel>.internal(
ActiveChatModel.new, ActiveChatModel.new,
name: r'activeChatModelProvider', name: r'activeChatModelProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$activeChatModelHash, ? null
dependencies: null, : _$activeChatModelHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$ActiveChatModel = Notifier<ChatModel>; typedef _$ActiveChatModel = Notifier<ChatModel>;
String _$showFindInPageHash() => r'7ee5703f7d0c7e8a8dd6b0849d7b1e0a41fe24d9'; String _$showFindInPageHash() => r'7ee5703f7d0c7e8a8dd6b0849d7b1e0a41fe24d9';
@@ -965,9 +919,10 @@ String _$showFindInPageHash() => r'7ee5703f7d0c7e8a8dd6b0849d7b1e0a41fe24d9';
final showFindInPageProvider = NotifierProvider<ShowFindInPage, bool>.internal( final showFindInPageProvider = NotifierProvider<ShowFindInPage, bool>.internal(
ShowFindInPage.new, ShowFindInPage.new,
name: r'showFindInPageProvider', name: r'showFindInPageProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$showFindInPageHash, ? null
: _$showFindInPageHash,
dependencies: null, dependencies: null,
allTransitiveDependencies: null, allTransitiveDependencies: null,
); );
@@ -13,18 +13,19 @@ part 'create_tab.g.dart';
final _parameterToCreateTabSheetTransformer = final _parameterToCreateTabSheetTransformer =
StreamTransformer<ReceivedParameter, CreateTabSheet>.fromHandlers( StreamTransformer<ReceivedParameter, CreateTabSheet>.fromHandlers(
handleData: (parameter, sink) { handleData: (parameter, sink) {
final createTab = CreateTabSheet( final createTab = CreateTabSheet(
preferredTool: KagiTool.values preferredTool: KagiTool.values.firstWhereOrNull(
.firstWhereOrNull((tool) => tool.name == parameter.tool), (tool) => tool.name == parameter.tool,
content: parameter.content, ),
); content: parameter.content,
);
if (createTab.hasParameters) { if (createTab.hasParameters) {
sink.add(createTab); sink.add(createTab);
} }
}, },
); );
@Riverpod() @Riverpod()
class CreateTabStream extends _$CreateTabStream { class CreateTabStream extends _$CreateTabStream {
@@ -12,14 +12,15 @@ String _$createTabStreamHash() => r'2e802a10ecaf1862074f32b76e89c26997bdd7b2';
@ProviderFor(CreateTabStream) @ProviderFor(CreateTabStream)
final createTabStreamProvider = final createTabStreamProvider =
AutoDisposeStreamNotifierProvider<CreateTabStream, CreateTabSheet>.internal( AutoDisposeStreamNotifierProvider<CreateTabStream, CreateTabSheet>.internal(
CreateTabStream.new, CreateTabStream.new,
name: r'createTabStreamProvider', name: r'createTabStreamProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$createTabStreamHash, ? null
dependencies: null, : _$createTabStreamHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$CreateTabStream = AutoDisposeStreamNotifier<CreateTabSheet>; typedef _$CreateTabStream = AutoDisposeStreamNotifier<CreateTabSheet>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -13,14 +13,15 @@ String _$deleteBrowserDataServiceHash() =>
@ProviderFor(DeleteBrowserDataService) @ProviderFor(DeleteBrowserDataService)
final deleteBrowserDataServiceProvider = final deleteBrowserDataServiceProvider =
AutoDisposeNotifierProvider<DeleteBrowserDataService, void>.internal( AutoDisposeNotifierProvider<DeleteBrowserDataService, void>.internal(
DeleteBrowserDataService.new, DeleteBrowserDataService.new,
name: r'deleteBrowserDataServiceProvider', name: r'deleteBrowserDataServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$deleteBrowserDataServiceHash, ? null
dependencies: null, : _$deleteBrowserDataServiceHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$DeleteBrowserDataService = AutoDisposeNotifier<void>; typedef _$DeleteBrowserDataService = AutoDisposeNotifier<void>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -16,8 +16,9 @@ class EngineSettingsReplicationService
var initialSettingsSent = false; var initialSettingsSent = false;
ref.listen( ref.listen(
generalSettingsRepositoryProvider generalSettingsRepositoryProvider.select(
.select((settings) => settings.themeMode), (settings) => settings.themeMode,
),
(previous, next) async { (previous, next) async {
final theme = switch (next) { final theme = switch (next) {
ThemeMode.system => ColorScheme.system, ThemeMode.system => ColorScheme.system,
@@ -29,62 +30,63 @@ class EngineSettingsReplicationService
}, },
); );
ref.listen( ref.listen(engineSettingsRepositoryProvider, (previous, next) async {
engineSettingsRepositoryProvider, if (initialSettingsSent && previous != null) {
(previous, next) async { if (previous.javascriptEnabled != next.javascriptEnabled) {
if (initialSettingsSent && previous != null) { await _service.javascriptEnabled(next.javascriptEnabled);
if (previous.javascriptEnabled != next.javascriptEnabled) {
await _service.javascriptEnabled(next.javascriptEnabled);
}
if (previous.trackingProtectionPolicy !=
next.trackingProtectionPolicy) {
await _service
.trackingProtectionPolicy(next.trackingProtectionPolicy);
}
if (previous.httpsOnlyMode != next.httpsOnlyMode) {
await _service.httpsOnlyMode(next.httpsOnlyMode);
}
if (previous.globalPrivacyControlEnabled !=
next.globalPrivacyControlEnabled) {
await _service
.globalPrivacyControlEnabled(next.globalPrivacyControlEnabled);
}
if (previous.preferredColorScheme != next.preferredColorScheme) {
await _service.preferredColorScheme(next.preferredColorScheme);
}
if (previous.cookieBannerHandlingMode !=
next.cookieBannerHandlingMode) {
await _service
.cookieBannerHandlingMode(next.cookieBannerHandlingMode);
}
if (previous.cookieBannerHandlingModePrivateBrowsing !=
next.cookieBannerHandlingModePrivateBrowsing) {
await _service.cookieBannerHandlingModePrivateBrowsing(
next.cookieBannerHandlingModePrivateBrowsing,
);
}
if (previous.cookieBannerHandlingGlobalRules !=
next.cookieBannerHandlingGlobalRules) {
await _service.cookieBannerHandlingGlobalRules(
next.cookieBannerHandlingGlobalRules,
);
}
if (previous.cookieBannerHandlingGlobalRulesSubFrames !=
next.cookieBannerHandlingGlobalRulesSubFrames) {
await _service.cookieBannerHandlingGlobalRulesSubFrames(
next.cookieBannerHandlingGlobalRulesSubFrames,
);
}
if (previous.webContentIsolationStrategy !=
next.webContentIsolationStrategy) {
await _service
.webContentIsolationStrategy(next.webContentIsolationStrategy);
}
} else {
await _service.setDefaultSettings(next);
initialSettingsSent = true;
} }
}, if (previous.trackingProtectionPolicy !=
); next.trackingProtectionPolicy) {
await _service.trackingProtectionPolicy(
next.trackingProtectionPolicy,
);
}
if (previous.httpsOnlyMode != next.httpsOnlyMode) {
await _service.httpsOnlyMode(next.httpsOnlyMode);
}
if (previous.globalPrivacyControlEnabled !=
next.globalPrivacyControlEnabled) {
await _service.globalPrivacyControlEnabled(
next.globalPrivacyControlEnabled,
);
}
if (previous.preferredColorScheme != next.preferredColorScheme) {
await _service.preferredColorScheme(next.preferredColorScheme);
}
if (previous.cookieBannerHandlingMode !=
next.cookieBannerHandlingMode) {
await _service.cookieBannerHandlingMode(
next.cookieBannerHandlingMode,
);
}
if (previous.cookieBannerHandlingModePrivateBrowsing !=
next.cookieBannerHandlingModePrivateBrowsing) {
await _service.cookieBannerHandlingModePrivateBrowsing(
next.cookieBannerHandlingModePrivateBrowsing,
);
}
if (previous.cookieBannerHandlingGlobalRules !=
next.cookieBannerHandlingGlobalRules) {
await _service.cookieBannerHandlingGlobalRules(
next.cookieBannerHandlingGlobalRules,
);
}
if (previous.cookieBannerHandlingGlobalRulesSubFrames !=
next.cookieBannerHandlingGlobalRulesSubFrames) {
await _service.cookieBannerHandlingGlobalRulesSubFrames(
next.cookieBannerHandlingGlobalRulesSubFrames,
);
}
if (previous.webContentIsolationStrategy !=
next.webContentIsolationStrategy) {
await _service.webContentIsolationStrategy(
next.webContentIsolationStrategy,
);
}
} else {
await _service.setDefaultSettings(next);
initialSettingsSent = true;
}
});
} }
} }
@@ -13,14 +13,15 @@ String _$engineSettingsReplicationServiceHash() =>
@ProviderFor(EngineSettingsReplicationService) @ProviderFor(EngineSettingsReplicationService)
final engineSettingsReplicationServiceProvider = final engineSettingsReplicationServiceProvider =
NotifierProvider<EngineSettingsReplicationService, void>.internal( NotifierProvider<EngineSettingsReplicationService, void>.internal(
EngineSettingsReplicationService.new, EngineSettingsReplicationService.new,
name: r'engineSettingsReplicationServiceProvider', name: r'engineSettingsReplicationServiceProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$engineSettingsReplicationServiceHash, ? null
dependencies: null, : _$engineSettingsReplicationServiceHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$EngineSettingsReplicationService = Notifier<void>; typedef _$EngineSettingsReplicationService = Notifier<void>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -12,14 +12,14 @@ class ProxySettingsReplucation extends _$ProxySettingsReplucation {
@override @override
void build() { void build() {
ref.listen( ref.listen(torProxyServiceProvider.select((data) => data.valueOrNull), (
torProxyServiceProvider.select((data) => data.valueOrNull), previous,
(previous, next) async { next,
if (next != null) { ) async {
await _service.setProxyPort(next); if (next != null) {
} await _service.setProxyPort(next);
}, }
); });
ref.listen( ref.listen(
containersWithCountProvider.select( containersWithCountProvider.select(
@@ -13,14 +13,15 @@ String _$proxySettingsReplucationHash() =>
@ProviderFor(ProxySettingsReplucation) @ProviderFor(ProxySettingsReplucation)
final proxySettingsReplucationProvider = final proxySettingsReplucationProvider =
NotifierProvider<ProxySettingsReplucation, void>.internal( NotifierProvider<ProxySettingsReplucation, void>.internal(
ProxySettingsReplucation.new, ProxySettingsReplucation.new,
name: r'proxySettingsReplucationProvider', name: r'proxySettingsReplucationProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') debugGetCreateSourceHash:
? null const bool.fromEnvironment('dart.vm.product')
: _$proxySettingsReplucationHash, ? null
dependencies: null, : _$proxySettingsReplucationHash,
allTransitiveDependencies: null, dependencies: null,
); allTransitiveDependencies: null,
);
typedef _$ProxySettingsReplucation = Notifier<void>; typedef _$ProxySettingsReplucation = Notifier<void>;
// ignore_for_file: type=lint // ignore_for_file: type=lint
@@ -36,11 +36,7 @@ class WebPageDialog extends HookConsumerWidget {
final Uri url; final Uri url;
final WebPageInfo? precachedInfo; final WebPageInfo? precachedInfo;
const WebPageDialog({ const WebPageDialog({required this.url, this.precachedInfo, super.key});
required this.url,
this.precachedInfo,
super.key,
});
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
@@ -63,8 +59,10 @@ class WebPageDialog extends HookConsumerWidget {
context: context, context: context,
removeBottom: true, removeBottom: true,
child: Dialog( child: Dialog(
insetPadding: insetPadding: const EdgeInsets.symmetric(
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 64.0), horizontal: 16.0,
vertical: 64.0,
),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@@ -79,26 +77,24 @@ class WebPageDialog extends HookConsumerWidget {
padding: const EdgeInsets.symmetric(horizontal: 16.0), padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: HookConsumer( child: HookConsumer(
builder: (context, ref, child) { builder: (context, ref, child) {
final addressTextController = final addressTextController = useTextEditingController(
useTextEditingController(text: url.toString()); text: url.toString(),
);
final addressTextFocusNode = useFocusNode(); final addressTextFocusNode = useFocusNode();
final suggestion = useState<String?>(null); final suggestion = useState<String?>(null);
useListenableCallback( useListenableCallback(addressTextController, () async {
addressTextController, if (addressTextController.text.isNotEmpty) {
() async { final result = await ref
if (addressTextController.text.isNotEmpty) { .read(engineSuggestionsProvider.notifier)
final result = await ref .getAutocompleteSuggestion(
.read(engineSuggestionsProvider.notifier) addressTextController.text,
.getAutocompleteSuggestion( );
addressTextController.text,
);
suggestion.value = result; suggestion.value = result;
} }
}, });
);
return AutoSuggestTextField( return AutoSuggestTextField(
controller: addressTextController, controller: addressTextController,
@@ -121,12 +117,15 @@ class WebPageDialog extends HookConsumerWidget {
}, },
onSubmitted: (value) async { onSubmitted: (value) async {
if (value.isNotEmpty) { if (value.isNotEmpty) {
var newUrl = var newUrl = uri_parser.tryParseUrl(
uri_parser.tryParseUrl(value, eagerParsing: true); value,
eagerParsing: true,
);
if (newUrl == null) { if (newUrl == null) {
final defaultSearchBang = await ref final defaultSearchBang = await ref.read(
.read(defaultSearchBangDataProvider.future); defaultSearchBangDataProvider.future,
);
newUrl = defaultSearchBang?.getUrl(value); newUrl = defaultSearchBang?.getUrl(value);
} }
@@ -147,9 +146,7 @@ class WebPageDialog extends HookConsumerWidget {
), ),
), ),
), ),
const SizedBox( const SizedBox(height: 4),
height: 4,
),
const Divider(), const Divider(),
Flexible( Flexible(
child: FadingScroll( child: FadingScroll(
@@ -173,21 +170,23 @@ class WebPageDialog extends HookConsumerWidget {
availableBangs: availableBangs, availableBangs: availableBangs,
); );
}, },
error: (error, stackTrace) => FailureWidget( error:
title: 'Could not load bangs', (error, stackTrace) => FailureWidget(
exception: error, title: 'Could not load bangs',
), exception: error,
loading: () => SiteSearch( ),
domain: url.host, loading:
availableBangs: [ () => SiteSearch(
BangData( domain: url.host,
websiteName: 'websiteName', availableBangs: [
domain: 'domain', BangData(
trigger: 'trigger', websiteName: 'websiteName',
urlTemplate: 'urlTemplate', domain: 'domain',
trigger: 'trigger',
urlTemplate: 'urlTemplate',
),
],
), ),
],
),
), ),
), ),
if (availableBangsAsync.isLoading || if (availableBangsAsync.isLoading ||
@@ -241,31 +240,30 @@ class WebPageDialog extends HookConsumerWidget {
leading: const Icon(Icons.mobile_screen_share), leading: const Icon(Icons.mobile_screen_share),
title: const Text('Share screenshot'), title: const Text('Share screenshot'),
onTap: () async { onTap: () async {
final screenshot = await ref final screenshot =
.read(selectedTabSessionNotifierProvider) await ref
.requestScreenshot(); .read(selectedTabSessionNotifierProvider)
.requestScreenshot();
if (screenshot != null) { if (screenshot != null) {
ui.decodeImageFromList( ui.decodeImageFromList(screenshot, (
screenshot, result,
(result) async { ) async {
final png = await result.toByteData( final png = await result.toByteData(
format: ui.ImageByteFormat.png, format: ui.ImageByteFormat.png,
);
if (png != null) {
final file = XFile.fromData(
png.buffer.asUint8List(),
mimeType: 'image/png',
); );
if (png != null) { await Share.shareXFiles([
final file = XFile.fromData( file,
png.buffer.asUint8List(), ], subject: precachedInfo?.title);
mimeType: 'image/png', }
); });
await Share.shareXFiles(
[file],
subject: precachedInfo?.title,
);
}
},
);
} }
if (context.mounted) { if (context.mounted) {
@@ -53,8 +53,9 @@ class BrowserScreen extends HookConsumerWidget {
final displayedSheet = ref.watch(bottomSheetControllerProvider); final displayedSheet = ref.watch(bottomSheetControllerProvider);
final displayedOverlayDialog = ref.watch(overlayDialogControllerProvider); final displayedOverlayDialog = ref.watch(overlayDialogControllerProvider);
final selectedTabId = final selectedTabId = ref.watch(
ref.watch(selectedTabStateProvider.select((value) => value?.id)); selectedTabStateProvider.select((value) => value?.id),
);
final trippleDotMenuController = useMenuController(); final trippleDotMenuController = useMenuController();
final tabMenuController = useMenuController(); final tabMenuController = useMenuController();
@@ -65,16 +66,13 @@ class BrowserScreen extends HookConsumerWidget {
final activeKagiTool = useValueNotifier<KagiTool?>(null, [displayedSheet]); final activeKagiTool = useValueNotifier<KagiTool?>(null, [displayedSheet]);
ref.listen( ref.listen(overlayDialogControllerProvider, (previous, next) {
overlayDialogControllerProvider, if (next != null) {
(previous, next) { overlayController.show();
if (next != null) { } else {
overlayController.show(); overlayController.hide();
} else { }
overlayController.hide(); });
}
},
);
// ref.listen( // ref.listen(
// generalSettingsRepositoryProvider // generalSettingsRepositoryProvider
@@ -96,8 +94,9 @@ class BrowserScreen extends HookConsumerWidget {
bottomNavigationBar: Consumer( bottomNavigationBar: Consumer(
builder: (context, ref, child) { builder: (context, ref, child) {
final tabInFullScreen = ref.watch( final tabInFullScreen = ref.watch(
selectedTabStateProvider selectedTabStateProvider.select(
.select((value) => value?.isFullScreen ?? false), (value) => value?.isFullScreen ?? false,
),
); );
return Visibility( return Visibility(
@@ -108,15 +107,17 @@ class BrowserScreen extends HookConsumerWidget {
child: AppBar( child: AppBar(
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
titleSpacing: 8.0, titleSpacing: 8.0,
title: (selectedTabId != null && title:
displayedSheet is! ViewTabsSheet) (selectedTabId != null &&
? Consumer( displayedSheet is! ViewTabsSheet)
builder: (context, ref, child) { ? Consumer(
final tabState = builder: (context, ref, child) {
ref.watch(tabStateProvider(selectedTabId)); final tabState = ref.watch(
tabStateProvider(selectedTabId),
);
return (tabState != null) return (tabState != null)
? AppBarTitle( ? AppBarTitle(
tab: tabState, tab: tabState,
onTap: () async { onTap: () async {
await context.push( await context.push(
@@ -129,93 +130,95 @@ class BrowserScreen extends HookConsumerWidget {
onDoubleTap: () async { onDoubleTap: () async {
final newUrl = await showDialog<Uri?>( final newUrl = await showDialog<Uri?>(
context: context, context: context,
builder: (context) => EditUrlDialog( builder:
initialUrl: tabState.url, (context) => EditUrlDialog(
), initialUrl: tabState.url,
),
); );
if (newUrl != null) { if (newUrl != null) {
await ref await ref
.read( .read(
tabSessionProvider(tabId: null) tabSessionProvider(
.notifier, tabId: null,
).notifier,
) )
.loadUrl(url: newUrl); .loadUrl(url: newUrl);
} }
}, },
) )
: const SizedBox.shrink(); : const SizedBox.shrink();
}, },
) )
: HookBuilder( : HookBuilder(
builder: (context) { builder: (context) {
// final activeTool = useListenableSelector( // final activeTool = useListenableSelector(
// activeKagiTool, // activeKagiTool,
// () { // () {
// if (displayedSheet is CreateTabSheetWidget) { // if (displayedSheet is CreateTabSheetWidget) {
// return null; // return null;
// } // }
// return activeKagiTool.value; // return activeKagiTool.value;
// }, // },
// ); // );
return Row( return Row(
children: [ children: [
// IconButton( // IconButton(
// color: (activeTool == KagiTool.search) // color: (activeTool == KagiTool.search)
// ? Theme.of(context).colorScheme.primary // ? Theme.of(context).colorScheme.primary
// : null, // : null,
// onPressed: () async { // onPressed: () async {
// // ref // // ref
// // .read(createTabStreamProvider.notifier) // // .read(createTabStreamProvider.notifier)
// // .createTab( // // .createTab(
// // CreateTabSheet( // // CreateTabSheet(
// // preferredTool: KagiTool.search, // // preferredTool: KagiTool.search,
// // ), // // ),
// // ); // // );
// await context // await context
// .push(const SearchRoute().location); // .push(const SearchRoute().location);
// }, // },
// icon: Icon(KagiTool.search.icon), // icon: Icon(KagiTool.search.icon),
// ), // ),
// IconButton( // IconButton(
// color: (activeTool == KagiTool.summarizer) // color: (activeTool == KagiTool.summarizer)
// ? Theme.of(context).colorScheme.primary // ? Theme.of(context).colorScheme.primary
// : null, // : null,
// onPressed: () { // onPressed: () {
// ref // ref
// .read(createTabStreamProvider.notifier) // .read(createTabStreamProvider.notifier)
// .createTab( // .createTab(
// CreateTabSheet( // CreateTabSheet(
// preferredTool: KagiTool.summarizer, // preferredTool: KagiTool.summarizer,
// ), // ),
// ); // );
// }, // },
// icon: Icon(KagiTool.summarizer.icon), // icon: Icon(KagiTool.summarizer.icon),
// ), // ),
// if (showEarlyAccessFeatures) // if (showEarlyAccessFeatures)
// IconButton( // IconButton(
// color: (activeTool == KagiTool.assistant) // color: (activeTool == KagiTool.assistant)
// ? Theme.of(context).colorScheme.primary // ? Theme.of(context).colorScheme.primary
// : null, // : null,
// onPressed: () { // onPressed: () {
// ref // ref
// .read( // .read(
// createTabStreamProvider.notifier, // createTabStreamProvider.notifier,
// ) // )
// .createTab( // .createTab(
// CreateTabSheet( // CreateTabSheet(
// preferredTool: KagiTool.assistant, // preferredTool: KagiTool.assistant,
// ), // ),
// ); // );
// }, // },
// icon: Icon(KagiTool.assistant.icon), // icon: Icon(KagiTool.assistant.icon),
// ), // ),
], ],
); );
}, },
), ),
actions: [ actions: [
if (selectedTabId != null && if (selectedTabId != null &&
displayedSheet is! ViewTabsSheet) displayedSheet is! ViewTabsSheet)
@@ -278,9 +281,7 @@ class BrowserScreen extends HookConsumerWidget {
MenuItemButton( MenuItemButton(
onPressed: () async { onPressed: () async {
await ref await ref
.read( .read(tabRepositoryProvider.notifier)
tabRepositoryProvider.notifier,
)
.closeTab(selectedTabId); .closeTab(selectedTabId);
}, },
leadingIcon: const Icon(Icons.close), leadingIcon: const Icon(Icons.close),
@@ -488,8 +489,9 @@ class BrowserScreen extends HookConsumerWidget {
if (selectedTabId != null) if (selectedTabId != null)
MenuItemButton( MenuItemButton(
onPressed: () async { onPressed: () async {
final tabState = final tabState = ref.read(
ref.read(tabStateProvider(selectedTabId)); tabStateProvider(selectedTabId),
);
if (tabState?.url case final Uri url) { if (tabState?.url case final Uri url) {
await ui_helper.launchUrlFeedback(context, url); await ui_helper.launchUrlFeedback(context, url);
@@ -501,8 +503,9 @@ class BrowserScreen extends HookConsumerWidget {
if (selectedTabId != null) if (selectedTabId != null)
MenuItemButton( MenuItemButton(
onPressed: () async { onPressed: () async {
final tabState = final tabState = ref.read(
ref.read(tabStateProvider(selectedTabId)); tabStateProvider(selectedTabId),
);
if (tabState?.url case final Uri url) { if (tabState?.url case final Uri url) {
await Share.shareUri(url); await Share.shareUri(url);
@@ -530,8 +533,9 @@ class BrowserScreen extends HookConsumerWidget {
MenuItemButton( MenuItemButton(
onPressed: () async { onPressed: () async {
final controller = ref.read( final controller = ref.read(
tabSessionProvider(tabId: selectedTabId) tabSessionProvider(
.notifier, tabId: selectedTabId,
).notifier,
); );
await controller.reload(); await controller.reload();
@@ -545,39 +549,45 @@ class BrowserScreen extends HookConsumerWidget {
Consumer( Consumer(
builder: (context, ref, child) { builder: (context, ref, child) {
final history = ref.watch( final history = ref.watch(
tabStateProvider(selectedTabId) tabStateProvider(
.select((value) => value?.historyState), selectedTabId,
).select((value) => value?.historyState),
); );
return Row( return Row(
children: [ children: [
Expanded( Expanded(
child: (history?.canGoBack == true) child:
? IconButton( (history?.canGoBack == true)
onPressed: () async { ? IconButton(
final controller = ref.read( onPressed: () async {
tabSessionProvider( final controller = ref.read(
tabId: selectedTabId, tabSessionProvider(
).notifier, tabId: selectedTabId,
); ).notifier,
);
await controller.goBack(); await controller.goBack();
trippleDotMenuController.close(); trippleDotMenuController
}, .close();
icon: const Icon(Icons.arrow_back), },
) icon: const Icon(
: IconButton( Icons.arrow_back,
onPressed: () async { ),
await ref )
.read( : IconButton(
tabRepositoryProvider onPressed: () async {
.notifier, await ref
) .read(
.closeTab(selectedTabId); tabRepositoryProvider
trippleDotMenuController.close(); .notifier,
}, )
icon: const Icon(Icons.close), .closeTab(selectedTabId);
), trippleDotMenuController
.close();
},
icon: const Icon(Icons.close),
),
), ),
const SizedBox( const SizedBox(
height: 48, height: 48,
@@ -585,18 +595,20 @@ class BrowserScreen extends HookConsumerWidget {
), ),
Expanded( Expanded(
child: IconButton( child: IconButton(
onPressed: (history?.canGoForward == true) onPressed:
? () async { (history?.canGoForward == true)
final controller = ref.read( ? () async {
tabSessionProvider( final controller = ref.read(
tabId: selectedTabId, tabSessionProvider(
).notifier, tabId: selectedTabId,
); ).notifier,
);
await controller.goForward(); await controller.goForward();
trippleDotMenuController.close(); trippleDotMenuController
} .close();
: null, }
: null,
icon: const Icon(Icons.arrow_forward), icon: const Icon(Icons.arrow_forward),
), ),
), ),
@@ -640,20 +652,22 @@ class BrowserScreen extends HookConsumerWidget {
return displayedOverlayDialog!; return displayedOverlayDialog!;
}, },
child: Listener( child: Listener(
onPointerDown: (displayedSheet != null) onPointerDown:
? (_) { (displayedSheet != null)
ref ? (_) {
.read(bottomSheetControllerProvider.notifier) ref
.dismiss(); .read(bottomSheetControllerProvider.notifier)
} .dismiss();
: null, }
: null,
child: HookConsumer( child: HookConsumer(
builder: (context, ref, child) { builder: (context, ref, child) {
return BackButtonListener( return BackButtonListener(
onBackButtonPressed: () async { onBackButtonPressed: () async {
final tabState = (selectedTabId != null) final tabState =
? ref.read(tabStateProvider(selectedTabId)) (selectedTabId != null)
: null; ? ref.read(tabStateProvider(selectedTabId))
: null;
final tabCount = ref.read( final tabCount = ref.read(
tabListProvider.select((tabs) => tabs.length), tabListProvider.select((tabs) => tabs.length),
@@ -698,8 +712,9 @@ class BrowserScreen extends HookConsumerWidget {
} }
if (lastBackButtonPress.value != null && if (lastBackButtonPress.value != null &&
DateTime.now() DateTime.now().difference(
.difference(lastBackButtonPress.value!) < lastBackButtonPress.value!,
) <
const Duration(seconds: 2)) { const Duration(seconds: 2)) {
lastBackButtonPress.value = null; lastBackButtonPress.value = null;
@@ -718,13 +733,14 @@ class BrowserScreen extends HookConsumerWidget {
..clearSnackBars() ..clearSnackBars()
..showSnackBar( ..showSnackBar(
SnackBar( SnackBar(
content: (tabCount > 1) content:
? const Text( (tabCount > 1)
'Please click BACK again to close current tab', ? const Text(
) 'Please click BACK again to close current tab',
: const Text( )
'Please click BACK again to exit app', : const Text(
), 'Please click BACK again to exit app',
),
), ),
); );
@@ -744,16 +760,16 @@ class BrowserScreen extends HookConsumerWidget {
child: Consumer( child: Consumer(
builder: (context, ref, child) { builder: (context, ref, child) {
final value = ref.watch( final value = ref.watch(
selectedTabStateProvider.select( selectedTabStateProvider.select((
(state) { state,
if (state?.isLoading == true) { ) {
return state?.progress ?? 100; if (state?.isLoading == true) {
} return state?.progress ?? 100;
}
//When not loading we assumed finished //When not loading we assumed finished
return 100; return 100;
}, }),
),
); );
return Visibility( return Visibility(
@@ -774,11 +790,13 @@ class BrowserScreen extends HookConsumerWidget {
final value = ref.watch( final value = ref.watch(
selectedTabStateProvider.select( selectedTabStateProvider.select(
(state) => EdgeInsets.only( (state) => EdgeInsets.only(
bottom: (state?.isLoading == true && bottom:
state?.progress != null && (state?.isLoading == true &&
state!.progress < 100) state?.progress !=
? 4.0 null &&
: 0.0, state!.progress < 100)
? 4.0
: 0.0,
), ),
), ),
); );
@@ -794,7 +812,7 @@ class BrowserScreen extends HookConsumerWidget {
ModalBarrier( ModalBarrier(
color: color:
Theme.of(context).dialogTheme.barrierColor ?? Theme.of(context).dialogTheme.barrierColor ??
Colors.black54, Colors.black54,
), ),
], ],
), ),
@@ -806,22 +824,25 @@ class BrowserScreen extends HookConsumerWidget {
}, },
), ),
floatingActionButton: ReaderAppearanceButton(), floatingActionButton: ReaderAppearanceButton(),
bottomSheet: (displayedSheet != null) bottomSheet:
? NotificationListener<DraggableScrollableNotification>( (displayedSheet != null)
onNotification: (notification) { ? NotificationListener<DraggableScrollableNotification>(
if (notification.extent <= 0.1) { onNotification: (notification) {
ref.read(bottomSheetControllerProvider.notifier).dismiss(); if (notification.extent <= 0.1) {
return true; ref
} else { .read(bottomSheetControllerProvider.notifier)
ref .dismiss();
.read(bottomSheetExtendProvider.notifier) return true;
.add(notification.extent); } else {
} ref
.read(bottomSheetExtendProvider.notifier)
.add(notification.extent);
}
return false; return false;
}, },
child: switch (displayedSheet) { child: switch (displayedSheet) {
ViewTabsSheet() => HookBuilder( ViewTabsSheet() => HookBuilder(
builder: (localContext) { builder: (localContext) {
final draggableScrollableController = final draggableScrollableController =
useDraggableScrollableController(); useDraggableScrollableController();
@@ -855,7 +876,7 @@ class BrowserScreen extends HookConsumerWidget {
); );
}, },
), ),
final CreateTabSheet parameter => DraggableScrollableSheet( final CreateTabSheet parameter => DraggableScrollableSheet(
key: ValueKey(displayedSheet), key: ValueKey(displayedSheet),
expand: false, expand: false,
initialChildSize: 0.8, initialChildSize: 0.8,
@@ -883,7 +904,7 @@ class BrowserScreen extends HookConsumerWidget {
); );
}, },
), ),
final TabQaChatSheet parameter => HookBuilder( final TabQaChatSheet parameter => HookBuilder(
builder: (localContext) { builder: (localContext) {
final draggableScrollableController = final draggableScrollableController =
useDraggableScrollableController(); useDraggableScrollableController();
@@ -937,9 +958,9 @@ class BrowserScreen extends HookConsumerWidget {
); );
}, },
), ),
}, },
) )
: null, : null,
), ),
); );
} }
@@ -31,15 +31,9 @@ class AppBarTitle extends StatelessWidget {
size: 14, size: 14,
); );
} else if (!tab.isLoading) { } else if (!tab.isLoading) {
return const Icon( return const Icon(MdiIcons.lock, size: 14);
MdiIcons.lock,
size: 14,
);
} else { } else {
return const Icon( return const Icon(MdiIcons.timerSand, size: 14);
MdiIcons.timerSand,
size: 14,
);
} }
} }
@@ -54,19 +48,11 @@ class AppBarTitle extends StatelessWidget {
Skeletonizer( Skeletonizer(
enabled: tab.icon == null, enabled: tab.icon == null,
child: Skeleton.replace( child: Skeleton.replace(
replacement: const Bone.icon( replacement: const Bone.icon(size: 16),
size: 16, child: RawImage(image: tab.icon?.value, height: 16, width: 16),
),
child: RawImage(
image: tab.icon?.value,
height: 16,
width: 16,
),
), ),
), ),
const SizedBox( const SizedBox(width: 8),
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -82,8 +68,9 @@ class AppBarTitle extends StatelessWidget {
child: TextScroll( child: TextScroll(
key: ValueKey(tab.title), key: ValueKey(tab.title),
tab.title, tab.title,
style: theme.textTheme.bodyLarge style: theme.textTheme.bodyLarge?.copyWith(
?.copyWith(color: theme.colorScheme.onSurface), color: theme.colorScheme.onSurface,
),
// mode: TextScrollMode.bouncing, // mode: TextScrollMode.bouncing,
velocity: const Velocity(pixelsPerSecond: Offset(75, 0)), velocity: const Velocity(pixelsPerSecond: Offset(75, 0)),
delayBefore: const Duration(milliseconds: 500), delayBefore: const Duration(milliseconds: 500),
@@ -99,14 +86,13 @@ class AppBarTitle extends StatelessWidget {
Row( Row(
children: [ children: [
_securityStatusIcon(context), _securityStatusIcon(context),
const SizedBox( const SizedBox(width: 4),
width: 4,
),
Expanded( Expanded(
child: Text( child: Text(
tab.url.authority, tab.url.authority,
style: theme.textTheme.bodyMedium style: theme.textTheme.bodyMedium?.copyWith(
?.copyWith(color: theme.colorScheme.onSurface), color: theme.colorScheme.onSurface,
),
), ),
), ),
], ],

Some files were not shown because too many files have changed in this diff Show More