part of '../state.dart'; @riverpod ProfilesState profilesState(Ref ref) { final currentProfileId = ref.watch(currentProfileIdProvider); final profiles = ref.watch(profilesProvider); return ProfilesState(profiles: profiles, currentProfileId: currentProfileId); } @riverpod Profile? currentProfile(Ref ref) { final profileId = ref.watch(currentProfileIdProvider); return ref.watch( profilesProvider.select((state) => state.getProfile(profileId)), ); } @riverpod Profile? profile(Ref ref, int? profileId) { return ref.watch( profilesProvider.select((state) => state.getProfile(profileId)), ); } @riverpod ExtendType extendType(Ref ref, int? profileId) { return ref.watch( profileProvider( profileId, ).select((state) => state?.extendType ?? ExtendType.standard), ); } @riverpod Future clashConfig(Ref ref, int profileId) async { final type = ref.read(profileProvider(profileId))?.type; if (type == ProfileType.custom) { return const ClashConfig(); } final outbounds = await ref .read(coreHandlerProvider) .getProfileOutbounds(profileId); return clashConfigTask(outbounds); } @riverpod Future setupState(Ref ref, int? profileId) async { final profile = ref.watch(profileProvider(profileId)); final scriptId = profile?.scriptId; final profileLastUpdateDate = profile?.lastUpdateDate?.millisecondsSinceEpoch; final profileType = profile?.type ?? ProfileType.file; final extendType = profile?.extendType ?? ExtendType.standard; final overrides = profileType == ProfileType.custom ? ref.watch( patchClashConfigProvider.select( (state) => (profile?.overrides ?? const ProfileOverrides()) .overAppTun(state.tunOverride, state.tunOverrideKeys), ), ) : ref.watch( patchClashConfigProvider.select( (state) => ProfileOverrides( dns: state.dns, dnsOverrideKeys: state.dnsOverrideKeys.intersection( DnsOverrideKey.normalProfileKeys, ), tun: state.tunOverride, tunOverrideKeys: state.tunOverrideKeys, ), ), ); final allProfileProviders = ref.watch(profileProvidersProvider); List proxyGroups = []; List rules = []; List addedRules = []; List clashProviders = []; Map profileProviders = const {}; List appProxies = []; Map proxyDialers = const {}; Script? script; if (profileId != null) { if (profileType == ProfileType.custom) { rules = await database.rulesDao.queryProfileRules(profileId).get(); proxyGroups = await database.proxyGroupsDao.query(profileId).get(); clashProviders = await database.clashProvidersDao.query().get(); profileProviders = allProfileProviders; appProxies = await database.customProxiesDao.query().get(); proxyDialers = { for (final dialer in await database.proxyDialersDao.query(profileId).get()) dialer.proxyId: dialer.target, }; } else if (extendType == ExtendType.standard) { addedRules = await database.rulesDao.queryAddedRules(profileId).get(); } else if (extendType == ExtendType.script) { script = scriptId == null ? null : await database.scriptsDao.get(scriptId).getSingleOrNull(); } } return SetupState( clashProviders: clashProviders, profileProviders: profileProviders, appProxies: appProxies, proxyDialers: proxyDialers, rules: rules, proxyGroups: proxyGroups, profileId: profileId, profileLastUpdateDate: profileLastUpdateDate, profileType: profileType, extendType: extendType, addedRules: addedRules, script: script, overrides: overrides, matchTarget: profileType != ProfileType.custom && extendType == ExtendType.standard ? profile?.matchTarget : null, ); } /// Subscription profiles double as proxy providers for custom profiles. @riverpod Map profileProviders(Ref ref) { final profiles = ref.watch(profilesProvider); return { for (final profile in profiles) if (profile.type != ProfileType.custom) profile.realLabel: profile.id, }; }