refactoring
This commit is contained in:
@@ -1,17 +0,0 @@
|
|||||||
Lensai enhances your mobile research experience while keeping your personal data and identity secure.
|
|
||||||
Powered by advanced AI tools and browser extensions, Lensai offers modern features designed to elevate your browsing experience.
|
|
||||||
|
|
||||||
Lensai is packed with a variety of features aimed at improving usability and maintaining privacy:
|
|
||||||
|
|
||||||
- **Privacy by Default**: Incognito mode is enabled by default to keep your searches and browsing history private.
|
|
||||||
- **[Kagi Integration](https://github.com/FaFre/lensai/wiki/Kagi-Tools)**: Seamlessly integrates Kagi's search, assistant, and summarizer tools within a user-friendly interface.
|
|
||||||
- **[Easy Sharing](https://github.com/FaFre/lensai/wiki/Kagi-Tools)**: Share URLs or text from any app directly into Lensai without the need to copy and paste, for direct use with summarizer/assistant.
|
|
||||||
- **[Quick Summarization](https://github.com/FaFre/lensai/wiki/Browser)**: Long press any link on a website to get a summary via Kagi's summarizer.
|
|
||||||
- **[Content Blocking](https://github.com/FaFre/lensai/wiki/Content-Blocking)**: A powerful content blocker is enabled by default to filter out ads, malware, and tracking sites.
|
|
||||||
- **[Home Widgets](https://github.com/FaFre/lensai/wiki/Home-Widget)**: Includes home screen widgets in three different sizes for quick actions, enhancing productivity.
|
|
||||||
- **[PDF processing](https://github.com/FaFre/lensai/wiki/Kagi-Tools)**: Open and directly summarize/prompt PDF documents.
|
|
||||||
- **Reader Mode**: Extract and simplify web pages, enhancing readability by removing ads, sidebars, and other non-essential elements.
|
|
||||||
- **[Chat Archive](https://github.com/FaFre/lensai/wiki/Chat-Archive)**: Easily archive conversations with the Kagi assistant on your device and search through them locally
|
|
||||||
- **[Bang Repository](https://github.com/FaFre/lensai/wiki/Bangs)**: Automatically synchronizes all official Kagi Bangs from the official Repository and makes them available through a convenient interface.
|
|
||||||
- **[Enhanced Text Interaction](https://github.com/FaFre/lensai/wiki/Browser)**: Custom context menu allows for easy passage of marked text to Kagi's search or assistant tools.
|
|
||||||
- **[Speech Input](https://github.com/FaFre/lensai/wiki/Kagi-Tools)**: Supports voice commands for hands-free operation and accessibility.
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class ReceivedIntentParameter {
|
||||||
|
final String? content;
|
||||||
|
final String? tool;
|
||||||
|
|
||||||
|
ReceivedIntentParameter(this.content, this.tool);
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
class ReceivedParameter {
|
|
||||||
final String? content;
|
|
||||||
final String? tool;
|
|
||||||
|
|
||||||
ReceivedParameter(this.content, this.tool);
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ import 'dart:async';
|
|||||||
import 'package:exceptions/exceptions.dart';
|
import 'package:exceptions/exceptions.dart';
|
||||||
import 'package:lensai/features/about/data/repositories/package_info_repository.dart';
|
import 'package:lensai/features/about/data/repositories/package_info_repository.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
import 'package:lensai/features/bangs/data/models/bang.dart';
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
import 'package:lensai/features/bangs/domain/repositories/sync.dart';
|
import 'package:lensai/features/bangs/domain/repositories/sync.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ class GenericWebsiteService extends _$GenericWebsiteService {
|
|||||||
return Result.fromAsync(() async {
|
return Result.fromAsync(() async {
|
||||||
final response = await _client
|
final response = await _client
|
||||||
.get(url)
|
.get(url)
|
||||||
.timeout(const Duration(seconds: 10));
|
.timeout(const Duration(seconds: 15));
|
||||||
|
|
||||||
final result = await compute((args) async {
|
final result = await compute((args) async {
|
||||||
final document = html_parser.parse(args[0]);
|
final document = html_parser.parse(args[0]);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'generic_website.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$genericWebsiteServiceHash() =>
|
String _$genericWebsiteServiceHash() =>
|
||||||
r'4c8c1c9ad430ab01f637f02ec97ee4ce5202975e';
|
r'7891376773d7e6a61eeab37e0e92bb21f1acd8e3';
|
||||||
|
|
||||||
/// See also [GenericWebsiteService].
|
/// See also [GenericWebsiteService].
|
||||||
@ProviderFor(GenericWebsiteService)
|
@ProviderFor(GenericWebsiteService)
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
extension RelativeSafeArea on MediaQueryData {
|
||||||
|
double relativeSafeArea() {
|
||||||
|
return 1.0 - (padding.top / size.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ class AboutDialogScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
applicationName: packageInfo.appName,
|
applicationName: packageInfo.appName,
|
||||||
applicationVersion: packageInfo.version,
|
applicationVersion: packageInfo.version,
|
||||||
applicationLegalese: 'Copyright © Fabian Freund, 2024',
|
applicationLegalese: 'Copyright © Fabian Freund, 2025',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:home_widget/home_widget.dart';
|
import 'package:home_widget/home_widget.dart';
|
||||||
import 'package:lensai/data/models/received_parameter.dart';
|
import 'package:lensai/data/models/received_intent_parameter.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
@@ -12,12 +12,12 @@ FutureOr<bool> widgetPinnable(Ref ref) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
Raw<Stream<ReceivedParameter>> appWidgetLaunchStream(Ref ref) {
|
Raw<Stream<ReceivedIntentParameter>> appWidgetLaunchStream(Ref ref) {
|
||||||
// ignore: discarded_futures is used as stream
|
// ignore: discarded_futures is used as stream
|
||||||
final initialStream = HomeWidget.initiallyLaunchedFromHomeWidget().asStream();
|
final initialStream = HomeWidget.initiallyLaunchedFromHomeWidget().asStream();
|
||||||
|
|
||||||
return ConcatStream([
|
return ConcatStream([
|
||||||
initialStream,
|
initialStream,
|
||||||
HomeWidget.widgetClicked,
|
HomeWidget.widgetClicked,
|
||||||
]).whereNotNull().map((uri) => ReceivedParameter(null, uri.host));
|
]).whereNotNull().map((uri) => ReceivedIntentParameter(null, uri.host));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ final widgetPinnableProvider = FutureProvider<bool>.internal(
|
|||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
typedef WidgetPinnableRef = FutureProviderRef<bool>;
|
typedef WidgetPinnableRef = FutureProviderRef<bool>;
|
||||||
String _$appWidgetLaunchStreamHash() =>
|
String _$appWidgetLaunchStreamHash() =>
|
||||||
r'8eb98d88e74cc4f7573968563c106b8e6beee289';
|
r'ed042d1391ae3dbc26f806d6fa2e9a4a2464ae44';
|
||||||
|
|
||||||
/// See also [appWidgetLaunchStream].
|
/// See also [appWidgetLaunchStream].
|
||||||
@ProviderFor(appWidgetLaunchStream)
|
@ProviderFor(appWidgetLaunchStream)
|
||||||
final appWidgetLaunchStreamProvider =
|
final appWidgetLaunchStreamProvider =
|
||||||
AutoDisposeProvider<Raw<Stream<ReceivedParameter>>>.internal(
|
AutoDisposeProvider<Raw<Stream<ReceivedIntentParameter>>>.internal(
|
||||||
appWidgetLaunchStream,
|
appWidgetLaunchStream,
|
||||||
name: r'appWidgetLaunchStreamProvider',
|
name: r'appWidgetLaunchStreamProvider',
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
@@ -42,6 +42,6 @@ final appWidgetLaunchStreamProvider =
|
|||||||
@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<ReceivedIntentParameter>>>;
|
||||||
// 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
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:lensai/extensions/nullable.dart';
|
|||||||
import 'package:lensai/features/bangs/data/database/database.dart';
|
import 'package:lensai/features/bangs/data/database/database.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
import 'package:lensai/features/bangs/data/models/bang.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
|
|
||||||
part 'bang.g.dart';
|
part 'bang.g.dart';
|
||||||
|
|
||||||
@@ -121,18 +122,4 @@ class BangDao extends DatabaseAccessor<BangDatabase> with _$BangDaoMixin {
|
|||||||
Future<int> removeSearchEntry(String searchQuery) {
|
Future<int> removeSearchEntry(String searchQuery) {
|
||||||
return db.bangHistory.deleteWhere((t) => t.searchQuery.equals(searchQuery));
|
return db.bangHistory.deleteWhere((t) => t.searchQuery.equals(searchQuery));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Future<int> upsertBangIcon(String trigger, BrowserIcon icon) async {
|
|
||||||
// //TODO: swithc to WEBP in future, requires 3rd party
|
|
||||||
// final compressed = await icon.image.toByteData(format: ImageByteFormat.png);
|
|
||||||
|
|
||||||
// return db.bangIcon.insertOne(
|
|
||||||
// BangIconCompanion.insert(
|
|
||||||
// trigger: trigger,
|
|
||||||
// iconData: compressed!.buffer.asUint8List(),
|
|
||||||
// fetchDate: DateTime.now(),
|
|
||||||
// ),
|
|
||||||
// mode: InsertMode.insertOrReplace,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:lensai/features/bangs/data/database/database.dart';
|
import 'package:lensai/features/bangs/data/database/database.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
import 'package:lensai/features/bangs/data/models/bang.dart';
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
|
|
||||||
part 'sync.g.dart';
|
part 'sync.g.dart';
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ part 'sync.g.dart';
|
|||||||
class SyncDao extends DatabaseAccessor<BangDatabase> with _$SyncDaoMixin {
|
class SyncDao extends DatabaseAccessor<BangDatabase> with _$SyncDaoMixin {
|
||||||
SyncDao(super.db);
|
SyncDao(super.db);
|
||||||
|
|
||||||
SingleOrNullSelectable<DateTime?> lastSyncOfGroup(BangGroup group) {
|
SingleOrNullSelectable<DateTime?> getLastSyncOfGroup(BangGroup group) {
|
||||||
final query =
|
final query =
|
||||||
selectOnly(db.bangSync)
|
selectOnly(db.bangSync)
|
||||||
..addColumns([db.bangSync.lastSync])
|
..addColumns([db.bangSync.lastSync])
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:lensai/features/bangs/data/database/daos/sync.dart';
|
|||||||
import 'package:lensai/features/bangs/data/database/drift/converters/bang_format.dart';
|
import 'package:lensai/features/bangs/data/database/drift/converters/bang_format.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
import 'package:lensai/features/bangs/data/models/bang.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/search_history_entry.dart';
|
import 'package:lensai/features/bangs/data/models/search_history_entry.dart';
|
||||||
import 'package:lensai/features/search/domain/fts_tokenizer.dart';
|
import 'package:lensai/features/search/domain/fts_tokenizer.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:lensai/features/bangs/data/database/drift/converters/bang_format.dart';
|
import 'package:lensai/features/bangs/data/database/drift/converters/bang_format.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
import 'package:lensai/features/bangs/data/models/bang.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/search_history_entry.dart';
|
import 'package:lensai/features/bangs/data/models/search_history_entry.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -4,26 +4,10 @@ import 'package:fast_equatable/fast_equatable.dart';
|
|||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
import 'package:lensai/features/bangs/data/database/database.dart'
|
import 'package:lensai/features/bangs/data/database/database.dart'
|
||||||
show BangCompanion;
|
show BangCompanion;
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
|
|
||||||
part 'bang.g.dart';
|
part 'bang.g.dart';
|
||||||
|
|
||||||
enum BangGroup {
|
|
||||||
general('https://raw.githubusercontent.com/FaFre/bangs/main/data/bangs.json'),
|
|
||||||
assistant(
|
|
||||||
'https://raw.githubusercontent.com/FaFre/bangs/main/data/assistant_bangs.json',
|
|
||||||
),
|
|
||||||
kagi(
|
|
||||||
'https://raw.githubusercontent.com/FaFre/bangs/main/data/kagi_bangs.json',
|
|
||||||
),
|
|
||||||
custom(
|
|
||||||
'https://raw.githubusercontent.com/FaFre/bangs/refs/heads/custom/data/custom.json',
|
|
||||||
);
|
|
||||||
|
|
||||||
final String url;
|
|
||||||
|
|
||||||
const BangGroup(this.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum BangFormat {
|
enum BangFormat {
|
||||||
///When the bang is invoked with no query, opens the base path of the URL (/)
|
///When the bang is invoked with no query, opens the base path of the URL (/)
|
||||||
///instead of any path given in the template (g., /search)
|
///instead of any path given in the template (g., /search)
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
enum BangGroup {
|
||||||
|
general('https://raw.githubusercontent.com/FaFre/bangs/main/data/bangs.json'),
|
||||||
|
assistant(
|
||||||
|
'https://raw.githubusercontent.com/FaFre/bangs/main/data/assistant_bangs.json',
|
||||||
|
),
|
||||||
|
kagi(
|
||||||
|
'https://raw.githubusercontent.com/FaFre/bangs/main/data/kagi_bangs.json',
|
||||||
|
),
|
||||||
|
custom(
|
||||||
|
'https://raw.githubusercontent.com/FaFre/bangs/refs/heads/custom/data/custom.json',
|
||||||
|
);
|
||||||
|
|
||||||
|
final String url;
|
||||||
|
|
||||||
|
const BangGroup(this.url);
|
||||||
|
}
|
||||||
+6
-3
@@ -5,12 +5,13 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:lensai/core/http_error_handler.dart';
|
import 'package:lensai/core/http_error_handler.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
import 'package:lensai/features/bangs/data/models/bang.dart';
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'source.g.dart';
|
part 'data_source.g.dart';
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
class BangSourceService extends _$BangSourceService {
|
class BangDataSourceService extends _$BangDataSourceService {
|
||||||
late http.Client _client;
|
late http.Client _client;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -20,7 +21,9 @@ 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(() async {
|
return Result.fromAsync(() async {
|
||||||
final response = await _client.get(url);
|
final response = await _client
|
||||||
|
.get(url)
|
||||||
|
.timeout(const Duration(seconds: 30));
|
||||||
return await compute((args) => jsonDecode(utf8.decode(args[0])) as List, [
|
return await compute((args) => jsonDecode(utf8.decode(args[0])) as List, [
|
||||||
response.bodyBytes,
|
response.bodyBytes,
|
||||||
]).then(
|
]).then(
|
||||||
+11
-10
@@ -1,26 +1,27 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'create_tab.dart';
|
part of 'data_source.dart';
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$createTabStreamHash() => r'2e802a10ecaf1862074f32b76e89c26997bdd7b2';
|
String _$bangDataSourceServiceHash() =>
|
||||||
|
r'fb00762858a2878505c14e2b1a0f26c1b2f60d7d';
|
||||||
|
|
||||||
/// See also [CreateTabStream].
|
/// See also [BangDataSourceService].
|
||||||
@ProviderFor(CreateTabStream)
|
@ProviderFor(BangDataSourceService)
|
||||||
final createTabStreamProvider =
|
final bangDataSourceServiceProvider =
|
||||||
AutoDisposeStreamNotifierProvider<CreateTabStream, CreateTabSheet>.internal(
|
AutoDisposeNotifierProvider<BangDataSourceService, void>.internal(
|
||||||
CreateTabStream.new,
|
BangDataSourceService.new,
|
||||||
name: r'createTabStreamProvider',
|
name: r'bangDataSourceServiceProvider',
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
? null
|
? null
|
||||||
: _$createTabStreamHash,
|
: _$bangDataSourceServiceHash,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
allTransitiveDependencies: null,
|
allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef _$CreateTabStream = AutoDisposeStreamNotifier<CreateTabSheet>;
|
typedef _$BangDataSourceService = AutoDisposeNotifier<void>;
|
||||||
// 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
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'source.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// RiverpodGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
String _$bangSourceServiceHash() => r'2f734d563fa20de306a72013526ef1f72f910fe1';
|
|
||||||
|
|
||||||
/// See also [BangSourceService].
|
|
||||||
@ProviderFor(BangSourceService)
|
|
||||||
final bangSourceServiceProvider =
|
|
||||||
AutoDisposeNotifierProvider<BangSourceService, void>.internal(
|
|
||||||
BangSourceService.new,
|
|
||||||
name: r'bangSourceServiceProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$bangSourceServiceHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$BangSourceService = AutoDisposeNotifier<void>;
|
|
||||||
// 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
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
|
||||||
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/search_history_entry.dart';
|
import 'package:lensai/features/bangs/data/models/search_history_entry.dart';
|
||||||
import 'package:lensai/features/bangs/domain/repositories/data.dart';
|
import 'package:lensai/features/bangs/domain/repositories/data.dart';
|
||||||
import 'package:lensai/features/bangs/domain/repositories/sync.dart';
|
import 'package:lensai/features/bangs/domain/repositories/sync.dart';
|
||||||
@@ -8,15 +8,10 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|||||||
|
|
||||||
part 'bangs.g.dart';
|
part 'bangs.g.dart';
|
||||||
|
|
||||||
@Riverpod()
|
|
||||||
Stream<BangData?> bangData(Ref ref, String? trigger) {
|
|
||||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
|
||||||
return repository.watchBang(trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
Stream<BangData?> defaultSearchBangData(Ref ref) {
|
Stream<BangData?> defaultSearchBangData(Ref ref) {
|
||||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||||
|
//TODO: Setting
|
||||||
return repository.watchBang('lai');
|
return repository.watchBang('lai');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,27 +22,24 @@ Stream<Map<String, List<String>>> bangCategories(Ref ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
Stream<List<BangData>> bangDataList(
|
Stream<List<BangData>> bangList(
|
||||||
Ref ref, {
|
Ref ref, {
|
||||||
({
|
List<BangGroup>? groups,
|
||||||
Iterable<BangGroup>? groups,
|
String? domain,
|
||||||
String? domain,
|
({String category, String? subCategory})? categoryFilter,
|
||||||
({String category, String? subCategory})? categoryFilter,
|
bool? orderMostFrequentFirst,
|
||||||
bool? orderMostFrequentFirst,
|
|
||||||
})?
|
|
||||||
filter,
|
|
||||||
}) {
|
}) {
|
||||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||||
return repository.watchBangs(
|
return repository.watchBangs(
|
||||||
groups: filter?.groups,
|
groups: groups,
|
||||||
domain: filter?.domain,
|
domain: domain,
|
||||||
categoryFilter: filter?.categoryFilter,
|
categoryFilter: categoryFilter,
|
||||||
orderMostFrequentFirst: filter?.orderMostFrequentFirst,
|
orderMostFrequentFirst: orderMostFrequentFirst,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
Stream<List<BangData>> frequentBangDataList(Ref ref) {
|
Stream<List<BangData>> frequentBangList(Ref ref) {
|
||||||
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
final repository = ref.watch(bangDataRepositoryProvider.notifier);
|
||||||
return repository.watchFrequentBangs();
|
return repository.watchFrequentBangs();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,156 +6,6 @@ part of 'bangs.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$bangDataHash() => r'057a002de9789ab74c8f3b337a43faa26b788d8d';
|
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
|
||||||
class _SystemHash {
|
|
||||||
_SystemHash._();
|
|
||||||
|
|
||||||
static int combine(int hash, int value) {
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = 0x1fffffff & (hash + value);
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
|
||||||
return hash ^ (hash >> 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int finish(int hash) {
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = hash ^ (hash >> 11);
|
|
||||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [bangData].
|
|
||||||
@ProviderFor(bangData)
|
|
||||||
const bangDataProvider = BangDataFamily();
|
|
||||||
|
|
||||||
/// See also [bangData].
|
|
||||||
class BangDataFamily extends Family<AsyncValue<BangData?>> {
|
|
||||||
/// See also [bangData].
|
|
||||||
const BangDataFamily();
|
|
||||||
|
|
||||||
/// See also [bangData].
|
|
||||||
BangDataProvider call(
|
|
||||||
String? trigger,
|
|
||||||
) {
|
|
||||||
return BangDataProvider(
|
|
||||||
trigger,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
BangDataProvider getProviderOverride(
|
|
||||||
covariant BangDataProvider provider,
|
|
||||||
) {
|
|
||||||
return call(
|
|
||||||
provider.trigger,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
|
||||||
_allTransitiveDependencies;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get name => r'bangDataProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [bangData].
|
|
||||||
class BangDataProvider extends AutoDisposeStreamProvider<BangData?> {
|
|
||||||
/// See also [bangData].
|
|
||||||
BangDataProvider(
|
|
||||||
String? trigger,
|
|
||||||
) : this._internal(
|
|
||||||
(ref) => bangData(
|
|
||||||
ref as BangDataRef,
|
|
||||||
trigger,
|
|
||||||
),
|
|
||||||
from: bangDataProvider,
|
|
||||||
name: r'bangDataProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$bangDataHash,
|
|
||||||
dependencies: BangDataFamily._dependencies,
|
|
||||||
allTransitiveDependencies: BangDataFamily._allTransitiveDependencies,
|
|
||||||
trigger: trigger,
|
|
||||||
);
|
|
||||||
|
|
||||||
BangDataProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.trigger,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final String? trigger;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(
|
|
||||||
Stream<BangData?> Function(BangDataRef provider) create,
|
|
||||||
) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
|
||||||
override: BangDataProvider._internal(
|
|
||||||
(ref) => create(ref as BangDataRef),
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
debugGetCreateSourceHash: null,
|
|
||||||
trigger: trigger,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
AutoDisposeStreamProviderElement<BangData?> createElement() {
|
|
||||||
return _BangDataProviderElement(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return other is BangDataProvider && other.trigger == trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode {
|
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
|
||||||
hash = _SystemHash.combine(hash, trigger.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
mixin BangDataRef on AutoDisposeStreamProviderRef<BangData?> {
|
|
||||||
/// The parameter `trigger` of this provider.
|
|
||||||
String? get trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BangDataProviderElement
|
|
||||||
extends AutoDisposeStreamProviderElement<BangData?> with BangDataRef {
|
|
||||||
_BangDataProviderElement(super.provider);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get trigger => (origin as BangDataProvider).trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
String _$defaultSearchBangDataHash() =>
|
String _$defaultSearchBangDataHash() =>
|
||||||
r'c93026fe7b1650fe8a39bb2a8850af3ee416c306';
|
r'c93026fe7b1650fe8a39bb2a8850af3ee416c306';
|
||||||
|
|
||||||
@@ -193,37 +43,62 @@ final bangCategoriesProvider =
|
|||||||
// 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 _$bangListHash() => r'dc168bd1246bea3e5f8015dd52fbf41c5f98ca13';
|
||||||
|
|
||||||
/// See also [bangDataList].
|
/// Copied from Dart SDK
|
||||||
@ProviderFor(bangDataList)
|
class _SystemHash {
|
||||||
const bangDataListProvider = BangDataListFamily();
|
_SystemHash._();
|
||||||
|
|
||||||
/// See also [bangDataList].
|
static int combine(int hash, int value) {
|
||||||
class BangDataListFamily extends Family<AsyncValue<List<BangData>>> {
|
// ignore: parameter_assignments
|
||||||
/// See also [bangDataList].
|
hash = 0x1fffffff & (hash + value);
|
||||||
const BangDataListFamily();
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||||
|
return hash ^ (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
/// See also [bangDataList].
|
static int finish(int hash) {
|
||||||
BangDataListProvider call({
|
// ignore: parameter_assignments
|
||||||
({
|
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||||
({String category, String? subCategory})? categoryFilter,
|
// ignore: parameter_assignments
|
||||||
String? domain,
|
hash = hash ^ (hash >> 11);
|
||||||
Iterable<BangGroup>? groups,
|
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||||
bool? orderMostFrequentFirst
|
}
|
||||||
})? filter,
|
}
|
||||||
|
|
||||||
|
/// See also [bangList].
|
||||||
|
@ProviderFor(bangList)
|
||||||
|
const bangListProvider = BangListFamily();
|
||||||
|
|
||||||
|
/// See also [bangList].
|
||||||
|
class BangListFamily extends Family<AsyncValue<List<BangData>>> {
|
||||||
|
/// See also [bangList].
|
||||||
|
const BangListFamily();
|
||||||
|
|
||||||
|
/// See also [bangList].
|
||||||
|
BangListProvider call({
|
||||||
|
List<BangGroup>? groups,
|
||||||
|
String? domain,
|
||||||
|
({String category, String? subCategory})? categoryFilter,
|
||||||
|
bool? orderMostFrequentFirst,
|
||||||
}) {
|
}) {
|
||||||
return BangDataListProvider(
|
return BangListProvider(
|
||||||
filter: filter,
|
groups: groups,
|
||||||
|
domain: domain,
|
||||||
|
categoryFilter: categoryFilter,
|
||||||
|
orderMostFrequentFirst: orderMostFrequentFirst,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BangDataListProvider getProviderOverride(
|
BangListProvider getProviderOverride(
|
||||||
covariant BangDataListProvider provider,
|
covariant BangListProvider provider,
|
||||||
) {
|
) {
|
||||||
return call(
|
return call(
|
||||||
filter: provider.filter,
|
groups: provider.groups,
|
||||||
|
domain: provider.domain,
|
||||||
|
categoryFilter: provider.categoryFilter,
|
||||||
|
orderMostFrequentFirst: provider.orderMostFrequentFirst,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,85 +114,99 @@ class BangDataListFamily extends Family<AsyncValue<List<BangData>>> {
|
|||||||
_allTransitiveDependencies;
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? get name => r'bangDataListProvider';
|
String? get name => r'bangListProvider';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See also [bangDataList].
|
/// See also [bangList].
|
||||||
class BangDataListProvider extends AutoDisposeStreamProvider<List<BangData>> {
|
class BangListProvider extends AutoDisposeStreamProvider<List<BangData>> {
|
||||||
/// See also [bangDataList].
|
/// See also [bangList].
|
||||||
BangDataListProvider({
|
BangListProvider({
|
||||||
({
|
List<BangGroup>? groups,
|
||||||
({String category, String? subCategory})? categoryFilter,
|
String? domain,
|
||||||
String? domain,
|
({String category, String? subCategory})? categoryFilter,
|
||||||
Iterable<BangGroup>? groups,
|
bool? orderMostFrequentFirst,
|
||||||
bool? orderMostFrequentFirst
|
|
||||||
})? filter,
|
|
||||||
}) : this._internal(
|
}) : this._internal(
|
||||||
(ref) => bangDataList(
|
(ref) => bangList(
|
||||||
ref as BangDataListRef,
|
ref as BangListRef,
|
||||||
filter: filter,
|
groups: groups,
|
||||||
|
domain: domain,
|
||||||
|
categoryFilter: categoryFilter,
|
||||||
|
orderMostFrequentFirst: orderMostFrequentFirst,
|
||||||
),
|
),
|
||||||
from: bangDataListProvider,
|
from: bangListProvider,
|
||||||
name: r'bangDataListProvider',
|
name: r'bangListProvider',
|
||||||
debugGetCreateSourceHash:
|
debugGetCreateSourceHash:
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
? null
|
? null
|
||||||
: _$bangDataListHash,
|
: _$bangListHash,
|
||||||
dependencies: BangDataListFamily._dependencies,
|
dependencies: BangListFamily._dependencies,
|
||||||
allTransitiveDependencies:
|
allTransitiveDependencies: BangListFamily._allTransitiveDependencies,
|
||||||
BangDataListFamily._allTransitiveDependencies,
|
groups: groups,
|
||||||
filter: filter,
|
domain: domain,
|
||||||
|
categoryFilter: categoryFilter,
|
||||||
|
orderMostFrequentFirst: orderMostFrequentFirst,
|
||||||
);
|
);
|
||||||
|
|
||||||
BangDataListProvider._internal(
|
BangListProvider._internal(
|
||||||
super._createNotifier, {
|
super._createNotifier, {
|
||||||
required super.name,
|
required super.name,
|
||||||
required super.dependencies,
|
required super.dependencies,
|
||||||
required super.allTransitiveDependencies,
|
required super.allTransitiveDependencies,
|
||||||
required super.debugGetCreateSourceHash,
|
required super.debugGetCreateSourceHash,
|
||||||
required super.from,
|
required super.from,
|
||||||
required this.filter,
|
required this.groups,
|
||||||
|
required this.domain,
|
||||||
|
required this.categoryFilter,
|
||||||
|
required this.orderMostFrequentFirst,
|
||||||
}) : super.internal();
|
}) : super.internal();
|
||||||
|
|
||||||
final ({
|
final List<BangGroup>? groups;
|
||||||
({String category, String? subCategory})? categoryFilter,
|
final String? domain;
|
||||||
String? domain,
|
final ({String category, String? subCategory})? categoryFilter;
|
||||||
Iterable<BangGroup>? groups,
|
final bool? orderMostFrequentFirst;
|
||||||
bool? orderMostFrequentFirst
|
|
||||||
})? filter;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Override overrideWith(
|
Override overrideWith(
|
||||||
Stream<List<BangData>> Function(BangDataListRef provider) create,
|
Stream<List<BangData>> Function(BangListRef provider) create,
|
||||||
) {
|
) {
|
||||||
return ProviderOverride(
|
return ProviderOverride(
|
||||||
origin: this,
|
origin: this,
|
||||||
override: BangDataListProvider._internal(
|
override: BangListProvider._internal(
|
||||||
(ref) => create(ref as BangDataListRef),
|
(ref) => create(ref as BangListRef),
|
||||||
from: from,
|
from: from,
|
||||||
name: null,
|
name: null,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
allTransitiveDependencies: null,
|
allTransitiveDependencies: null,
|
||||||
debugGetCreateSourceHash: null,
|
debugGetCreateSourceHash: null,
|
||||||
filter: filter,
|
groups: groups,
|
||||||
|
domain: domain,
|
||||||
|
categoryFilter: categoryFilter,
|
||||||
|
orderMostFrequentFirst: orderMostFrequentFirst,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
AutoDisposeStreamProviderElement<List<BangData>> createElement() {
|
AutoDisposeStreamProviderElement<List<BangData>> createElement() {
|
||||||
return _BangDataListProviderElement(this);
|
return _BangListProviderElement(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is BangDataListProvider && other.filter == filter;
|
return other is BangListProvider &&
|
||||||
|
other.groups == groups &&
|
||||||
|
other.domain == domain &&
|
||||||
|
other.categoryFilter == categoryFilter &&
|
||||||
|
other.orderMostFrequentFirst == orderMostFrequentFirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
hash = _SystemHash.combine(hash, filter.hashCode);
|
hash = _SystemHash.combine(hash, groups.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, domain.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, categoryFilter.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, orderMostFrequentFirst.hashCode);
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
@@ -325,49 +214,54 @@ class BangDataListProvider extends AutoDisposeStreamProvider<List<BangData>> {
|
|||||||
|
|
||||||
@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
|
||||||
mixin BangDataListRef on AutoDisposeStreamProviderRef<List<BangData>> {
|
mixin BangListRef on AutoDisposeStreamProviderRef<List<BangData>> {
|
||||||
/// The parameter `filter` of this provider.
|
/// The parameter `groups` of this provider.
|
||||||
({
|
List<BangGroup>? get groups;
|
||||||
({String category, String? subCategory})? categoryFilter,
|
|
||||||
String? domain,
|
/// The parameter `domain` of this provider.
|
||||||
Iterable<BangGroup>? groups,
|
String? get domain;
|
||||||
bool? orderMostFrequentFirst
|
|
||||||
})? get filter;
|
/// The parameter `categoryFilter` of this provider.
|
||||||
|
({String category, String? subCategory})? get categoryFilter;
|
||||||
|
|
||||||
|
/// The parameter `orderMostFrequentFirst` of this provider.
|
||||||
|
bool? get orderMostFrequentFirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BangDataListProviderElement
|
class _BangListProviderElement
|
||||||
extends AutoDisposeStreamProviderElement<List<BangData>>
|
extends AutoDisposeStreamProviderElement<List<BangData>> with BangListRef {
|
||||||
with BangDataListRef {
|
_BangListProviderElement(super.provider);
|
||||||
_BangDataListProviderElement(super.provider);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
({
|
List<BangGroup>? get groups => (origin as BangListProvider).groups;
|
||||||
({String category, String? subCategory})? categoryFilter,
|
@override
|
||||||
String? domain,
|
String? get domain => (origin as BangListProvider).domain;
|
||||||
Iterable<BangGroup>? groups,
|
@override
|
||||||
bool? orderMostFrequentFirst
|
({String category, String? subCategory})? get categoryFilter =>
|
||||||
})? get filter => (origin as BangDataListProvider).filter;
|
(origin as BangListProvider).categoryFilter;
|
||||||
|
@override
|
||||||
|
bool? get orderMostFrequentFirst =>
|
||||||
|
(origin as BangListProvider).orderMostFrequentFirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$frequentBangDataListHash() =>
|
String _$frequentBangListHash() => r'2c1ecb7e9416772fc1c32d01d767e1eb4f865975';
|
||||||
r'27bc10ddf502266458af3910fff09bc8282a8e5c';
|
|
||||||
|
|
||||||
/// See also [frequentBangDataList].
|
/// See also [frequentBangList].
|
||||||
@ProviderFor(frequentBangDataList)
|
@ProviderFor(frequentBangList)
|
||||||
final frequentBangDataListProvider =
|
final frequentBangListProvider =
|
||||||
AutoDisposeStreamProvider<List<BangData>>.internal(
|
AutoDisposeStreamProvider<List<BangData>>.internal(
|
||||||
frequentBangDataList,
|
frequentBangList,
|
||||||
name: r'frequentBangDataListProvider',
|
name: r'frequentBangListProvider',
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
? null
|
? null
|
||||||
: _$frequentBangDataListHash,
|
: _$frequentBangListHash,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
allTransitiveDependencies: 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 FrequentBangDataListRef = AutoDisposeStreamProviderRef<List<BangData>>;
|
typedef FrequentBangListRef = AutoDisposeStreamProviderRef<List<BangData>>;
|
||||||
String _$searchHistoryHash() => r'7b97798729643de8e44fd8024cdc02f35124b08b';
|
String _$searchHistoryHash() => r'7b97798729643de8e44fd8024cdc02f35124b08b';
|
||||||
|
|
||||||
/// See also [searchHistory].
|
/// See also [searchHistory].
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
||||||
import 'package:lensai/features/bangs/domain/repositories/data.dart';
|
import 'package:lensai/features/bangs/domain/repositories/data.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'search.g.dart';
|
part 'search.g.dart';
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
Future<Uri> triggerBangSearch(
|
class BangSearch extends _$BangSearch {
|
||||||
Ref ref,
|
Future<Uri> triggerBangSearch(BangData bang, String searchQuery) async {
|
||||||
BangData bang,
|
final bangDataNotifier = ref.read(bangDataRepositoryProvider.notifier);
|
||||||
String searchQuery,
|
|
||||||
) async {
|
|
||||||
final bangDataNotifier = ref.watch(bangDataRepositoryProvider.notifier);
|
|
||||||
|
|
||||||
await bangDataNotifier.increaseFrequency(bang.trigger);
|
await bangDataNotifier.increaseFrequency(bang.trigger);
|
||||||
await bangDataNotifier.addSearchEntry(
|
await bangDataNotifier.addSearchEntry(
|
||||||
bang.trigger,
|
bang.trigger,
|
||||||
searchQuery,
|
searchQuery,
|
||||||
maxEntryCount: 3,
|
maxEntryCount: 3,
|
||||||
); //TODO: make count dynamic
|
); //TODO: make count dynamic
|
||||||
|
|
||||||
return bang.getUrl(searchQuery);
|
return bang.getUrl(searchQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void build() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,172 +6,20 @@ part of 'search.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$triggerBangSearchHash() => r'a5cff116ae09b26d4fa476ce6a2e6052fa6fa177';
|
String _$bangSearchHash() => r'a9bc5efc6e0df7b64bb648623f65911373a8e8e4';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// See also [BangSearch].
|
||||||
class _SystemHash {
|
@ProviderFor(BangSearch)
|
||||||
_SystemHash._();
|
final bangSearchProvider =
|
||||||
|
AutoDisposeNotifierProvider<BangSearch, void>.internal(
|
||||||
|
BangSearch.new,
|
||||||
|
name: r'bangSearchProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product') ? null : _$bangSearchHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
static int combine(int hash, int value) {
|
typedef _$BangSearch = AutoDisposeNotifier<void>;
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = 0x1fffffff & (hash + value);
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
|
||||||
return hash ^ (hash >> 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int finish(int hash) {
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
hash = hash ^ (hash >> 11);
|
|
||||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [triggerBangSearch].
|
|
||||||
@ProviderFor(triggerBangSearch)
|
|
||||||
const triggerBangSearchProvider = TriggerBangSearchFamily();
|
|
||||||
|
|
||||||
/// See also [triggerBangSearch].
|
|
||||||
class TriggerBangSearchFamily extends Family<AsyncValue<Uri>> {
|
|
||||||
/// See also [triggerBangSearch].
|
|
||||||
const TriggerBangSearchFamily();
|
|
||||||
|
|
||||||
/// See also [triggerBangSearch].
|
|
||||||
TriggerBangSearchProvider call(
|
|
||||||
BangData bang,
|
|
||||||
String searchQuery,
|
|
||||||
) {
|
|
||||||
return TriggerBangSearchProvider(
|
|
||||||
bang,
|
|
||||||
searchQuery,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
TriggerBangSearchProvider getProviderOverride(
|
|
||||||
covariant TriggerBangSearchProvider provider,
|
|
||||||
) {
|
|
||||||
return call(
|
|
||||||
provider.bang,
|
|
||||||
provider.searchQuery,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
|
||||||
_allTransitiveDependencies;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get name => r'triggerBangSearchProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [triggerBangSearch].
|
|
||||||
class TriggerBangSearchProvider extends AutoDisposeFutureProvider<Uri> {
|
|
||||||
/// See also [triggerBangSearch].
|
|
||||||
TriggerBangSearchProvider(
|
|
||||||
BangData bang,
|
|
||||||
String searchQuery,
|
|
||||||
) : this._internal(
|
|
||||||
(ref) => triggerBangSearch(
|
|
||||||
ref as TriggerBangSearchRef,
|
|
||||||
bang,
|
|
||||||
searchQuery,
|
|
||||||
),
|
|
||||||
from: triggerBangSearchProvider,
|
|
||||||
name: r'triggerBangSearchProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$triggerBangSearchHash,
|
|
||||||
dependencies: TriggerBangSearchFamily._dependencies,
|
|
||||||
allTransitiveDependencies:
|
|
||||||
TriggerBangSearchFamily._allTransitiveDependencies,
|
|
||||||
bang: bang,
|
|
||||||
searchQuery: searchQuery,
|
|
||||||
);
|
|
||||||
|
|
||||||
TriggerBangSearchProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.bang,
|
|
||||||
required this.searchQuery,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final BangData bang;
|
|
||||||
final String searchQuery;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(
|
|
||||||
FutureOr<Uri> Function(TriggerBangSearchRef provider) create,
|
|
||||||
) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
|
||||||
override: TriggerBangSearchProvider._internal(
|
|
||||||
(ref) => create(ref as TriggerBangSearchRef),
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
debugGetCreateSourceHash: null,
|
|
||||||
bang: bang,
|
|
||||||
searchQuery: searchQuery,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
AutoDisposeFutureProviderElement<Uri> createElement() {
|
|
||||||
return _TriggerBangSearchProviderElement(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return other is TriggerBangSearchProvider &&
|
|
||||||
other.bang == bang &&
|
|
||||||
other.searchQuery == searchQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode {
|
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
|
||||||
hash = _SystemHash.combine(hash, bang.hashCode);
|
|
||||||
hash = _SystemHash.combine(hash, searchQuery.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
mixin TriggerBangSearchRef on AutoDisposeFutureProviderRef<Uri> {
|
|
||||||
/// The parameter `bang` of this provider.
|
|
||||||
BangData get bang;
|
|
||||||
|
|
||||||
/// The parameter `searchQuery` of this provider.
|
|
||||||
String get searchQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _TriggerBangSearchProviderElement
|
|
||||||
extends AutoDisposeFutureProviderElement<Uri> with TriggerBangSearchRef {
|
|
||||||
_TriggerBangSearchProviderElement(super.provider);
|
|
||||||
|
|
||||||
@override
|
|
||||||
BangData get bang => (origin as TriggerBangSearchProvider).bang;
|
|
||||||
@override
|
|
||||||
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
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
|
||||||
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
||||||
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/search_history_entry.dart';
|
import 'package:lensai/features/bangs/data/models/search_history_entry.dart';
|
||||||
import 'package:lensai/features/bangs/data/providers.dart';
|
import 'package:lensai/features/bangs/data/providers.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|||||||
@@ -57,6 +57,6 @@ class SeamlessBangProvider extends _$SeamlessBangProvider {
|
|||||||
AsyncValue<List<BangData>> build() {
|
AsyncValue<List<BangData>> build() {
|
||||||
return _hasSearch
|
return _hasSearch
|
||||||
? ref.watch(bangSearchProvider)
|
? ref.watch(bangSearchProvider)
|
||||||
: ref.watch(frequentBangDataListProvider);
|
: ref.watch(frequentBangListProvider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ final bangSearchProvider =
|
|||||||
|
|
||||||
typedef _$BangSearch = AutoDisposeStreamNotifier<List<BangData>>;
|
typedef _$BangSearch = AutoDisposeStreamNotifier<List<BangData>>;
|
||||||
String _$seamlessBangProviderHash() =>
|
String _$seamlessBangProviderHash() =>
|
||||||
r'd2c8e94d6305a6a37cc27f8bc3617521f513e537';
|
r'c4c0b452c94ba447be5b02dfef5bc16148cc3dc7';
|
||||||
|
|
||||||
/// See also [SeamlessBangProvider].
|
/// See also [SeamlessBangProvider].
|
||||||
@ProviderFor(SeamlessBangProvider)
|
@ProviderFor(SeamlessBangProvider)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'package:drift/isolate.dart';
|
import 'package:drift/isolate.dart';
|
||||||
import 'package:exceptions/exceptions.dart';
|
import 'package:exceptions/exceptions.dart';
|
||||||
import 'package:lensai/features/bangs/data/database/database.dart';
|
import 'package:lensai/features/bangs/data/database/database.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang.dart';
|
import 'package:lensai/features/bangs/data/models/bang_group.dart';
|
||||||
import 'package:lensai/features/bangs/data/providers.dart';
|
import 'package:lensai/features/bangs/data/providers.dart';
|
||||||
import 'package:lensai/features/bangs/data/services/source.dart';
|
import 'package:lensai/features/bangs/data/services/data_source.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ part 'sync.g.dart';
|
|||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
class BangSyncRepository extends _$BangSyncRepository {
|
class BangSyncRepository extends _$BangSyncRepository {
|
||||||
static Future<Result<void>> _fetchAndSync({
|
static Future<Result<void>> _fetchAndSync({
|
||||||
required BangSourceService sourceService,
|
required BangDataSourceService sourceService,
|
||||||
required BangDatabase db,
|
required BangDatabase db,
|
||||||
required Uri url,
|
required Uri url,
|
||||||
required BangGroup group,
|
required BangGroup group,
|
||||||
@@ -20,7 +20,7 @@ class BangSyncRepository extends _$BangSyncRepository {
|
|||||||
}) async {
|
}) async {
|
||||||
if (syncInterval != null) {
|
if (syncInterval != null) {
|
||||||
final lastSync =
|
final lastSync =
|
||||||
await db.syncDao.lastSyncOfGroup(group).getSingleOrNull();
|
await db.syncDao.getLastSyncOfGroup(group).getSingleOrNull();
|
||||||
|
|
||||||
if (lastSync != null &&
|
if (lastSync != null &&
|
||||||
DateTime.now().difference(lastSync) < syncInterval) {
|
DateTime.now().difference(lastSync) < syncInterval) {
|
||||||
@@ -52,7 +52,9 @@ class BangSyncRepository extends _$BangSyncRepository {
|
|||||||
computation: (db) async {
|
computation: (db) async {
|
||||||
final ref = ProviderContainer();
|
final ref = ProviderContainer();
|
||||||
final result = await _fetchAndSync(
|
final result = await _fetchAndSync(
|
||||||
sourceService: ref.read(bangSourceServiceProvider.notifier),
|
sourceService: ref.read(
|
||||||
|
bangDataSourceServiceProvider.notifier,
|
||||||
|
),
|
||||||
db: db,
|
db: db,
|
||||||
url: Uri.parse(group.url),
|
url: Uri.parse(group.url),
|
||||||
group: group,
|
group: group,
|
||||||
@@ -79,7 +81,7 @@ class BangSyncRepository extends _$BangSyncRepository {
|
|||||||
return ref
|
return ref
|
||||||
.read(bangDatabaseProvider)
|
.read(bangDatabaseProvider)
|
||||||
.syncDao
|
.syncDao
|
||||||
.lastSyncOfGroup(group)
|
.getLastSyncOfGroup(group)
|
||||||
.watchSingleOrNull();
|
.watchSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'sync.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$bangSyncRepositoryHash() =>
|
String _$bangSyncRepositoryHash() =>
|
||||||
r'a46813f953e550585f432b11c364d87791819c34';
|
r'122dd04da82d4124e7c6be5234831bd62242845e';
|
||||||
|
|
||||||
/// See also [BangSyncRepository].
|
/// See also [BangSyncRepository].
|
||||||
@ProviderFor(BangSyncRepository)
|
@ProviderFor(BangSyncRepository)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import 'package:lensai/features/bangs/presentation/widgets/bang_details.dart';
|
|||||||
import 'package:lensai/features/geckoview/domain/controllers/bottom_sheet.dart';
|
import 'package:lensai/features/geckoview/domain/controllers/bottom_sheet.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/providers.dart';
|
import 'package:lensai/features/geckoview/features/browser/domain/providers.dart';
|
||||||
import 'package:lensai/features/kagi/data/entities/modes.dart';
|
|
||||||
import 'package:lensai/presentation/widgets/failure_widget.dart';
|
import 'package:lensai/presentation/widgets/failure_widget.dart';
|
||||||
|
|
||||||
class BangListScreen extends HookConsumerWidget {
|
class BangListScreen extends HookConsumerWidget {
|
||||||
@@ -20,14 +19,9 @@ class BangListScreen extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final bangsAsync = ref.watch(
|
final bangsAsync = ref.watch(
|
||||||
bangDataListProvider(
|
bangListProvider(
|
||||||
filter: (
|
categoryFilter: category.mapNotNull(
|
||||||
categoryFilter: category.mapNotNull(
|
(category) => (category: category, subCategory: subCategory),
|
||||||
(category) => (category: category, subCategory: subCategory),
|
|
||||||
),
|
|
||||||
domain: null,
|
|
||||||
groups: null,
|
|
||||||
orderMostFrequentFirst: null,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -49,16 +43,7 @@ class BangListScreen extends HookConsumerWidget {
|
|||||||
.read(selectedBangTriggerProvider().notifier)
|
.read(selectedBangTriggerProvider().notifier)
|
||||||
.setTrigger(bang.trigger);
|
.setTrigger(bang.trigger);
|
||||||
|
|
||||||
if (ref.read(bottomSheetControllerProvider)
|
context.go(const SearchRoute().location);
|
||||||
is! CreateTabSheet) {
|
|
||||||
ref
|
|
||||||
.read(bottomSheetControllerProvider.notifier)
|
|
||||||
.show(
|
|
||||||
CreateTabSheet(preferredTool: KagiTool.search),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.go(BrowserRoute().location);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -74,14 +74,6 @@ class BangSearchScreen extends HookConsumerWidget {
|
|||||||
.read(selectedBangTriggerProvider().notifier)
|
.read(selectedBangTriggerProvider().notifier)
|
||||||
.setTrigger(bang.trigger);
|
.setTrigger(bang.trigger);
|
||||||
|
|
||||||
// if (ref.read(bottomSheetControllerProvider)
|
|
||||||
// is! CreateTabSheet) {
|
|
||||||
// ref.read(bottomSheetControllerProvider.notifier).show(
|
|
||||||
// CreateTabSheet(preferredTool: KagiTool.search),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// context.go(BrowserRoute().location);
|
|
||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ class SiteSearch extends HookConsumerWidget {
|
|||||||
|
|
||||||
Future<void> submitSearch(String query) async {
|
Future<void> submitSearch(String query) async {
|
||||||
if (activeBang != null && (formKey.currentState?.validate() == true)) {
|
if (activeBang != null && (formKey.currentState?.validate() == true)) {
|
||||||
final searchUri = await ref.read(
|
final searchUri = await ref
|
||||||
triggerBangSearchProvider(activeBang, query).future,
|
.read(bangSearchProvider.notifier)
|
||||||
);
|
.triggerBangSearch(activeBang, query);
|
||||||
|
|
||||||
await ref.read(tabRepositoryProvider.notifier).addTab(url: searchUri);
|
await ref.read(tabRepositoryProvider.notifier).addTab(url: searchUri);
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ class MessagesDao extends DatabaseAccessor<ChatDatabase>
|
|||||||
with _$MessagesDaoMixin {
|
with _$MessagesDaoMixin {
|
||||||
MessagesDao(super.db);
|
MessagesDao(super.db);
|
||||||
|
|
||||||
Selectable<int> messageCount({required String chatId}) {
|
Selectable<int> getMessageCount({required String chatId}) {
|
||||||
return db.chatMessage.count(where: (row) => row.chatId.equals(chatId));
|
return db.chatMessage.count(where: (row) => row.chatId.equals(chatId));
|
||||||
}
|
}
|
||||||
|
|
||||||
Selectable<ChatMessageData> chatMessages({required String chatId}) {
|
Selectable<ChatMessageData> getChatMessages({required String chatId}) {
|
||||||
return db.chatMessage.select()
|
return db.chatMessage.select()
|
||||||
..where((t) => t.chatId.equals(chatId))
|
..where((t) => t.chatId.equals(chatId))
|
||||||
..orderBy([(row) => OrderingTerm(expression: row.orderKey)]);
|
..orderBy([(row) => OrderingTerm(expression: row.orderKey)]);
|
||||||
@@ -32,7 +32,7 @@ class MessagesDao extends DatabaseAccessor<ChatDatabase>
|
|||||||
.map((row) => row.read(existsExpression)!);
|
.map((row) => row.read(existsExpression)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleOrNullSelectable<int> messageIndex({
|
SingleOrNullSelectable<int> getMessageIndex({
|
||||||
required String chatId,
|
required String chatId,
|
||||||
required String messageId,
|
required String messageId,
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class MetadataDao extends DatabaseAccessor<ChatDatabase>
|
|||||||
with _$MetadataDaoMixin {
|
with _$MetadataDaoMixin {
|
||||||
MetadataDao(super.db);
|
MetadataDao(super.db);
|
||||||
|
|
||||||
SingleOrNullSelectable<ChatMetadata> chatMetadata(String chatId) {
|
SingleOrNullSelectable<ChatMetadata> getChatMetadata(String chatId) {
|
||||||
final statement =
|
final statement =
|
||||||
db.chatData.selectOnly()
|
db.chatData.selectOnly()
|
||||||
..addColumns([db.chatData.metadata])
|
..addColumns([db.chatData.metadata])
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
import 'package:fast_equatable/fast_equatable.dart';
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
part 'chat_metadata.g.dart';
|
part 'chat_metadata.g.dart';
|
||||||
|
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class ChatMetadata {
|
class ChatMetadata with FastEquatable {
|
||||||
final String? mainDocumentId;
|
final String? mainDocumentId;
|
||||||
final String? contextId;
|
final String? contextId;
|
||||||
|
|
||||||
@@ -13,4 +14,10 @@ class ChatMetadata {
|
|||||||
_$ChatMetadataFromJson(json);
|
_$ChatMetadataFromJson(json);
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => _$ChatMetadataToJson(this);
|
Map<String, dynamic> toJson() => _$ChatMetadataToJson(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get cacheHash => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get hashParameters => [mainDocumentId, contextId];
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -19,7 +19,7 @@ class DriftChatController implements ChatController {
|
|||||||
DriftChatController(this._dao, {required this.chatId}) {
|
DriftChatController(this._dao, {required this.chatId}) {
|
||||||
final chatMessagesStream =
|
final chatMessagesStream =
|
||||||
_dao
|
_dao
|
||||||
.chatMessages(chatId: chatId)
|
.getChatMessages(chatId: chatId)
|
||||||
.map(
|
.map(
|
||||||
(data) => Message.fromJson(
|
(data) => Message.fromJson(
|
||||||
jsonDecode(data.messageJson) as Map<String, dynamic>,
|
jsonDecode(data.messageJson) as Map<String, dynamic>,
|
||||||
@@ -78,7 +78,7 @@ class DriftChatController implements ChatController {
|
|||||||
Future<void> remove(Message message) async {
|
Future<void> remove(Message message) async {
|
||||||
final index =
|
final index =
|
||||||
await _dao
|
await _dao
|
||||||
.messageIndex(chatId: chatId, messageId: message.id)
|
.getMessageIndex(chatId: chatId, messageId: message.id)
|
||||||
.getSingleOrNull();
|
.getSingleOrNull();
|
||||||
|
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:lensai/features/chat/features/chat_store/data/models/chat_metadata.dart';
|
import 'package:lensai/features/chat/features/chat_store/data/models/chat_metadata.dart';
|
||||||
import 'package:lensai/features/chat/features/chat_store/data/providers.dart';
|
import 'package:lensai/features/chat/features/chat_store/data/providers.dart';
|
||||||
import 'package:lensai/features/chat/features/chat_store/domain/drift_chat_controller.dart';
|
import 'package:lensai/features/chat/features/chat_store/domain/controllers/drift_chat_controller.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
@@ -21,5 +21,5 @@ DriftChatController chatController(Ref ref, String chatId) {
|
|||||||
@Riverpod()
|
@Riverpod()
|
||||||
Stream<ChatMetadata?> chatMetadata(Ref ref, String chatId) {
|
Stream<ChatMetadata?> chatMetadata(Ref ref, String chatId) {
|
||||||
final db = ref.watch(chatDatabaseProvider);
|
final db = ref.watch(chatDatabaseProvider);
|
||||||
return db.metadataDao.chatMetadata(chatId).watchSingleOrNull();
|
return db.metadataDao.getChatMetadata(chatId).watchSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ class _ChatControllerProviderElement
|
|||||||
String get chatId => (origin as ChatControllerProvider).chatId;
|
String get chatId => (origin as ChatControllerProvider).chatId;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$chatMetadataHash() => r'22252e4a4c4e9cb039c5eee0e0f6eb5b8bd03944';
|
String _$chatMetadataHash() => r'e50f492ae69168c9f9c4df89e29424b72b681e27';
|
||||||
|
|
||||||
/// See also [chatMetadata].
|
/// See also [chatMetadata].
|
||||||
@ProviderFor(chatMetadata)
|
@ProviderFor(chatMetadata)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'package:flutter_chat_core/flutter_chat_core.dart';
|
|||||||
import 'package:langchain/langchain.dart';
|
import 'package:langchain/langchain.dart';
|
||||||
import 'package:lensai/core/uuid.dart';
|
import 'package:lensai/core/uuid.dart';
|
||||||
import 'package:lensai/features/chat/features/chat_store/data/models/message_types.dart';
|
import 'package:lensai/features/chat/features/chat_store/data/models/message_types.dart';
|
||||||
import 'package:lensai/features/chat/features/chat_store/domain/drift_chat_controller.dart';
|
import 'package:lensai/features/chat/features/chat_store/domain/controllers/drift_chat_controller.dart';
|
||||||
import 'package:lensai/features/chat/features/chat_store/domain/providers.dart';
|
import 'package:lensai/features/chat/features/chat_store/domain/providers.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/services/create_tab.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
|
|
||||||
@@ -11,8 +10,7 @@ part 'bottom_sheet.g.dart';
|
|||||||
class BottomSheetController extends _$BottomSheetController {
|
class BottomSheetController extends _$BottomSheetController {
|
||||||
@override
|
@override
|
||||||
Sheet? build() {
|
Sheet? build() {
|
||||||
//Don't use select here because it will only fire on new != previous
|
return null;
|
||||||
return ref.watch(createTabStreamProvider).valueOrNull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore: use_setters_to_change_properties api decision
|
// ignore: use_setters_to_change_properties api decision
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'bottom_sheet.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$bottomSheetControllerHash() =>
|
String _$bottomSheetControllerHash() =>
|
||||||
r'ae91f911fc35fdc0dfb14149ac2295e58ad13a86';
|
r'0b0ea53a96b80b8c1cba79b1d5913274b7127d5b';
|
||||||
|
|
||||||
/// See also [BottomSheetController].
|
/// See also [BottomSheetController].
|
||||||
@ProviderFor(BottomSheetController)
|
@ProviderFor(BottomSheetController)
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'overlay_dialog.g.dart';
|
part 'overlay.g.dart';
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
class OverlayDialogController extends _$OverlayDialogController {
|
class OverlayController extends _$OverlayController {
|
||||||
@override
|
@override
|
||||||
Widget? build() {
|
Widget? build() {
|
||||||
return null;
|
return null;
|
||||||
+10
-10
@@ -1,26 +1,26 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'chat.dart';
|
part of 'overlay.dart';
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$kagiChatServiceHash() => r'a112b70b42fe9d650c9d4dc643bf965ddce7bfa6';
|
String _$overlayControllerHash() => r'b6dc3ca17611c4efadc7e8248d493cd3c7061e01';
|
||||||
|
|
||||||
/// See also [KagiChatService].
|
/// See also [OverlayController].
|
||||||
@ProviderFor(KagiChatService)
|
@ProviderFor(OverlayController)
|
||||||
final kagiChatServiceProvider =
|
final overlayControllerProvider =
|
||||||
NotifierProvider<KagiChatService, void>.internal(
|
AutoDisposeNotifierProvider<OverlayController, Widget?>.internal(
|
||||||
KagiChatService.new,
|
OverlayController.new,
|
||||||
name: r'kagiChatServiceProvider',
|
name: r'overlayControllerProvider',
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
? null
|
? null
|
||||||
: _$kagiChatServiceHash,
|
: _$overlayControllerHash,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
allTransitiveDependencies: null,
|
allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef _$KagiChatService = Notifier<void>;
|
typedef _$OverlayController = AutoDisposeNotifier<Widget?>;
|
||||||
// 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
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'overlay_dialog.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// RiverpodGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
String _$overlayDialogControllerHash() =>
|
|
||||||
r'53b44d9567bcb5bd9faecbfb8bb1af5aafb369c9';
|
|
||||||
|
|
||||||
/// See also [OverlayDialogController].
|
|
||||||
@ProviderFor(OverlayDialogController)
|
|
||||||
final overlayDialogControllerProvider =
|
|
||||||
AutoDisposeNotifierProvider<OverlayDialogController, Widget?>.internal(
|
|
||||||
OverlayDialogController.new,
|
|
||||||
name: r'overlayDialogControllerProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$overlayDialogControllerHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$OverlayDialogController = AutoDisposeNotifier<Widget?>;
|
|
||||||
// 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
|
|
||||||
+5
-5
@@ -5,12 +5,12 @@ import 'package:lensai/data/models/web_page_info.dart';
|
|||||||
import 'package:lensai/domain/entities/equatable_image.dart';
|
import 'package:lensai/domain/entities/equatable_image.dart';
|
||||||
import 'package:lensai/extensions/nullable.dart';
|
import 'package:lensai/extensions/nullable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/browser_icon.dart';
|
import 'package:lensai/features/geckoview/domain/entities/browser_icon.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/find_result_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/find_result.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/history_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/history.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/readerable_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/readerable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/security_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/security.dart';
|
||||||
|
|
||||||
part 'tab_state.g.dart';
|
part 'tab.g.dart';
|
||||||
|
|
||||||
@CopyWith()
|
@CopyWith()
|
||||||
class TabState extends WebPageInfo with FastEquatable {
|
class TabState extends WebPageInfo with FastEquatable {
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'tab_state.dart';
|
part of 'tab.dart';
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// CopyWithGenerator
|
// CopyWithGenerator
|
||||||
+1
-1
@@ -4,7 +4,7 @@ import 'package:copy_with_extension/copy_with_extension.dart';
|
|||||||
import 'package:fast_equatable/fast_equatable.dart';
|
import 'package:fast_equatable/fast_equatable.dart';
|
||||||
import 'package:lensai/domain/entities/equatable_image.dart';
|
import 'package:lensai/domain/entities/equatable_image.dart';
|
||||||
|
|
||||||
part 'web_extension_state.g.dart';
|
part 'web_extension.g.dart';
|
||||||
|
|
||||||
@CopyWith()
|
@CopyWith()
|
||||||
class WebExtensionState with FastEquatable {
|
class WebExtensionState with FastEquatable {
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'web_extension_state.dart';
|
part of 'web_extension.dart';
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// CopyWithGenerator
|
// CopyWithGenerator
|
||||||
@@ -3,7 +3,6 @@ import 'dart:async';
|
|||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
import 'package:lensai/core/logger.dart';
|
import 'package:lensai/core/logger.dart';
|
||||||
import 'package:lensai/features/bangs/domain/providers/bangs.dart';
|
import 'package:lensai/features/bangs/domain/providers/bangs.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
|
||||||
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
@@ -152,8 +151,3 @@ class EngineReadyState extends _$EngineReadyState {
|
|||||||
return currentState;
|
return currentState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod()
|
|
||||||
Raw<TabSession> selectedTabSessionNotifier(Ref ref) {
|
|
||||||
return ref.watch(tabSessionProvider(tabId: null).notifier);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -93,25 +93,6 @@ final engineSuggestionsServiceProvider =
|
|||||||
@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 EngineSuggestionsServiceRef = ProviderRef<GeckoSuggestionsService>;
|
typedef EngineSuggestionsServiceRef = ProviderRef<GeckoSuggestionsService>;
|
||||||
String _$selectedTabSessionNotifierHash() =>
|
|
||||||
r'aef19991d5b05a2bb28e8a6ccb57dc75c2f3148f';
|
|
||||||
|
|
||||||
/// See also [selectedTabSessionNotifier].
|
|
||||||
@ProviderFor(selectedTabSessionNotifier)
|
|
||||||
final selectedTabSessionNotifierProvider =
|
|
||||||
AutoDisposeProvider<Raw<TabSession>>.internal(
|
|
||||||
selectedTabSessionNotifier,
|
|
||||||
name: r'selectedTabSessionNotifierProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$selectedTabSessionNotifierHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
typedef SelectedTabSessionNotifierRef = AutoDisposeProviderRef<Raw<TabSession>>;
|
|
||||||
String _$engineReadyStateHash() => r'c682333e2e07cf0635aa7ae793a2088ca648c950';
|
String _$engineReadyStateHash() => r'c682333e2e07cf0635aa7ae793a2088ca648c950';
|
||||||
|
|
||||||
/// See also [EngineReadyState].
|
/// See also [EngineReadyState].
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
|
import 'package:lensai/domain/entities/equatable_iterable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers.dart';
|
import 'package:lensai/features/geckoview/domain/providers.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ part 'tab_list.g.dart';
|
|||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
class TabList extends _$TabList {
|
class TabList extends _$TabList {
|
||||||
@override
|
@override
|
||||||
List<String> build() {
|
EquatableCollection<List<String>> build() {
|
||||||
final eventService = ref.watch(eventServiceProvider);
|
final eventService = ref.watch(eventServiceProvider);
|
||||||
|
|
||||||
ref.listen(fireImmediately: true, engineReadyStateProvider, (
|
ref.listen(fireImmediately: true, engineReadyStateProvider, (
|
||||||
@@ -23,8 +23,10 @@ class TabList extends _$TabList {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final tabListSub = eventService.tabListEvents.listen((tabs) async {
|
final tabListSub = eventService.tabListEvents.listen((tabs) async {
|
||||||
if (!const DeepCollectionEquality().equals(state, tabs)) {
|
final equatableTabs = EquatableCollection(tabs, immutable: true);
|
||||||
state = tabs;
|
|
||||||
|
if (equatableTabs != state) {
|
||||||
|
state = equatableTabs;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -32,6 +34,6 @@ class TabList extends _$TabList {
|
|||||||
unawaited(tabListSub.cancel());
|
unawaited(tabListSub.cancel());
|
||||||
});
|
});
|
||||||
|
|
||||||
return [];
|
return EquatableCollection([], immutable: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ part of 'tab_list.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$tabListHash() => r'039099bfa102a86fd73c0544ea71f93f91e9d352';
|
String _$tabListHash() => r'bb8b6cca42a8aace8bd9808fdeac4fe4965ac867';
|
||||||
|
|
||||||
/// See also [TabList].
|
/// See also [TabList].
|
||||||
@ProviderFor(TabList)
|
@ProviderFor(TabList)
|
||||||
final tabListProvider = NotifierProvider<TabList, List<String>>.internal(
|
final tabListProvider =
|
||||||
|
NotifierProvider<TabList, EquatableCollection<List<String>>>.internal(
|
||||||
TabList.new,
|
TabList.new,
|
||||||
name: r'tabListProvider',
|
name: r'tabListProvider',
|
||||||
debugGetCreateSourceHash:
|
debugGetCreateSourceHash:
|
||||||
@@ -19,6 +20,6 @@ final tabListProvider = NotifierProvider<TabList, List<String>>.internal(
|
|||||||
allTransitiveDependencies: null,
|
allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef _$TabList = Notifier<List<String>>;
|
typedef _$TabList = Notifier<EquatableCollection<List<String>>>;
|
||||||
// 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
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'tab_session.g.dart';
|
part 'tab_session.g.dart';
|
||||||
@@ -49,3 +50,8 @@ class TabSession extends _$TabSession {
|
|||||||
: GeckoSessionService.forActiveTab();
|
: GeckoSessionService.forActiveTab();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Riverpod()
|
||||||
|
Raw<TabSession> selectedTabSessionNotifier(Ref ref) {
|
||||||
|
return ref.watch(tabSessionProvider(tabId: null).notifier);
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,25 @@ part of 'tab_session.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$selectedTabSessionNotifierHash() =>
|
||||||
|
r'aef19991d5b05a2bb28e8a6ccb57dc75c2f3148f';
|
||||||
|
|
||||||
|
/// See also [selectedTabSessionNotifier].
|
||||||
|
@ProviderFor(selectedTabSessionNotifier)
|
||||||
|
final selectedTabSessionNotifierProvider =
|
||||||
|
AutoDisposeProvider<Raw<TabSession>>.internal(
|
||||||
|
selectedTabSessionNotifier,
|
||||||
|
name: r'selectedTabSessionNotifierProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$selectedTabSessionNotifierHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
typedef SelectedTabSessionNotifierRef = AutoDisposeProviderRef<Raw<TabSession>>;
|
||||||
String _$tabSessionHash() => r'e4fbbcd430037cc01adb799783fb7974a11a27bf';
|
String _$tabSessionHash() => r'e4fbbcd430037cc01adb799783fb7974a11a27bf';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
|
|||||||
@@ -3,24 +3,21 @@ import 'dart:async';
|
|||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
import 'package:lensai/extensions/image.dart';
|
import 'package:lensai/extensions/image.dart';
|
||||||
import 'package:lensai/extensions/nullable.dart';
|
import 'package:lensai/extensions/nullable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/find_result_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/find_result.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/history_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/history.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/readerable_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/readerable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/security_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/security.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/tab.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers.dart';
|
import 'package:lensai/features/geckoview/domain/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
||||||
import 'package:lensai/features/geckoview/utils/image_helper.dart';
|
import 'package:lensai/features/geckoview/utils/image_helper.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:synchronized/synchronized.dart';
|
|
||||||
|
|
||||||
part 'tab_state.g.dart';
|
part 'tab_state.g.dart';
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
class TabStates extends _$TabStates {
|
class TabStates extends _$TabStates {
|
||||||
final _lock = Lock();
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -137,25 +134,25 @@ class TabStates extends _$TabStates {
|
|||||||
|
|
||||||
final subscriptions = [
|
final subscriptions = [
|
||||||
eventService.tabContentEvents.listen((event) async {
|
eventService.tabContentEvents.listen((event) async {
|
||||||
await _lock.synchronized(() => _onTabContentStateChange(event));
|
_onTabContentStateChange(event);
|
||||||
}),
|
}),
|
||||||
eventService.iconChangeEvents.listen((event) async {
|
eventService.iconChangeEvents.listen((event) async {
|
||||||
await _lock.synchronized(() => _onIconChange(event));
|
await _onIconChange(event);
|
||||||
}),
|
}),
|
||||||
eventService.thumbnailEvents.listen((event) async {
|
eventService.thumbnailEvents.listen((event) async {
|
||||||
await _lock.synchronized(() => _onThumbnailChange(event));
|
await _onThumbnailChange(event);
|
||||||
}),
|
}),
|
||||||
eventService.securityInfoEvents.listen((event) async {
|
eventService.securityInfoEvents.listen((event) async {
|
||||||
await _lock.synchronized(() => _onSecurityInfoStateChange(event));
|
_onSecurityInfoStateChange(event);
|
||||||
}),
|
}),
|
||||||
eventService.historyEvents.listen((event) async {
|
eventService.historyEvents.listen((event) async {
|
||||||
await _lock.synchronized(() => _onHistoryStateChange(event));
|
_onHistoryStateChange(event);
|
||||||
}),
|
}),
|
||||||
eventService.readerableEvents.listen((event) async {
|
eventService.readerableEvents.listen((event) async {
|
||||||
await _lock.synchronized(() => _onReaderableStateChange(event));
|
_onReaderableStateChange(event);
|
||||||
}),
|
}),
|
||||||
eventService.findResultsEvent.listen((event) async {
|
eventService.findResultsEvent.listen((event) async {
|
||||||
await _lock.synchronized(() => _onFindResultsChange(event));
|
_onFindResultsChange(event);
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ final selectedTabStateProvider = AutoDisposeProvider<TabState?>.internal(
|
|||||||
@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 SelectedTabStateRef = AutoDisposeProviderRef<TabState?>;
|
typedef SelectedTabStateRef = AutoDisposeProviderRef<TabState?>;
|
||||||
String _$tabStatesHash() => r'296d85ec016b22236b5830fce6b01cda81fbc02d';
|
String _$tabStatesHash() => r'c2169e467962d006015bf50d09e93b3f4bf596e6';
|
||||||
|
|
||||||
/// See also [TabStates].
|
/// See also [TabStates].
|
||||||
@ProviderFor(TabStates)
|
@ProviderFor(TabStates)
|
||||||
|
|||||||
@@ -5,11 +5,10 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
|||||||
import 'package:lensai/domain/entities/equatable_image.dart';
|
import 'package:lensai/domain/entities/equatable_image.dart';
|
||||||
import 'package:lensai/extensions/image.dart';
|
import 'package:lensai/extensions/image.dart';
|
||||||
import 'package:lensai/extensions/nullable.dart';
|
import 'package:lensai/extensions/nullable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/web_extension_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/web_extension.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers.dart';
|
import 'package:lensai/features/geckoview/domain/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/utils/image_helper.dart';
|
import 'package:lensai/features/geckoview/utils/image_helper.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:synchronized/synchronized.dart';
|
|
||||||
|
|
||||||
part 'web_extensions_state.g.dart';
|
part 'web_extensions_state.g.dart';
|
||||||
|
|
||||||
@@ -17,8 +16,6 @@ part 'web_extensions_state.g.dart';
|
|||||||
class WebExtensionsState extends _$WebExtensionsState {
|
class WebExtensionsState extends _$WebExtensionsState {
|
||||||
final _imageCache = <String, EquatableImage>{};
|
final _imageCache = <String, EquatableImage>{};
|
||||||
|
|
||||||
final _lock = Lock();
|
|
||||||
|
|
||||||
void _onExtensionUpdate(ExtensionDataEvent event) {
|
void _onExtensionUpdate(ExtensionDataEvent event) {
|
||||||
final ExtensionDataEvent(:extensionId, :data) = event;
|
final ExtensionDataEvent(:extensionId, :data) = event;
|
||||||
|
|
||||||
@@ -76,18 +73,18 @@ class WebExtensionsState extends _$WebExtensionsState {
|
|||||||
final subscriptions = switch (actionType) {
|
final subscriptions = switch (actionType) {
|
||||||
WebExtensionActionType.browser => [
|
WebExtensionActionType.browser => [
|
||||||
addonService.browserExtensionStream.listen((event) async {
|
addonService.browserExtensionStream.listen((event) async {
|
||||||
await _lock.synchronized(() => _onExtensionUpdate(event));
|
_onExtensionUpdate(event);
|
||||||
}),
|
}),
|
||||||
addonService.browserIconStream.listen((event) async {
|
addonService.browserIconStream.listen((event) async {
|
||||||
await _lock.synchronized(() => _onIconChange(event));
|
await _onIconChange(event);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
WebExtensionActionType.page => [
|
WebExtensionActionType.page => [
|
||||||
addonService.pageExtensionStream.listen((event) async {
|
addonService.pageExtensionStream.listen((event) async {
|
||||||
await _lock.synchronized(() => _onExtensionUpdate(event));
|
_onExtensionUpdate(event);
|
||||||
}),
|
}),
|
||||||
addonService.pageIconStream.listen((event) async {
|
addonService.pageIconStream.listen((event) async {
|
||||||
await _lock.synchronized(() => _onIconChange(event));
|
await _onIconChange(event);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'web_extensions_state.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$webExtensionsStateHash() =>
|
String _$webExtensionsStateHash() =>
|
||||||
r'4e6dc46e49ff353e1c3cc4616008685c0e21501d';
|
r'7fd0cb313fb433f7896bfe0f89a4545f94f58793';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|||||||
@@ -3,14 +3,16 @@ import 'dart:async';
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
import 'package:lensai/extensions/nullable.dart';
|
import 'package:lensai/extensions/nullable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/tab.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers.dart';
|
import 'package:lensai/features/geckoview/domain/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_list.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_list.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/browser/domain/providers/intent.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/data/providers.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/domain/providers/selected_container.dart';
|
import 'package:lensai/features/geckoview/features/tabs/domain/providers/selected_container.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/domain/repositories/container.dart';
|
import 'package:lensai/features/geckoview/features/tabs/domain/repositories/container.dart';
|
||||||
|
import 'package:lensai/features/share_intent/domain/entities/shared_content.dart';
|
||||||
import 'package:lensai/utils/debouncer.dart';
|
import 'package:lensai/utils/debouncer.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
@@ -93,9 +95,6 @@ class TabRepository extends _$TabRepository {
|
|||||||
final eventSerivce = ref.watch(eventServiceProvider);
|
final eventSerivce = ref.watch(eventServiceProvider);
|
||||||
final tabContentService = ref.watch(tabContentServiceProvider);
|
final tabContentService = ref.watch(tabContentServiceProvider);
|
||||||
|
|
||||||
final tabStateDebouncer = Debouncer(const Duration(seconds: 3));
|
|
||||||
Map<String, TabState>? debounceStartValue;
|
|
||||||
|
|
||||||
final db = ref.watch(tabDatabaseProvider);
|
final db = ref.watch(tabDatabaseProvider);
|
||||||
|
|
||||||
final tabAddedSub = eventSerivce.tabAddedStream.listen((tabId) async {
|
final tabAddedSub = eventSerivce.tabAddedStream.listen((tabId) async {
|
||||||
@@ -127,13 +126,18 @@ class TabRepository extends _$TabRepository {
|
|||||||
|
|
||||||
ref.listen(tabListProvider, (previous, next) async {
|
ref.listen(tabListProvider, (previous, next) async {
|
||||||
//Only sync tabs if there has been a previous value or is not empty
|
//Only sync tabs if there has been a previous value or is not empty
|
||||||
final syncTabs = next.isNotEmpty || (previous?.isNotEmpty ?? false);
|
final syncTabs =
|
||||||
|
next.collection.isNotEmpty ||
|
||||||
|
(previous?.collection.isNotEmpty ?? false);
|
||||||
|
|
||||||
if (syncTabs) {
|
if (syncTabs) {
|
||||||
await db.tabDao.syncTabs(retainTabIds: next);
|
await db.tabDao.syncTabs(retainTabIds: next.collection);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final tabStateDebouncer = Debouncer(const Duration(seconds: 3));
|
||||||
|
Map<String, TabState>? debounceStartValue;
|
||||||
|
|
||||||
ref.listen(tabStatesProvider, (previous, next) async {
|
ref.listen(tabStatesProvider, (previous, next) async {
|
||||||
//Since state changes occure pretty often and our map always contains
|
//Since state changes occure pretty often and our map always contains
|
||||||
//the latest state, we cache the value before starting debouncing and
|
//the latest state, we cache the value before starting debouncing and
|
||||||
@@ -147,6 +151,16 @@ class TabRepository extends _$TabRepository {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ref.listen(intentStreamProvider, (previous, next) {
|
||||||
|
next.whenData((value) async {
|
||||||
|
switch (value) {
|
||||||
|
case SharedUrl():
|
||||||
|
await addTab(url: value.url);
|
||||||
|
case SharedText():
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
ref.onDispose(() {
|
ref.onDispose(() {
|
||||||
tabStateDebouncer.dispose();
|
tabStateDebouncer.dispose();
|
||||||
unawaited(tabAddedSub.cancel());
|
unawaited(tabAddedSub.cancel());
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part of 'tab.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$tabRepositoryHash() => r'85af29fa18ea5a4a67fbffbb9478c801dafddac2';
|
String _$tabRepositoryHash() => r'ce0db685127eeb706ce047d7afcc58fafd1394ba';
|
||||||
|
|
||||||
/// See also [TabRepository].
|
/// See also [TabRepository].
|
||||||
@ProviderFor(TabRepository)
|
@ProviderFor(TabRepository)
|
||||||
|
|||||||
@@ -1,24 +1,8 @@
|
|||||||
import 'package:fast_equatable/fast_equatable.dart';
|
import 'package:fast_equatable/fast_equatable.dart';
|
||||||
import 'package:lensai/features/kagi/data/entities/modes.dart';
|
|
||||||
|
|
||||||
sealed class Sheet with FastEquatable {}
|
sealed class Sheet with FastEquatable {}
|
||||||
|
|
||||||
class CreateTabSheet extends Sheet {
|
final class ViewTabsSheet extends Sheet {
|
||||||
final String? content;
|
|
||||||
final KagiTool? preferredTool;
|
|
||||||
|
|
||||||
bool get hasParameters => content != null || preferredTool != null;
|
|
||||||
|
|
||||||
CreateTabSheet({this.content, this.preferredTool});
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get cacheHash => true;
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get hashParameters => [content, preferredTool];
|
|
||||||
}
|
|
||||||
|
|
||||||
class ViewTabsSheet extends Sheet {
|
|
||||||
@override
|
@override
|
||||||
bool get cacheHash => true;
|
bool get cacheHash => true;
|
||||||
|
|
||||||
@@ -26,7 +10,7 @@ class ViewTabsSheet extends Sheet {
|
|||||||
List<Object?> get hashParameters => [];
|
List<Object?> get hashParameters => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class TabQaChatSheet extends Sheet {
|
final class TabQaChatSheet extends Sheet {
|
||||||
final String chatId;
|
final String chatId;
|
||||||
|
|
||||||
TabQaChatSheet({required this.chatId});
|
TabQaChatSheet({required this.chatId});
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:lensai/data/models/equatable_iterable.dart';
|
import 'package:lensai/domain/entities/equatable_iterable.dart';
|
||||||
import 'package:lensai/extensions/nullable.dart';
|
import 'package:lensai/extensions/nullable.dart';
|
||||||
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
import 'package:lensai/features/bangs/data/models/bang_data.dart';
|
||||||
import 'package:lensai/features/bangs/domain/repositories/data.dart';
|
import 'package:lensai/features/bangs/domain/repositories/data.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/tab.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_list.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_list.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||||
import 'package:lensai/features/geckoview/features/search/domain/entities/tab_preview.dart';
|
import 'package:lensai/features/geckoview/features/search/domain/entities/tab_preview.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/data/entities/container_filter.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/entities/container_filter.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/domain/providers.dart';
|
import 'package:lensai/features/geckoview/features/tabs/domain/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/domain/repositories/tab_search.dart';
|
import 'package:lensai/features/geckoview/features/tabs/domain/repositories/tab_search.dart';
|
||||||
import 'package:lensai/features/kagi/data/entities/modes.dart';
|
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
@@ -58,48 +57,6 @@ class SelectedBangData extends _$SelectedBangData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
|
||||||
class LastUsedAssistantMode extends _$LastUsedAssistantMode {
|
|
||||||
// ignore: document_ignores api decision
|
|
||||||
// ignore: use_setters_to_change_properties
|
|
||||||
void update(AssistantMode mode) {
|
|
||||||
state = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
AssistantMode build() {
|
|
||||||
return AssistantMode.research;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
|
||||||
class ActiveResearchVariant extends _$ActiveResearchVariant {
|
|
||||||
// ignore: document_ignores api decision
|
|
||||||
// ignore: use_setters_to_change_properties
|
|
||||||
void update(ResearchVariant mode) {
|
|
||||||
state = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
ResearchVariant build() {
|
|
||||||
return ResearchVariant.expert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
|
||||||
class ActiveChatModel extends _$ActiveChatModel {
|
|
||||||
// ignore: document_ignores api decision
|
|
||||||
// ignore: use_setters_to_change_properties
|
|
||||||
void update(ChatModel model) {
|
|
||||||
state = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
ChatModel build() {
|
|
||||||
return ChatModel.gpt4o;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
class ShowFindInPage extends _$ShowFindInPage {
|
class ShowFindInPage extends _$ShowFindInPage {
|
||||||
// ignore: document_ignores api decision
|
// ignore: document_ignores api decision
|
||||||
@@ -127,7 +84,10 @@ EquatableCollection<List<String>> availableTabIds(
|
|||||||
final tabList = ref.watch(tabListProvider);
|
final tabList = ref.watch(tabListProvider);
|
||||||
|
|
||||||
return EquatableCollection(
|
return EquatableCollection(
|
||||||
containerTabs?.where((tabId) => tabList.contains(tabId)).toList() ?? [],
|
containerTabs
|
||||||
|
?.where((tabId) => tabList.collection.contains(tabId))
|
||||||
|
.toList() ??
|
||||||
|
[],
|
||||||
immutable: true,
|
immutable: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part of 'providers.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$availableTabIdsHash() => r'd8b55b012b38111c8d5e069987a55645d1a71b89';
|
String _$availableTabIdsHash() => r'e5c5f25dea67f7739dfb1d0d9e4453079817a7bc';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -908,56 +908,6 @@ class _SelectedBangDataProviderElement
|
|||||||
String? get domain => (origin as SelectedBangDataProvider).domain;
|
String? get domain => (origin as SelectedBangDataProvider).domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$lastUsedAssistantModeHash() =>
|
|
||||||
r'1255a2754a3ea5ea058d110fd9743897fe103a69';
|
|
||||||
|
|
||||||
/// See also [LastUsedAssistantMode].
|
|
||||||
@ProviderFor(LastUsedAssistantMode)
|
|
||||||
final lastUsedAssistantModeProvider =
|
|
||||||
NotifierProvider<LastUsedAssistantMode, AssistantMode>.internal(
|
|
||||||
LastUsedAssistantMode.new,
|
|
||||||
name: r'lastUsedAssistantModeProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$lastUsedAssistantModeHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$LastUsedAssistantMode = Notifier<AssistantMode>;
|
|
||||||
String _$activeResearchVariantHash() =>
|
|
||||||
r'8c65a3f5ead6cc4f9e2af85b607b7a49b0764ee3';
|
|
||||||
|
|
||||||
/// See also [ActiveResearchVariant].
|
|
||||||
@ProviderFor(ActiveResearchVariant)
|
|
||||||
final activeResearchVariantProvider =
|
|
||||||
NotifierProvider<ActiveResearchVariant, ResearchVariant>.internal(
|
|
||||||
ActiveResearchVariant.new,
|
|
||||||
name: r'activeResearchVariantProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$activeResearchVariantHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$ActiveResearchVariant = Notifier<ResearchVariant>;
|
|
||||||
String _$activeChatModelHash() => r'675f406af8b4aa92699d59e37b5805a81d03a799';
|
|
||||||
|
|
||||||
/// See also [ActiveChatModel].
|
|
||||||
@ProviderFor(ActiveChatModel)
|
|
||||||
final activeChatModelProvider =
|
|
||||||
NotifierProvider<ActiveChatModel, ChatModel>.internal(
|
|
||||||
ActiveChatModel.new,
|
|
||||||
name: r'activeChatModelProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$activeChatModelHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$ActiveChatModel = Notifier<ChatModel>;
|
|
||||||
String _$showFindInPageHash() => r'7ee5703f7d0c7e8a8dd6b0849d7b1e0a41fe24d9';
|
String _$showFindInPageHash() => r'7ee5703f7d0c7e8a8dd6b0849d7b1e0a41fe24d9';
|
||||||
|
|
||||||
/// See also [ShowFindInPage].
|
/// See also [ShowFindInPage].
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:lensai/data/models/received_intent_parameter.dart';
|
||||||
|
import 'package:lensai/extensions/nullable.dart';
|
||||||
|
import 'package:lensai/features/app_widget/domain/services/home_widget.dart';
|
||||||
|
import 'package:lensai/features/share_intent/domain/entities/shared_content.dart';
|
||||||
|
import 'package:lensai/features/share_intent/domain/services/sharing_intent.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:rxdart/rxdart.dart';
|
||||||
|
|
||||||
|
part 'intent.g.dart';
|
||||||
|
|
||||||
|
final _contentParserTransformer =
|
||||||
|
StreamTransformer<ReceivedIntentParameter, SharedContent>.fromHandlers(
|
||||||
|
handleData: (parameter, sink) {
|
||||||
|
final parsed = parameter.content.mapNotNull(
|
||||||
|
(content) => SharedContent.parse(content),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (parsed != null) {
|
||||||
|
sink.add(parsed);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
@Riverpod()
|
||||||
|
class IntentStream extends _$IntentStream {
|
||||||
|
late StreamController<SharedContent> _streamController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<SharedContent> build() {
|
||||||
|
_streamController = StreamController();
|
||||||
|
ref.onDispose(() async {
|
||||||
|
await _streamController.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
final sharingItentStream = ref.watch(sharingIntentStreamProvider);
|
||||||
|
final appWidgetLaunchStream = ref.watch(appWidgetLaunchStreamProvider);
|
||||||
|
|
||||||
|
return MergeStream([
|
||||||
|
sharingItentStream.transform(_contentParserTransformer),
|
||||||
|
appWidgetLaunchStream.transform(_contentParserTransformer),
|
||||||
|
_streamController.stream,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'intent.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$intentStreamHash() => r'e78268ec703cd0d1f08d41b9e10a487e6000b7da';
|
||||||
|
|
||||||
|
/// See also [IntentStream].
|
||||||
|
@ProviderFor(IntentStream)
|
||||||
|
final intentStreamProvider =
|
||||||
|
AutoDisposeStreamNotifierProvider<IntentStream, SharedContent>.internal(
|
||||||
|
IntentStream.new,
|
||||||
|
name: r'intentStreamProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product') ? null : _$intentStreamHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$IntentStream = AutoDisposeStreamNotifier<SharedContent>;
|
||||||
|
// 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
|
||||||
+2
-2
@@ -2,10 +2,10 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
|||||||
import 'package:lensai/features/user/data/models/general_settings.dart';
|
import 'package:lensai/features/user/data/models/general_settings.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'delete_browser_data.g.dart';
|
part 'browser_data.g.dart';
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
class DeleteBrowserDataService extends _$DeleteBrowserDataService {
|
class BrowserDataService extends _$BrowserDataService {
|
||||||
final _service = GeckoDeleteBrowserDataService();
|
final _service = GeckoDeleteBrowserDataService();
|
||||||
|
|
||||||
Future<void> deleteData(Set<DeleteBrowsingDataType>? types) async {
|
Future<void> deleteData(Set<DeleteBrowsingDataType>? types) async {
|
||||||
+11
-11
@@ -1,27 +1,27 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'session.dart';
|
part of 'browser_data.dart';
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$kagiSessionServiceHash() =>
|
String _$browserDataServiceHash() =>
|
||||||
r'8bed5d74d319ff2f874f42bc8596d02f05347c1f';
|
r'f56c60635505e06dbd5b05f1bcee9c25c4d0eaaf';
|
||||||
|
|
||||||
/// See also [KagiSessionService].
|
/// See also [BrowserDataService].
|
||||||
@ProviderFor(KagiSessionService)
|
@ProviderFor(BrowserDataService)
|
||||||
final kagiSessionServiceProvider =
|
final browserDataServiceProvider =
|
||||||
AutoDisposeNotifierProvider<KagiSessionService, void>.internal(
|
AutoDisposeNotifierProvider<BrowserDataService, void>.internal(
|
||||||
KagiSessionService.new,
|
BrowserDataService.new,
|
||||||
name: r'kagiSessionServiceProvider',
|
name: r'browserDataServiceProvider',
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
? null
|
? null
|
||||||
: _$kagiSessionServiceHash,
|
: _$browserDataServiceHash,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
allTransitiveDependencies: null,
|
allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef _$KagiSessionService = AutoDisposeNotifier<void>;
|
typedef _$BrowserDataService = AutoDisposeNotifier<void>;
|
||||||
// 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
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:lensai/data/models/received_parameter.dart';
|
|
||||||
import 'package:lensai/features/app_widget/domain/services/home_widget.dart';
|
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
|
||||||
import 'package:lensai/features/kagi/data/entities/modes.dart';
|
|
||||||
import 'package:lensai/features/share_intent/domain/services/sharing_intent.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
||||||
import 'package:rxdart/rxdart.dart';
|
|
||||||
|
|
||||||
part 'create_tab.g.dart';
|
|
||||||
|
|
||||||
final _parameterToCreateTabSheetTransformer =
|
|
||||||
StreamTransformer<ReceivedParameter, CreateTabSheet>.fromHandlers(
|
|
||||||
handleData: (parameter, sink) {
|
|
||||||
final createTab = CreateTabSheet(
|
|
||||||
preferredTool: KagiTool.values.firstWhereOrNull(
|
|
||||||
(tool) => tool.name == parameter.tool,
|
|
||||||
),
|
|
||||||
content: parameter.content,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (createTab.hasParameters) {
|
|
||||||
sink.add(createTab);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
@Riverpod()
|
|
||||||
class CreateTabStream extends _$CreateTabStream {
|
|
||||||
late StreamController<CreateTabSheet> _streamController;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<CreateTabSheet> build() {
|
|
||||||
_streamController = StreamController();
|
|
||||||
ref.onDispose(() async {
|
|
||||||
await _streamController.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
final sharingItentStream = ref.watch(sharingIntentStreamProvider);
|
|
||||||
final appWidgetLaunchStream = ref.watch(appWidgetLaunchStreamProvider);
|
|
||||||
|
|
||||||
return MergeStream([
|
|
||||||
sharingItentStream.transform(_parameterToCreateTabSheetTransformer),
|
|
||||||
appWidgetLaunchStream.transform(_parameterToCreateTabSheetTransformer),
|
|
||||||
_streamController.stream,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void createTab(CreateTabSheet parameter) {
|
|
||||||
if (!_streamController.isClosed) {
|
|
||||||
_streamController.add(parameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'delete_browser_data.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// RiverpodGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
String _$deleteBrowserDataServiceHash() =>
|
|
||||||
r'f5fdbac17c14693fceac913591750ca9285b496c';
|
|
||||||
|
|
||||||
/// See also [DeleteBrowserDataService].
|
|
||||||
@ProviderFor(DeleteBrowserDataService)
|
|
||||||
final deleteBrowserDataServiceProvider =
|
|
||||||
AutoDisposeNotifierProvider<DeleteBrowserDataService, void>.internal(
|
|
||||||
DeleteBrowserDataService.new,
|
|
||||||
name: r'deleteBrowserDataServiceProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$deleteBrowserDataServiceHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$DeleteBrowserDataService = AutoDisposeNotifier<void>;
|
|
||||||
// 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
|
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
import 'package:lensai/data/models/equatable_iterable.dart';
|
import 'package:lensai/domain/entities/equatable_iterable.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/domain/providers.dart';
|
import 'package:lensai/features/geckoview/features/tabs/domain/providers.dart';
|
||||||
import 'package:lensai/features/tor/domain/services/tor_proxy.dart';
|
import 'package:lensai/features/tor/domain/services/tor_proxy.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
// import 'package:collection/collection.dart';
|
|
||||||
// import 'package:flutter/material.dart';
|
|
||||||
// import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
// import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
// import 'package:lensai/data/models/equatable_iterable.dart';
|
|
||||||
// import 'package:lensai/extensions/nullable.dart';
|
|
||||||
// import 'package:lensai/features/geckoview/domain/entities/tab_state.dart';
|
|
||||||
// import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
|
||||||
// import 'package:lensai/features/geckoview/features/tabs/domain/providers.dart';
|
|
||||||
// import 'package:lensai/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
|
||||||
|
|
||||||
// class TabActionDialog extends HookConsumerWidget {
|
|
||||||
// final TabState initialTab;
|
|
||||||
|
|
||||||
// final void Function()? onDismiss;
|
|
||||||
|
|
||||||
// const TabActionDialog({
|
|
||||||
// required this.initialTab,
|
|
||||||
// this.onDismiss,
|
|
||||||
// super.key,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
// final tabState = ref.watch(tabStateProvider(initialTab.id)) ?? initialTab;
|
|
||||||
// final tabContainerId = ref.watch(
|
|
||||||
// tabContainerIdProvider(initialTab.id)
|
|
||||||
// .select((value) => value.valueOrNull),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// final containers = ref
|
|
||||||
// .watch(
|
|
||||||
// containersWithCountProvider.select(
|
|
||||||
// (value) => EquatableCollection(value.valueOrNull, immutable: true),
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
// .collection;
|
|
||||||
|
|
||||||
// final selectedContainer = containers
|
|
||||||
// ?.firstWhereOrNull((container) => container.id == tabContainerId);
|
|
||||||
|
|
||||||
// final expansionController = useExpansionTileController();
|
|
||||||
|
|
||||||
// return Stack(
|
|
||||||
// children: [
|
|
||||||
// ModalBarrier(
|
|
||||||
// color: Theme.of(context).dialogTheme.barrierColor ?? Colors.black54,
|
|
||||||
// onDismiss: onDismiss,
|
|
||||||
// ),
|
|
||||||
// SimpleDialog(
|
|
||||||
// titlePadding: const EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 0.0),
|
|
||||||
// contentPadding: EdgeInsets.zero,
|
|
||||||
// insetPadding: const EdgeInsets.symmetric(
|
|
||||||
// horizontal: 20.0,
|
|
||||||
// vertical: 24.0,
|
|
||||||
// ),
|
|
||||||
// title: ListTile(
|
|
||||||
// leading: RawImage(
|
|
||||||
// image: tabState.icon?.value,
|
|
||||||
// width: 24,
|
|
||||||
// height: 24,
|
|
||||||
// ),
|
|
||||||
// contentPadding: EdgeInsets.zero,
|
|
||||||
// title: Text(tabState.title),
|
|
||||||
// subtitle: Text(tabState.url.authority),
|
|
||||||
// ),
|
|
||||||
// children: [
|
|
||||||
// SizedBox(
|
|
||||||
// //We need this to stretch the dialog, then padding from dialog is applied
|
|
||||||
// width: double.maxFinite,
|
|
||||||
// child: ExpansionTile(
|
|
||||||
// controller: expansionController,
|
|
||||||
// leading: selectedContainer?.color.mapNotNull(
|
|
||||||
// (color) => CircleAvatar(backgroundColor: color),
|
|
||||||
// ),
|
|
||||||
// title: (selectedContainer != null)
|
|
||||||
// ? Text(selectedContainer.name ?? 'New Container')
|
|
||||||
// : const Text('Assign a Container'),
|
|
||||||
// children: containers
|
|
||||||
// ?.where((container) => container.id != tabContainerId)
|
|
||||||
// .map(
|
|
||||||
// (container) => ListTile(
|
|
||||||
// leading:
|
|
||||||
// CircleAvatar(backgroundColor: container.color),
|
|
||||||
// title: Text(container.name ?? 'New Container'),
|
|
||||||
// onTap: () async {
|
|
||||||
// await ref
|
|
||||||
// .read(tabDataRepositoryProvider.notifier)
|
|
||||||
// .assignContainer(initialTab.id, container.id);
|
|
||||||
|
|
||||||
// expansionController.collapse();
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
// .toList() ??
|
|
||||||
// [],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
+23
-102
@@ -3,7 +3,6 @@ import 'dart:ui' as ui;
|
|||||||
import 'package:fading_scroll/fading_scroll.dart';
|
import 'package:fading_scroll/fading_scroll.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@@ -14,22 +13,16 @@ import 'package:lensai/features/bangs/presentation/widgets/site_search.dart';
|
|||||||
import 'package:lensai/features/chat/features/chat_store/data/models/chat_metadata.dart';
|
import 'package:lensai/features/chat/features/chat_store/data/models/chat_metadata.dart';
|
||||||
import 'package:lensai/features/chat/features/chat_store/domain/repositories/chat_metadata.dart';
|
import 'package:lensai/features/chat/features/chat_store/domain/repositories/chat_metadata.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/controllers/bottom_sheet.dart';
|
import 'package:lensai/features/geckoview/domain/controllers/bottom_sheet.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers.dart';
|
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
||||||
import 'package:lensai/features/geckoview/features/search/domain/providers/engine_suggestions.dart';
|
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/browser_modules/address_with_suggestions_field.dart';
|
||||||
import 'package:lensai/features/kagi/data/entities/modes.dart';
|
|
||||||
import 'package:lensai/features/kagi/utils/url_builder.dart' as uri_builder;
|
|
||||||
import 'package:lensai/features/share_intent/domain/entities/shared_content.dart';
|
|
||||||
import 'package:lensai/features/user/domain/providers.dart';
|
import 'package:lensai/features/user/domain/providers.dart';
|
||||||
import 'package:lensai/presentation/hooks/listenable_callback.dart';
|
|
||||||
import 'package:lensai/presentation/widgets/auto_suggest_text_field.dart';
|
|
||||||
import 'package:lensai/presentation/widgets/failure_widget.dart';
|
import 'package:lensai/presentation/widgets/failure_widget.dart';
|
||||||
import 'package:lensai/presentation/widgets/website_title_tile.dart';
|
import 'package:lensai/presentation/widgets/website_title_tile.dart';
|
||||||
import 'package:lensai/utils/ui_helper.dart' as ui_helper;
|
import 'package:lensai/utils/ui_helper.dart' as ui_helper;
|
||||||
import 'package:lensai/utils/uri_parser.dart' as uri_parser;
|
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
||||||
class WebPageDialog extends HookConsumerWidget {
|
class WebPageDialog extends HookConsumerWidget {
|
||||||
@@ -43,14 +36,7 @@ class WebPageDialog extends HookConsumerWidget {
|
|||||||
final incognitoEnabled = ref.watch(incognitoModeEnabledProvider);
|
final incognitoEnabled = ref.watch(incognitoModeEnabledProvider);
|
||||||
|
|
||||||
final availableBangsAsync = ref.watch(
|
final availableBangsAsync = ref.watch(
|
||||||
bangDataListProvider(
|
bangListProvider(domain: url.host, orderMostFrequentFirst: true),
|
||||||
filter: (
|
|
||||||
domain: url.host,
|
|
||||||
groups: null,
|
|
||||||
categoryFilter: null,
|
|
||||||
orderMostFrequentFirst: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final availableBangCount = availableBangsAsync.valueOrNull?.length;
|
final availableBangCount = availableBangsAsync.valueOrNull?.length;
|
||||||
@@ -75,74 +61,9 @@ class WebPageDialog extends HookConsumerWidget {
|
|||||||
width: double.maxFinite,
|
width: double.maxFinite,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: HookConsumer(
|
child: AddressWithSuggestionsField(
|
||||||
builder: (context, ref, child) {
|
url: url,
|
||||||
final addressTextController = useTextEditingController(
|
incognitoEnabled: incognitoEnabled,
|
||||||
text: url.toString(),
|
|
||||||
);
|
|
||||||
final addressTextFocusNode = useFocusNode();
|
|
||||||
|
|
||||||
final suggestion = useState<String?>(null);
|
|
||||||
|
|
||||||
useListenableCallback(addressTextController, () async {
|
|
||||||
if (addressTextController.text.isNotEmpty) {
|
|
||||||
final result = await ref
|
|
||||||
.read(engineSuggestionsProvider.notifier)
|
|
||||||
.getAutocompleteSuggestion(
|
|
||||||
addressTextController.text,
|
|
||||||
);
|
|
||||||
|
|
||||||
suggestion.value = result;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return AutoSuggestTextField(
|
|
||||||
controller: addressTextController,
|
|
||||||
focusNode: addressTextFocusNode,
|
|
||||||
suggestion: suggestion.value,
|
|
||||||
enableIMEPersonalizedLearning: !incognitoEnabled,
|
|
||||||
keyboardType: TextInputType.url,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
label: Text('Address'),
|
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
if (!addressTextFocusNode.hasFocus) {
|
|
||||||
// Select all text when the field is tapped
|
|
||||||
addressTextController.selection = TextSelection(
|
|
||||||
baseOffset: 0,
|
|
||||||
extentOffset: addressTextController.text.length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSubmitted: (value) async {
|
|
||||||
if (value.isNotEmpty) {
|
|
||||||
var newUrl = uri_parser.tryParseUrl(
|
|
||||||
value,
|
|
||||||
eagerParsing: true,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (newUrl == null) {
|
|
||||||
final defaultSearchBang = await ref.read(
|
|
||||||
defaultSearchBangDataProvider.future,
|
|
||||||
);
|
|
||||||
|
|
||||||
newUrl = defaultSearchBang?.getUrl(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newUrl != null) {
|
|
||||||
await ref
|
|
||||||
.read(tabSessionProvider(tabId: null).notifier)
|
|
||||||
.loadUrl(url: newUrl);
|
|
||||||
|
|
||||||
if (context.mounted) {
|
|
||||||
context.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -273,7 +194,7 @@ class WebPageDialog extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(KagiTool.assistant.icon),
|
leading: const Icon(MdiIcons.brain),
|
||||||
title: const Text('QA Chat'),
|
title: const Text('QA Chat'),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final selectedTabId =
|
final selectedTabId =
|
||||||
@@ -306,24 +227,24 @@ class WebPageDialog extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
// ListTile(
|
||||||
leading: Icon(KagiTool.summarizer.icon),
|
// leading: Icon(MdiIcons.text),
|
||||||
title: const Text('Summarize'),
|
// title: const Text('Summarize'),
|
||||||
onTap: () async {
|
// onTap: () async {
|
||||||
final summarizerUrl = uri_builder.summarizerUri(
|
// final summarizerUrl = uri_builder.summarizerUri(
|
||||||
document: SharedUrl(url),
|
// document: SharedUrl(url),
|
||||||
mode: SummarizerMode.keyMoments,
|
// mode: SummarizerMode.keyMoments,
|
||||||
);
|
// );
|
||||||
|
|
||||||
await ref
|
// await ref
|
||||||
.read(tabRepositoryProvider.notifier)
|
// .read(tabRepositoryProvider.notifier)
|
||||||
.addTab(url: summarizerUrl);
|
// .addTab(url: summarizerUrl);
|
||||||
|
|
||||||
if (context.mounted) {
|
// if (context.mounted) {
|
||||||
context.pop();
|
// context.pop();
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+85
@@ -0,0 +1,85 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:lensai/features/bangs/domain/providers/bangs.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/search/domain/providers/engine_suggestions.dart';
|
||||||
|
import 'package:lensai/presentation/hooks/listenable_callback.dart';
|
||||||
|
import 'package:lensai/presentation/widgets/auto_suggest_text_field.dart';
|
||||||
|
import 'package:lensai/utils/uri_parser.dart' as uri_parser;
|
||||||
|
|
||||||
|
class AddressWithSuggestionsField extends HookConsumerWidget {
|
||||||
|
const AddressWithSuggestionsField({
|
||||||
|
super.key,
|
||||||
|
required this.url,
|
||||||
|
required this.incognitoEnabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Uri url;
|
||||||
|
final bool incognitoEnabled;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final addressTextController = useTextEditingController(
|
||||||
|
text: url.toString(),
|
||||||
|
);
|
||||||
|
final addressTextFocusNode = useFocusNode();
|
||||||
|
|
||||||
|
final suggestion = useState<String?>(null);
|
||||||
|
|
||||||
|
useListenableCallback(addressTextController, () async {
|
||||||
|
if (addressTextController.text.isNotEmpty) {
|
||||||
|
final result = await ref
|
||||||
|
.read(engineSuggestionsProvider.notifier)
|
||||||
|
.getAutocompleteSuggestion(addressTextController.text);
|
||||||
|
|
||||||
|
suggestion.value = result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return AutoSuggestTextField(
|
||||||
|
controller: addressTextController,
|
||||||
|
focusNode: addressTextFocusNode,
|
||||||
|
suggestion: suggestion.value,
|
||||||
|
enableIMEPersonalizedLearning: !incognitoEnabled,
|
||||||
|
keyboardType: TextInputType.url,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
label: Text('Address'),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (!addressTextFocusNode.hasFocus) {
|
||||||
|
// Select all text when the field is tapped
|
||||||
|
addressTextController.selection = TextSelection(
|
||||||
|
baseOffset: 0,
|
||||||
|
extentOffset: addressTextController.text.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSubmitted: (value) async {
|
||||||
|
if (value.isNotEmpty) {
|
||||||
|
var newUrl = uri_parser.tryParseUrl(value, eagerParsing: true);
|
||||||
|
|
||||||
|
if (newUrl == null) {
|
||||||
|
final defaultSearchBang = await ref.read(
|
||||||
|
defaultSearchBangDataProvider.future,
|
||||||
|
);
|
||||||
|
|
||||||
|
newUrl = defaultSearchBang?.getUrl(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newUrl != null) {
|
||||||
|
await ref
|
||||||
|
.read(tabSessionProvider(tabId: null).notifier)
|
||||||
|
.loadUrl(url: newUrl);
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/tab.dart';
|
||||||
import 'package:skeletonizer/skeletonizer.dart';
|
import 'package:skeletonizer/skeletonizer.dart';
|
||||||
import 'package:text_scroll/text_scroll.dart';
|
import 'package:text_scroll/text_scroll.dart';
|
||||||
|
|
||||||
+373
@@ -0,0 +1,373 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||||
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:lensai/core/routing/routes.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/controllers/bottom_sheet.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/providers.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/providers/web_extensions_state.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/edit_url_dialog.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/extension_badge_icon.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/tabs_action_button.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/find_in_page/presentation/controllers/find_in_page_visibility.dart';
|
||||||
|
import 'package:lensai/features/geckoview/features/readerview/presentation/widgets/reader_button.dart';
|
||||||
|
import 'package:lensai/presentation/hooks/menu_controller.dart';
|
||||||
|
import 'package:lensai/presentation/icons/tor_icons.dart';
|
||||||
|
import 'package:lensai/utils/ui_helper.dart' as ui_helper;
|
||||||
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
||||||
|
class BrowserBottomAppBar extends HookConsumerWidget {
|
||||||
|
const BrowserBottomAppBar({
|
||||||
|
required this.selectedTabId,
|
||||||
|
required this.displayedSheet,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String? selectedTabId;
|
||||||
|
final Sheet? displayedSheet;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final addonService = ref.watch(addonServiceProvider);
|
||||||
|
|
||||||
|
final tabMenuController = useMenuController();
|
||||||
|
final trippleDotMenuController = useMenuController();
|
||||||
|
|
||||||
|
return BottomAppBar(
|
||||||
|
height: AppBar().preferredSize.height,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: AppBar(
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
titleSpacing: 8.0,
|
||||||
|
title:
|
||||||
|
(selectedTabId != null && displayedSheet is! ViewTabsSheet)
|
||||||
|
? HookConsumer(
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
final tabState = ref.watch(tabStateProvider(selectedTabId));
|
||||||
|
|
||||||
|
return (tabState != null)
|
||||||
|
? AppBarTitle(
|
||||||
|
tab: tabState,
|
||||||
|
onTap: () async {
|
||||||
|
await context.push(
|
||||||
|
WebPageRoute(
|
||||||
|
url: tabState.url.toString(),
|
||||||
|
).location,
|
||||||
|
extra: tabState,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onDoubleTap: () async {
|
||||||
|
final newUrl = await showDialog<Uri?>(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) =>
|
||||||
|
EditUrlDialog(initialUrl: tabState.url),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (newUrl != null) {
|
||||||
|
await ref
|
||||||
|
.read(
|
||||||
|
tabSessionProvider(tabId: null).notifier,
|
||||||
|
)
|
||||||
|
.loadUrl(url: newUrl);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink();
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
actions: [
|
||||||
|
if (selectedTabId != null && displayedSheet is! ViewTabsSheet)
|
||||||
|
ReaderButton(),
|
||||||
|
MenuAnchor(
|
||||||
|
controller: tabMenuController,
|
||||||
|
builder: (context, controller, child) {
|
||||||
|
return child!;
|
||||||
|
},
|
||||||
|
menuChildren: [
|
||||||
|
if (selectedTabId != null)
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await ref
|
||||||
|
.read(tabRepositoryProvider.notifier)
|
||||||
|
.closeTab(selectedTabId!);
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.close),
|
||||||
|
child: const Text('Close Tab'),
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await context.push(const SearchRoute().location);
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.add),
|
||||||
|
child: const Text('Add Tab'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: TabsActionButton(
|
||||||
|
isActive: displayedSheet is ViewTabsSheet,
|
||||||
|
onTap: () {
|
||||||
|
if (displayedSheet case ViewTabsSheet()) {
|
||||||
|
ref.read(bottomSheetControllerProvider.notifier).dismiss();
|
||||||
|
} else {
|
||||||
|
ref
|
||||||
|
.read(bottomSheetControllerProvider.notifier)
|
||||||
|
.show(ViewTabsSheet());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLongPress: () {
|
||||||
|
if (tabMenuController.isOpen) {
|
||||||
|
tabMenuController.close();
|
||||||
|
} else {
|
||||||
|
tabMenuController.open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
MenuAnchor(
|
||||||
|
controller: trippleDotMenuController,
|
||||||
|
builder: (context, controller, child) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 4.0),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
if (controller.isOpen) {
|
||||||
|
controller.close();
|
||||||
|
} else {
|
||||||
|
controller.open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
vertical: 15.0,
|
||||||
|
horizontal: 8.0,
|
||||||
|
),
|
||||||
|
child: Icon(Icons.more_vert),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
menuChildren: [
|
||||||
|
Consumer(
|
||||||
|
builder: (context, childRef, child) {
|
||||||
|
final pageExtensions = childRef.watch(
|
||||||
|
webExtensionsStateProvider(
|
||||||
|
WebExtensionActionType.page,
|
||||||
|
).select((value) => value.values.toList()),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Wrap(
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
|
children: [
|
||||||
|
...pageExtensions.map(
|
||||||
|
(extension) => IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
//Use parents .ref because after onPressed this consumer gets disposed already
|
||||||
|
await addonService.invokeAddonAction(
|
||||||
|
extension.extensionId,
|
||||||
|
WebExtensionActionType.page,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: ExtensionBadgeIcon(extension),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await context.push(AboutRoute().location);
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.info),
|
||||||
|
child: const Text('About'),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await context.push(SettingsRoute().location);
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.settings),
|
||||||
|
child: const Text('Settings'),
|
||||||
|
),
|
||||||
|
Consumer(
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
final browserExtensions = ref.watch(
|
||||||
|
webExtensionsStateProvider(
|
||||||
|
WebExtensionActionType.browser,
|
||||||
|
).select((value) => value.values.toList()),
|
||||||
|
);
|
||||||
|
|
||||||
|
return SubmenuButton(
|
||||||
|
menuChildren: [
|
||||||
|
...browserExtensions.map(
|
||||||
|
(extension) => MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
//Use parents .ref because after onPressed this consumer gets disposed already
|
||||||
|
await addonService.invokeAddonAction(
|
||||||
|
extension.extensionId,
|
||||||
|
WebExtensionActionType.browser,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
leadingIcon: ExtensionBadgeIcon(extension),
|
||||||
|
child: Text(extension.title ?? ''),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await addonService.startAddonManagerActivity();
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(MdiIcons.puzzleEdit),
|
||||||
|
child: const Text('Addon Manager'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
leadingIcon: const Icon(MdiIcons.puzzle),
|
||||||
|
child: const Text('Addons'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await context.push(TorProxyRoute().location);
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(TorIcons.onionAlt),
|
||||||
|
child: const Text('Tor'),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await context.push(BangCategoriesRoute().location);
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(MdiIcons.exclamationThick),
|
||||||
|
child: const Text('Bangs'),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
if (selectedTabId != null)
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final tabState = ref.read(tabStateProvider(selectedTabId));
|
||||||
|
|
||||||
|
if (tabState?.url case final Uri url) {
|
||||||
|
await ui_helper.launchUrlFeedback(context, url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.open_in_browser),
|
||||||
|
child: const Text('Launch External'),
|
||||||
|
),
|
||||||
|
if (selectedTabId != null)
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final tabState = ref.read(tabStateProvider(selectedTabId));
|
||||||
|
|
||||||
|
if (tabState?.url case final Uri url) {
|
||||||
|
await Share.shareUri(url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.share),
|
||||||
|
child: const Text('Share'),
|
||||||
|
),
|
||||||
|
if (selectedTabId != null) const Divider(),
|
||||||
|
if (selectedTabId != null)
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () {
|
||||||
|
ref
|
||||||
|
.read(findInPageVisibilityControllerProvider.notifier)
|
||||||
|
.show();
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.search),
|
||||||
|
child: const Text('Find in page'),
|
||||||
|
),
|
||||||
|
if (selectedTabId != null) const Divider(),
|
||||||
|
if (selectedTabId != null)
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final controller = ref.read(
|
||||||
|
tabSessionProvider(tabId: selectedTabId).notifier,
|
||||||
|
);
|
||||||
|
|
||||||
|
await controller.reload();
|
||||||
|
trippleDotMenuController.close();
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.refresh),
|
||||||
|
child: const Text('Reload'),
|
||||||
|
),
|
||||||
|
if (selectedTabId != null) const Divider(),
|
||||||
|
if (selectedTabId != null)
|
||||||
|
Consumer(
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
final history = ref.watch(
|
||||||
|
tabStateProvider(
|
||||||
|
selectedTabId,
|
||||||
|
).select((value) => value?.historyState),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child:
|
||||||
|
(history?.canGoBack == true)
|
||||||
|
? IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final controller = ref.read(
|
||||||
|
tabSessionProvider(
|
||||||
|
tabId: selectedTabId,
|
||||||
|
).notifier,
|
||||||
|
);
|
||||||
|
|
||||||
|
await controller.goBack();
|
||||||
|
trippleDotMenuController.close();
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
)
|
||||||
|
: IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await ref
|
||||||
|
.read(tabRepositoryProvider.notifier)
|
||||||
|
.closeTab(selectedTabId!);
|
||||||
|
trippleDotMenuController.close();
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.close),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 48, child: VerticalDivider()),
|
||||||
|
Expanded(
|
||||||
|
child: IconButton(
|
||||||
|
onPressed:
|
||||||
|
(history?.canGoForward == true)
|
||||||
|
? () async {
|
||||||
|
final controller = ref.read(
|
||||||
|
tabSessionProvider(
|
||||||
|
tabId: selectedTabId,
|
||||||
|
).notifier,
|
||||||
|
);
|
||||||
|
|
||||||
|
await controller.goForward();
|
||||||
|
trippleDotMenuController.close();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
icon: const Icon(Icons.arrow_forward),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await context.push(UserAuthRoute().location);
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.info),
|
||||||
|
child: const Text('Auth'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-2
@@ -6,10 +6,11 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:lensai/core/logger.dart';
|
import 'package:lensai/core/logger.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers.dart';
|
import 'package:lensai/features/geckoview/domain/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/web_extensions_state.dart';
|
import 'package:lensai/features/geckoview/domain/providers/web_extensions_state.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/services/delete_browser_data.dart';
|
import 'package:lensai/features/geckoview/features/browser/domain/services/browser_data.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/services/engine_settings_replication.dart';
|
import 'package:lensai/features/geckoview/features/browser/domain/services/engine_settings_replication.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/services/proxy_settings_replucation.dart';
|
import 'package:lensai/features/geckoview/features/browser/domain/services/proxy_settings_replucation.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/features/vector_store/domain/repositories/document.dart';
|
import 'package:lensai/features/geckoview/features/tabs/features/vector_store/domain/repositories/document.dart';
|
||||||
@@ -87,7 +88,7 @@ class _BrowserViewState extends ConsumerState<BrowserView>
|
|||||||
.fetch()
|
.fetch()
|
||||||
.then((settings) {
|
.then((settings) {
|
||||||
ref
|
ref
|
||||||
.read(deleteBrowserDataServiceProvider.notifier)
|
.read(browserDataServiceProvider.notifier)
|
||||||
.deleteData(settings.deleteBrowsingDataOnQuit);
|
.deleteData(settings.deleteBrowsingDataOnQuit);
|
||||||
});
|
});
|
||||||
|
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/web_extension_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/web_extension.dart';
|
||||||
|
|
||||||
class ExtensionBadgeIcon extends StatelessWidget {
|
class ExtensionBadgeIcon extends StatelessWidget {
|
||||||
final WebExtensionState state;
|
final WebExtensionState state;
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:lensai/core/routing/routes.dart';
|
|
||||||
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/error_container.dart';
|
|
||||||
|
|
||||||
class LandingAction extends HookConsumerWidget {
|
|
||||||
const LandingAction({super.key});
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
//TODO: REWORK!
|
|
||||||
final sessionTokenAvailable = false;
|
|
||||||
|
|
||||||
// ref.watch(
|
|
||||||
// generalSettingsRepositoryProvider.select(
|
|
||||||
// (value) => value.valueOrNull?.kagiSession?.isNotEmpty ?? false,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
return Visibility(
|
|
||||||
visible: !sessionTokenAvailable,
|
|
||||||
child: ErrorContainer(
|
|
||||||
content: Markdown(
|
|
||||||
shrinkWrap: true,
|
|
||||||
onTapLink: (text, href, title) async {
|
|
||||||
if (href == 'settings') {
|
|
||||||
await context.push(SettingsRoute().location);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data:
|
|
||||||
'## No Kagi Session Provided\n'
|
|
||||||
'Please navigate to [Settings](settings) and enter your Kagi Session Token.\n'
|
|
||||||
"You must provide a valid session in order to use Kagi's features.",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-151
@@ -1,151 +0,0 @@
|
|||||||
import 'package:fading_scroll/fading_scroll.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart' show rootBundle;
|
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:lensai/data/models/equatable_iterable.dart';
|
|
||||||
import 'package:lensai/domain/services/app_initialization.dart';
|
|
||||||
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
|
||||||
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/error_container.dart';
|
|
||||||
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/landing/action.dart';
|
|
||||||
import 'package:lensai/presentation/hooks/cached_future.dart';
|
|
||||||
|
|
||||||
class LandingContent extends HookConsumerWidget {
|
|
||||||
const LandingContent({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final textTheme = Theme.of(context).textTheme;
|
|
||||||
|
|
||||||
final descriptionAsset = useCachedFuture(
|
|
||||||
() async => rootBundle.loadString('assets/landing/description.md'),
|
|
||||||
);
|
|
||||||
final changelogAsset = useCachedFuture(
|
|
||||||
() async => rootBundle.loadString('assets/landing/changelog.md'),
|
|
||||||
);
|
|
||||||
|
|
||||||
return FadingScroll(
|
|
||||||
fadingSize: 25,
|
|
||||||
builder: (context, controller) {
|
|
||||||
return SingleChildScrollView(
|
|
||||||
controller: controller,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Lensai',
|
|
||||||
style: textTheme.titleLarge?.copyWith(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: Text(
|
|
||||||
'The Privacy-Focused & AI-Powered Research Browser with Kagi integration',
|
|
||||||
style: textTheme.titleMedium,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FractionallySizedBox(
|
|
||||||
widthFactor: 0.5,
|
|
||||||
child: Image.asset('assets/icon/icon.png'),
|
|
||||||
),
|
|
||||||
const LandingAction(),
|
|
||||||
Consumer(
|
|
||||||
builder: (context, ref, child) {
|
|
||||||
final errors =
|
|
||||||
ref
|
|
||||||
.watch(
|
|
||||||
appInitializationServiceProvider.select(
|
|
||||||
(result) => EquatableCollection(
|
|
||||||
result.valueOrNull?.errors,
|
|
||||||
immutable: false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.collection;
|
|
||||||
|
|
||||||
if (errors == null || errors.isEmpty) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
...errors.map((error) {
|
|
||||||
final theme = Theme.of(context);
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
||||||
child: ErrorContainer(
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Error during App Initialization!',
|
|
||||||
style: theme.textTheme.titleMedium,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
error.message,
|
|
||||||
style: theme.textTheme.titleSmall,
|
|
||||||
),
|
|
||||||
if (error.details != null)
|
|
||||||
Text(error.details.toString()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
child: FilledButton.tonalIcon(
|
|
||||||
onPressed: () async {
|
|
||||||
await ref
|
|
||||||
.read(
|
|
||||||
appInitializationServiceProvider.notifier,
|
|
||||||
)
|
|
||||||
.reinitialize();
|
|
||||||
},
|
|
||||||
style: OutlinedButton.styleFrom(
|
|
||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
),
|
|
||||||
label: const Text('Restart App'),
|
|
||||||
icon: const Icon(Icons.refresh_outlined),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Markdown(
|
|
||||||
data: descriptionAsset.data ?? '',
|
|
||||||
onTapLink: (text, href, title) async {
|
|
||||||
if (href != null) {
|
|
||||||
await ref
|
|
||||||
.read(tabRepositoryProvider.notifier)
|
|
||||||
.addTab(url: Uri.parse(href));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selectable: true,
|
|
||||||
shrinkWrap: true,
|
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'Changelog',
|
|
||||||
style: textTheme.titleLarge?.copyWith(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
MarkdownBody(data: changelogAsset.data ?? '', selectable: true),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-111
@@ -1,111 +0,0 @@
|
|||||||
import 'package:expandable_page_view/expandable_page_view.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:lensai/extensions/nullable.dart';
|
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/entities/sheet.dart';
|
|
||||||
import 'package:lensai/features/kagi/data/entities/modes.dart';
|
|
||||||
import 'package:lensai/features/kagi/presentation/tabs/summarize_tab.dart';
|
|
||||||
import 'package:lensai/features/share_intent/domain/entities/shared_content.dart';
|
|
||||||
import 'package:lensai/presentation/hooks/sync_page_tab.dart';
|
|
||||||
|
|
||||||
typedef OnSubmitUri = void Function(Uri url);
|
|
||||||
|
|
||||||
class CreateTabSheetWidget extends HookConsumerWidget {
|
|
||||||
final CreateTabSheet parameter;
|
|
||||||
final OnSubmitUri onSubmit;
|
|
||||||
final void Function(KagiTool tool)? onActiveToolChanged;
|
|
||||||
|
|
||||||
const CreateTabSheetWidget({
|
|
||||||
required this.parameter,
|
|
||||||
required this.onSubmit,
|
|
||||||
this.onActiveToolChanged,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final sharedContent = useMemoized(
|
|
||||||
() => parameter.content.mapNotNull(
|
|
||||||
(content) => SharedContent.parse(content),
|
|
||||||
),
|
|
||||||
[parameter],
|
|
||||||
);
|
|
||||||
|
|
||||||
final initialIndex = useMemoized(
|
|
||||||
() =>
|
|
||||||
parameter.preferredTool?.index ??
|
|
||||||
switch (sharedContent) {
|
|
||||||
SharedText(text: final _) => KagiTool.search.index,
|
|
||||||
// (showEarlyAccessFeatures && text.length > 25)
|
|
||||||
// ? KagiTool.assistant.index
|
|
||||||
// : KagiTool.search.index,
|
|
||||||
SharedUrl() => KagiTool.summarizer.index,
|
|
||||||
null => KagiTool.search.index,
|
|
||||||
// showEarlyAccessFeatures
|
|
||||||
// ? KagiTool.assistant.index
|
|
||||||
// : KagiTool.search.index,
|
|
||||||
},
|
|
||||||
[sharedContent],
|
|
||||||
);
|
|
||||||
|
|
||||||
final tabController = useTabController(
|
|
||||||
initialLength: KagiTool.values.length - 1,
|
|
||||||
initialIndex: initialIndex,
|
|
||||||
);
|
|
||||||
final pageController = usePageController(initialPage: tabController.index);
|
|
||||||
|
|
||||||
useSyncPageWithTab(
|
|
||||||
tabController,
|
|
||||||
pageController,
|
|
||||||
onIndexChanged: (index) {
|
|
||||||
onActiveToolChanged?.call(KagiTool.values[index]);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() {
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
onActiveToolChanged?.call(KagiTool.values[initialIndex]);
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}, [initialIndex]);
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
TabBar(
|
|
||||||
controller: tabController,
|
|
||||||
tabs: [
|
|
||||||
// Tab(
|
|
||||||
// icon: Icon(KagiTool.search.icon),
|
|
||||||
// text: 'Search',
|
|
||||||
// ),
|
|
||||||
Tab(icon: Icon(KagiTool.summarizer.icon), text: 'Summarize'),
|
|
||||||
// if (showEarlyAccessFeatures)
|
|
||||||
// Tab(
|
|
||||||
// icon: Icon(KagiTool.assistant.icon),
|
|
||||||
// text: 'Assistant',
|
|
||||||
// ),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
|
|
||||||
child: ExpandablePageView(
|
|
||||||
controller: pageController,
|
|
||||||
children: [
|
|
||||||
// SearchTab(
|
|
||||||
// sharedContent: sharedContent,
|
|
||||||
// onSubmit: onSubmit,
|
|
||||||
// ),
|
|
||||||
SummarizeTab(sharedContent: sharedContent, onSubmit: onSubmit),
|
|
||||||
// if (showEarlyAccessFeatures)
|
|
||||||
// AssistantTab(
|
|
||||||
// sharedContent: sharedContent,
|
|
||||||
// onSubmit: onSubmit,
|
|
||||||
// ),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+8
-55
@@ -10,8 +10,6 @@ import 'package:lensai/core/providers/global_drop.dart';
|
|||||||
import 'package:lensai/core/routing/routes.dart';
|
import 'package:lensai/core/routing/routes.dart';
|
||||||
import 'package:lensai/data/models/drag_data.dart';
|
import 'package:lensai/data/models/drag_data.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
import 'package:lensai/features/geckoview/domain/providers/selected_tab.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
|
||||||
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
|
||||||
import 'package:lensai/features/geckoview/features/browser/domain/providers.dart';
|
import 'package:lensai/features/geckoview/features/browser/domain/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/draggable_scrollable_header.dart';
|
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/draggable_scrollable_header.dart';
|
||||||
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/tab_preview.dart';
|
import 'package:lensai/features/geckoview/features/browser/presentation/widgets/tab_preview.dart';
|
||||||
@@ -25,60 +23,12 @@ import 'package:lensai/features/tor/presentation/controllers/start_tor_proxy.dar
|
|||||||
import 'package:lensai/presentation/hooks/listenable_callback.dart';
|
import 'package:lensai/presentation/hooks/listenable_callback.dart';
|
||||||
import 'package:lensai/presentation/widgets/speech_to_text_button.dart';
|
import 'package:lensai/presentation/widgets/speech_to_text_button.dart';
|
||||||
|
|
||||||
class _TabDraggable extends HookConsumerWidget {
|
class _TabSheetHeader extends HookConsumerWidget {
|
||||||
final String tabId;
|
|
||||||
final String? activeTabId;
|
|
||||||
|
|
||||||
final void Function() onClose;
|
|
||||||
|
|
||||||
_TabDraggable({
|
|
||||||
required this.tabId,
|
|
||||||
required this.activeTabId,
|
|
||||||
required this.onClose,
|
|
||||||
}) : super(key: ValueKey(tabId));
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final tab = ref.watch(tabStateProvider(tabId));
|
|
||||||
|
|
||||||
if (tab == null) {
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
return TabPreview(
|
|
||||||
tab: tab,
|
|
||||||
isActive: tabId == activeTabId,
|
|
||||||
onTap: () async {
|
|
||||||
if (tabId != activeTabId) {
|
|
||||||
//Close first to avoid rebuilds
|
|
||||||
onClose();
|
|
||||||
await ref.read(tabRepositoryProvider.notifier).selectTab(tab.id);
|
|
||||||
} else {
|
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// onDoubleTap: () {
|
|
||||||
// ref.read(overlayDialogControllerProvider.notifier).show(
|
|
||||||
// TabActionDialog(
|
|
||||||
// initialTab: tab,
|
|
||||||
// onDismiss:
|
|
||||||
// ref.read(overlayDialogControllerProvider.notifier).dismiss,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
onDelete: () async {
|
|
||||||
await ref.read(tabRepositoryProvider.notifier).closeTab(tab.id);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Tab extends HookConsumerWidget {
|
|
||||||
static const headerSize = 124.0;
|
static const headerSize = 124.0;
|
||||||
|
|
||||||
final VoidCallback onClose;
|
final VoidCallback onClose;
|
||||||
|
|
||||||
const _Tab({required this.onClose});
|
const _TabSheetHeader({required this.onClose});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -245,7 +195,7 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
DraggableScrollableHeader(
|
DraggableScrollableHeader(
|
||||||
controller: draggableScrollableController,
|
controller: draggableScrollableController,
|
||||||
child: _Tab(onClose: onClose),
|
child: _TabSheetHeader(onClose: onClose),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: HookConsumer(
|
child: HookConsumer(
|
||||||
@@ -304,7 +254,7 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
|
|||||||
key: Key(tabId),
|
key: Key(tabId),
|
||||||
data: TabDragData(tabId),
|
data: TabDragData(tabId),
|
||||||
child: Consumer(
|
child: Consumer(
|
||||||
child: _TabDraggable(
|
child: TabPreviewDraggable(
|
||||||
tabId: tabId,
|
tabId: tabId,
|
||||||
activeTabId: activeTab,
|
activeTabId: activeTab,
|
||||||
onClose: onClose,
|
onClose: onClose,
|
||||||
@@ -420,7 +370,10 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: _Tab.headerSize + 4, right: 4),
|
padding: const EdgeInsets.only(
|
||||||
|
top: _TabSheetHeader.headerSize + 4,
|
||||||
|
right: 4,
|
||||||
|
),
|
||||||
child: FloatingActionButton.small(
|
child: FloatingActionButton.small(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await context.push(const SearchRoute().location);
|
await context.push(const SearchRoute().location);
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/tab_state.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/entities/states/tab.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
||||||
|
|
||||||
class TabPreview extends StatelessWidget {
|
class TabPreview extends StatelessWidget {
|
||||||
final TabState tab;
|
final TabState tab;
|
||||||
@@ -99,3 +102,51 @@ class TabPreview extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TabPreviewDraggable extends HookConsumerWidget {
|
||||||
|
final String tabId;
|
||||||
|
final String? activeTabId;
|
||||||
|
|
||||||
|
final void Function() onClose;
|
||||||
|
|
||||||
|
TabPreviewDraggable({
|
||||||
|
required this.tabId,
|
||||||
|
required this.activeTabId,
|
||||||
|
required this.onClose,
|
||||||
|
}) : super(key: ValueKey(tabId));
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final tab = ref.watch(tabStateProvider(tabId));
|
||||||
|
|
||||||
|
if (tab == null) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
return TabPreview(
|
||||||
|
tab: tab,
|
||||||
|
isActive: tabId == activeTabId,
|
||||||
|
onTap: () async {
|
||||||
|
if (tabId != activeTabId) {
|
||||||
|
//Close first to avoid rebuilds
|
||||||
|
onClose();
|
||||||
|
await ref.read(tabRepositoryProvider.notifier).selectTab(tab.id);
|
||||||
|
} else {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// onDoubleTap: () {
|
||||||
|
// ref.read(overlayDialogControllerProvider.notifier).show(
|
||||||
|
// TabActionDialog(
|
||||||
|
// initialTab: tab,
|
||||||
|
// onDismiss:
|
||||||
|
// ref.read(overlayDialogControllerProvider.notifier).dismiss,
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
onDelete: () async {
|
||||||
|
await ref.read(tabRepositoryProvider.notifier).closeTab(tab.id);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+3
-1
@@ -18,7 +18,9 @@ class TabsActionButton extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
final tabCount = ref.watch(tabListProvider.select((tabs) => tabs.length));
|
final tabCount = ref.watch(
|
||||||
|
tabListProvider.select((tabs) => tabs.collection.length),
|
||||||
|
);
|
||||||
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/readerable_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/readerable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||||
import 'package:lensai/features/geckoview/features/readerview/domain/providers/readerable.dart';
|
import 'package:lensai/features/geckoview/features/readerview/domain/providers/readerable.dart';
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/readerable_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/readerable.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_state.dart';
|
||||||
import 'package:lensai/features/geckoview/features/readerview/presentation/controllers/readerable.dart';
|
import 'package:lensai/features/geckoview/features/readerview/presentation/controllers/readerable.dart';
|
||||||
import 'package:lensai/features/user/domain/repositories/general_settings.dart';
|
import 'package:lensai/features/user/domain/repositories/general_settings.dart';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:lensai/features/kagi/data/services/autosuggest.dart';
|
import 'package:lensai/features/geckoview/features/search/domain/repositories/search_suggestions.dart';
|
||||||
import 'package:lensai/features/kagi/domain/repositories/search_suggestions.dart';
|
import 'package:lensai/features/search/domain/autosuggest/kagi.dart';
|
||||||
import 'package:lensai/features/search/domain/entities/abstract/i_search_suggestion_provider.dart';
|
import 'package:lensai/features/search/domain/entities/abstract/i_search_suggestion_provider.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ class SearchScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
Future<void> submitSearch(String query) async {
|
Future<void> submitSearch(String query) async {
|
||||||
if (activeBang != null && (formKey.currentState?.validate() == true)) {
|
if (activeBang != null && (formKey.currentState?.validate() == true)) {
|
||||||
final searchUri = await ref.read(
|
final searchUri = await ref
|
||||||
triggerBangSearchProvider(activeBang, query).future,
|
.read(bangSearchProvider.notifier)
|
||||||
);
|
.triggerBangSearch(activeBang, query);
|
||||||
|
|
||||||
await ref.read(tabRepositoryProvider.notifier).addTab(url: searchUri);
|
await ref.read(tabRepositoryProvider.notifier).addTab(url: searchUri);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/entities/tab_state.dart';
|
import 'package:lensai/features/geckoview/domain/entities/states/tab.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/data/database/database.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/database/database.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/data/models/tab_query_result.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/models/tab_query_result.dart';
|
||||||
import 'package:lexo_rank/lexo_rank.dart';
|
import 'package:lexo_rank/lexo_rank.dart';
|
||||||
@@ -17,7 +17,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with _$TabDaoMixin {
|
|||||||
|
|
||||||
Selectable<TabData> allTabData() => db.tab.select();
|
Selectable<TabData> allTabData() => db.tab.select();
|
||||||
|
|
||||||
SingleOrNullSelectable<TabData> tabDataById(String id) =>
|
SingleOrNullSelectable<TabData> getTabDataById(String id) =>
|
||||||
db.tab.select()..where((t) => t.id.equals(id));
|
db.tab.select()..where((t) => t.id.equals(id));
|
||||||
|
|
||||||
Selectable<String> containerTabIds(String? containerId) {
|
Selectable<String> containerTabIds(String? containerId) {
|
||||||
@@ -34,7 +34,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with _$TabDaoMixin {
|
|||||||
return query.map((row) => row.read(db.tab.id)!);
|
return query.map((row) => row.read(db.tab.id)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selectable<String> allTabIds() {
|
Selectable<String> getAllTabIds() {
|
||||||
final query =
|
final query =
|
||||||
selectOnly(db.tab)
|
selectOnly(db.tab)
|
||||||
..addColumns([db.tab.id])
|
..addColumns([db.tab.id])
|
||||||
@@ -43,7 +43,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with _$TabDaoMixin {
|
|||||||
return query.map((row) => row.read(db.tab.id)!);
|
return query.map((row) => row.read(db.tab.id)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleOrNullSelectable<String?> tabContainerId(String tabId) {
|
SingleOrNullSelectable<String?> getTabContainerId(String tabId) {
|
||||||
final query =
|
final query =
|
||||||
selectOnly(db.tab)
|
selectOnly(db.tab)
|
||||||
..addColumns([db.tab.containerId])
|
..addColumns([db.tab.containerId])
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import 'package:lensai/features/geckoview/features/tabs/data/database/daos/tab.d
|
|||||||
import 'package:lensai/features/geckoview/features/tabs/data/models/container_data.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/models/container_data.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/data/models/tab_query_result.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/models/tab_query_result.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/features/vector_store/data/database/daos/vector.dart';
|
import 'package:lensai/features/geckoview/features/tabs/features/vector_store/data/database/daos/vector.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/features/vector_store/data/database/database.dart';
|
import 'package:lensai/features/geckoview/features/tabs/features/vector_store/data/database/migrator.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/features/vector_store/data/models/vector_result.dart';
|
import 'package:lensai/features/geckoview/features/tabs/features/vector_store/data/models/vector_result.dart';
|
||||||
import 'package:lensai/features/search/domain/fts_tokenizer.dart';
|
import 'package:lensai/features/search/domain/fts_tokenizer.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
class TabQueryResult {
|
import 'package:fast_equatable/fast_equatable.dart';
|
||||||
|
|
||||||
|
class TabQueryResult with FastEquatable {
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
final String? title;
|
final String? title;
|
||||||
@@ -19,4 +21,18 @@ class TabQueryResult {
|
|||||||
this.fullContent,
|
this.fullContent,
|
||||||
required this.weightedRank,
|
required this.weightedRank,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get cacheHash => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get hashParameters => [
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
cleanUrl,
|
||||||
|
url,
|
||||||
|
extractedContent,
|
||||||
|
fullContent,
|
||||||
|
weightedRank,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,12 @@
|
|||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:lensai/features/geckoview/features/tabs/data/entities/container_filter.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/entities/container_filter.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/data/models/container_data.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/models/container_data.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/data/providers.dart';
|
import 'package:lensai/features/geckoview/features/tabs/data/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/features/tabs/domain/repositories/container.dart';
|
|
||||||
import 'package:lensai/features/geckoview/features/tabs/utils/color_palette.dart';
|
|
||||||
import 'package:lensai/features/search/util/tokenized_filter.dart';
|
import 'package:lensai/features/search/util/tokenized_filter.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
part 'providers.g.dart';
|
part 'providers.g.dart';
|
||||||
|
|
||||||
@Riverpod()
|
|
||||||
Future<Color> unusedRandomContainerColor(Ref ref) async {
|
|
||||||
final repository = ref.watch(containerRepositoryProvider.notifier);
|
|
||||||
|
|
||||||
final allColors = colorTypes.flattened.toList();
|
|
||||||
final usedColors = await repository.getDistinctColors();
|
|
||||||
|
|
||||||
Color randomColor;
|
|
||||||
do {
|
|
||||||
randomColor = randomColorShade(allColors);
|
|
||||||
} while (usedColors.contains(randomColor));
|
|
||||||
|
|
||||||
return randomColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
Stream<List<ContainerDataWithCount>> containersWithCount(Ref ref) {
|
Stream<List<ContainerDataWithCount>> containersWithCount(Ref ref) {
|
||||||
final db = ref.watch(tabDatabaseProvider);
|
final db = ref.watch(tabDatabaseProvider);
|
||||||
@@ -64,6 +44,6 @@ Stream<List<String>> containerTabIds(Ref ref, ContainerFilter containerFilter) {
|
|||||||
case ContainerFilterById(:final containerId):
|
case ContainerFilterById(:final containerId):
|
||||||
return db.tabDao.containerTabIds(containerId).watch();
|
return db.tabDao.containerTabIds(containerId).watch();
|
||||||
case ContainerFilterDisabled():
|
case ContainerFilterDisabled():
|
||||||
return db.tabDao.allTabIds().watch();
|
return db.tabDao.getAllTabIds().watch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,25 +6,6 @@ part of 'providers.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$unusedRandomContainerColorHash() =>
|
|
||||||
r'913499b3de281ea0020db97ed67121652f53ec08';
|
|
||||||
|
|
||||||
/// See also [unusedRandomContainerColor].
|
|
||||||
@ProviderFor(unusedRandomContainerColor)
|
|
||||||
final unusedRandomContainerColorProvider =
|
|
||||||
AutoDisposeFutureProvider<Color>.internal(
|
|
||||||
unusedRandomContainerColor,
|
|
||||||
name: r'unusedRandomContainerColorProvider',
|
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$unusedRandomContainerColorHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
typedef UnusedRandomContainerColorRef = AutoDisposeFutureProviderRef<Color>;
|
|
||||||
String _$containersWithCountHash() =>
|
String _$containersWithCountHash() =>
|
||||||
r'ee0734e4b71472b79636816616a158f54fa6bc23';
|
r'ee0734e4b71472b79636816616a158f54fa6bc23';
|
||||||
|
|
||||||
@@ -207,7 +188,7 @@ class _MatchSortedContainersWithCountProviderElement
|
|||||||
(origin as MatchSortedContainersWithCountProvider).searchText;
|
(origin as MatchSortedContainersWithCountProvider).searchText;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$containerTabIdsHash() => r'6472a865c287d7f87ec49a401c8184bfe7528ab8';
|
String _$containerTabIdsHash() => r'355c65523db29f376faa293ab1f1ed8273696548';
|
||||||
|
|
||||||
/// See also [containerTabIds].
|
/// See also [containerTabIds].
|
||||||
@ProviderFor(containerTabIds)
|
@ProviderFor(containerTabIds)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user