2025-11-22 21:53:14 +05:30
|
|
|
import 'dart:async';
|
|
|
|
|
|
2025-09-30 14:39:22 +05:30
|
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
|
|
|
|
2025-08-19 20:26:19 +05:30
|
|
|
import 'package:conduit/core/models/tool.dart';
|
2025-11-22 21:53:14 +05:30
|
|
|
import 'package:conduit/core/providers/storage_providers.dart';
|
2025-08-19 20:26:19 +05:30
|
|
|
import 'package:conduit/core/services/tools_service.dart';
|
|
|
|
|
|
2025-09-30 14:39:22 +05:30
|
|
|
part 'tools_providers.g.dart';
|
|
|
|
|
|
2025-10-01 18:32:16 +05:30
|
|
|
@Riverpod(keepAlive: true)
|
2025-11-22 21:53:14 +05:30
|
|
|
class ToolsList extends _$ToolsList {
|
|
|
|
|
@override
|
|
|
|
|
Future<List<Tool>> build() async {
|
|
|
|
|
final storage = ref.watch(optimizedStorageServiceProvider);
|
|
|
|
|
final toolsService = ref.watch(toolsServiceProvider);
|
|
|
|
|
final cached = await storage.getLocalTools();
|
|
|
|
|
|
|
|
|
|
if (cached.isNotEmpty) {
|
|
|
|
|
_scheduleWarmRefresh(toolsService);
|
|
|
|
|
return cached;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (toolsService == null) {
|
|
|
|
|
return const [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _fetchAndPersist(toolsService);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> refresh() async {
|
|
|
|
|
final toolsService = ref.read(toolsServiceProvider);
|
|
|
|
|
if (toolsService == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
final result = await AsyncValue.guard(() => _fetchAndPersist(toolsService));
|
|
|
|
|
if (!ref.mounted) return;
|
|
|
|
|
state = result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _scheduleWarmRefresh(ToolsService? service) {
|
|
|
|
|
if (service == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Future.microtask(() async {
|
2025-12-05 13:01:17 +05:30
|
|
|
if (!ref.mounted) return;
|
2025-11-22 21:53:14 +05:30
|
|
|
await refresh();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<List<Tool>> _fetchAndPersist(ToolsService service) async {
|
|
|
|
|
final tools = await service.getTools();
|
|
|
|
|
final storage = ref.read(optimizedStorageServiceProvider);
|
|
|
|
|
await storage.saveLocalTools(tools);
|
|
|
|
|
return tools;
|
|
|
|
|
}
|
2025-09-30 14:39:22 +05:30
|
|
|
}
|
2025-09-21 22:31:44 +05:30
|
|
|
|
2025-10-01 18:32:16 +05:30
|
|
|
@Riverpod(keepAlive: true)
|
2025-09-30 14:39:22 +05:30
|
|
|
class SelectedToolIds extends _$SelectedToolIds {
|
2025-09-21 22:31:44 +05:30
|
|
|
@override
|
|
|
|
|
List<String> build() => [];
|
|
|
|
|
|
|
|
|
|
void set(List<String> ids) => state = List<String>.from(ids);
|
|
|
|
|
}
|
2025-12-05 22:19:31 +05:30
|
|
|
|
|
|
|
|
/// Provider for selected filter IDs (toggle filters enabled by user).
|
|
|
|
|
///
|
|
|
|
|
/// These filters are dynamically created by OpenWebUI filters with
|
|
|
|
|
/// `toggle = True` set in their module. They appear as toggleable
|
|
|
|
|
/// buttons in the chat input UI.
|
|
|
|
|
@Riverpod(keepAlive: true)
|
|
|
|
|
class SelectedFilterIds extends _$SelectedFilterIds {
|
|
|
|
|
@override
|
|
|
|
|
List<String> build() => [];
|
|
|
|
|
|
|
|
|
|
void set(List<String> ids) => state = List<String>.from(ids);
|
|
|
|
|
|
|
|
|
|
void toggle(String id) {
|
|
|
|
|
if (state.contains(id)) {
|
|
|
|
|
state = state.where((i) => i != id).toList();
|
|
|
|
|
} else {
|
|
|
|
|
state = [...state, id];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void clear() => state = [];
|
|
|
|
|
}
|