basic container sugegstion implementation
This commit is contained in:
@@ -279,6 +279,7 @@ class _TabSheetHeader extends HookConsumerWidget {
|
||||
);
|
||||
|
||||
return ContainerChips(
|
||||
showGroupSuggestions: true,
|
||||
selectedContainer: selectedContainer,
|
||||
onSelected: (container) async {
|
||||
if (container != null) {
|
||||
|
||||
@@ -134,8 +134,8 @@ class GeckoInferenceRepository extends _$GeckoInferenceRepository {
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
Future<List<List<String>>?> suggestClusters({
|
||||
required List<String> unassignedDocumentsInput,
|
||||
Future<List<({String? topic, List<String> tabIds})>?> suggestClusters({
|
||||
required Map<String, String> unassignedDocumentsInput,
|
||||
}) async {
|
||||
if (!ref.read(
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
@@ -146,7 +146,9 @@ class GeckoInferenceRepository extends _$GeckoInferenceRepository {
|
||||
}
|
||||
|
||||
final processedDocuments = <String, String>{};
|
||||
final unassignedDocumentsProcessed = unassignedDocumentsInput.map((doc) {
|
||||
final unassignedDocumentsProcessed = unassignedDocumentsInput.values.map((
|
||||
doc,
|
||||
) {
|
||||
final processed = preprocessText(doc);
|
||||
if (processed != doc) {
|
||||
processedDocuments[processed] = doc;
|
||||
@@ -168,9 +170,25 @@ class GeckoInferenceRepository extends _$GeckoInferenceRepository {
|
||||
.toList(),
|
||||
);
|
||||
|
||||
print(clusters);
|
||||
final clusterResult = await clusters.mapNotNull(
|
||||
(cluster) => Future.wait(
|
||||
cluster.map((clusterTitles) async {
|
||||
final topic = await predictDocumentTopic(clusterTitles.toSet());
|
||||
|
||||
return null;
|
||||
return (
|
||||
topic: topic,
|
||||
tabIds: clusterTitles.map((title) {
|
||||
final originalTitle = processedDocuments[title] ?? title;
|
||||
return unassignedDocumentsInput.entries
|
||||
.firstWhere((entry) => entry.value == originalTitle)
|
||||
.key;
|
||||
}).toList(),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return clusterResult;
|
||||
}
|
||||
|
||||
Future<Map<String, List<double>>?> generateDocumentEmbeddings(
|
||||
@@ -236,26 +254,25 @@ Future<String?> containerTopic(Ref ref, String containerId) async {
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Future<List<List<String>>?> suggestClusters(Ref ref) async {
|
||||
Future<List<({List<String> tabIds, String? topic})>?> suggestClusters(
|
||||
Ref ref,
|
||||
) async {
|
||||
final unassignedTitles = await ref.watch(
|
||||
containerTabsDataProvider(null).selectAsync(
|
||||
(tabData) => EquatableValue(
|
||||
tabData
|
||||
.where((tab) => tab.title.isNotEmpty)
|
||||
.map((tab) => (tab.id, tab.title!))
|
||||
.toSet(),
|
||||
Map.fromEntries(
|
||||
tabData
|
||||
.where((tab) => tab.title.isNotEmpty)
|
||||
.map((tab) => MapEntry(tab.id, tab.title!)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (unassignedTitles.value.isNotEmpty) {
|
||||
await ref
|
||||
return await ref
|
||||
.read(geckoInferenceRepositoryProvider.notifier)
|
||||
.suggestClusters(
|
||||
unassignedDocumentsInput: unassignedTitles.value
|
||||
.map((tab) => tab.$2)
|
||||
.toList(),
|
||||
);
|
||||
.suggestClusters(unassignedDocumentsInput: unassignedTitles.value);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
+10
-11
@@ -42,7 +42,7 @@ final class GeckoInferenceRepositoryProvider
|
||||
}
|
||||
|
||||
String _$geckoInferenceRepositoryHash() =>
|
||||
r'1f08047bee912a475bfd0851f8a9868a41bca836';
|
||||
r'eb174c9f80f3537bc075ebbffcef787ec55ad217';
|
||||
|
||||
abstract class _$GeckoInferenceRepository extends $Notifier<void> {
|
||||
void build();
|
||||
@@ -138,13 +138,13 @@ const suggestClustersProvider = SuggestClustersProvider._();
|
||||
final class SuggestClustersProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
AsyncValue<List<List<String>>?>,
|
||||
List<List<String>>?,
|
||||
FutureOr<List<List<String>>?>
|
||||
AsyncValue<List<({List<String> tabIds, String? topic})>?>,
|
||||
List<({List<String> tabIds, String? topic})>?,
|
||||
FutureOr<List<({List<String> tabIds, String? topic})>?>
|
||||
>
|
||||
with
|
||||
$FutureModifier<List<List<String>>?>,
|
||||
$FutureProvider<List<List<String>>?> {
|
||||
$FutureModifier<List<({List<String> tabIds, String? topic})>?>,
|
||||
$FutureProvider<List<({List<String> tabIds, String? topic})>?> {
|
||||
const SuggestClustersProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
@@ -161,17 +161,16 @@ final class SuggestClustersProvider
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$FutureProviderElement<List<List<String>>?> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $FutureProviderElement(pointer);
|
||||
$FutureProviderElement<List<({List<String> tabIds, String? topic})>?>
|
||||
$createElement($ProviderPointer pointer) => $FutureProviderElement(pointer);
|
||||
|
||||
@override
|
||||
FutureOr<List<List<String>>?> create(Ref ref) {
|
||||
FutureOr<List<({List<String> tabIds, String? topic})>?> create(Ref ref) {
|
||||
return suggestClusters(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$suggestClustersHash() => r'9d212158b80ba53afe305db938ab399b1e931d88';
|
||||
String _$suggestClustersHash() => r'592058ed092384c37a185dcd5657276a3dde5b4e';
|
||||
|
||||
@ProviderFor(containerTabSuggestions)
|
||||
const containerTabSuggestionsProvider = ContainerTabSuggestionsFamily._();
|
||||
|
||||
@@ -23,16 +23,21 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:nullability/nullability.dart';
|
||||
import 'package:weblibre/core/logger.dart';
|
||||
import 'package:weblibre/core/routing/routes.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/controllers/tab_suggestions.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/entities/container_filter.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/gecko_inference.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_title.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/tab_drag_container_target.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
import 'package:weblibre/presentation/widgets/selectable_chips.dart';
|
||||
|
||||
class ContainerChips extends HookConsumerWidget {
|
||||
final bool displayMenu;
|
||||
final bool showGroupSuggestions;
|
||||
|
||||
final ContainerData? selectedContainer;
|
||||
final bool Function(ContainerDataWithCount)? containerFilter;
|
||||
@@ -48,6 +53,7 @@ class ContainerChips extends HookConsumerWidget {
|
||||
this.containerFilter,
|
||||
this.searchTextListenable,
|
||||
this.displayMenu = true,
|
||||
this.showGroupSuggestions = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -132,6 +138,53 @@ class ContainerChips extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
if (showGroupSuggestions)
|
||||
Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final tabSuggestionsEnabled = ref.watch(
|
||||
tabSuggestionsControllerProvider,
|
||||
);
|
||||
final enableAiFeatures = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(settings) => settings.enableLocalAiFeatures,
|
||||
),
|
||||
);
|
||||
|
||||
if (!enableAiFeatures || !tabSuggestionsEnabled) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final suggestions = ref.watch(
|
||||
suggestClustersProvider,
|
||||
);
|
||||
|
||||
return suggestions.when(
|
||||
data: (data) {
|
||||
if (data.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return FilterChip(
|
||||
avatar: const Icon(MdiIcons.autoFix),
|
||||
label: Text(data!.length.toString()),
|
||||
showCheckmark: false,
|
||||
onSelected: (value) {},
|
||||
);
|
||||
},
|
||||
error: (error, stackTrace) {
|
||||
logger.e(
|
||||
'Error suggesting containers',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
loading: () {
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
availableItems: availableContainers,
|
||||
selectedItem: selectedContainer,
|
||||
|
||||
Reference in New Issue
Block a user