import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:tatlock_ui/features/front_hall/data/datasources/quick_links_datasource.dart'; import 'package:tatlock_ui/features/front_hall/domain/entities/quick_link.dart'; part 'quick_links_provider.g.dart'; /// Provides the list of all quick links. /// Falls back to default links if API is unavailable. @riverpod Future> quickLinks(Ref ref) async { try { final datasource = ref.watch(quickLinksDatasourceProvider); final links = await datasource.getQuickLinks(); // Return defaults if API returns empty list return links.isEmpty ? getDefaultQuickLinks() : links; } catch (_) { // Return default links if API fails (e.g., backend not running) return getDefaultQuickLinks(); } } /// Provides a single quick link by ID. /// Falls back to default links if API is unavailable. @riverpod Future quickLink(Ref ref, String id) async { // First try to find in defaults (works offline) final defaults = getDefaultQuickLinks(); final defaultLink = defaults.where((link) => link.id == id).firstOrNull; if (defaultLink != null) { return defaultLink; } // If not in defaults, try API try { final datasource = ref.watch(quickLinksDatasourceProvider); return await datasource.getQuickLink(id); } catch (_) { throw Exception('Link not found: $id'); } } /// Controller for quick link CRUD operations. @riverpod class QuickLinkActions extends _$QuickLinkActions { @override AsyncValue build() => const AsyncValue.data(null); /// Creates a new quick link. Future create(QuickLink link) async { state = const AsyncValue.loading(); QuickLink? result; state = await AsyncValue.guard(() async { final datasource = ref.read(quickLinksDatasourceProvider); result = await datasource.createQuickLink(link); ref.invalidate(quickLinksProvider); }); return result; } /// Updates an existing quick link. Future update(QuickLink link) async { state = const AsyncValue.loading(); QuickLink? result; state = await AsyncValue.guard(() async { final datasource = ref.read(quickLinksDatasourceProvider); result = await datasource.updateQuickLink(link); ref.invalidate(quickLinksProvider); ref.invalidate(quickLinkProvider(link.id)); }); return result; } /// Deletes a quick link. Future delete(String id) async { state = const AsyncValue.loading(); state = await AsyncValue.guard(() async { final datasource = ref.read(quickLinksDatasourceProvider); await datasource.deleteQuickLink(id); ref.invalidate(quickLinksProvider); }); } /// Reorders quick links. Future reorder(List orderedIds) async { state = const AsyncValue.loading(); state = await AsyncValue.guard(() async { final datasource = ref.read(quickLinksDatasourceProvider); await datasource.reorderQuickLinks(orderedIds); ref.invalidate(quickLinksProvider); }); } } /// Default seed data for quick links (used when API returns empty). List getDefaultQuickLinks() { return [ // Home category const QuickLink( id: 'jellyfin', name: 'Jellyfin', url: 'https://jellyfin.schweitz.net', iconName: 'movie', category: 'Home', type: QuickLinkType.iframe, sortOrder: 0, ), const QuickLink( id: 'webui', name: 'Open WebUI', url: 'https://webui.schweitz.net', iconName: 'chat', category: 'Home', type: QuickLinkType.iframe, sortOrder: 1, ), const QuickLink( id: 'searxng', name: 'SearXNG', url: 'https://search.schweitz.net', iconName: 'search', category: 'Home', type: QuickLinkType.newTab, sortOrder: 2, ), // AMP category const QuickLink( id: 'amp', name: 'AMP Home', url: 'https://amp.schweitz.net', iconName: 'videogame_asset', category: 'AMP', type: QuickLinkType.newTab, sortOrder: 0, ), // Coding category const QuickLink( id: 'gitea', name: 'Gitea', url: 'https://git.schweitz.net', iconName: 'code', category: 'Coding', type: QuickLinkType.iframe, sortOrder: 0, ), const QuickLink( id: 'cloud-ide', name: 'Cloud IDE', url: 'https://code.schweitz.net', iconName: 'terminal', category: 'Coding', type: QuickLinkType.newTab, sortOrder: 1, ), // Infrastructure category const QuickLink( id: 'netdata', name: 'Netdata', url: 'https://netdata.schweitz.net', iconName: 'monitoring', category: 'Infrastructure', type: QuickLinkType.iframe, sortOrder: 0, ), const QuickLink( id: 'portainer', name: 'Portainer', url: 'https://portainer.schweitz.net', iconName: 'dns', category: 'Infrastructure', type: QuickLinkType.iframe, sortOrder: 1, ), const QuickLink( id: 'npm', name: 'Proxy Manager', url: 'https://npm.schweitz.net', iconName: 'public', category: 'Infrastructure', type: QuickLinkType.iframe, sortOrder: 2, ), const QuickLink( id: 'core-api', name: 'Core API', url: 'https://api.schweitz.net/docs', iconName: 'api', category: 'Infrastructure', type: QuickLinkType.iframe, sortOrder: 3, ), ]; }