diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml new file mode 100644 index 0000000..b3cd1eb --- /dev/null +++ b/.github/workflows/release-beta.yaml @@ -0,0 +1,102 @@ +name: Compile and release beta build + +on: + workflow_dispatch: + inputs: + version: + description: "Version (beta)" + required: true + default: "1.0.0-beta.1" + number: + description: "Build number" + required: true + default: "1" +jobs: + build-android: + name: Build Android .apk and .aab + runs-on: ubuntu-latest + env: + ANDROID_AAB_RELEASE_PATH: build/app/outputs/bundle/release + ANDROID_APK_RELEASE_PATH: build/app/outputs/apk/release + steps: + - uses: actions/checkout@v3 + - name: Decode android/app/keystore.jks + run: echo "${{ secrets.KEYSTORE_JKS }}" | base64 --decode > android/app/keystore.jks + - name: Decode android/key.properties + run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties + - name: Decode .env + run: echo "${{ secrets.ENV }}" | base64 --decode > .env + - name: Update version in YAML + run: sed -i 's/99.99.99+99/${{ github.event.inputs.version }}+${{ github.event.inputs.number }}/g' pubspec.yaml + - name: Update KeyStore password in gradle properties + run: sed -i 's/#{KEYSTORE_PASS}#/${{ secrets.KEYSTORE_PASS }}/g' android/key.properties + - name: Update KeyStore key password in gradle properties + run: sed -i 's/#{KEYSTORE_KEY_PASS}#/${{ secrets.KEYSTORE_KEY_PASS }}/g' android/key.properties + - uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: '18.x' + - uses: subosito/flutter-action@v2 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build apk --release + - run: flutter build appbundle --release + - name: Rename apk + run: mv $ANDROID_APK_RELEASE_PATH/app-release.apk $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + - name: Rename aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + - name: Copy apk to project root + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + - name: Copy aab to project root + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: android + path: | + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + AdGuardHomeManager_${{ github.event.inputs.version }}_Android.apk + release-builds-github: + name: Release beta build to GitHub + runs-on: ubuntu-latest + needs: [build-android] + steps: + - uses: actions/checkout@v3 + - name: Create builds directory + run: mkdir releases + - name: Download Android artifacts + uses: actions/download-artifact@v3 + with: + name: android + path: releases/ + - name: Release to GitHub + uses: ncipollo/release-action@v1 + with: + artifacts: "releases/*" + token: ${{ secrets.GH_TOKEN }} + tag: '${{ github.event.inputs.version }}_(${{ github.event.inputs.number }})' + name: v${{ github.event.inputs.version }} + draft: true + prerelease: true + commit: ${{ github.sha }} + release-build-google-play: + name: Release Android beta build to the Google Play Store + runs-on: ubuntu-latest + needs: [build-android] + steps: + - uses: actions/checkout@v3 + - name: Download Android artifacts + uses: actions/download-artifact@v3 + with: + name: android + - name: Release app to Google Play + uses: r0adkll/upload-google-play@v1 + with: + serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} + packageName: com.jgeek00.adguard_home_manager + releaseFiles: AdGuardHomeManager_${{ github.event.inputs.version }}_Android.aab + track: beta + status: draft + releaseName: ${{ github.event.inputs.version }} \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release-stable.yaml similarity index 100% rename from .github/workflows/release.yaml rename to .github/workflows/release-stable.yaml diff --git a/lib/base.dart b/lib/base.dart index 5c6289b..b2b593b 100644 --- a/lib/base.dart +++ b/lib/base.dart @@ -1,15 +1,11 @@ // ignore_for_file: use_build_context_synchronously, depend_on_referenced_packages -import 'dart:async'; -import 'dart:io'; - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:provider/provider.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:store_checker/store_checker.dart'; import 'package:flutter/services.dart'; import 'package:adguard_home_manager/widgets/bottom_nav_bar.dart'; @@ -18,21 +14,14 @@ import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/widgets/navigation_rail.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; -import 'package:adguard_home_manager/models/github_release.dart'; +import 'package:adguard_home_manager/functions/check_app_updates.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_screen.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; class Base extends StatefulWidget { - final AppConfigProvider appConfigProvider; - - const Base({ - Key? key, - required this.appConfigProvider, - }) : super(key: key); + const Base({Key? key}) : super(key: key); @override State createState() => _BaseState(); @@ -41,35 +30,6 @@ class Base extends StatefulWidget { class _BaseState extends State with WidgetsBindingObserver { int selectedScreen = 0; - Future checkInstallationSource() async { - final result = await checkAppUpdatesGitHub(); - if (result['result'] == 'success') { - final update = gitHubUpdateExists(widget.appConfigProvider.getAppInfo!.version, result['body'].tagName); - if (update == true) { - widget.appConfigProvider.setAppUpdatesAvailable(result['body']); - if (Platform.isAndroid) { - if ( - widget.appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || - widget.appConfigProvider.installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || - widget.appConfigProvider.installationSource == Source.UNKNOWN - ) { - return result['body']; - } - else { - return null; - } - } - else if (Platform.isIOS) { - return null; - } - else { - return result['body']; - } - } - } - return null; - } - @override void initState() { WidgetsBinding.instance.addObserver(this); @@ -77,9 +37,15 @@ class _BaseState extends State with WidgetsBindingObserver { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { - final result = await checkInstallationSource(); + final appConfigProvider = Provider.of(context, listen: false); + final result = await checkAppUpdates( + currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, + installationSource: appConfigProvider.installationSource, + setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), + ); - if (result != null && widget.appConfigProvider.doNotRememberVersion != result.tagName) { + if (result != null && appConfigProvider.doNotRememberVersion != result.tagName) { await showDialog( context: context, builder: (context) => UpdateModal( diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index c8b1afa..cd92b8c 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -2,6 +2,6 @@ class Urls { static const String playStore = "https://play.google.com/store/apps/details?id=com.jgeek00.adguard_home_manager"; static const String gitHub = "https://github.com/JGeek00/adguard-home-manager"; static const String customRuleDocs = "https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters"; - static const String checkLatestReleaseUrl = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases/latest"; + static const String getReleasesGitHub = "https://api.github.com/repos/JGeek00/adguard-home-manager/releases"; static const String adGuardHomeReleasesTags = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/tags"; } \ No newline at end of file diff --git a/lib/functions/app_update_download_link.dart b/lib/functions/app_update_download_link.dart index 76c1a2d..48c798a 100644 --- a/lib/functions/app_update_download_link.dart +++ b/lib/functions/app_update_download_link.dart @@ -3,19 +3,23 @@ import 'dart:io'; import 'package:adguard_home_manager/models/github_release.dart'; String? getAppUpdateDownloadLink(GitHubRelease gitHubRelease) { - if (Platform.isAndroid) { - return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('apk')).browserDownloadUrl; - } - else if (Platform.isMacOS) { - return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('macOS')).browserDownloadUrl; // macOS package is a zip - } - else if (Platform.isWindows) { - return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('exe')).browserDownloadUrl; - } - else if (Platform.isLinux) { - return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('deb')).browserDownloadUrl; - } - else { + try { + if (Platform.isAndroid) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('apk')).browserDownloadUrl; + } + else if (Platform.isMacOS) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('macOS')).browserDownloadUrl; + } + else if (Platform.isWindows) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('exe')).browserDownloadUrl; + } + else if (Platform.isLinux) { + return gitHubRelease.assets.firstWhere((item) => item.browserDownloadUrl.contains('deb')).browserDownloadUrl; + } + else { + return null; + } + } catch (e) { return null; } } \ No newline at end of file diff --git a/lib/functions/block_unblock_domain.dart b/lib/functions/block_unblock_domain.dart deleted file mode 100644 index cc2c8ed..0000000 --- a/lib/functions/block_unblock_domain.dart +++ /dev/null @@ -1,61 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/filtering_status.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; - -Future> blockUnblock(BuildContext context, String domain, String newStatus) async { - final serversProvider = Provider.of(context, listen: false); - final appConfigProvider = Provider.of(context, listen: false); - - final ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.savingUserFilters); - - final rules = await getFilteringRules(server: serversProvider.selectedServer!); - - if (rules['result'] == 'success') { - FilteringStatus oldStatus = serversProvider.serverStatus.data!.filteringStatus; - List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); - if (newStatus == 'block') { - newRules.add("||$domain^"); - } - else if (newStatus == 'unblock') { - newRules.add("@@||$domain^"); - } - FilteringStatus newObj = serversProvider.serverStatus.data!.filteringStatus; - newObj.userRules = newRules; - serversProvider.setFilteringStatus(newObj); - - final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); - - processModal.close(); - - if (result['result'] == 'success') { - return { - 'success': true, - 'message': AppLocalizations.of(context)!.userFilteringRulesUpdated - }; - } - else { - appConfigProvider.addLog(result['log']); - serversProvider.setFilteringStatus(oldStatus); - return { - 'success': false, - 'message': AppLocalizations.of(context)!.userFilteringRulesNotUpdated - }; - } - } - else { - appConfigProvider.addLog(rules['log']); - return { - 'success': false, - 'message': AppLocalizations.of(context)!.userFilteringRulesNotUpdated - }; - } -} \ No newline at end of file diff --git a/lib/functions/check_app_updates.dart b/lib/functions/check_app_updates.dart new file mode 100644 index 0000000..eb44177 --- /dev/null +++ b/lib/functions/check_app_updates.dart @@ -0,0 +1,55 @@ +import 'dart:io'; + +import 'package:store_checker/store_checker.dart'; + +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/models/github_release.dart'; +import 'package:adguard_home_manager/services/http_requests.dart'; + +Future checkAppUpdates({ + required String currentBuildNumber, + required void Function(GitHubRelease?) setUpdateAvailable, + required Source installationSource, + required bool isBeta +}) async { + final result = await checkAppUpdatesGitHub(); + + if (result['result'] == 'success') { + final update = gitHubUpdateExists( + currentBuildNumber: currentBuildNumber, + gitHubReleases: result['body'], + isBeta: isBeta + ); + + if (update == true) { + final release = isBeta == true + ? result['body'].firstWhere((release) => release.prerelease == true) + : result['body'].firstWhere((release) => release.prerelease == false); + + setUpdateAvailable(release); + + if (Platform.isAndroid) { + if ( + installationSource == Source.IS_INSTALLED_FROM_LOCAL_SOURCE || + installationSource == Source.IS_INSTALLED_FROM_PLAY_PACKAGE_INSTALLER || + installationSource == Source.UNKNOWN + ) { + return release; + } + else { + return null; + } + } + else if (Platform.isIOS) { + return null; + } + else { + return release; + } + } + else { + setUpdateAvailable(null); + } + } + return null; +} \ No newline at end of file diff --git a/lib/functions/clear_dns_cache.dart b/lib/functions/clear_dns_cache.dart index 44c81d9..0ff1606 100644 --- a/lib/functions/clear_dns_cache.dart +++ b/lib/functions/clear_dns_cache.dart @@ -5,15 +5,17 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; Future clearDnsCache(BuildContext context, Server server) async { + final serversProvider = Provider.of(context, listen: false); + final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.clearingDnsCache); - final result = await resetDnsCache(server: server); + final result = await serversProvider.apiClient!.resetDnsCache(); processModal.close(); diff --git a/lib/functions/compare_versions.dart b/lib/functions/compare_versions.dart index b28bf65..4bdc178 100644 --- a/lib/functions/compare_versions.dart +++ b/lib/functions/compare_versions.dart @@ -1,5 +1,7 @@ import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:adguard_home_manager/models/github_release.dart'; + bool compareVersions({ required String currentVersion, required String newVersion @@ -147,20 +149,36 @@ bool serverVersionIsAhead({ } } -bool gitHubUpdateExists(String appVersion, String gitHubVersion) { - final List appVersionSplit = List.from(appVersion.split('.').map((e) => int.parse(e))); - final List gitHubVersionSplit = List.from(gitHubVersion.split('.').map((e) => int.parse(e))); +bool gitHubUpdateExists({ + required String currentBuildNumber, + required List gitHubReleases, + required bool isBeta +}) { + final release = isBeta == true + ? gitHubReleases.firstWhere((release) => release.prerelease == true) + : gitHubReleases.firstWhere((release) => release.prerelease == false); + + final versionNumberRegex = RegExp(r'\(\d+\)'); + final releaseNumberExtracted = versionNumberRegex.allMatches(release.tagName).first.group(0); - if (gitHubVersionSplit[0] > appVersionSplit[0]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] > appVersionSplit[1]) { - return true; - } - else if (gitHubVersionSplit[0] == appVersionSplit[0] && gitHubVersionSplit[1] == appVersionSplit[1] && gitHubVersionSplit[2] > appVersionSplit[2]) { - return true; + if (releaseNumberExtracted != null) { + final releaseNumber = releaseNumberExtracted.replaceAll(RegExp(r'\(|\)'), ''); + try { + final newReleaseParsed = int.parse(releaseNumber); + final currentReleaseParsed = int.parse(currentBuildNumber); + if (newReleaseParsed > currentReleaseParsed) { + return true; + } + else { + return false; + } + } catch (e) { + Sentry.captureMessage("Invalid release number. Current release: $currentBuildNumber. New release: $releaseNumber"); + return false; + } } else { + Sentry.captureMessage("Invalid release number. Tagname: ${release.tagName}"); return false; } } \ No newline at end of file diff --git a/lib/functions/format_time.dart b/lib/functions/format_time.dart index e5baff0..41f0dd4 100644 --- a/lib/functions/format_time.dart +++ b/lib/functions/format_time.dart @@ -13,4 +13,17 @@ String convertTimestampLocalTimezone(DateTime timestamp, String format) { String formatTimeOfDay(TimeOfDay timestamp, String format) { DateFormat f = DateFormat(format); return f.format(DateTime(0, 0, 0, timestamp.hour, timestamp.minute)); +} + +String formatRemainingSeconds(int seconds) { + int h, m, s; + h = seconds ~/ 3600; + m = ((seconds - h * 3600)) ~/ 60; + s = seconds - (h * 3600) - (m * 60); + + String hourLeft = h.toString().length < 2 ? "0$h" : h.toString(); + String minuteLeft = m.toString().length < 2 ? "0$m" : m.toString(); + String secondsLeft = s.toString().length < 2 ? "0$s" : s.toString(); + + return "$hourLeft:$minuteLeft:$secondsLeft"; } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index a96efab..1504716 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -628,5 +628,7 @@ "application": "Application", "combinedChart": "Combined chart", "combinedChartDescription": "Combine all charts into one", - "statistics": "Statistics" + "statistics": "Statistics", + "errorLoadFilters": "Error when loading filters.", + "clientRemovedSuccessfully": "Client removed successfully." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 4739f4b..88d248f 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -628,5 +628,7 @@ "application": "Aplicación", "combinedChart": "Gráfico combinado", "combinedChartDescription": "Combina todos los gráficos en uno solo", - "statistics": "Estadísticas" + "statistics": "Estadísticas", + "errorLoadFilters": "Error al cargar los filtros.", + "clientRemovedSuccessfully": "Cliente eliminado correctamente." } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index e768f7d..4dcd872 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,15 +17,20 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/base.dart'; -import 'package:adguard_home_manager/classes/http_override.dart'; -import 'package:adguard_home_manager/services/db/database.dart'; -import 'package:adguard_home_manager/constants/colors.dart'; -import 'package:adguard_home_manager/config/globals.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/config/theme.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; +import 'package:adguard_home_manager/providers/rewrite_rules_provider.dart'; +import 'package:adguard_home_manager/providers/dhcp_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; - +import 'package:adguard_home_manager/constants/colors.dart'; +import 'package:adguard_home_manager/config/globals.dart'; +import 'package:adguard_home_manager/config/theme.dart'; +import 'package:adguard_home_manager/classes/http_override.dart'; +import 'package:adguard_home_manager/services/db/database.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -41,9 +46,15 @@ void main() async { await dotenv.load(fileName: '.env'); - AppConfigProvider appConfigProvider = AppConfigProvider(); - ServersProvider serversProvider = ServersProvider(); - LogsProvider logsProvider = LogsProvider(); + final AppConfigProvider appConfigProvider = AppConfigProvider(); + final ServersProvider serversProvider = ServersProvider(); + final StatusProvider statusProvider = StatusProvider(); + final ClientsProvider clientsProvider = ClientsProvider(); + final FilteringProvider filtersProvider = FilteringProvider(); + final DhcpProvider dhcpProvider = DhcpProvider(); + final RewriteRulesProvider rewriteRulesProvider = RewriteRulesProvider(); + final DnsProvider dnsProvider = DnsProvider(); + final LogsProvider logsProvider = LogsProvider(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); if (Platform.isAndroid) { @@ -73,6 +84,69 @@ void main() async { PackageInfo appInfo = await PackageInfo.fromPlatform(); appConfigProvider.setAppInfo(appInfo); + void startApp() => runApp( + MultiProvider( + providers: [ + ChangeNotifierProvider( + create: ((context) => serversProvider) + ), + ChangeNotifierProvider( + create: ((context) => appConfigProvider) + ), + ChangeNotifierProvider( + create: ((context) => statusProvider) + ), + ChangeNotifierProvider( + create: ((context) => clientsProvider) + ), + ChangeNotifierProvider( + create: ((context) => logsProvider) + ), + ChangeNotifierProvider( + create: ((context) => filtersProvider) + ), + ChangeNotifierProvider( + create: ((context) => dhcpProvider) + ), + ChangeNotifierProvider( + create: ((context) => rewriteRulesProvider) + ), + ChangeNotifierProvider( + create: ((context) => dnsProvider) + ), + ChangeNotifierProxyProvider2( + create: (context) => clientsProvider, + update: (context, servers, status, clients) => clients!..update(servers, status), + ), + ChangeNotifierProxyProvider2( + create: (context) => filtersProvider, + update: (context, servers, status, filtering) => filtering!..update(servers, status), + ), + ChangeNotifierProxyProvider( + create: (context) => statusProvider, + update: (context, servers, status) => status!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => logsProvider, + update: (context, servers, logs) => logs!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => dhcpProvider, + update: (context, servers, dhcp) => dhcp!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => rewriteRulesProvider, + update: (context, servers, rewrite) => rewrite!..update(servers), + ), + ChangeNotifierProxyProvider( + create: (context) => dnsProvider, + update: (context, servers, dns) => dns!..update(servers), + ), + ], + child: const Main(), + ) + ); + if ( ( kReleaseMode && @@ -87,41 +161,11 @@ void main() async { options.dsn = dotenv.env['SENTRY_DSN']; options.sendDefaultPii = false; }, - appRunner: () => runApp( - MultiProvider( - providers: [ - ChangeNotifierProvider( - create: ((context) => serversProvider) - ), - ChangeNotifierProvider( - create: ((context) => appConfigProvider) - ), - ChangeNotifierProvider( - create: ((context) => logsProvider) - ), - ], - child: const Main(), - ) - ) + appRunner: () => startApp() ); } else { - runApp( - MultiProvider( - providers: [ - ChangeNotifierProvider( - create: ((context) => serversProvider) - ), - ChangeNotifierProvider( - create: ((context) => appConfigProvider) - ), - ChangeNotifierProvider( - create: ((context) => logsProvider) - ), - ], - child: const Main(), - ) - ); + startApp(); } } @@ -163,15 +207,15 @@ class _MainState extends State
{ builder: (lightDynamic, darkDynamic) => MaterialApp( title: 'AdGuard Home Manager', theme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? lightTheme(lightDynamic) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]) - : lightThemeOldVersions(colors[appConfigProvider.staticColor]), - darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 - ? appConfigProvider.useDynamicColor == true - ? darkTheme(darkDynamic) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]) - : darkThemeOldVersions(colors[appConfigProvider.staticColor]), + ? appConfigProvider.useDynamicColor == true + ? lightTheme(lightDynamic) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]) + : lightThemeOldVersions(colors[appConfigProvider.staticColor]), + darkTheme: appConfigProvider.androidDeviceInfo != null && appConfigProvider.androidDeviceInfo!.version.sdkInt >= 31 + ? appConfigProvider.useDynamicColor == true + ? darkTheme(darkDynamic) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]) + : darkThemeOldVersions(colors[appConfigProvider.staticColor]), themeMode: appConfigProvider.selectedTheme, debugShowCheckedModeBanner: false, localizationsDelegates: const [ @@ -195,7 +239,7 @@ class _MainState extends State
{ child: child!, ); }, - home: Base(appConfigProvider: appConfigProvider), + home: const Base(), ), ); } diff --git a/lib/models/blocked_services.dart b/lib/models/blocked_services.dart index cb5c78a..659bebc 100644 --- a/lib/models/blocked_services.dart +++ b/lib/models/blocked_services.dart @@ -11,12 +11,10 @@ class BlockedServicesFromApi { } class BlockedServices { - int loadStatus = 0; - List? services; + List services; BlockedServices({ - this.loadStatus = 0, - this.services + required this.services }); } diff --git a/lib/models/clients.dart b/lib/models/clients.dart index 2c9f222..4d8e7db 100644 --- a/lib/models/clients.dart +++ b/lib/models/clients.dart @@ -1,45 +1,28 @@ -import 'dart:convert'; - -import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; import 'package:adguard_home_manager/models/safe_search.dart'; class Clients { - LoadStatus loadStatus; - ClientsData? data; - - Clients({ - required this.loadStatus, - this.data - }); -} - -ClientsData clientsFromJson(String str) => ClientsData.fromJson(json.decode(str)); - -String clientsToJson(ClientsData data) => json.encode(data.toJson()); - -class ClientsData { List clients; - final List autoClientsData; + final List autoClients; final List supportedTags; ClientsAllowedBlocked? clientsAllowedBlocked; - ClientsData({ + Clients({ required this.clients, - required this.autoClientsData, + required this.autoClients, required this.supportedTags, this.clientsAllowedBlocked }); - factory ClientsData.fromJson(Map json) => ClientsData( + factory Clients.fromJson(Map json) => Clients( clients: json["clients"] != null ? List.from(json["clients"].map((x) => Client.fromJson(x))) : [], - autoClientsData: json["auto_clients"] != null ? List.from(json["auto_clients"].map((x) => AutoClient.fromJson(x))) : [], + autoClients: json["auto_clients"] != null ? List.from(json["auto_clients"].map((x) => AutoClient.fromJson(x))) : [], supportedTags: json["supported_tags"] != null ? List.from(json["supported_tags"].map((x) => x)) : [], ); Map toJson() => { "clients": List.from(clients.map((x) => x.toJson())), - "auto_clients": List.from(autoClientsData.map((x) => x.toJson())), + "auto_clients": List.from(autoClients.map((x) => x.toJson())), "supported_tags": List.from(supportedTags.map((x) => x)), }; } diff --git a/lib/models/dhcp.dart b/lib/models/dhcp.dart index 4910e68..c870b9b 100644 --- a/lib/models/dhcp.dart +++ b/lib/models/dhcp.dart @@ -1,20 +1,9 @@ import 'dart:convert'; - class DhcpModel { - int loadStatus = 0; - DhcpData? data; - - DhcpModel({ - required this.loadStatus, - this.data, - }); -} - -class DhcpData { List networkInterfaces; DhcpStatus dhcpStatus; - DhcpData({ + DhcpModel({ required this.networkInterfaces, required this.dhcpStatus, }); diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index de2e308..1fc1979 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -1,20 +1,4 @@ -import 'dart:convert'; - class DnsInfo { - int loadStatus = 0; - DnsInfoData? data; - - DnsInfo({ - required this.loadStatus, - this.data - }); -} - -DnsInfoData dnsInfoDataFromJson(String str) => DnsInfoData.fromJson(json.decode(str)); - -String dnsInfoDataToJson(DnsInfoData data) => json.encode(data.toJson()); - -class DnsInfoData { List upstreamDns; String upstreamDnsFile; List bootstrapDns; @@ -34,9 +18,9 @@ class DnsInfoData { List localPtrUpstreams; String blockingIpv4; String blockingIpv6; - List defaultLocalPtrUpstreams; - DnsInfoData({ + + DnsInfo({ required this.upstreamDns, required this.upstreamDnsFile, required this.bootstrapDns, @@ -59,7 +43,7 @@ class DnsInfoData { required this.defaultLocalPtrUpstreams, }); - factory DnsInfoData.fromJson(Map json) => DnsInfoData( + factory DnsInfo.fromJson(Map json) => DnsInfo( upstreamDns: json["upstream_dns"] != null ? List.from(json["upstream_dns"].map((x) => x)) : [], upstreamDnsFile: json["upstream_dns_file"], bootstrapDns: List.from(json["bootstrap_dns"].map((x) => x)), diff --git a/lib/models/filtering.dart b/lib/models/filtering.dart index 74a4710..9b1d6ce 100644 --- a/lib/models/filtering.dart +++ b/lib/models/filtering.dart @@ -1,22 +1,4 @@ -import 'dart:convert'; - -import 'package:adguard_home_manager/constants/enums.dart'; - -FilteringData filteringFromJson(String str) => FilteringData.fromJson(json.decode(str)); - -String filteringToJson(FilteringData data) => json.encode(data.toJson()); - class Filtering { - LoadStatus loadStatus = LoadStatus.loading; - FilteringData? data; - - Filtering({ - required this.loadStatus, - this.data - }); -} - -class FilteringData { final List filters; final List whitelistFilters; List userRules; @@ -24,7 +6,7 @@ class FilteringData { int interval; bool enabled; - FilteringData({ + Filtering({ required this.filters, required this.whitelistFilters, required this.userRules, @@ -33,7 +15,7 @@ class FilteringData { required this.enabled, }); - factory FilteringData.fromJson(Map json) => FilteringData( + factory Filtering.fromJson(Map json) => Filtering( filters: json["filters"] != null ? List.from(json["filters"].map((x) => Filter.fromJson(x))) : [], whitelistFilters: json["whitelist_filters"] != null ? List.from(json["whitelist_filters"].map((x) => Filter.fromJson(x))) : [], userRules: json["user_rules"] != null ? List.from(json["user_rules"].map((x) => x)).where((i) => i != '').toList() : [], diff --git a/lib/models/rewrite_rules.dart b/lib/models/rewrite_rules.dart index 44bef8d..5af2851 100644 --- a/lib/models/rewrite_rules.dart +++ b/lib/models/rewrite_rules.dart @@ -1,29 +1,13 @@ -import 'dart:convert'; - class RewriteRules { - int loadStatus = 0; - List? data; - - RewriteRules({ - required this.loadStatus, - this.data - }); -} - -List rewriteRulesDataFromJson(String str) => List.from(json.decode(str).map((x) => RewriteRulesData.fromJson(x))); - -String rewriteRulesDataToJson(List data) => json.encode(List.from(data.map((x) => x.toJson()))); - -class RewriteRulesData { final String domain; final String answer; - RewriteRulesData({ + RewriteRules({ required this.domain, required this.answer, }); - factory RewriteRulesData.fromJson(Map json) => RewriteRulesData( + factory RewriteRules.fromJson(Map json) => RewriteRules( domain: json["domain"], answer: json["answer"], ); diff --git a/lib/models/server_info.dart b/lib/models/server_info.dart index 6e170a5..84f9a57 100644 --- a/lib/models/server_info.dart +++ b/lib/models/server_info.dart @@ -1,7 +1,9 @@ import 'dart:convert'; +import 'package:adguard_home_manager/constants/enums.dart'; + class ServerInfo { - int loadStatus = 0; + LoadStatus loadStatus = LoadStatus.loading; ServerInfoData? data; ServerInfo({ diff --git a/lib/models/server_status.dart b/lib/models/server_status.dart index 3d68399..b43dbd1 100644 --- a/lib/models/server_status.dart +++ b/lib/models/server_status.dart @@ -4,15 +4,6 @@ import 'package:adguard_home_manager/models/dns_statistics.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; class ServerStatus { - int loadStatus; - ServerStatusData? data; - - ServerStatus({ - required this.loadStatus, - this.data - }); -} -class ServerStatusData { final DnsStatistics stats; final List clients; final FilteringStatus filteringStatus; @@ -31,7 +22,7 @@ class ServerStatusData { bool? safeSearchYandex; bool? safeSearchYoutube; - ServerStatusData({ + ServerStatus({ required this.stats, required this.clients, required this.filteringStatus, @@ -51,7 +42,7 @@ class ServerStatusData { required this.safeSearchYoutube }); - factory ServerStatusData.fromJson(Map json) => ServerStatusData( + factory ServerStatus.fromJson(Map json) => ServerStatus( stats: DnsStatistics.fromJson(json['stats']), clients: json["clients"] != null ? List.from(json["clients"].map((x) => Client.fromJson(x))) : [], generalEnabled: json['status']['protection_enabled'], diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index 0f8096d..7aeb917 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -199,7 +199,7 @@ class AppConfigProvider with ChangeNotifier { } } - void setAppUpdatesAvailable(GitHubRelease value) { + void setAppUpdatesAvailable(GitHubRelease? value) { _appUpdatesAvailable = value; notifyListeners(); } diff --git a/lib/providers/clients_provider.dart b/lib/providers/clients_provider.dart new file mode 100644 index 0000000..8cf79a5 --- /dev/null +++ b/lib/providers/clients_provider.dart @@ -0,0 +1,285 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/models/clients.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/functions/maps_fns.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; + +class ClientsProvider with ChangeNotifier { + ServersProvider? _serversProvider; + StatusProvider? _statusProvider; + + update(ServersProvider? servers, StatusProvider? status) { + _serversProvider = servers; + _statusProvider = status; + } + + LoadStatus _loadStatus = LoadStatus.loading; + Clients? _clients; + String? _searchTermClients; + List _filteredActiveClients = []; + List _filteredAddedClients = []; + + LoadStatus get loadStatus { + return _loadStatus; + } + + Clients? get clients { + return _clients; + } + + String? get searchTermClients { + return _searchTermClients; + } + + List get filteredActiveClients { + return _filteredActiveClients; + } + + List get filteredAddedClients { + return _filteredAddedClients; + } + + void setClientsLoadStatus(LoadStatus status, bool notify) { + _loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } + + void setClientsData(Clients data, bool notify) { + _clients = data; + if (_searchTermClients != null && _searchTermClients != '') { + _filteredActiveClients = _clients!.autoClients.where( + (client) => client.ip.contains(_searchTermClients!.toLowerCase()) || (client.name != null ? client.name!.contains(_searchTermClients!.toLowerCase()) : false) + ).toList(); + _filteredAddedClients = _clients!.clients.where( + (client) { + isContained(String value) => value.contains(value.toLowerCase()); + return client.ids.any(isContained); + } + ).toList(); + } + else { + _filteredActiveClients = data.autoClients; + _filteredAddedClients = data.clients; + } + if (notify == true) notifyListeners(); + } + + void setSearchTermClients(String? value) { + _searchTermClients = value; + if (value != null && value != '') { + if (_clients != null) { + _filteredActiveClients = _clients!.autoClients.where( + (client) => client.ip.contains(value.toLowerCase()) || (client.name != null ? client.name!.contains(value.toLowerCase()) : false) + ).toList(); + _filteredAddedClients = _clients!.clients.where( + (client) { + isContained(String value) => value.contains(value.toLowerCase()); + return client.ids.any(isContained); + } + ).toList(); + } + } + else { + if (_clients != null) _filteredActiveClients = _clients!.autoClients; + if (_clients != null) _filteredAddedClients = _clients!.clients; + } + notifyListeners(); + } + + void setAllowedDisallowedClientsBlockedDomains(ClientsAllowedBlocked data) { + _clients?.clientsAllowedBlocked = data; + notifyListeners(); + } + + Future fetchClients({ + bool? updateLoading + }) async { + if (updateLoading == true) { + _loadStatus = LoadStatus.loading; + } + final result = await _serversProvider!.apiClient!.getClients(); + if (result['result'] == 'success') { + setClientsData(result['data'], false); + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (updateLoading == true) { + _loadStatus = LoadStatus.error; + notifyListeners(); + } + return false; + } + } + + Future deleteClient(Client client) async { + final result = await _serversProvider!.apiClient!.postDeleteClient(name: client.name); + + if (result['result'] == 'success') { + Clients clientsData = clients!; + clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); + setClientsData(clientsData, false); + + notifyListeners(); + return true; + } + else { + return false; + } + } + + Future editClient(Client client) async { + final result = await _serversProvider!.apiClient!.postUpdateClient( + data: { + 'name': client.name, + 'data': serverVersionIsAhead( + currentVersion: _statusProvider!.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == false + ? removePropFromMap(client.toJson(), 'safesearch_enabled') + : removePropFromMap(client.toJson(), 'safe_search') + } + ); + + if (result['result'] == 'success') { + Clients clientsData = clients!; + clientsData.clients = clientsData.clients.map((e) { + if (e.name == client.name) { + return client; + } + else { + return e; + } + }).toList(); + setClientsData(clientsData, false); + + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future addClient(Client client) async { + final result = await _serversProvider!.apiClient!.postAddClient( + data: serverVersionIsAhead( + currentVersion: _statusProvider!.serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == false + ? removePropFromMap(client.toJson(), 'safesearch_enabled') + : removePropFromMap(client.toJson(), 'safe_search') + ); + + if (result['result'] == 'success') { + Clients clientsData = clients!; + clientsData.clients.add(client); + setClientsData(clientsData, false); + + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future> addClientList(String item, String type) async { + Map> body = { + "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], + "disallowed_clients": clients!.clientsAllowedBlocked?.disallowedClients ?? [], + "blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [], + }; + + if (type == 'allowed') { + body['allowed_clients']!.add(item); + } + else if (type == 'disallowed') { + body['disallowed_clients']!.add(item); + } + else if (type == 'domains') { + body['blocked_hosts']!.add(item); + } + + final result = await _serversProvider!.apiClient!.requestAllowedBlockedClientsHosts(body); + + if (result['result'] == 'success') { + _clients?.clientsAllowedBlocked = ClientsAllowedBlocked( + allowedClients: body['allowed_clients'] ?? [], + disallowedClients: body['disallowed_clients'] ?? [], + blockedHosts: body['blocked_hosts'] ?? [], + ); + notifyListeners(); + return { 'success': true }; + } + else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + notifyListeners(); + return { + 'success': false, + 'error': 'client_another_list' + }; + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } + + Future> removeClientList(String client, String type) async { + Map> body = { + "allowed_clients": clients!.clientsAllowedBlocked?.allowedClients ?? [], + "disallowed_clients": clients!.clientsAllowedBlocked?.disallowedClients ?? [], + "blocked_hosts": clients!.clientsAllowedBlocked?.blockedHosts ?? [], + }; + + if (type == 'allowed') { + body['allowed_clients'] = body['allowed_clients']!.where((c) => c != client).toList(); + } + else if (type == 'disallowed') { + body['disallowed_clients'] = body['disallowed_clients']!.where((c) => c != client).toList(); + } + else if (type == 'domains') { + body['blocked_hosts'] = body['blocked_hosts']!.where((c) => c != client).toList(); + } + + final result = await _serversProvider!.apiClient!.requestAllowedBlockedClientsHosts(body); + + if (result['result'] == 'success') { + _clients?.clientsAllowedBlocked = ClientsAllowedBlocked( + allowedClients: body['allowed_clients'] ?? [], + disallowedClients: body['disallowed_clients'] ?? [], + blockedHosts: body['blocked_hosts'] ?? [], + ); + notifyListeners(); + return { 'success': true }; + } + else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + notifyListeners(); + return { + 'success': false, + 'error': 'client_another_list' + }; + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } +} \ No newline at end of file diff --git a/lib/providers/dhcp_provider.dart b/lib/providers/dhcp_provider.dart new file mode 100644 index 0000000..2c2e7d9 --- /dev/null +++ b/lib/providers/dhcp_provider.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/dhcp.dart'; + +class DhcpProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + + LoadStatus _loadStatus = LoadStatus.loading; + DhcpModel? _dhcp; + + DhcpModel? get dhcp { + return _dhcp; + } + + LoadStatus get loadStatus { + return _loadStatus; + } + + void setDhcpData(DhcpModel data) { + _dhcp = data; + notifyListeners(); + } + + void setDhcpLoadStatus(LoadStatus status, bool notify) { + _loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } + + Future loadDhcpStatus({ + bool? showLoading + }) async { + if (showLoading == true) { + _loadStatus = LoadStatus.loading; + notifyListeners(); + } + final result = await _serversProvider!.apiClient!.getDhcpData(); + if (result['result'] == 'success') { + _dhcp = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (showLoading == true) { + _loadStatus = LoadStatus.error; + notifyListeners(); + } + return false; + } + } + + Future deleteLease(Lease lease) async { + final result = await _serversProvider!.apiClient!.deleteStaticLease( + data: { + "mac": lease.mac, + "ip": lease.ip, + "hostname": lease.hostname + } + ); + + if (result['result'] == 'success') { + DhcpModel data = dhcp!; + data.dhcpStatus.staticLeases = data.dhcpStatus.staticLeases.where((l) => l.mac != lease.mac).toList(); + setDhcpData(data); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future> createLease(Lease lease) async { + final result = await _serversProvider!.apiClient!.createStaticLease( + data: { + "mac": lease.mac, + "ip": lease.ip, + "hostname": lease.hostname, + } + ); + + if (result['result'] == 'success') { + DhcpModel data = dhcp!; + data.dhcpStatus.staticLeases.add(lease); + setDhcpData(data); + return { 'success': true }; + } + else if (result['result'] == 'error' && result['message'] == 'already_exists' ) { + return { + 'success': false, + 'error': 'already_exists' + }; + } + else if (result['result'] == 'error' && result['message'] == 'server_not_configured' ) { + return { + 'success': false, + 'error': 'server_not_configured' + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } +} \ No newline at end of file diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart new file mode 100644 index 0000000..1468f18 --- /dev/null +++ b/lib/providers/dns_provider.dart @@ -0,0 +1,199 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/models/dns_info.dart'; + +class DnsProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + + LoadStatus _loadStatus = LoadStatus.loading; + DnsInfo? _dnsInfo; + + LoadStatus get loadStatus { + return _loadStatus; + } + + DnsInfo? get dnsInfo { + return _dnsInfo; + } + + void setDnsInfoData(DnsInfo data) { + _dnsInfo = data; + notifyListeners(); + } + + void setDnsInfoLoadStatus(LoadStatus status, bool notify) { + _loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } + + Future fetchDnsData({ + bool? showLoading + }) async { + if (showLoading == true) { + _loadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getDnsInfo(); + + if (result['result'] == 'success') { + _dnsInfo = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (showLoading == false) { + _loadStatus = LoadStatus.loaded; + notifyListeners(); + } + return false; + } + } + + Future> savePrivateReverseServersConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + if (value['local_ptr_upstreams'] != null) { + data.localPtrUpstreams = value['local_ptr_upsreams']; + } + data.usePrivatePtrResolvers = value['use_private_ptr_resolvers']; + data.resolveClients = value['resolve_clients']; + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } + + Future> saveUpstreamDnsConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + data.upstreamDns = List.from(value['upstream_dns']); + data.upstreamMode = value['upstream_mode']; + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } + + Future> saveBootstrapDnsConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + data.bootstrapDns = List.from(value['bootstrap_dns']); + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } + + Future> saveCacheCacheConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + data.cacheSize = value['cache_size']; + data.cacheTtlMin = value['cache_ttl_min']; + data.cacheTtlMax = value['cache_ttl_max']; + data.cacheOptimistic = value['cache_optimistic']; + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } + + Future> saveDnsServerConfig(Map value) async { + final result = await _serversProvider!.apiClient!.setDnsConfig( + data: value + ); + + if (result['result'] == 'success') { + DnsInfo data = dnsInfo!; + data.ratelimit = value['ratelimit']; + data.ednsCsEnabled = value['edns_cs_enabled']; + data.dnssecEnabled = value['dnssec_enabled']; + data.disableIpv6 = value['disable_ipv6']; + data.blockingMode = value['blocking_mode']; + data.blockingIpv4 = value['blocking_ipv4']; + data.blockingIpv6 = value['blocking_ipv6']; + setDnsInfoData(data); + return { 'success': true }; + } + else if (result['log'] != null && result['log'].statusCode == '400') { + return { + 'success': false, + 'error': 400 + }; + } + else { + return { + 'success': false, + 'error': null + }; + } + } +} \ No newline at end of file diff --git a/lib/providers/filtering_provider.dart b/lib/providers/filtering_provider.dart new file mode 100644 index 0000000..8b2d459 --- /dev/null +++ b/lib/providers/filtering_provider.dart @@ -0,0 +1,387 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/models/blocked_services.dart'; +import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; + +enum FilteringListActions { edit, enable, disable } + +class FilteringProvider with ChangeNotifier { + StatusProvider? _statusProvider; + ServersProvider? _serversProvider; + + update(ServersProvider? servers, StatusProvider? status) { + _serversProvider = servers; + _statusProvider = status; + } + + LoadStatus _loadStatus = LoadStatus.loading; + Filtering? _filtering; + LoadStatus _blockedServicesLoadStatus = LoadStatus.loading; + BlockedServices? _blockedServicesList; + + LoadStatus get loadStatus { + return _loadStatus; + } + + Filtering? get filtering { + return _filtering; + } + + LoadStatus get blockedServicesLoadStatus { + return _blockedServicesLoadStatus; + } + + BlockedServices? get blockedServices { + return _blockedServicesList; + } + + void setFilteringData(Filtering data) { + _filtering = data; + notifyListeners(); + } + + void setFilteringLoadStatus(LoadStatus loadStatus, bool notify) { + _loadStatus = loadStatus; + if (notify == true) { + notifyListeners(); + } + } + + void setFilteringProtectionStatus(bool status, bool notify) { + _statusProvider!.setFilteringEnabledStatus(status); + _filtering!.enabled = status; + if (notify == true) notifyListeners(); + } + + void setFiltersUpdateFrequency(int frequency) { + if (_filtering != null) { + _filtering!.interval = frequency; + notifyListeners(); + } + } + + void setBlockedServices(List blockedServices) { + if (_filtering != null) { + _filtering!.blockedServices = blockedServices; + notifyListeners(); + } + } + + void setBlockedServiceListData(List data) { + _blockedServicesList = BlockedServices(services: data); + notifyListeners(); + } + + void setBlockedServicesListLoadStatus(LoadStatus status, bool notify) { + _blockedServicesLoadStatus = status; + if (notify == true) { + notifyListeners(); + } + } + + Future getBlockedServices({ + bool? showLoader + }) async { + _blockedServicesLoadStatus = LoadStatus.loading; + if (showLoader == true) notifyListeners(); + + final result = await _serversProvider!.apiClient!.getBlockedServices(); + if (result['result'] == 'success') { + _blockedServicesLoadStatus = LoadStatus.loaded; + _blockedServicesList = BlockedServices(services: result['data']); + + notifyListeners(); + return true; + } + else { + if (showLoader == true) { + _blockedServicesLoadStatus = LoadStatus.error; + notifyListeners(); + } + return false; + } + } + + Future fetchFilters({ + bool? showLoading + }) async { + if (showLoading == true) { + _loadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getFiltering(); + if (result['result'] == 'success') { + _filtering = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future> updateLists() async { + final result = await _serversProvider!.apiClient!.updateLists(); + if (result['result'] == 'success') { + final result2 = await _serversProvider!.apiClient!.getFiltering(); + if (result2['result'] == 'success') { + _filtering = result2['data']; + notifyListeners(); + return { + "success": true, + "data": result['data'] + }; + } + else { + notifyListeners(); + return { "success": false }; + } + } + else { + notifyListeners(); + return { "success": false }; + } + } + + Future enableDisableFiltering() async { + final newValue = !_statusProvider!.serverStatus!.filteringEnabled; + final result = await _serversProvider!.apiClient!.updateFiltering( + enable: newValue + ); + if (result['result'] == 'success') { + setFilteringProtectionStatus(newValue, false); + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future changeUpdateFrequency(int value) async { + final result = await _serversProvider!.apiClient!.requestChangeUpdateFrequency( + data: { + "enabled": filtering!.enabled, + "interval": value + } + ); + if (result['result'] == 'success') { + setFiltersUpdateFrequency(value); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future removeCustomRule(String rule) async { + final List newRules = filtering!.userRules.where((r) => r != rule).toList(); + + final result = await _serversProvider!.apiClient!.setCustomRules(rules: newRules); + + if (result['result'] == 'success') { + Filtering filteringData = filtering!; + filteringData.userRules = newRules; + _filtering = filteringData; + + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future deleteList({ + required String listUrl, + required String type + }) async { + final result1 = await _serversProvider!.apiClient!.deleteFilterList( + data: { + "url": listUrl, + "whitelist": type == 'whitelist' ? true : false + } + ); + + if (result1['result'] == 'success') { + final result2 = await _serversProvider!.apiClient!.getFiltering(); + + if (result2['result'] == 'success') { + _filtering = result2['data']; + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + else { + notifyListeners(); + return false; + } + } + + Future updateList({ + required Filter list, + required String type, + required FilteringListActions action + }) async { + final result1 = await _serversProvider!.apiClient!.updateFilterList( + data: { + "data": { + "enabled": action == FilteringListActions.disable || action == FilteringListActions.enable + ? !list.enabled + : list.enabled, + "name": list.name, + "url": list.url + }, + "url": list.url, + "whitelist": type == 'whitelist' ? true : false + } + ); + + if (result1['result'] == 'success') { + final result2 = await _serversProvider!.apiClient!.getFiltering(); + + if (result2['result'] == 'success') { + _filtering = result2['data']; + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + else { + notifyListeners(); + return false; + } + } + + Future addCustomRule(String rule) async { + final List newRules = filtering!.userRules; + newRules.add(rule); + + final result = await _serversProvider!.apiClient!.setCustomRules(rules: newRules); + + if (result['result'] == 'success') { + Filtering filteringData = filtering!; + filteringData.userRules = newRules; + _filtering = filteringData; + notifyListeners(); + return true; + } + else { + notifyListeners(); + return false; + } + } + Future> addList({required String name, required String url, required String type}) async { + final result1 = await _serversProvider!.apiClient!.addFilteringList( + data: { + 'name': name, + 'url': url, + 'whitelist': type == 'whitelist' ? true : false + } + ); + + if (result1['result'] == 'success') { + if (result1['data'].toString().contains("OK")) { + final result2 = await _serversProvider!.apiClient!.getFiltering(); + final items = result1['data'].toString().split(' ')[1]; + + if (result2['result'] == 'success') { + _filtering = result2['data']; + notifyListeners(); + return { + 'success': true, + 'data': items + }; + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } + else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains("Couldn't fetch filter from url")) { + notifyListeners(); + return { + 'success': false, + 'error': 'invalid_url' + }; + } + else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains('Filter URL already added')) { + notifyListeners(); + return { + 'success': false, + 'error': 'url_exists' + }; + } + else { + notifyListeners(); + return { + 'success': false, + 'error': null + }; + } + } + + Future loadBlockedServices({ + bool? showLoading + }) async { + if (showLoading == true) { + _blockedServicesLoadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getBlockedServices(); + if (result['result'] == 'success') { + _blockedServicesList = BlockedServices(services: result['data']); + _blockedServicesLoadStatus = LoadStatus.loaded; + + notifyListeners(); + return true; + } + else { + if (showLoading == true) _blockedServicesLoadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future updateBlockedServices(List values) async { + final result = await _serversProvider!.apiClient!.setBlockedServices( + data: values + ); + + if (result['result'] == 'success') { + setBlockedServices(values); + return true; + } + else { + notifyListeners(); + return false; + } + } +} \ No newline at end of file diff --git a/lib/providers/logs_provider.dart b/lib/providers/logs_provider.dart index db2619c..e999470 100644 --- a/lib/providers/logs_provider.dart +++ b/lib/providers/logs_provider.dart @@ -1,14 +1,21 @@ -import 'package:adguard_home_manager/models/clients.dart'; import 'package:flutter/material.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/models/logs.dart'; class LogsProvider with ChangeNotifier { - int _loadStatus = 0; + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + + LoadStatus _loadStatus = LoadStatus.loading; LogsData? _logsData; List? _clients; - int _clientsLoadStatus = 0; DateTime? _logsOlderThan; String _selectedResultStatus = 'all'; @@ -18,13 +25,15 @@ class LogsProvider with ChangeNotifier { int _logsQuantity = 100; int _offset = 0; + bool _isLoadingMore = false; + AppliedFiters _appliedFilters = AppliedFiters( selectedResultStatus: 'all', searchText: null, clients: null ); - int get loadStatus { + LoadStatus get loadStatus { return _loadStatus; } @@ -60,16 +69,15 @@ class LogsProvider with ChangeNotifier { return _selectedClients; } - int get clientsLoadStatus { - return _clientsLoadStatus; - } - AppliedFiters get appliedFilters { return _appliedFilters; } + bool get isLoadingMore { + return _isLoadingMore; + } - void setLoadStatus(int value) { + void setLoadStatus(LoadStatus value) { _loadStatus = value; notifyListeners(); } @@ -83,11 +91,6 @@ class LogsProvider with ChangeNotifier { _clients = clients; notifyListeners(); } - - void setClientsLoadStatus(int status) { - _clientsLoadStatus = status; - notifyListeners(); - } void setLogsOlderThan(DateTime? value) { _logsOlderThan = value; @@ -130,4 +133,136 @@ class LogsProvider with ChangeNotifier { _appliedFilters = value; notifyListeners(); } + + void setIsLoadingMore(bool status) { + _isLoadingMore = status; + } + + Future fetchLogs({ + int? inOffset, + bool? loadingMore, + String? responseStatus, + String? searchText, + }) async { + int offst = inOffset ?? offset; + + String resStatus = responseStatus ?? selectedResultStatus; + String? search = searchText ?? searchText; + + if (loadingMore != null && loadingMore == true) { + _isLoadingMore = true; + notifyListeners(); + } + + final result = await _serversProvider!.apiClient!.getLogs( + count: logsQuantity, + offset: offst, + olderThan: logsOlderThan, + responseStatus: resStatus, + search: search + ); + + if (loadingMore != null && loadingMore == true) { + _isLoadingMore = false; + notifyListeners(); + } + + if (result['result'] == 'success') { + _offset = inOffset != null ? inOffset+logsQuantity : offset+logsQuantity; + if (loadingMore != null && loadingMore == true && logsData != null) { + LogsData newLogsData = result['data']; + newLogsData.data = [...logsData!.data, ...result['data'].data]; + if (appliedFilters.clients != null) { + newLogsData.data = newLogsData.data.where( + (item) => appliedFilters.clients!.contains(item.client) + ).toList(); + } + _logsData = newLogsData; + } + else { + LogsData newLogsData = result['data']; + if (appliedFilters.clients != null) { + newLogsData.data = newLogsData.data.where( + (item) => appliedFilters.clients!.contains(item.client) + ).toList(); + } + _logsData = newLogsData; + } + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future requestResetFilters() async { + _loadStatus = LoadStatus.loading; + notifyListeners(); + + resetFilters(); + + final result = await _serversProvider!.apiClient!.getLogs( + count: logsQuantity + ); + + _appliedFilters = AppliedFiters( + selectedResultStatus: 'all', + searchText: null, + clients: null + ); + + if (result['result'] == 'success') { + _logsData = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future filterLogs() async { + _loadStatus = LoadStatus.loading; + notifyListeners(); + + setOffset(0); + + final result = await _serversProvider!.apiClient!.getLogs( + count: logsQuantity, + olderThan: logsOlderThan, + responseStatus: selectedResultStatus, + search: searchText, + ); + + _appliedFilters = AppliedFiters( + selectedResultStatus: selectedResultStatus, + searchText: searchText, + clients: selectedClients + ); + + if (result['result'] == 'success') { + LogsData newLogsData = result['data']; + if (appliedFilters.clients != null) { + newLogsData.data = newLogsData.data.where( + (item) => appliedFilters.clients!.contains(item.client) + ).toList(); + } + _logsData = newLogsData; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } } \ No newline at end of file diff --git a/lib/providers/rewrite_rules_provider.dart b/lib/providers/rewrite_rules_provider.dart new file mode 100644 index 0000000..1db40c5 --- /dev/null +++ b/lib/providers/rewrite_rules_provider.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/models/rewrite_rules.dart'; + +class RewriteRulesProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + + LoadStatus _loadStatus = LoadStatus.loading; + List? _rewriteRules; + + LoadStatus get loadStatus { + return _loadStatus; + } + + List? get rewriteRules { + return _rewriteRules; + } + + void setRewriteRulesData(List data) { + _rewriteRules = data; + notifyListeners(); + } + + void setRewriteRulesLoadStatus(LoadStatus status, bool notify) { + _loadStatus = status; + if (notify == true) { + notifyListeners(); + } + } + + Future addDnsRewrite(RewriteRules rule) async { + final result = await _serversProvider!.apiClient!.addDnsRewriteRule( + data: { + "domain": rule.domain, + "answer": rule.answer + } + ); + + if (result['result'] == 'success') { + List data = rewriteRules!; + data.add(rule); + setRewriteRulesData(data); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future deleteDnsRewrite(RewriteRules rule) async { + final result = await _serversProvider!.apiClient!.deleteDnsRewriteRule( + data: { + "domain": rule.domain, + "answer": rule.answer + } + ); + + if (result['result'] == 'success') { + List data = rewriteRules!; + data = data.where((item) => item.domain != rule.domain).toList(); + setRewriteRulesData(data); + return true; + } + else { + notifyListeners(); + return false; + } + } + + Future fetchRules({ + bool? showLoading + }) async { + if (showLoading == true) { + _loadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getDnsRewriteRules(); + + if (result['result'] == 'success') { + _rewriteRules = result['data']; + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (showLoading == true) { + _loadStatus = LoadStatus.error; + notifyListeners(); + } + return false; + } + } +} \ No newline at end of file diff --git a/lib/providers/servers_provider.dart b/lib/providers/servers_provider.dart index 6d8500c..4b45394 100644 --- a/lib/providers/servers_provider.dart +++ b/lib/providers/servers_provider.dart @@ -1,19 +1,9 @@ import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; -import 'package:adguard_home_manager/models/filtering.dart'; -import 'package:adguard_home_manager/models/dhcp.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; -import 'package:adguard_home_manager/models/rewrite_rules.dart'; -import 'package:adguard_home_manager/models/filtering_status.dart'; -import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; -import 'package:adguard_home_manager/models/blocked_services.dart'; -import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/models/server_status.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/models/update_available.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/functions/time_server_disabled.dart'; import 'package:adguard_home_manager/functions/conversions.dart'; import 'package:adguard_home_manager/services/db/queries.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; @@ -24,51 +14,16 @@ class ServersProvider with ChangeNotifier { List _serversList = []; Server? _selectedServer; - final ServerStatus _serverStatus = ServerStatus( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error - data: null - ); // serverStatus != null means server is connected - List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled - - final Clients _clients = Clients( - loadStatus: LoadStatus.loading, - data: null - ); - String? _searchTermClients; - List _filteredActiveClients = []; - List _filteredAddedClients = []; - - final Filtering _filtering = Filtering( - loadStatus: LoadStatus.loading, - data: null - ); - - final DhcpModel _dhcp = DhcpModel( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error - data: null - ); - - final RewriteRules _rewriteRules = RewriteRules( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error - data: null - ); - - final DnsInfo _dnsInfo = DnsInfo( - loadStatus: 0, // 0 = loading, 1 = loaded, 2 = error - data: null - ); - - final BlockedServices _blockedServicesList = BlockedServices( - loadStatus: 0, - services: null - ); + ApiClient? _apiClient; final UpdateAvailable _updateAvailable = UpdateAvailable( loadStatus: LoadStatus.loading, data: null, ); - FilteringStatus? _filteringStatus; + ApiClient? get apiClient { + return _apiClient; + } List get serversList { return _serversList; @@ -78,54 +33,6 @@ class ServersProvider with ChangeNotifier { return _selectedServer; } - ServerStatus get serverStatus { - return _serverStatus; - } - - List get protectionsManagementProcess { - return _protectionsManagementProcess; - } - - Clients get clients { - return _clients; - } - - String? get searchTermClients { - return _searchTermClients; - } - - List get filteredActiveClients { - return _filteredActiveClients; - } - - List get filteredAddedClients { - return _filteredAddedClients; - } - - FilteringStatus? get filteringStatus { - return _filteringStatus; - } - - Filtering get filtering { - return _filtering; - } - - DhcpModel get dhcp { - return _dhcp; - } - - RewriteRules get rewriteRules { - return _rewriteRules; - } - - DnsInfo get dnsInfo { - return _dnsInfo; - } - - BlockedServices get blockedServicesList { - return _blockedServicesList; - } - UpdateAvailable get updateAvailable { return _updateAvailable; } @@ -144,151 +51,6 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } - void setServerStatusData(ServerStatusData data) { - _serverStatus.data = data; - notifyListeners(); - } - - void setServerStatusLoad(int status) { - _serverStatus.loadStatus = status; - notifyListeners(); - } - - void setClientsLoadStatus(LoadStatus status, bool notify) { - _clients.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - - void setClientsData(ClientsData data) { - _clients.data = data; - if (_searchTermClients != null && _searchTermClients != '') { - _filteredActiveClients = _clients.data!.autoClientsData.where( - (client) => client.ip.contains(_searchTermClients!.toLowerCase()) || (client.name != null ? client.name!.contains(_searchTermClients!.toLowerCase()) : false) - ).toList(); - _filteredAddedClients = _clients.data!.clients.where( - (client) { - isContained(String value) => value.contains(value.toLowerCase()); - return client.ids.any(isContained); - } - ).toList(); - } - else { - _filteredActiveClients = data.autoClientsData; - _filteredAddedClients = data.clients; - } - notifyListeners(); - } - - void setSearchTermClients(String? value) { - _searchTermClients = value; - if (value != null && value != '') { - if (_clients.data != null) { - _filteredActiveClients = _clients.data!.autoClientsData.where( - (client) => client.ip.contains(value.toLowerCase()) || (client.name != null ? client.name!.contains(value.toLowerCase()) : false) - ).toList(); - _filteredAddedClients = _clients.data!.clients.where( - (client) { - isContained(String value) => value.contains(value.toLowerCase()); - return client.ids.any(isContained); - } - ).toList(); - } - } - else { - if (_clients.data != null) _filteredActiveClients = _clients.data!.autoClientsData; - if (_clients.data != null) _filteredAddedClients = _clients.data!.clients; - } - notifyListeners(); - } - - void setAllowedDisallowedClientsBlockedDomains(ClientsAllowedBlocked data) { - _clients.data?.clientsAllowedBlocked = data; - notifyListeners(); - } - - void setFilteringStatus(FilteringStatus status) { - _filteringStatus = status; - notifyListeners(); - } - - void setFilteringData(FilteringData data) { - _filtering.data = data; - notifyListeners(); - } - - void setFilteringLoadStatus(LoadStatus loadStatus, bool notify) { - _filtering.loadStatus = loadStatus; - if (notify == true) { - notifyListeners(); - } - } - - void setFilteringProtectionStatus(bool status) { - _serverStatus.data!.filteringEnabled = status; - _filtering.data!.enabled = status; - notifyListeners(); - } - - void setFiltersUpdateFrequency(int frequency) { - _filtering.data!.interval = frequency; - notifyListeners(); - } - - void setBlockedServices(List blockedServices) { - _filtering.data!.blockedServices = blockedServices; - notifyListeners(); - } - - void setDhcpData(DhcpData data) { - _dhcp.data = data; - notifyListeners(); - } - - void setDhcpLoadStatus(int status, bool notify) { - _dhcp.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - - void setRewriteRulesData(List data) { - _rewriteRules.data = data; - notifyListeners(); - } - - void setRewriteRulesLoadStatus(int status, bool notify) { - _rewriteRules.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - - void setDnsInfoData(DnsInfoData data) { - _dnsInfo.data = data; - notifyListeners(); - } - - void setDnsInfoLoadStatus(int status, bool notify) { - _dnsInfo.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - - void setBlockedServiceListData(List data) { - _blockedServicesList.services = data; - notifyListeners(); - } - - void setBlockedServicesListLoadStatus(int status, bool notify) { - _blockedServicesList.loadStatus = status; - if (notify == true) { - notifyListeners(); - } - } - void setUpdateAvailableLoadStatus(LoadStatus status, bool notify) { _updateAvailable.loadStatus = status; if (notify == true) { @@ -301,6 +63,11 @@ class ServersProvider with ChangeNotifier { notifyListeners(); } + void setApiClient(ApiClient client) { + _apiClient = client; + notifyListeners(); + } + Future createServer(Server server) async { final saved = await saveServerQuery(_dbInstance!, server); if (saved == null) { @@ -360,6 +127,11 @@ class ServersProvider with ChangeNotifier { } }).toList(); _serversList = newServers; + + if (selectedServer != null &&server.id == selectedServer!.id) { + _apiClient = ApiClient(server: server); + } + notifyListeners(); return null; } @@ -372,6 +144,7 @@ class ServersProvider with ChangeNotifier { final result = await removeServerQuery(_dbInstance!, server.id); if (result == true) { _selectedServer = null; + _apiClient = null; List newServers = _serversList.where((s) => s.id != server.id).toList(); _serversList = newServers; notifyListeners(); @@ -382,155 +155,12 @@ class ServersProvider with ChangeNotifier { } } - Future updateBlocking({ - required Server server, - required String block, - required bool newStatus, - int? time - }) async { - switch (block) { - case 'general': - _protectionsManagementProcess.add('general'); - notifyListeners(); - - final result = await updateGeneralProtection( - server: server, - enable: newStatus, - time: time - ); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.generalEnabled = newStatus; - if (time != null) { - _serverStatus.data!.timeGeneralDisabled = time; - _serverStatus.data!.disabledUntil = generateTimeDeadline(time); - } - else { - _serverStatus.data!.timeGeneralDisabled = 0; - _serverStatus.data!.disabledUntil = null; - } - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - case 'general_legacy': - _protectionsManagementProcess.add('general'); - notifyListeners(); - - final result = await updateGeneralProtectionLegacy(server, newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.generalEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - - case 'filtering': - _protectionsManagementProcess.add('filtering'); - notifyListeners(); - - final result = await updateFiltering( - server: server, - enable: newStatus, - ); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'filtering').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.filteringEnabled = newStatus; - notifyListeners(); - return null; - } - else { - - notifyListeners(); - return result['log']; - } - - case 'safeSearch': - _protectionsManagementProcess.add('safeSearch'); - notifyListeners(); - - final result = serverVersionIsAhead( - currentVersion: serverStatus.data!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == true - ? await updateSafeSearchSettings(server: server, body: { 'enabled': newStatus }) - : await updateSafeSearchLegacy(server, newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeSearch').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.safeSearchEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - case 'safeBrowsing': - _protectionsManagementProcess.add('safeBrowsing'); - notifyListeners(); - - final result = await updateSafeBrowsing(server, newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeBrowsing').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.safeBrowsingEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - case 'parentalControl': - _protectionsManagementProcess.add('parentalControl'); - notifyListeners(); - - final result = await updateParentalControl(server, newStatus); - - _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'parentalControl').toList(); - - if (result['result'] == 'success') { - _serverStatus.data!.parentalControlEnabled = newStatus; - notifyListeners(); - return null; - } - else { - notifyListeners(); - return result['log']; - } - - default: - return false; - } - } - void checkServerUpdatesAvailable(Server server) async { setUpdateAvailableLoadStatus(LoadStatus.loading, true); - final result = await checkServerUpdates(server: server); + final result = await _apiClient!.checkServerUpdates(); if (result['result'] == 'success') { UpdateAvailableData data = UpdateAvailableData.fromJson(result['data']); - final gitHubResult = await getUpdateChangelog(server: server, releaseTag: data.newVersion ?? data.currentVersion); + final gitHubResult = await _apiClient!.getUpdateChangelog(releaseTag: data.newVersion ?? data.currentVersion); if (gitHubResult['result'] == 'success') { data.changelog = gitHubResult['body']; } @@ -556,8 +186,16 @@ class ServersProvider with ChangeNotifier { } } - void saveFromDb(List>? data) async { + Future initializateServer(Server server) async { + final serverStatus = await _apiClient!.getServerStatus(); + if (serverStatus['result'] == 'success') { + checkServerUpdatesAvailable(server); // Do not await + } + } + + Future saveFromDb(List>? data) async { if (data != null) { + Server? defaultServer; for (var server in data) { final Server serverObj = Server( id: server['id'], @@ -574,20 +212,21 @@ class ServersProvider with ChangeNotifier { ); _serversList.add(serverObj); if (convertFromIntToBool(server['defaultServer']) == true) { - _selectedServer = serverObj; - _serverStatus.loadStatus = 0; - final serverStatus = await getServerStatus(serverObj); - if (serverStatus['result'] == 'success') { - _serverStatus.data = serverStatus['data']; - _serverStatus.loadStatus = 1; - checkServerUpdatesAvailable(serverObj); // Do not await - } - else { - _serverStatus.loadStatus = 2; - } + defaultServer = serverObj; } } + + notifyListeners(); + + if (defaultServer != null) { + _selectedServer = defaultServer; + _apiClient = ApiClient(server: defaultServer); + initializateServer(defaultServer); + } + } + else { + notifyListeners(); + return null; } - notifyListeners(); } } \ No newline at end of file diff --git a/lib/providers/status_provider.dart b/lib/providers/status_provider.dart new file mode 100644 index 0000000..7fa1682 --- /dev/null +++ b/lib/providers/status_provider.dart @@ -0,0 +1,347 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +import 'package:adguard_home_manager/models/server_status.dart'; +import 'package:adguard_home_manager/models/filtering_status.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/functions/time_server_disabled.dart'; + +class StatusProvider with ChangeNotifier { + ServersProvider? _serversProvider; + + update(ServersProvider? provider) { + _serversProvider = provider; + } + + LoadStatus _loadStatus = LoadStatus.loading; + ServerStatus? _serverStatus; // serverStatus != null means server is connected + List _protectionsManagementProcess = []; // protections that are currenty being enabled or disabled + FilteringStatus? _filteringStatus; + + // Countdown + DateTime? _currentDeadline; + Timer? _countdown; + int _remaining = 0; + + LoadStatus get loadStatus { + return _loadStatus; + } + + ServerStatus? get serverStatus { + return _serverStatus; + } + + List get protectionsManagementProcess { + return _protectionsManagementProcess; + } + + FilteringStatus? get filteringStatus { + return _filteringStatus; + } + + int get remainingTime { + return _remaining; + } + + DateTime? get currentDeadline { + return _currentDeadline; + } + + void setServerStatusData({ + required ServerStatus data, + }) { + _serverStatus = data; + if ( + (_countdown == null ||( _countdown != null && _countdown!.isActive == false)) && + data.disabledUntil != null + ) { + startCountdown(data.disabledUntil!); + } + notifyListeners(); + } + + void setServerStatusLoad(LoadStatus status) { + _loadStatus = status; + notifyListeners(); + } + + void setFilteringStatus(FilteringStatus status) { + _filteringStatus = status; + notifyListeners(); + } + + void startCountdown(DateTime deadline) { + stopCountdown(); + + _currentDeadline = deadline; + _remaining = deadline.difference(DateTime.now()).inSeconds+1; + + _countdown = Timer.periodic( + const Duration(seconds: 1), + (Timer timer) async { + if (_remaining == 0) { + timer.cancel(); + notifyListeners(); + getServerStatus(); + } + else { + _remaining = _remaining - 1; + notifyListeners(); + } + }, + ); + } + + void stopCountdown() { + if (_countdown != null && _countdown!.isActive) { + _countdown!.cancel(); + _countdown = null; + _remaining = 0; + _currentDeadline = null; + } + } + + Future updateBlocking({ + required String block, + required bool newStatus, + int? time + }) async { + switch (block) { + case 'general': + _protectionsManagementProcess.add('general'); + notifyListeners(); + + final result = await _serversProvider!.apiClient!.updateGeneralProtection( + enable: newStatus, + time: time + ); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); + + if (result['result'] == 'success') { + _serverStatus!.generalEnabled = newStatus; + if (time != null) { + final deadline = generateTimeDeadline(time); + _serverStatus!.timeGeneralDisabled = time; + _serverStatus!.disabledUntil = deadline; + startCountdown(deadline); + } + else { + _serverStatus!.timeGeneralDisabled = 0; + _serverStatus!.disabledUntil = null; + stopCountdown(); + } + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + case 'general_legacy': + _protectionsManagementProcess.add('general'); + notifyListeners(); + + final result = await _serversProvider!.apiClient!.updateGeneralProtectionLegacy(newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'general').toList(); + + if (result['result'] == 'success') { + _serverStatus!.generalEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + + case 'filtering': + _protectionsManagementProcess.add('filtering'); + notifyListeners(); + + final result = await _serversProvider!.apiClient!.updateFiltering( + enable: newStatus, + ); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'filtering').toList(); + + if (result['result'] == 'success') { + _serverStatus!.filteringEnabled = newStatus; + notifyListeners(); + return null; + } + else { + + notifyListeners(); + return result['log']; + } + + case 'safeSearch': + _protectionsManagementProcess.add('safeSearch'); + notifyListeners(); + + final result = serverVersionIsAhead( + currentVersion: serverStatus!.serverVersion, + referenceVersion: 'v0.107.28', + referenceVersionBeta: 'v0.108.0-b.33' + ) == true + ? await _serversProvider!.apiClient!.updateSafeSearchSettings(body: { 'enabled': newStatus }) + : await _serversProvider!.apiClient!.updateSafeSearchLegacy(newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeSearch').toList(); + + if (result['result'] == 'success') { + _serverStatus!.safeSearchEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + case 'safeBrowsing': + _protectionsManagementProcess.add('safeBrowsing'); + notifyListeners(); + + final result = await _serversProvider!.apiClient!.updateSafeBrowsing(newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'safeBrowsing').toList(); + + if (result['result'] == 'success') { + _serverStatus!.safeBrowsingEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + case 'parentalControl': + _protectionsManagementProcess.add('parentalControl'); + notifyListeners(); + + final result = await _serversProvider!.apiClient!.updateParentalControl(newStatus); + + _protectionsManagementProcess = _protectionsManagementProcess.where((e) => e != 'parentalControl').toList(); + + if (result['result'] == 'success') { + _serverStatus!.parentalControlEnabled = newStatus; + notifyListeners(); + return null; + } + else { + notifyListeners(); + return result['log']; + } + + default: + return false; + } + } + + void setFilteringEnabledStatus(bool status) { + _serverStatus!.filteringEnabled = status; + } + + Future getFilteringRules() async { + final result = await _serversProvider!.apiClient!.getFilteringRules(); + if (result['result'] == 'success') { + _filteringStatus = result['data']; + notifyListeners(); + return true; + } + else { + return false; + } + } + + Future getServerStatus({ + bool? withLoadingIndicator + }) async { + if (withLoadingIndicator == true) { + _loadStatus = LoadStatus.loading; + } + + final result = await _serversProvider!.apiClient!.getServerStatus(); + if (result['result'] == 'success') { + setServerStatusData( + data: result['data'] + ); + _loadStatus = LoadStatus.loaded; + notifyListeners(); + return true; + } + else { + if (withLoadingIndicator == true) _loadStatus = LoadStatus.error; + notifyListeners(); + return false; + } + } + + Future blockUnblockDomain({ + required String domain, + required String newStatus + }) async { + final rules = await _serversProvider!.apiClient!.getFilteringRules(); + + if (rules['result'] == 'success') { + FilteringStatus oldStatus = serverStatus!.filteringStatus; + + List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); + if (newStatus == 'block') { + newRules.add("||$domain^"); + } + else if (newStatus == 'unblock') { + newRules.add("@@||$domain^"); + } + FilteringStatus newObj = serverStatus!.filteringStatus; + newObj.userRules = newRules; + _filteringStatus = newObj; + + final result = await _serversProvider!.apiClient!.postFilteringRules(data: {'rules': newRules}); + + if (result['result'] == 'success') { + return true; + } + else { + _filteringStatus = oldStatus; + return false; + } + } + else { + return false; + } + } + + Future updateSafeSearchConfig(Map status) async { + final result = await _serversProvider!.apiClient!.updateSafeSearchSettings( + body: status + ); + + if (result['result'] == 'success') { + ServerStatus data = serverStatus!; + data.safeSearchEnabled = status['enabled'] ?? false; + data.safeSeachBing = status['bing'] ?? false; + data.safeSearchDuckduckgo = status['duckduckgo'] ?? false; + data.safeSearchGoogle = status['google'] ?? false; + data.safeSearchPixabay = status['pixabay'] ?? false; + data.safeSearchYandex = status['yandex'] ?? false; + data.safeSearchYoutube = status['youtube'] ?? false; + + setServerStatusData(data: data); + return true; + } + else { + notifyListeners(); + return false; + } + } +} \ No newline at end of file diff --git a/lib/screens/clients/added_list.dart b/lib/screens/clients/added_list.dart index 43f3a44..6b7f33c 100644 --- a/lib/screens/clients/added_list.dart +++ b/lib/screens/clients/added_list.dart @@ -17,20 +17,16 @@ import 'package:adguard_home_manager/screens/clients/options_modal.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/functions/maps_fns.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class AddedList extends StatefulWidget { final ScrollController scrollController; - final LoadStatus loadStatus; final List data; - final Future Function() fetchClients; final void Function(Client) onClientSelected; final Client? selectedClient; final bool splitView; @@ -38,9 +34,7 @@ class AddedList extends StatefulWidget { const AddedList({ Key? key, required this.scrollController, - required this.loadStatus, required this.data, - required this.fetchClients, required this.onClientSelected, this.selectedClient, required this.splitView @@ -76,7 +70,8 @@ class _AddedListState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -85,31 +80,11 @@ class _AddedListState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); - final result = await postUpdateClient(server: serversProvider.selectedServer!, data: { - 'name': client.name, - 'data': serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == false - ? removePropFromMap(client.toJson(), 'safesearch_enabled') - : removePropFromMap(client.toJson(), 'safe_search') - }); + final result = await clientsProvider.editClient(client); processModal.close(); - if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; - clientsData.clients = clientsData.clients.map((e) { - if (e.name == client.name) { - return client; - } - else { - return e; - } - }).toList(); - serversProvider.setClientsData(clientsData); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientUpdatedSuccessfully, @@ -117,8 +92,6 @@ class _AddedListState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotUpdated, @@ -131,19 +104,14 @@ class _AddedListState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); - final result = await postDeleteClient(server: serversProvider.selectedServer!, name: client.name); + final result = await clientsProvider.deleteClient(client); processModal.close(); - if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; - clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); - serversProvider.setClientsData(clientsData); - + if (result == true) { if (widget.splitView == true) { SplitView.of(context).popUntil(0); } - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientDeletedSuccessfully, @@ -151,15 +119,13 @@ class _AddedListState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotDeleted, color: Colors.red ); } - } + } void openClientModal(Client client) { if (width > 900 || !(Platform.isAndroid | Platform.isIOS)) { @@ -168,7 +134,7 @@ class _AddedListState extends State { context: context, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, onDelete: deleteClient, client: client, dialog: true, @@ -180,7 +146,7 @@ class _AddedListState extends State { fullscreenDialog: true, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, onDelete: deleteClient, client: client, dialog: false, @@ -240,7 +206,7 @@ class _AddedListState extends State { onLongPress: openOptionsModal, onEdit: openClientModal, splitView: widget.splitView, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, ), noData: SizedBox( width: double.maxFinite, @@ -260,7 +226,7 @@ class _AddedListState extends State { ), const SizedBox(height: 30), TextButton.icon( - onPressed: widget.fetchClients, + onPressed: () => clientsProvider.fetchClients(updateLoading: true), icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh), ) @@ -290,8 +256,10 @@ class _AddedListState extends State { ], ), ), - loadStatus: widget.loadStatus, - onRefresh: widget.fetchClients, + loadStatus: statusProvider.loadStatus == LoadStatus.loading || clientsProvider.loadStatus == LoadStatus.loading + ? LoadStatus.loading + : clientsProvider.loadStatus, + onRefresh: () => clientsProvider.fetchClients(updateLoading: false), fab: const ClientsFab(), fabVisible: isVisible, ); diff --git a/lib/screens/clients/client_screen.dart b/lib/screens/clients/client_screen.dart index 2e282f5..c40a6d4 100644 --- a/lib/screens/clients/client_screen.dart +++ b/lib/screens/clients/client_screen.dart @@ -11,7 +11,8 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/models/safe_search.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; class ClientScreen extends StatefulWidget { @@ -130,7 +131,8 @@ class _ClientScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); + final statusProvider = Provider.of(context); void createClient() { final Client client = Client( @@ -200,7 +202,7 @@ class _ClientScreenState extends State { context: context, builder: (context) => TagsModal( selectedTags: selectedTags, - tags: serversProvider.clients.data!.supportedTags, + tags: clientsProvider.clients!.supportedTags, onConfirm: (selected) => setState(() => selectedTags = selected), ) ); @@ -506,7 +508,7 @@ class _ClientScreenState extends State { ), if ( serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true @@ -531,7 +533,7 @@ class _ClientScreenState extends State { ), if ( serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == false diff --git a/lib/screens/clients/clients.dart b/lib/screens/clients/clients.dart index 9e13c77..1dada10 100644 --- a/lib/screens/clients/clients.dart +++ b/lib/screens/clients/clients.dart @@ -11,84 +11,40 @@ import 'package:adguard_home_manager/screens/clients/logs_list_client.dart'; import 'package:adguard_home_manager/screens/clients/clients_desktop_view.dart'; import 'package:adguard_home_manager/screens/clients/added_list.dart'; -import 'package:adguard_home_manager/models/app_log.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class Clients extends StatelessWidget { +class Clients extends StatefulWidget { const Clients({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return ClientsWidget( - server: serversProvider.selectedServer!, - setLoadingStatus: serversProvider.setClientsLoadStatus, - setClientsData: serversProvider.setClientsData, - setSelectedClientsTab: appConfigProvider.setSelectedClientsTab, - addLog: appConfigProvider.addLog, - ); - } + State createState() => _ClientsState(); } -class ClientsWidget extends StatefulWidget { - final Server server; - final void Function(LoadStatus, bool) setLoadingStatus; - final void Function(ClientsData) setClientsData; - final void Function(int) setSelectedClientsTab; - final void Function(AppLog) addLog; - - const ClientsWidget({ - Key? key, - required this.server, - required this.setLoadingStatus, - required this.setClientsData, - required this.setSelectedClientsTab, - required this.addLog, - }) : super(key: key); - - @override - State createState() => _ClientsWidgetState(); -} - -class _ClientsWidgetState extends State with TickerProviderStateMixin { +class _ClientsState extends State with TickerProviderStateMixin { late TabController tabController; final ScrollController scrollController = ScrollController(); bool searchMode = false; final TextEditingController searchController = TextEditingController(); - Future fetchClients() async { - widget.setLoadingStatus(LoadStatus.loading, false); - final result = await getClients(widget.server); - if (mounted) { - if (result['result'] == 'success') { - widget.setClientsData(result['data']); - widget.setLoadingStatus(LoadStatus.loaded, true); - } - else { - widget.addLog(result['log']); - widget.setLoadingStatus(LoadStatus.error, true); - } - } - } - @override void initState() { - fetchClients(); + final clientsProvider = Provider.of(context, listen: false); + clientsProvider.fetchClients(updateLoading: true); + super.initState(); tabController = TabController( initialIndex: 0, length: 2, vsync: this, ); - tabController.addListener(() => widget.setSelectedClientsTab(tabController.index)); + tabController.addListener( + () => Provider.of(context, listen: false).setSelectedClientsTab(tabController.index) + ); } List generateClientsList(List clients, List ips) { @@ -98,6 +54,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -137,10 +94,8 @@ class _ClientsWidgetState extends State with TickerProviderStateM children: [ ClientsList( scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.filteredActiveClients : [], - fetchClients: fetchClients, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredActiveClients : [], onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( builder: (context) => LogsListClient( ip: client.ip, @@ -153,10 +108,8 @@ class _ClientsWidgetState extends State with TickerProviderStateM ), AddedList( scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.filteredAddedClients : [], - fetchClients: fetchClients, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredAddedClients : [], onClientSelected: (client) => Navigator.push(context, MaterialPageRoute( builder: (context) => LogsListClient( ip: client.ids[0], @@ -190,7 +143,6 @@ class _ClientsWidgetState extends State with TickerProviderStateM child: ClientsDesktopView( serversProvider: serversProvider, appConfigProvider: appConfigProvider, - fetchClients: fetchClients, ) ); } @@ -203,7 +155,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM title: Text(AppLocalizations.of(context)!.clients), centerTitle: false, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded) ...[ + if (clientsProvider.loadStatus == LoadStatus.loaded) ...[ IconButton( onPressed: () => { Navigator.push(context, MaterialPageRoute( @@ -240,7 +192,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM setState(() { searchMode = false; searchController.text = ""; - serversProvider.setSearchTermClients(null); + clientsProvider.setSearchTermClients(null); }); }, icon: const Icon(Icons.arrow_back_rounded) @@ -249,13 +201,13 @@ class _ClientsWidgetState extends State with TickerProviderStateM Expanded( child: TextField( controller: searchController, - onChanged: (value) => serversProvider.setSearchTermClients(value), + onChanged: (value) => clientsProvider.setSearchTermClients(value), decoration: InputDecoration( suffixIcon: IconButton( onPressed: () { setState(() { searchController.text = ""; - serversProvider.setSearchTermClients(null); + clientsProvider.setSearchTermClients(null); }); }, icon: const Icon(Icons.clear_rounded) @@ -281,7 +233,7 @@ class _ClientsWidgetState extends State with TickerProviderStateM centerTitle: false, forceElevated: innerBoxIsScrolled, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ IconButton( onPressed: () => setState(() => searchMode = true), icon: const Icon(Icons.search), diff --git a/lib/screens/clients/clients_desktop_view.dart b/lib/screens/clients/clients_desktop_view.dart index 0a4b783..d6707ad 100644 --- a/lib/screens/clients/clients_desktop_view.dart +++ b/lib/screens/clients/clients_desktop_view.dart @@ -10,6 +10,7 @@ import 'package:adguard_home_manager/screens/clients/added_list.dart'; import 'package:adguard_home_manager/screens/clients/clients_list.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/clients.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -18,13 +19,11 @@ import 'package:adguard_home_manager/providers/servers_provider.dart'; class ClientsDesktopView extends StatefulWidget { final ServersProvider serversProvider; final AppConfigProvider appConfigProvider; - final Future Function() fetchClients; const ClientsDesktopView({ Key? key, required this.serversProvider, required this.appConfigProvider, - required this.fetchClients }) : super(key: key); @override @@ -55,6 +54,7 @@ class _ClientsDesktopViewState extends State with TickerPro @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); PreferredSizeWidget tabBar() { @@ -92,10 +92,8 @@ class _ClientsDesktopViewState extends State with TickerPro children: [ ClientsList( scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.filteredActiveClients : [], - fetchClients: widget.fetchClients, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredActiveClients : [], onClientSelected: (client) => setState(() { selectedAddedClient = null; selectedActiveClient = client; @@ -114,10 +112,8 @@ class _ClientsDesktopViewState extends State with TickerPro ), AddedList( scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.filteredAddedClients : [], - fetchClients: widget.fetchClients, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.filteredAddedClients : [], onClientSelected: (client) => setState(() { selectedActiveClient = null; selectedAddedClient = client; @@ -146,7 +142,7 @@ class _ClientsDesktopViewState extends State with TickerPro setState(() { searchMode = false; searchController.text = ""; - serversProvider.setSearchTermClients(null); + clientsProvider.setSearchTermClients(null); }); }, icon: const Icon(Icons.arrow_back_rounded) @@ -155,13 +151,13 @@ class _ClientsDesktopViewState extends State with TickerPro Expanded( child: TextField( controller: searchController, - onChanged: (value) => serversProvider.setSearchTermClients(value), + onChanged: (value) => clientsProvider.setSearchTermClients(value), decoration: InputDecoration( suffixIcon: IconButton( onPressed: () { setState(() { searchController.text = ""; - serversProvider.setSearchTermClients(null); + clientsProvider.setSearchTermClients(null); }); }, icon: const Icon(Icons.clear_rounded) @@ -195,7 +191,7 @@ class _ClientsDesktopViewState extends State with TickerPro title: title(), centerTitle: false, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ IconButton( onPressed: () => setState(() => searchMode = true), icon: const Icon(Icons.search), @@ -226,7 +222,7 @@ class _ClientsDesktopViewState extends State with TickerPro centerTitle: false, forceElevated: innerBoxIsScrolled, actions: [ - if (serversProvider.clients.loadStatus == LoadStatus.loaded && searchMode == false) ...[ + if (clientsProvider.loadStatus == LoadStatus.loaded && searchMode == false) ...[ IconButton( onPressed: () => setState(() => searchMode = true), icon: const Icon(Icons.search), diff --git a/lib/screens/clients/clients_list.dart b/lib/screens/clients/clients_list.dart index de284c5..4ecd98c 100644 --- a/lib/screens/clients/clients_list.dart +++ b/lib/screens/clients/clients_list.dart @@ -1,18 +1,17 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/active_client_tile.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; class ClientsList extends StatelessWidget { final ScrollController scrollController; - final LoadStatus loadStatus; final List data; - final Future Function() fetchClients; final void Function(AutoClient) onClientSelected; final AutoClient? selectedClient; final bool splitView; @@ -21,9 +20,7 @@ class ClientsList extends StatelessWidget { const ClientsList({ Key? key, required this.scrollController, - required this.loadStatus, required this.data, - required this.fetchClients, required this.onClientSelected, this.selectedClient, required this.splitView, @@ -32,6 +29,8 @@ class ClientsList extends StatelessWidget { @override Widget build(BuildContext context) { + final clientsProvider = Provider.of(context); + return CustomTabContentList( listPadding: splitView == true ? const EdgeInsets.only(top: 8) @@ -79,7 +78,7 @@ class ClientsList extends StatelessWidget { ), const SizedBox(height: 30), TextButton.icon( - onPressed: fetchClients, + onPressed: () => clientsProvider.fetchClients(updateLoading: false), icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh) ) @@ -110,8 +109,8 @@ class ClientsList extends StatelessWidget { ], ), ), - loadStatus: loadStatus, - onRefresh: fetchClients + loadStatus: clientsProvider.loadStatus, + onRefresh: () => clientsProvider.fetchClients(updateLoading: false), ); } } \ No newline at end of file diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 3c05c7e..8d73050 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -9,12 +9,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/clients/client_screen.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/functions/maps_fns.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class ClientsFab extends StatelessWidget { @@ -22,8 +20,9 @@ class ClientsFab extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final statusProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -31,24 +30,11 @@ class ClientsFab extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); - final result = await postAddClient( - server: serversProvider.selectedServer!, - data: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, - referenceVersion: 'v0.107.28', - referenceVersionBeta: 'v0.108.0-b.33' - ) == false - ? removePropFromMap(client.toJson(), 'safesearch_enabled') - : removePropFromMap(client.toJson(), 'safe_search') - ); + final result = await clientsProvider.addClient(client); processModal.close(); - if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; - clientsData.clients.add(client); - serversProvider.setClientsData(clientsData); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAddedSuccessfully, @@ -56,8 +42,6 @@ class ClientsFab extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotAdded, @@ -73,7 +57,7 @@ class ClientsFab extends StatelessWidget { context: context, builder: (BuildContext context) => ClientScreen( onConfirm: confirmAddClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, dialog: true, ) ); @@ -83,7 +67,7 @@ class ClientsFab extends StatelessWidget { fullscreenDialog: true, builder: (BuildContext context) => ClientScreen( onConfirm: confirmAddClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, dialog: false, ) )); diff --git a/lib/screens/clients/logs_list_client.dart b/lib/screens/clients/logs_list_client.dart index 6fe4782..0ddc99a 100644 --- a/lib/screens/clients/logs_list_client.dart +++ b/lib/screens/clients/logs_list_client.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:async/async.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/logs/log_tile.dart'; @@ -10,7 +11,6 @@ import 'package:adguard_home_manager/screens/logs/log_details_screen.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class LogsListClient extends StatefulWidget { final String ip; @@ -53,6 +53,8 @@ class _LogsListClientState extends State { String? responseStatus, String? searchText, }) async { + final serversProvider = Provider.of(context, listen: false); + int offst = inOffset ?? offset; if (loadingMore != null && loadingMore == true) { @@ -62,8 +64,7 @@ class _LogsListClientState extends State { if (cancelableRequest != null) cancelableRequest!.cancel(); cancelableRequest = CancelableOperation.fromFuture( - getLogs( - server: widget.serversProvider.selectedServer!, + serversProvider.apiClient!.getLogs( count: logsQuantity, offset: offst, search: '"${widget.ip}"' diff --git a/lib/screens/clients/search_clients.dart b/lib/screens/clients/search_clients.dart index c9e72d8..4d2c754 100644 --- a/lib/screens/clients/search_clients.dart +++ b/lib/screens/clients/search_clients.dart @@ -11,43 +11,25 @@ import 'package:adguard_home_manager/screens/clients/remove_client_modal.dart'; import 'package:adguard_home_manager/screens/clients/client_screen.dart'; import 'package:adguard_home_manager/screens/clients/options_modal.dart'; +import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/widgets/section_label.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; -class SearchClients extends StatelessWidget { +class SearchClients extends StatefulWidget { const SearchClients({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - - return SearchClientsWidget( - serversProvider: serversProvider, - ); - } + State createState() => _SearchClientsState(); } -class SearchClientsWidget extends StatefulWidget { - final ServersProvider serversProvider; - - const SearchClientsWidget({ - Key? key, - required this.serversProvider, - }) : super(key: key); - - @override - State createState() => _SearchClientsWidgetState(); -} - -class _SearchClientsWidgetState extends State { +class _SearchClientsState extends State { late ScrollController scrollController; final TextEditingController searchController = TextEditingController(); @@ -86,11 +68,13 @@ class _SearchClientsWidgetState extends State { @override void initState() { + final clientsProvider = Provider.of(context, listen: false); + scrollController = ScrollController()..addListener(scrollListener); setState(() { - clients = widget.serversProvider.clients.data!.clients; - autoClients = widget.serversProvider.clients.data!.autoClientsData; + clients = clientsProvider.clients!.clients; + autoClients = clientsProvider.clients!.autoClients; }); super.initState(); @@ -98,7 +82,8 @@ class _SearchClientsWidgetState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -107,19 +92,11 @@ class _SearchClientsWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); - final result = await postDeleteClient(server: serversProvider.selectedServer!, name: client.name); + final result = await clientsProvider.deleteClient(client); processModal.close(); - if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; - clientsData.clients = clientsData.clients.where((c) => c.name != client.name).toList(); - serversProvider.setClientsData(clientsData); - setState(() { - clients = clientsData.clients; - }); - search(searchController.text); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientDeletedSuccessfully, @@ -127,44 +104,23 @@ class _SearchClientsWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotDeleted, color: Colors.red ); } - } + } void confirmEditClient(Client client) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingClient); - final result = await postUpdateClient(server: serversProvider.selectedServer!, data: { - 'name': client.name, - 'data': client.toJson() - }); + final result = await clientsProvider.editClient(client); processModal.close(); - if (result['result'] == 'success') { - ClientsData clientsData = serversProvider.clients.data!; - clientsData.clients = clientsData.clients.map((e) { - if (e.name == client.name) { - return client; - } - else { - return e; - } - }).toList(); - serversProvider.setClientsData(clientsData); - - setState(() { - clients = clientsData.clients; - }); - search(searchController.text); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientUpdatedSuccessfully, @@ -172,8 +128,6 @@ class _SearchClientsWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientNotUpdated, @@ -189,7 +143,7 @@ class _SearchClientsWidgetState extends State { context: context, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, onDelete: deleteClient, client: client, dialog: true, @@ -201,7 +155,7 @@ class _SearchClientsWidgetState extends State { fullscreenDialog: true, builder: (BuildContext context) => ClientScreen( onConfirm: confirmEditClient, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, onDelete: deleteClient, client: client, dialog: false, @@ -356,7 +310,7 @@ class _SearchClientsWidgetState extends State { Icons.search_rounded, size: 19, color: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true diff --git a/lib/screens/clients/services_modal.dart b/lib/screens/clients/services_modal.dart index fa5c2aa..1a98275 100644 --- a/lib/screens/clients/services_modal.dart +++ b/lib/screens/clients/services_modal.dart @@ -2,11 +2,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; -class ServicesModal extends StatelessWidget { +class ServicesModal extends StatefulWidget { final List blockedServices; final void Function(List) onConfirm; @@ -17,56 +16,20 @@ class ServicesModal extends StatelessWidget { }) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return ServicesModalWidget( - blockedServices: blockedServices, - onConfirm: onConfirm, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _ServicesModalStateWidget(); } -class ServicesModalWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - final List blockedServices; - final void Function(List) onConfirm; - - const ServicesModalWidget({ - Key? key, - required this.blockedServices, - required this.onConfirm, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _ServicesModalStateWidget(); -} - -class _ServicesModalStateWidget extends State { +class _ServicesModalStateWidget extends State { List blockedServices = []; - Future loadBlockedServices() async { - final result = await getBlockedServices(server: widget.serversProvider.selectedServer!); - if (result['result'] == 'success') { - widget.serversProvider.setBlockedServicesListLoadStatus(1, true); - widget.serversProvider.setBlockedServiceListData(result['data']); - } - else { - widget.serversProvider.setBlockedServicesListLoadStatus(2, true); - widget.appConfigProvider.addLog(result['log']); - } - } + @override void initState() { - if (widget.serversProvider.blockedServicesList.loadStatus != 1) { - loadBlockedServices(); + final filteringProvider = Provider.of(context, listen: false); + + if (filteringProvider.blockedServicesLoadStatus != LoadStatus.loaded) { + filteringProvider.getBlockedServices(); } blockedServices = widget.blockedServices; @@ -88,11 +51,11 @@ class _ServicesModalStateWidget extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); Widget content() { - switch (serversProvider.blockedServicesList.loadStatus) { - case 0: + switch (filteringProvider.blockedServicesLoadStatus) { + case LoadStatus.loading: return Padding( padding: const EdgeInsets.all(24), child: SizedBox( @@ -116,34 +79,34 @@ class _ServicesModalStateWidget extends State { ), ); - case 1: + case LoadStatus.loaded: return SizedBox( width: double.minPositive, height: MediaQuery.of(context).size.height*0.5, child: ListView.builder( shrinkWrap: true, - itemCount: serversProvider.blockedServicesList.services!.length, + itemCount: filteringProvider.blockedServices!.services.length, itemBuilder: (context, index) => CheckboxListTile( title: Padding( padding: const EdgeInsets.only(left: 10), child: Text( - serversProvider.blockedServicesList.services![index].name, + filteringProvider.blockedServices!.services[index].name, style: TextStyle( fontWeight: FontWeight.normal, color: Theme.of(context).colorScheme.onSurface ), ), ), - value: blockedServices.contains(serversProvider.blockedServicesList.services![index].id), + value: blockedServices.contains(filteringProvider.blockedServices!.services[index].id), checkboxShape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5) ), - onChanged: (value) => checkUncheckService(value!, serversProvider.blockedServicesList.services![index].id) + onChanged: (value) => checkUncheckService(value!, filteringProvider.blockedServices!.services[index].id) ) ), ); - case 2: + case LoadStatus.error: return Padding( padding: const EdgeInsets.all(24), child: SizedBox( diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index 1a86671..3cbedc9 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -9,13 +9,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_custom_rule.dart'; import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/models/filtering.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class AddFiltersButton extends StatelessWidget { final String type; @@ -29,7 +26,7 @@ class AddFiltersButton extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -38,18 +35,11 @@ class AddFiltersButton extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingRule); - final List newRules = serversProvider.filtering.data!.userRules; - newRules.add(rule); - - final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules); + final result = await filteringProvider.addCustomRule(rule); processModal.close(); - if (result['result'] == 'success') { - FilteringData filteringData = serversProvider.filtering.data!; - filteringData.userRules = newRules; - serversProvider.setFilteringData(filteringData); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleAddedSuccessfully, @@ -57,8 +47,6 @@ class AddFiltersButton extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotAdded, @@ -95,58 +83,25 @@ class AddFiltersButton extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingList); - final result1 = await addFilteringList(server: serversProvider.selectedServer!, data: { - 'name': name, - 'url': url, - 'whitelist': type == 'whitelist' ? true : false - }); + final result = await filteringProvider.addList(name: name, url: url, type: type); - if (result1['result'] == 'success') { - if (result1['data'].toString().contains("OK")) { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - final items = result1['data'].toString().split(' ')[1]; + processModal.close(); - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - processModal.close(); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: "${AppLocalizations.of(context)!.listAdded} $items.", - color: Colors.green - ); - } - else { - processModal.close(); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listNotAdded, - color: Colors.red - ); - } + if (result['success'] == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: "${AppLocalizations.of(context)!.listAdded} ${result['data']}.", + color: Colors.green + ); } - else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains("Couldn't fetch filter from url")) { - processModal.close(); - appConfigProvider.addLog(result1['log']); - + else if (result['success'] == false && result['error'] == 'invalid_url') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listUrlInvalid, color: Colors.red ); } - else if (result1['result'] == 'error' && result1['log'].statusCode == '400' && result1['log'].resBody.toString().contains('Filter URL already added')) { - processModal.close(); - appConfigProvider.addLog(result1['log']); - + else if (result['success'] == false && result['error'] == 'url_exists') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listAlreadyAdded, @@ -154,9 +109,6 @@ class AddFiltersButton extends StatelessWidget { ); } else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listNotAdded, diff --git a/lib/screens/filters/blocked_services_screen.dart b/lib/screens/filters/blocked_services_screen.dart index 85d2d23..75d941b 100644 --- a/lib/screens/filters/blocked_services_screen.dart +++ b/lib/screens/filters/blocked_services_screen.dart @@ -7,11 +7,11 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/models/blocked_services.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -class BlockedServicesScreen extends StatelessWidget { +class BlockedServicesScreen extends StatefulWidget { final bool dialog; const BlockedServicesScreen({ @@ -20,63 +20,28 @@ class BlockedServicesScreen extends StatelessWidget { }) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return BlockedServicesScreenWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - dialog: dialog, - ); - } + State createState() => _BlockedServicesScreenStateWidget(); } -class BlockedServicesScreenWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - final bool dialog; - - const BlockedServicesScreenWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - required this.dialog - }) : super(key: key); - - @override - State createState() => _BlockedServicesScreenStateWidget(); -} - -class _BlockedServicesScreenStateWidget extends State { +class _BlockedServicesScreenStateWidget extends State { List values = []; - Future loadBlockedServices() async { - final result = await getBlockedServices(server: widget.serversProvider.selectedServer!); - if (result['result'] == 'success') { - widget.serversProvider.setBlockedServicesListLoadStatus(1, true); - widget.serversProvider.setBlockedServiceListData(result['data']); - } - else { - widget.serversProvider.setBlockedServicesListLoadStatus(2, true); - widget.appConfigProvider.addLog(result['log']); - } - } - @override void initState() { - if (widget.serversProvider.blockedServicesList.loadStatus != 1) { - loadBlockedServices(); + final filteringProvider = Provider.of(context, listen: false); + + if (filteringProvider.blockedServicesLoadStatus != LoadStatus.loaded) { + filteringProvider.loadBlockedServices(showLoading: true); } - values = widget.serversProvider.filtering.data!.blockedServices; + values = filteringProvider.filtering!.blockedServices; super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void updateValues(bool value, BlockedService item) { @@ -96,13 +61,11 @@ class _BlockedServicesScreenStateWidget extends State Material( color: Colors.transparent, child: InkWell( onTap: () => updateValues( - values.contains(serversProvider.blockedServicesList.services![index].id), - serversProvider.blockedServicesList.services![index] + values.contains(filteringProvider.blockedServices!.services[index].id), + filteringProvider.blockedServices!.services[index] ), child: Padding( padding: const EdgeInsets.only( @@ -163,17 +126,17 @@ class _BlockedServicesScreenStateWidget extends State updateValues( value!, - serversProvider.blockedServicesList.services![index] + filteringProvider.blockedServices!.services[index] ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5) @@ -186,7 +149,7 @@ class _BlockedServicesScreenStateWidget extends State { final appConfigProvider = Provider.of(context); void checkHost() async { + setState(() => resultWidget = checking()); + + final result = await serversProvider.apiClient!.checkHostFiltered(host: domainController.text); + if (mounted) { - setState(() => resultWidget = checking()); - - final result = await checkHostFiltered(server: serversProvider.selectedServer!, host: domainController.text); - if (result['result'] == 'success') { final status = getFilteredStatus(context, appConfigProvider, result['data']['reason'], true); if (mounted) { @@ -98,26 +97,24 @@ class _CheckHostModalState extends State { } } else { - if (mounted) { - setState(() => resultWidget = Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - Icons.cancel, - size: 18, + setState(() => resultWidget = Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.cancel, + size: 18, + color: Colors.red, + ), + const SizedBox(width: 10), + Text( + AppLocalizations.of(context)!.check, + style: const TextStyle( color: Colors.red, + fontWeight: FontWeight.w500 ), - const SizedBox(width: 10), - Text( - AppLocalizations.of(context)!.check, - style: const TextStyle( - color: Colors.red, - fontWeight: FontWeight.w500 - ), - ) - ], - )); - } + ) + ], + )); } } } diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 5a96716..8706f1a 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -2,18 +2,21 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_button.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; class CustomRulesList extends StatefulWidget { final LoadStatus loadStatus; final ScrollController scrollController; final List data; - final Future Function() fetchData; final void Function(String) onRemoveCustomRule; const CustomRulesList({ @@ -21,7 +24,6 @@ class CustomRulesList extends StatefulWidget { required this.loadStatus, required this.scrollController, required this.data, - required this.fetchData, required this.onRemoveCustomRule }) : super(key: key); @@ -55,6 +57,9 @@ class _CustomRulesListState extends State { @override Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); + bool checkIfComment(String value) { final regex = RegExp(r'^(!|#).*$'); if (regex.hasMatch(value)) { @@ -155,7 +160,16 @@ class _CustomRulesListState extends State { ), const SizedBox(height: 30), TextButton.icon( - onPressed: widget.fetchData, + onPressed: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh), ) @@ -186,7 +200,16 @@ class _CustomRulesListState extends State { ), ), loadStatus: widget.loadStatus, - onRefresh: widget.fetchData, + onRefresh: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, fab: AddFiltersButton( type: 'custom_rule', widget: (fn) => FloatingActionButton( diff --git a/lib/screens/filters/filters.dart b/lib/screens/filters/filters.dart index ce7e858..00cc214 100644 --- a/lib/screens/filters/filters.dart +++ b/lib/screens/filters/filters.dart @@ -15,115 +15,57 @@ import 'package:adguard_home_manager/screens/filters/blocked_services_screen.dar import 'package:adguard_home_manager/screens/filters/update_interval_lists_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/clients.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -class Filters extends StatelessWidget { +class Filters extends StatefulWidget { const Filters({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return FiltersWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider - ); - } + State createState() => _FiltersState(); } -class FiltersWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const FiltersWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _FiltersWidgetState(); -} - -class _FiltersWidgetState extends State { - Future fetchFilters() async { - widget.serversProvider.setFilteringLoadStatus(LoadStatus.loading, false); - - final result = await getFiltering(server: widget.serversProvider.selectedServer!); - - if (mounted) { - if (result['result'] == 'success') { - widget.serversProvider.setFilteringData(result['data']); - widget.serversProvider.setFilteringLoadStatus(LoadStatus.loaded, false); - } - else { - widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setFilteringLoadStatus(LoadStatus.error, false); - } - } - } - +class _FiltersState extends State { List generateClientsList(List clients, List ips) { return clients.where((client) => ips.contains(client.ip)).toList(); } @override void initState() { - fetchFilters(); + final filteringProvider = Provider.of(context, listen: false); + filteringProvider.fetchFilters(showLoading: true); super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - void fetchUpdateLists() async { + void updateLists() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingLists); - final result = await updateLists(server: serversProvider.selectedServer!); + final result = await filteringProvider.updateLists(); - if (result['result'] == 'success') { - final result2 = await getFiltering(server: widget.serversProvider.selectedServer!); + processModal.close(); - processModal.close(); - - if (mounted) { - if (result2['result'] == 'success') { - widget.serversProvider.setFilteringData(result2['data']); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: "${result['data']['updated']} ${AppLocalizations.of(context)!.listsUpdated}", - color: Colors.green - ); - } - else { - widget.appConfigProvider.addLog(result2['log']); - - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listsNotLoaded, - color: Colors.red - ); - } - } - + if (result['success'] == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: "${result['data']['updated']} ${AppLocalizations.of(context)!.listsUpdated}", + color: Colors.green + ); } else { - processModal.close(); - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.listsNotUpdated, @@ -158,21 +100,16 @@ class _FiltersWidgetState extends State { void enableDisableFiltering() async { ProcessModal processModal = ProcessModal(context: context); processModal.open( - serversProvider.serverStatus.data!.filteringEnabled == true + statusProvider.serverStatus!.filteringEnabled == true ? AppLocalizations.of(context)!.disableFiltering : AppLocalizations.of(context)!.enableFiltering ); - final result = await updateFiltering( - server: serversProvider.selectedServer!, - enable: !serversProvider.serverStatus.data!.filteringEnabled - ); + final result = await filteringProvider.enableDisableFiltering(); processModal.close(); - if (result['result'] == 'success') { - serversProvider.setFilteringProtectionStatus(!serversProvider.serverStatus.data!.filteringEnabled); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.filteringStatusUpdated, @@ -192,16 +129,11 @@ class _FiltersWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.changingUpdateFrequency); - final result = await requestChangeUpdateFrequency(server: serversProvider.selectedServer!, data: { - "enabled": serversProvider.filtering.data!.enabled, - "interval": value - }); + final result = await filteringProvider.changeUpdateFrequency(value); processModal.close(); - if (result['result'] == 'success') { - serversProvider.setFiltersUpdateFrequency(value); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.updateFrequencyChanged, @@ -244,17 +176,11 @@ class _FiltersWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deletingRule); - final List newRules = serversProvider.filtering.data!.userRules.where((r) => r != rule).toList(); - - final result = await setCustomRules(server: serversProvider.selectedServer!, rules: newRules); + final result = await filteringProvider.removeCustomRule(rule); processModal.close(); - if (result['result'] == 'success') { - FilteringData filteringData = serversProvider.filtering.data!; - filteringData.userRules = newRules; - serversProvider.setFilteringData(filteringData); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleRemovedSuccessfully, @@ -262,13 +188,11 @@ class _FiltersWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.ruleNotRemoved, color: Colors.red - ); + ); } } @@ -307,11 +231,11 @@ class _FiltersWidgetState extends State { } List actions() { - if (serversProvider.filtering.loadStatus == LoadStatus.loaded) { + if (filteringProvider.loadStatus == LoadStatus.loaded) { return [ - IconButton( + if (statusProvider.loadStatus == LoadStatus.loaded) IconButton( onPressed: enableDisableFiltering, - tooltip: serversProvider.filtering.data!.enabled == true + tooltip: filteringProvider.filtering!.enabled == true ? AppLocalizations.of(context)!.disableFiltering : AppLocalizations.of(context)!.enableFiltering, icon: Stack( @@ -328,11 +252,11 @@ class _FiltersWidgetState extends State { color: Colors.white ), child: Icon( - serversProvider.filtering.data!.enabled == true + filteringProvider.filtering!.enabled == true ? Icons.check_circle_rounded : Icons.cancel, size: 12, - color: serversProvider.filtering.data!.enabled == true + color: filteringProvider.filtering!.enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -353,7 +277,7 @@ class _FiltersWidgetState extends State { showDialog( context: context, builder: (context) => UpdateIntervalListsModal( - interval: serversProvider.filtering.data!.interval, + interval: filteringProvider.filtering!.interval, onChange: setUpdateFrequency, dialog: true, ), @@ -363,7 +287,7 @@ class _FiltersWidgetState extends State { showModalBottomSheet( context: context, builder: (context) => UpdateIntervalListsModal( - interval: serversProvider.filtering.data!.interval, + interval: filteringProvider.filtering!.interval, onChange: setUpdateFrequency, dialog: false, ), @@ -378,7 +302,7 @@ class _FiltersWidgetState extends State { PopupMenuButton( itemBuilder: (context) => [ PopupMenuItem( - onTap: fetchUpdateLists, + onTap: updateLists, child: Row( children: [ const Icon(Icons.sync_rounded), @@ -422,13 +346,11 @@ class _FiltersWidgetState extends State { onRemoveCustomRule: openRemoveCustomRuleModal, onOpenDetailsModal: openListDetails, actions: actions(), - refreshData: fetchFilters, ); } else { return FiltersTabsView( - appConfigProvider: appConfigProvider, - fetchFilters: fetchFilters, + appConfigProvider: appConfigProvider, actions: actions(), onRemoveCustomRule: openRemoveCustomRuleModal, onOpenDetailsModal: openListDetails, diff --git a/lib/screens/filters/filters_list.dart b/lib/screens/filters/filters_list.dart index 8f87b34..3fdf3d5 100644 --- a/lib/screens/filters/filters_list.dart +++ b/lib/screens/filters/filters_list.dart @@ -14,6 +14,8 @@ import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/models/filtering.dart'; @@ -21,7 +23,6 @@ class FiltersList extends StatefulWidget { final LoadStatus loadStatus; final ScrollController scrollController; final List data; - final Future Function() fetchData; final String type; final void Function(Filter, String) onOpenDetailsScreen; @@ -30,7 +31,6 @@ class FiltersList extends StatefulWidget { required this.loadStatus, required this.scrollController, required this.data, - required this.fetchData, required this.type, required this.onOpenDetailsScreen }) : super(key: key); @@ -65,6 +65,7 @@ class _FiltersListState extends State { @override Widget build(BuildContext context) { + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); return CustomTabContentList( @@ -129,7 +130,16 @@ class _FiltersListState extends State { ), const SizedBox(height: 30), TextButton.icon( - onPressed: widget.fetchData, + onPressed: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh), ) @@ -160,7 +170,16 @@ class _FiltersListState extends State { ), ), loadStatus: widget.loadStatus, - onRefresh: widget.fetchData, + onRefresh: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, fab: AddFiltersButton( type: widget.type, widget: (fn) => FloatingActionButton( diff --git a/lib/screens/filters/filters_tabs_view.dart b/lib/screens/filters/filters_tabs_view.dart index 17f74a9..81cd67a 100644 --- a/lib/screens/filters/filters_tabs_view.dart +++ b/lib/screens/filters/filters_tabs_view.dart @@ -5,14 +5,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/custom_rules_list.dart'; import 'package:adguard_home_manager/screens/filters/filters_list.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class FiltersTabsView extends StatefulWidget { final AppConfigProvider appConfigProvider; - final Future Function() fetchFilters; final List actions; final void Function(String) onRemoveCustomRule; final void Function(Filter, String) onOpenDetailsModal; @@ -20,7 +19,6 @@ class FiltersTabsView extends StatefulWidget { const FiltersTabsView({ Key? key, required this.appConfigProvider, - required this.fetchFilters, required this.actions, required this.onOpenDetailsModal, required this.onRemoveCustomRule @@ -36,7 +34,6 @@ class _FiltersTabsViewState extends State with TickerProviderSt @override void initState() { - widget.fetchFilters(); super.initState(); tabController = TabController( initialIndex: 0, @@ -48,7 +45,7 @@ class _FiltersTabsViewState extends State with TickerProviderSt @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); return DefaultTabController( length: 3, @@ -110,29 +107,26 @@ class _FiltersTabsViewState extends State with TickerProviderSt controller: tabController, children: [ FiltersList( - loadStatus: serversProvider.filtering.loadStatus, + loadStatus: filteringProvider.loadStatus, scrollController: scrollController, type: 'whitelist', - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.whitelistFilters : [], - fetchData: widget.fetchFilters, + data: filteringProvider.loadStatus == LoadStatus.loaded + ? filteringProvider.filtering!.whitelistFilters : [], onOpenDetailsScreen: widget.onOpenDetailsModal, ), FiltersList( - loadStatus: serversProvider.filtering.loadStatus, + loadStatus: filteringProvider.loadStatus, scrollController: scrollController, type: 'blacklist', - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.filters : [], - fetchData: widget.fetchFilters, + data: filteringProvider.loadStatus == LoadStatus.loaded + ? filteringProvider.filtering!.filters : [], onOpenDetailsScreen: widget.onOpenDetailsModal, ), CustomRulesList( - loadStatus: serversProvider.filtering.loadStatus, + loadStatus: filteringProvider.loadStatus, scrollController: scrollController, - data: serversProvider.filtering.loadStatus == LoadStatus.loaded - ? serversProvider.filtering.data!.userRules : [], - fetchData: widget.fetchFilters, + data: filteringProvider.loadStatus == LoadStatus.loaded + ? filteringProvider.filtering!.userRules : [], onRemoveCustomRule: widget.onRemoveCustomRule, ), ] diff --git a/lib/screens/filters/filters_triple_column.dart b/lib/screens/filters/filters_triple_column.dart index d8bc00a..c481749 100644 --- a/lib/screens/filters/filters_triple_column.dart +++ b/lib/screens/filters/filters_triple_column.dart @@ -14,41 +14,30 @@ import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/constants/enums.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class FiltersTripleColumn extends StatelessWidget { final void Function(String) onRemoveCustomRule; final void Function(Filter, String) onOpenDetailsModal; final List actions; - final Future Function() refreshData; const FiltersTripleColumn({ Key? key, required this.onRemoveCustomRule, required this.onOpenDetailsModal, required this.actions, - required this.refreshData }) : super(key: key); @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - - bool checkIfComment(String value) { - final regex = RegExp(r'^(!|#).*$'); - if (regex.hasMatch(value)) { - return true; - } - else { - return false; - } - } - + Widget? generateSubtitle(String rule) { final allowRegex = RegExp(r'^@@.*$'); final blockRegex = RegExp(r'^\|\|.*$'); @@ -84,7 +73,7 @@ class FiltersTripleColumn extends StatelessWidget { } Widget content() { - switch (serversProvider.filtering.loadStatus) { + switch (filteringProvider.loadStatus) { case LoadStatus.loading: return Row( mainAxisAlignment: MainAxisAlignment.center, @@ -140,18 +129,18 @@ class FiltersTripleColumn extends StatelessWidget { ), Expanded( child: ListView.builder( - itemCount: serversProvider.filtering.data!.whitelistFilters.length, + itemCount: filteringProvider.filtering!.whitelistFilters.length, itemBuilder: (context, index) => ListOptionsMenu( - list: serversProvider.filtering.data!.whitelistFilters[index], + list: filteringProvider.filtering!.whitelistFilters[index], listType: 'whitelist', child: CustomListTile( - title: serversProvider.filtering.data!.whitelistFilters[index].name, - subtitle: "${intFormat(serversProvider.filtering.data!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + title: filteringProvider.filtering!.whitelistFilters[index].name, + subtitle: "${intFormat(filteringProvider.filtering!.whitelistFilters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", trailing: Icon( - serversProvider.filtering.data!.whitelistFilters[index].enabled == true + filteringProvider.filtering!.whitelistFilters[index].enabled == true ? Icons.check_circle_rounded : Icons.cancel, - color: serversProvider.filtering.data!.whitelistFilters[index].enabled == true + color: filteringProvider.filtering!.whitelistFilters[index].enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -159,7 +148,7 @@ class FiltersTripleColumn extends StatelessWidget { ? Colors.grey : Colors.red ), - onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.whitelistFilters[index], 'whitelist'), + onTap: () => onOpenDetailsModal(filteringProvider.filtering!.whitelistFilters[index], 'whitelist'), ), ), ), @@ -196,18 +185,18 @@ class FiltersTripleColumn extends StatelessWidget { ), Expanded( child: ListView.builder( - itemCount: serversProvider.filtering.data!.filters.length, + itemCount: filteringProvider.filtering!.filters.length, itemBuilder: (context, index) => ListOptionsMenu( - list: serversProvider.filtering.data!.filters[index], + list: filteringProvider.filtering!.filters[index], listType: 'blacklist', child: CustomListTile( - title: serversProvider.filtering.data!.filters[index].name, - subtitle: "${intFormat(serversProvider.filtering.data!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", + title: filteringProvider.filtering!.filters[index].name, + subtitle: "${intFormat(filteringProvider.filtering!.filters[index].rulesCount, Platform.localeName)} ${AppLocalizations.of(context)!.enabledRules}", trailing: Icon( - serversProvider.filtering.data!.filters[index].enabled == true + filteringProvider.filtering!.filters[index].enabled == true ? Icons.check_circle_rounded : Icons.cancel, - color: serversProvider.filtering.data!.filters[index].enabled == true + color: filteringProvider.filtering!.filters[index].enabled == true ? appConfigProvider.useThemeColorForStatus == true ? Theme.of(context).colorScheme.primary : Colors.green @@ -215,7 +204,7 @@ class FiltersTripleColumn extends StatelessWidget { ? Colors.grey : Colors.red ), - onTap: () => onOpenDetailsModal(serversProvider.filtering.data!.filters[index], 'blacklist'), + onTap: () => onOpenDetailsModal(filteringProvider.filtering!.filters[index], 'blacklist'), ), ), ), @@ -252,7 +241,7 @@ class FiltersTripleColumn extends StatelessWidget { ), Expanded( child: ListView.builder( - itemCount: serversProvider.filtering.data!.userRules.length, + itemCount: filteringProvider.filtering!.userRules.length, itemBuilder: (context, index) => ContextMenuArea( builder: (context) => [ CustomListTile( @@ -261,7 +250,7 @@ class FiltersTripleColumn extends StatelessWidget { onTap: () { copyToClipboard( context: context, - value: serversProvider.filtering.data!.userRules[index], + value: filteringProvider.filtering!.userRules[index], successMessage: AppLocalizations.of(context)!.copiedClipboard, ); Navigator.pop(context); @@ -278,17 +267,17 @@ class FiltersTripleColumn extends StatelessWidget { icon: Icons.copy_rounded, action: () => copyToClipboard( context: context, - value: serversProvider.filtering.data!.userRules[index], + value: filteringProvider.filtering!.userRules[index], successMessage: AppLocalizations.of(context)!.copiedClipboard, ) ) ] ) ), - title: serversProvider.filtering.data!.userRules[index], - subtitleWidget: generateSubtitle(serversProvider.filtering.data!.userRules[index]), + title: filteringProvider.filtering!.userRules[index], + subtitleWidget: generateSubtitle(filteringProvider.filtering!.userRules[index]), trailing: IconButton( - onPressed: () => onRemoveCustomRule(serversProvider.filtering.data!.userRules[index]), + onPressed: () => onRemoveCustomRule(filteringProvider.filtering!.userRules[index]), icon: const Icon(Icons.delete) ), ), @@ -340,7 +329,16 @@ class FiltersTripleColumn extends StatelessWidget { title: Text(AppLocalizations.of(context)!.filters), actions: [ IconButton( - onPressed: refreshData, + onPressed: () async { + final result = await filteringProvider.fetchFilters(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.errorLoadFilters, + color: Colors.red + ); + } + }, icon: const Icon(Icons.refresh_rounded), tooltip: AppLocalizations.of(context)!.refresh, ), diff --git a/lib/screens/filters/list_details_screen.dart b/lib/screens/filters/list_details_screen.dart index 0117390..42464ec 100644 --- a/lib/screens/filters/list_details_screen.dart +++ b/lib/screens/filters/list_details_screen.dart @@ -9,13 +9,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/filters/add_list_modal.dart'; import 'package:adguard_home_manager/screens/filters/delete_list_modal.dart'; -import 'package:adguard_home_manager/screens/filters/list_functions.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; +import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/models/filtering.dart'; class ListDetailsScreen extends StatefulWidget { @@ -60,22 +60,51 @@ class _ListDetailsScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; Filter? list; try { - list = serversProvider.filtering.data != null + list = filteringProvider.filtering != null ? widget.type == 'whitelist' - ? serversProvider.filtering.data!.whitelistFilters.firstWhere((l) => l.id == widget.listId) - : serversProvider.filtering.data!.filters.firstWhere((l) => l.id == widget.listId) + ? filteringProvider.filtering!.whitelistFilters.firstWhere((l) => l.id == widget.listId) + : filteringProvider.filtering!.filters.firstWhere((l) => l.id == widget.listId) : null; } catch (e) { // ------- // } + void updateList(FilteringListActions action) async { + ProcessModal processModal = ProcessModal(context: context); + processModal.open( + list!.enabled == true + ? AppLocalizations.of(context)!.disablingList + : AppLocalizations.of(context)!.enablingList, + ); + final result = await filteringProvider.updateList( + list: list, + type: widget.type, + action: action + ); + processModal.close(); + if (result == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataUpdated, + color: Colors.green + ); + } + else { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.listDataNotUpdated, + color: Colors.red + ); + } + } + List content() { return [ CustomListTile( @@ -174,29 +203,9 @@ class _ListDetailsScreenState extends State { builder: (ctx) => AddListModal( list: list, type: widget.type, - onEdit: ({required Filter list, required String type}) async { - final result = await editList( - context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - list: list, - type: widget.type - ); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - }, + onEdit: ({required Filter list, required String type}) async => updateList( + FilteringListActions.edit + ), dialog: true, ), ) @@ -207,29 +216,9 @@ class _ListDetailsScreenState extends State { builder: (ctx) => AddListModal( list: list, type: widget.type, - onEdit: ({required Filter list, required String type}) async { - final result = await editList( - context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - list: list, - type: widget.type - ); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - }, + onEdit: ({required Filter list, required String type}) async => updateList( + FilteringListActions.edit + ), dialog: false, ), isScrollControlled: true, @@ -246,13 +235,13 @@ class _ListDetailsScreenState extends State { context: context, builder: (c) => DeleteListModal( onConfirm: () async { - final result = await deleteList( - context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - list: list!, + ProcessModal processModal = ProcessModal(context: context); + processModal.open(AppLocalizations.of(context)!.deletingList); + final result = await filteringProvider.deleteList( + listUrl: list!.url, type: widget.type, ); + processModal.close(); if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, @@ -312,29 +301,11 @@ class _ListDetailsScreenState extends State { if (list != null) Row( children: [ IconButton( - onPressed: () async { - final result = await enableDisableList( - context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - list: list!, - listType: widget.type, - ); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - }, + onPressed: () => updateList( + list!.enabled == true + ? FilteringListActions.disable + : FilteringListActions.enable + ), icon: Icon( list.enabled == true ? Icons.gpp_bad_rounded @@ -399,29 +370,11 @@ class _ListDetailsScreenState extends State { : -70, right: 20, child: FloatingActionButton( - onPressed: () async { - final result = await enableDisableList( - context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - list: list!, - listType: widget.type, - ); - if (result == true) { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataUpdated, - color: Colors.green - ); - } - else { - showSnacbkar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.listDataNotUpdated, - color: Colors.red - ); - } - }, + onPressed: () => updateList( + list!.enabled == true + ? FilteringListActions.disable + : FilteringListActions.enable + ), child: Icon( list.enabled == true ? Icons.gpp_bad_rounded diff --git a/lib/screens/filters/list_functions.dart b/lib/screens/filters/list_functions.dart deleted file mode 100644 index 7db194f..0000000 --- a/lib/screens/filters/list_functions.dart +++ /dev/null @@ -1,141 +0,0 @@ -// ignore_for_file: use_build_context_synchronously - -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/filtering.dart'; -import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; - -Future enableDisableList({ - required BuildContext context, - required ServersProvider serversProvider, - required AppConfigProvider appConfigProvider, - required Filter list, - required String listType, -}) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open( - list.enabled == true - ? AppLocalizations.of(context)!.disablingList - : AppLocalizations.of(context)!.enablingList, - ); - - final result = await updateFilterList(server: serversProvider.selectedServer!, data: { - "data": { - "enabled": !list.enabled, - "name": list.name, - "url": list.url - }, - "url": list.url, - "whitelist": listType == 'whitelist' ? true : false - }); - - processModal.close(); - - if (result['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - return true; - } - else { - appConfigProvider.addLog(result['log']); - - return false; - } -} - -Future editList({ - required BuildContext context, - required ServersProvider serversProvider, - required AppConfigProvider appConfigProvider, - required Filter list, - required String type -}) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.updatingListData); - - final result1 = await updateFilterList(server: serversProvider.selectedServer!, data: { - "data": { - "enabled": list.enabled, - "name": list.name, - "url": list.url - }, - "url": list.url, - "whitelist": type == 'whitelist' ? true : false - }); - - if (result1['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.error, true); - } - - processModal.close(); - - return true; - } - else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - - return false; - } -} - -Future deleteList({ - required BuildContext context, - required ServersProvider serversProvider, - required AppConfigProvider appConfigProvider, - required Filter list, - required String type -}) async { - ProcessModal processModal = ProcessModal(context: context); - processModal.open(AppLocalizations.of(context)!.deletingList); - - final result1 = await deleteFilterList(server: serversProvider.selectedServer!, data: { - "url": list.url, - "whitelist": type == 'whitelist' ? true : false - }); - - if (result1['result'] == 'success') { - final result2 = await getFiltering(server: serversProvider.selectedServer!); - - if (result2['result'] == 'success') { - serversProvider.setFilteringData(result2['data']); - serversProvider.setFilteringLoadStatus(LoadStatus.loaded, true); - } - else { - appConfigProvider.addLog(result2['log']); - serversProvider.setFilteringLoadStatus(LoadStatus.loading, true); - } - - processModal.close(); - - return true; - } - else { - processModal.close(); - appConfigProvider.addLog(result1['log']); - - return false; - } -} \ No newline at end of file diff --git a/lib/screens/filters/list_options_menu.dart b/lib/screens/filters/list_options_menu.dart index f052890..6482ecd 100644 --- a/lib/screens/filters/list_options_menu.dart +++ b/lib/screens/filters/list_options_menu.dart @@ -1,20 +1,20 @@ // ignore_for_file: use_build_context_synchronously +import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:flutter/material.dart'; import 'package:contextmenu/contextmenu.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/screens/filters/list_functions.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/models/filtering.dart'; +import 'package:adguard_home_manager/providers/filtering_provider.dart'; import 'package:adguard_home_manager/functions/copy_clipboard.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class ListOptionsMenu extends StatelessWidget { final Filter list; @@ -30,17 +30,27 @@ class ListOptionsMenu extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void enableDisable() async { - final result = await enableDisableList( - context: context, - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - list: list, - listType: listType, + ProcessModal processModal = ProcessModal(context: context); + processModal.open( + list.enabled == true + ? AppLocalizations.of(context)!.disablingList + : AppLocalizations.of(context)!.enablingList ); + + final result = await filteringProvider.updateList( + list: list, + type: listType, + action: list.enabled == true + ? FilteringListActions.disable + : FilteringListActions.enable + ); + + processModal.close(); + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index 58284d5..675dafd 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -4,6 +4,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/servers/servers.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/models/server.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -20,6 +22,7 @@ class HomeAppBar extends StatelessWidget { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final Server? server = serversProvider.selectedServer; @@ -37,22 +40,48 @@ class HomeAppBar extends StatelessWidget { floating: true, centerTitle: false, forceElevated: innerBoxScrolled, - leading: Icon( - serversProvider.selectedServer != null && serversProvider.serverStatus.data != null - ? serversProvider.serverStatus.data!.generalEnabled == true - ? Icons.gpp_good_rounded - : Icons.gpp_bad_rounded - : Icons.shield, - size: 30, - color: serversProvider.selectedServer != null && serversProvider.serverStatus.data != null - ? serversProvider.serverStatus.data!.generalEnabled == true - ? appConfigProvider.useThemeColorForStatus - ? Theme.of(context).colorScheme.primary - : Colors.green - : appConfigProvider.useThemeColorForStatus == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - : Colors.red - : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + leading: Stack( + children: [ + Center( + child: Icon( + serversProvider.selectedServer != null && statusProvider.serverStatus != null + ? statusProvider.serverStatus!.generalEnabled == true + ? Icons.gpp_good_rounded + : Icons.gpp_bad_rounded + : Icons.shield, + size: 30, + color: serversProvider.selectedServer != null && statusProvider.serverStatus != null + ? statusProvider.serverStatus!.generalEnabled == true + ? appConfigProvider.useThemeColorForStatus + ? Theme.of(context).colorScheme.primary + : Colors.green + : appConfigProvider.useThemeColorForStatus == true + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + : Colors.red + : Theme.of(context).colorScheme.onSurface.withOpacity(0.38) + ), + ), + if (statusProvider.remainingTime > 0) Positioned( + bottom: 15, + right: 15, + child: Stack( + children: [ + Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Theme.of(context).colorScheme.surface + ), + child: Icon( + Icons.timer_rounded, + size: 12, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ], + ), + ) + ], ), title: Column( mainAxisSize: MainAxisSize.min, @@ -95,7 +124,7 @@ class HomeAppBar extends StatelessWidget { ], ), ), - if (serversProvider.selectedServer != null && serversProvider.serverStatus.loadStatus == 1) PopupMenuItem( + if (serversProvider.selectedServer != null && statusProvider.loadStatus == LoadStatus.loaded) PopupMenuItem( onTap: () => openUrl("${server!.connectionMethod}://${server.domain}${server.path ?? ""}${server.port != null ? ':${server.port}' : ""}"), child: Row( children: [ diff --git a/lib/screens/home/combined_chart.dart b/lib/screens/home/combined_chart.dart index 9bd9d36..3de92f9 100644 --- a/lib/screens/home/combined_chart.dart +++ b/lib/screens/home/combined_chart.dart @@ -7,7 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/combined_line_chart.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class CombinedChartData { @@ -51,56 +51,56 @@ class CombinedHomeChart extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - if (serversProvider.serverStatus.data != null) { + if (statusProvider.serverStatus != null) { final data = CombinedChartData( totalQueries: CombinedChartItem( label: AppLocalizations.of(context)!.dnsQueries, color: Colors.blue, - data: serversProvider.serverStatus.data!.stats.dnsQueries + data: statusProvider.serverStatus!.stats.dnsQueries ), blockedFilters: appConfigProvider.hideZeroValues == true - ? removeZero(serversProvider.serverStatus.data!.stats.blockedFiltering) != null + ? removeZero(statusProvider.serverStatus!.stats.blockedFiltering) != null ? CombinedChartItem( label: AppLocalizations.of(context)!.blockedFilters, color: Colors.red, - data: serversProvider.serverStatus.data!.stats.blockedFiltering + data: statusProvider.serverStatus!.stats.blockedFiltering ) : null : CombinedChartItem( label: AppLocalizations.of(context)!.blockedFilters, color: Colors.red, - data: serversProvider.serverStatus.data!.stats.blockedFiltering + data: statusProvider.serverStatus!.stats.blockedFiltering ) , replacedSafeBrowsing: appConfigProvider.hideZeroValues == true - ? removeZero(serversProvider.serverStatus.data!.stats.replacedSafebrowsing) != null + ? removeZero(statusProvider.serverStatus!.stats.replacedSafebrowsing) != null ? CombinedChartItem( label: AppLocalizations.of(context)!.malwarePhisingBlocked, color: Colors.green, - data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing + data: statusProvider.serverStatus!.stats.replacedSafebrowsing ) : null : CombinedChartItem( label: AppLocalizations.of(context)!.malwarePhisingBlocked, color: Colors.green, - data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing + data: statusProvider.serverStatus!.stats.replacedSafebrowsing ) , replacedParental: appConfigProvider.hideZeroValues == true - ? removeZero(serversProvider.serverStatus.data!.stats.replacedParental) != null + ? removeZero(statusProvider.serverStatus!.stats.replacedParental) != null ? CombinedChartItem( label: AppLocalizations.of(context)!.blockedAdultWebsites, color: Colors.orange, - data: serversProvider.serverStatus.data!.stats.replacedParental + data: statusProvider.serverStatus!.stats.replacedParental ) : null : CombinedChartItem( label: AppLocalizations.of(context)!.blockedAdultWebsites, color: Colors.orange, - data: serversProvider.serverStatus.data!.stats.replacedParental + data: statusProvider.serverStatus!.stats.replacedParental ) , ); @@ -184,29 +184,29 @@ class CombinedHomeChart extends StatelessWidget { legend( label: data.totalQueries.label, color: data.totalQueries.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", ), const SizedBox(height: 16), if (data.blockedFilters != null) legend( label: data.blockedFilters!.label, color: data.blockedFilters!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), if (data.replacedSafeBrowsing != null) legend( label: data.replacedSafeBrowsing!.label, color: data.replacedSafeBrowsing!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), if (data.replacedParental != null) legend( label: data.replacedParental!.label, color: data.replacedParental!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), ], ), @@ -247,29 +247,29 @@ class CombinedHomeChart extends StatelessWidget { legend( label: data.totalQueries.label, color: data.totalQueries.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", ), const SizedBox(height: 16), if (data.blockedFilters != null) legend( label: data.blockedFilters!.label, color: data.blockedFilters!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), if (data.replacedSafeBrowsing != null) legend( label: data.replacedSafeBrowsing!.label, color: data.replacedSafeBrowsing!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), if (data.replacedParental != null) legend( label: data.replacedParental!.label, color: data.replacedParental!.color, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", ), const SizedBox(height: 16), ], diff --git a/lib/screens/home/fab.dart b/lib/screens/home/fab.dart index 1369535..0e7db97 100644 --- a/lib/screens/home/fab.dart +++ b/lib/screens/home/fab.dart @@ -3,14 +3,15 @@ import 'package:flutter/material.dart'; import 'package:adguard_home_manager/screens/home/management_modal.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; class HomeFab extends StatelessWidget { const HomeFab({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -35,7 +36,7 @@ class HomeFab extends StatelessWidget { } } - return serversProvider.serverStatus.loadStatus == 1 + return statusProvider.loadStatus == LoadStatus.loaded ? FloatingActionButton( onPressed: openManagementBottomSheet, child: const Icon(Icons.shield_rounded), diff --git a/lib/screens/home/home.dart b/lib/screens/home/home.dart index 9626130..e288175 100644 --- a/lib/screens/home/home.dart +++ b/lib/screens/home/home.dart @@ -15,10 +15,10 @@ import 'package:adguard_home_manager/screens/home/top_items.dart'; import 'package:adguard_home_manager/screens/home/chart.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @@ -33,6 +33,8 @@ class _HomeState extends State { @override initState(){ + Provider.of(context, listen: false).getServerStatus(); + super.initState(); isVisible = true; @@ -54,7 +56,7 @@ class _HomeState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -109,7 +111,7 @@ class _HomeState extends State { List listItems() { return [ - ServerStatus(serverStatus: serversProvider.serverStatus.data!), + ServerStatusWidget(serverStatus: statusProvider.serverStatus!), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Divider( @@ -124,40 +126,40 @@ class _HomeState extends State { FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( - data: serversProvider.serverStatus.data!.stats.dnsQueries, + data: statusProvider.serverStatus!.stats.dnsQueries, label: AppLocalizations.of(context)!.dnsQueries, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numDnsQueries, Platform.localeName), - secondaryValue: "${doubleFormat(serversProvider.serverStatus.data!.stats.avgProcessingTime*1000, Platform.localeName)} ms", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numDnsQueries, Platform.localeName), + secondaryValue: "${doubleFormat(statusProvider.serverStatus!.stats.avgProcessingTime*1000, Platform.localeName)} ms", color: Colors.blue, ), ), FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( - data: serversProvider.serverStatus.data!.stats.blockedFiltering, + data: statusProvider.serverStatus!.stats.blockedFiltering, label: AppLocalizations.of(context)!.blockedFilters, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numBlockedFiltering, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numBlockedFiltering/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numBlockedFiltering, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numBlockedFiltering/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.red, ), ), FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( - data: serversProvider.serverStatus.data!.stats.replacedSafebrowsing, + data: statusProvider.serverStatus!.stats.replacedSafebrowsing, label: AppLocalizations.of(context)!.malwarePhisingBlocked, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedSafebrowsing/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedSafebrowsing, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedSafebrowsing/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.green, ), ), FractionallySizedBox( widthFactor: width > 700 ? 0.5 : 1, child: HomeChart( - data: serversProvider.serverStatus.data!.stats.replacedParental, + data: statusProvider.serverStatus!.stats.replacedParental, label: AppLocalizations.of(context)!.blockedAdultWebsites, - primaryValue: intFormat(serversProvider.serverStatus.data!.stats.numReplacedParental, Platform.localeName), - secondaryValue: "${serversProvider.serverStatus.data!.stats.numDnsQueries > 0 ? doubleFormat((serversProvider.serverStatus.data!.stats.numReplacedParental/serversProvider.serverStatus.data!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", + primaryValue: intFormat(statusProvider.serverStatus!.stats.numReplacedParental, Platform.localeName), + secondaryValue: "${statusProvider.serverStatus!.stats.numDnsQueries > 0 ? doubleFormat((statusProvider.serverStatus!.stats.numReplacedParental/statusProvider.serverStatus!.stats.numDnsQueries)*100, Platform.localeName) : 0}%", color: Colors.orange, ), ), @@ -172,7 +174,7 @@ class _HomeState extends State { if (width <= 700) ...[ TopItems( label: AppLocalizations.of(context)!.topQueriedDomains, - data: serversProvider.serverStatus.data!.stats.topQueriedDomains, + data: statusProvider.serverStatus!.stats.topQueriedDomains, type: 'topQueriedDomains', ), Padding( @@ -187,7 +189,7 @@ class _HomeState extends State { TopItems( label: AppLocalizations.of(context)!.topBlockedDomains, - data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + data: statusProvider.serverStatus!.stats.topBlockedDomains, type: 'topBlockedDomains', ), Padding( @@ -201,7 +203,7 @@ class _HomeState extends State { TopItems( label: AppLocalizations.of(context)!.topClients, - data: serversProvider.serverStatus.data!.stats.topClients, + data: statusProvider.serverStatus!.stats.topClients, type: 'topClients', clients: true, ), @@ -219,7 +221,7 @@ class _HomeState extends State { ), child: TopItems( label: AppLocalizations.of(context)!.topQueriedDomains, - data: serversProvider.serverStatus.data!.stats.topQueriedDomains, + data: statusProvider.serverStatus!.stats.topQueriedDomains, type: 'topQueriedDomains', ), ), @@ -232,7 +234,7 @@ class _HomeState extends State { ), child: TopItems( label: AppLocalizations.of(context)!.topBlockedDomains, - data: serversProvider.serverStatus.data!.stats.topBlockedDomains, + data: statusProvider.serverStatus!.stats.topBlockedDomains, type: 'topBlockedDomains', ), ), @@ -245,7 +247,7 @@ class _HomeState extends State { ), child: TopItems( label: AppLocalizations.of(context)!.topClients, - data: serversProvider.serverStatus.data!.stats.topClients, + data: statusProvider.serverStatus!.stats.topClients, type: 'topClients', ), ), @@ -277,12 +279,8 @@ class _HomeState extends State { builder: (context) => RefreshIndicator( color: Theme.of(context).colorScheme.primary, onRefresh: () async { - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); - } - else { - appConfigProvider.addLog(result['log']); + final result = await statusProvider.getServerStatus(); + if (result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, @@ -295,13 +293,13 @@ class _HomeState extends State { SliverOverlapInjector( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), - if (serversProvider.serverStatus.loadStatus == 0) SliverFillRemaining( + if (statusProvider.loadStatus == LoadStatus.loading) SliverFillRemaining( child: loading(), ), - if (serversProvider.serverStatus.loadStatus == 1) SliverList.list( + if (statusProvider.loadStatus == LoadStatus.loaded) SliverList.list( children: listItems() ), - if (serversProvider.serverStatus.loadStatus == 2) SliverFillRemaining( + if (statusProvider.loadStatus == LoadStatus.error) SliverFillRemaining( child: loadError(), ), ], diff --git a/lib/screens/home/management_modal.dart b/lib/screens/home/management_modal.dart index 9781206..aaeaab7 100644 --- a/lib/screens/home/management_modal.dart +++ b/lib/screens/home/management_modal.dart @@ -10,10 +10,9 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; -import 'package:adguard_home_manager/functions/time_server_disabled.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; +import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class ManagementModal extends StatefulWidget { final bool dialog; @@ -32,10 +31,6 @@ class _ManagementModalState extends State with SingleTickerProv late Animation animation; final ExpandableController expandableController = ExpandableController(); - DateTime? currentDeadline; - Timer? countdown; - int start = 0; - @override void initState() { expandableController.addListener(() async { @@ -66,70 +61,21 @@ class _ManagementModalState extends State with SingleTickerProv @override void dispose() { - if (countdown != null) countdown!.cancel(); animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - void startTimer(DateTime deadline) { - setState(() { - currentDeadline = deadline; - start = deadline.difference(DateTime.now()).inSeconds+1; - }); - - const oneSec = Duration(seconds: 1); - countdown = Timer.periodic( - oneSec, - (Timer timer) async { - if (start == 0) { - setState(() { - timer.cancel(); - }); - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); - } - } else { - setState(() { - start = start - 1; - }); - } - }, - ); - } - - if ( - serversProvider.serverStatus.data != null && - serversProvider.serverStatus.data!.disabledUntil != null && - serversProvider.serverStatus.data!.disabledUntil != currentDeadline - ) { - startTimer(serversProvider.serverStatus.data!.disabledUntil!); - } - - if ( - serversProvider.serverStatus.data != null && - serversProvider.serverStatus.data!.generalEnabled == true - ) { - setState(() { - start = 0; - currentDeadline = null; - if (countdown != null) countdown!.cancel(); - countdown = null; - }); - } - void updateBlocking({ required bool value, required String filter, int? time }) async { - final result = await serversProvider.updateBlocking( - server: serversProvider.selectedServer!, + final result = await statusProvider.updateBlocking( block: filter, newStatus: value, time: time @@ -164,7 +110,7 @@ class _ManagementModalState extends State with SingleTickerProv child: Icon( Icons.keyboard_arrow_down_rounded, size: 26, - color: serversProvider.serverStatus.data!.generalEnabled == true + color: statusProvider.serverStatus!.generalEnabled == true ? Theme.of(context).colorScheme.onSurfaceVariant : Colors.grey, ), @@ -180,10 +126,10 @@ class _ManagementModalState extends State with SingleTickerProv fontSize: 18, ), ), - if (serversProvider.serverStatus.data!.timeGeneralDisabled > 0) ...[ + if (statusProvider.serverStatus!.timeGeneralDisabled > 0) ...[ const SizedBox(height: 2), - if (currentDeadline != null) Text( - "${AppLocalizations.of(context)!.remainingTime}: ${generateRemainingTimeString(currentDeadline!.difference(DateTime.now()))}" + if (statusProvider.currentDeadline != null) Text( + "${AppLocalizations.of(context)!.remainingTime}: ${formatRemainingSeconds(statusProvider.remainingTime)}" ) ] ], @@ -191,8 +137,8 @@ class _ManagementModalState extends State with SingleTickerProv ], ), Switch( - value: serversProvider.serverStatus.data!.generalEnabled, - onChanged: serversProvider.protectionsManagementProcess.contains('general') == false + value: statusProvider.serverStatus!.generalEnabled, + onChanged: statusProvider.protectionsManagementProcess.contains('general') == false ? (value) { if (value == false && expandableController.expanded == true && legacyMode == false) { expandableController.toggle(); @@ -216,35 +162,35 @@ class _ManagementModalState extends State with SingleTickerProv children: [ ActionChip( label: Text(AppLocalizations.of(context)!.seconds(30)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(29000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.minute(1)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(59000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.minutes(10)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(599000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.hour(1)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(3599000) : null, ), const SizedBox(width: 8), ActionChip( label: Text(AppLocalizations.of(context)!.hours(24)), - onPressed: serversProvider.protectionsManagementProcess.contains('general') == false && serversProvider.serverStatus.data!.generalEnabled == true + onPressed: statusProvider.protectionsManagementProcess.contains('general') == false && statusProvider.serverStatus!.generalEnabled == true ? () => disableWithCountdown(86399000) : null, ), @@ -256,7 +202,7 @@ class _ManagementModalState extends State with SingleTickerProv return Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true @@ -266,7 +212,7 @@ class _ManagementModalState extends State with SingleTickerProv color: Colors.transparent, borderRadius: BorderRadius.circular(28), child: InkWell( - onTap: serversProvider.serverStatus.data!.generalEnabled == true && !serversProvider.protectionsManagementProcess.contains('general') + onTap: statusProvider.serverStatus!.generalEnabled == true && !statusProvider.protectionsManagementProcess.contains('general') ? () => expandableController.toggle() : null, borderRadius: BorderRadius.circular(28), @@ -277,7 +223,7 @@ class _ManagementModalState extends State with SingleTickerProv ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(28), - color: Theme.of(context).primaryColor.withOpacity(0.1) + color: Theme.of(context).colorScheme.primary.withOpacity(0.1) ), child: Expandable( theme: const ExpandableThemeData( @@ -301,9 +247,9 @@ class _ManagementModalState extends State with SingleTickerProv color: Colors.transparent, borderRadius: BorderRadius.circular(28), child: InkWell( - onTap: serversProvider.protectionsManagementProcess.contains('general') == false + onTap: statusProvider.protectionsManagementProcess.contains('general') == false ? () => updateBlocking( - value: !serversProvider.serverStatus.data!.generalEnabled, + value: !statusProvider.serverStatus!.generalEnabled, filter: 'general_legacy' ) : null, borderRadius: BorderRadius.circular(28), @@ -408,30 +354,30 @@ class _ManagementModalState extends State with SingleTickerProv smallSwitch( AppLocalizations.of(context)!.ruleFiltering, Icons.filter_list_rounded, - serversProvider.serverStatus.data!.filteringEnabled, + statusProvider.serverStatus!.filteringEnabled, (value) => updateBlocking(value: value, filter: 'filtering'), - serversProvider.protectionsManagementProcess.contains('filtering') + statusProvider.protectionsManagementProcess.contains('filtering') ), smallSwitch( AppLocalizations.of(context)!.safeBrowsing, Icons.vpn_lock_rounded, - serversProvider.serverStatus.data!.safeBrowsingEnabled, + statusProvider.serverStatus!.safeBrowsingEnabled, (value) => updateBlocking(value: value, filter: 'safeBrowsing'), - serversProvider.protectionsManagementProcess.contains('safeBrowsing') + statusProvider.protectionsManagementProcess.contains('safeBrowsing') ), smallSwitch( AppLocalizations.of(context)!.parentalFiltering, Icons.block, - serversProvider.serverStatus.data!.parentalControlEnabled, + statusProvider.serverStatus!.parentalControlEnabled, (value) => updateBlocking(value: value, filter: 'parentalControl'), - serversProvider.protectionsManagementProcess.contains('parentalControl') + statusProvider.protectionsManagementProcess.contains('parentalControl') ), smallSwitch( AppLocalizations.of(context)!.safeSearch, Icons.search_rounded, - serversProvider.serverStatus.data!.safeSearchEnabled, + statusProvider.serverStatus!.safeSearchEnabled, (value) => updateBlocking(value: value, filter: 'safeSearch'), - serversProvider.protectionsManagementProcess.contains('safeSearch') + statusProvider.protectionsManagementProcess.contains('safeSearch') ), ]; } diff --git a/lib/screens/home/server_status.dart b/lib/screens/home/server_status.dart index 2a52889..c130564 100644 --- a/lib/screens/home/server_status.dart +++ b/lib/screens/home/server_status.dart @@ -5,10 +5,10 @@ import 'package:adguard_home_manager/screens/home/status_box.dart'; import 'package:adguard_home_manager/models/server_status.dart'; -class ServerStatus extends StatelessWidget { - final ServerStatusData serverStatus; +class ServerStatusWidget extends StatelessWidget { + final ServerStatus serverStatus; - const ServerStatus({ + const ServerStatusWidget({ Key? key, required this.serverStatus, }) : super(key: key); diff --git a/lib/screens/home/top_items.dart b/lib/screens/home/top_items.dart index e956409..f2b836c 100644 --- a/lib/screens/home/top_items.dart +++ b/lib/screens/home/top_items.dart @@ -9,16 +9,14 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/domain_options.dart'; import 'package:adguard_home_manager/screens/top_items/top_items_modal.dart'; -import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/screens/top_items/top_items.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/filtering_status.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class TopItems extends StatelessWidget { final String type; @@ -36,7 +34,7 @@ class TopItems extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -58,52 +56,26 @@ class TopItems extends StatelessWidget { final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingUserFilters); - final rules = await getFilteringRules(server: serversProvider.selectedServer!); + final rules = await statusProvider.blockUnblockDomain( + domain: domain, + newStatus: newStatus + ); - if (rules['result'] == 'success') { - FilteringStatus oldStatus = serversProvider.serverStatus.data!.filteringStatus; + processModal.close(); - List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); - if (newStatus == 'block') { - newRules.add("||$domain^"); - } - else if (newStatus == 'unblock') { - newRules.add("@@||$domain^"); - } - FilteringStatus newObj = serversProvider.serverStatus.data!.filteringStatus; - newObj.userRules = newRules; - serversProvider.setFilteringStatus(newObj); - - final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); - - processModal.close(); - - if (result['result'] == 'success') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesUpdated), - backgroundColor: Colors.green, - ) - ); - } - else { - appConfigProvider.addLog(result['log']); - serversProvider.setFilteringStatus(oldStatus); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) - ); - } + if (rules == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesUpdated, + color: Colors.green + ); } else { - appConfigProvider.addLog(rules['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, + color: Colors.red + ); } } @@ -141,20 +113,11 @@ class TopItems extends StatelessWidget { ]; } - void openOptionsModal(String domain, String type) { - showDialog( - context: context, - builder: (context) => OptionsModal( - options: generateOptions(domain), - ) - ); - } - Widget rowItem(Map item) { String? name; if (clients != null && clients == true) { try { - name = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(item.keys.toList()[0])).name; + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(item.keys.toList()[0])).name; } catch (e) { // ---- // } @@ -241,13 +204,13 @@ class TopItems extends StatelessWidget { List> generateData() { switch (type) { case 'topQueriedDomains': - return serversProvider.serverStatus.data!.stats.topQueriedDomains; + return statusProvider.serverStatus!.stats.topQueriedDomains; case 'topBlockedDomains': - return serversProvider.serverStatus.data!.stats.topBlockedDomains; + return statusProvider.serverStatus!.stats.topBlockedDomains; case 'topClients': - return serversProvider.serverStatus.data!.stats.topClients; + return statusProvider.serverStatus!.stats.topClients; default: return []; diff --git a/lib/screens/logs/clients_modal.dart b/lib/screens/logs/clients_modal.dart index bd39541..fcd9d74 100644 --- a/lib/screens/logs/clients_modal.dart +++ b/lib/screens/logs/clients_modal.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; class ClientsModal extends StatefulWidget { @@ -32,6 +33,7 @@ class _ClientsModalState extends State { @override Widget build(BuildContext context) { final logsProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final height = MediaQuery.of(context).size.height; @@ -86,7 +88,7 @@ class _ClientsModalState extends State { void selectAll() { setState(() { - selectedClients = logsProvider.clients!.map((item) => item.ip).toList(); + selectedClients = clientsProvider.clients!.autoClients.map((item) => item.ip).toList(); }); } @@ -126,20 +128,20 @@ class _ClientsModalState extends State { ), Flexible( child: ListView.builder( - itemCount: logsProvider.clients!.length, + itemCount: clientsProvider.clients!.autoClients.length, itemBuilder: (context, index) => listItem( - label: logsProvider.clients![index].ip, + label: clientsProvider.clients!.autoClients[index].ip, onChanged: () { - if (selectedClients.contains(logsProvider.clients![index].ip)) { + if (selectedClients.contains(clientsProvider.clients!.autoClients[index].ip)) { setState(() { selectedClients = selectedClients.where( - (item) => item != logsProvider.clients![index].ip + (item) => item != clientsProvider.clients!.autoClients[index].ip ).toList(); }); } else { setState(() { - selectedClients.add(logsProvider.clients![index].ip); + selectedClients.add(clientsProvider.clients!.autoClients[index].ip); }); } } @@ -152,11 +154,11 @@ class _ClientsModalState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton( - onPressed: selectedClients.length == logsProvider.clients!.length + onPressed: selectedClients.length == clientsProvider.clients!.autoClients.length ? () => unselectAll() : () => selectAll(), child: Text( - selectedClients.length == logsProvider.clients!.length + selectedClients.length == clientsProvider.clients!.autoClients.length ? AppLocalizations.of(context)!.unselectAll : AppLocalizations.of(context)!.selectAll ) diff --git a/lib/screens/logs/log_details_screen.dart b/lib/screens/logs/log_details_screen.dart index 1dafc64..32fbd73 100644 --- a/lib/screens/logs/log_details_screen.dart +++ b/lib/screens/logs/log_details_screen.dart @@ -10,11 +10,11 @@ import 'package:adguard_home_manager/screens/logs/log_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/get_filtered_status.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/logs.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/format_time.dart'; import 'package:adguard_home_manager/models/filtering_status.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; class LogDetailsScreen extends StatelessWidget { @@ -29,13 +29,13 @@ class LogDetailsScreen extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final statusProvider = Provider.of(context); Filter? getList(int id) { try { - return serversProvider.filteringStatus!.filters.firstWhere((filter) => filter.id == id, orElse: () { - return serversProvider.filteringStatus!.whitelistFilters.firstWhere((filter) => filter.id == id); + return statusProvider.filteringStatus!.filters.firstWhere((filter) => filter.id == id, orElse: () { + return statusProvider.filteringStatus!.whitelistFilters.firstWhere((filter) => filter.id == id); }); } catch (_) { return null; @@ -53,56 +53,29 @@ class LogDetailsScreen extends StatelessWidget { ); } - void blockUnblock(Log log, String newStatus) async { + void blockUnblock(String domain, String newStatus) async { final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingUserFilters); - final rules = await getFilteringRules(server: serversProvider.selectedServer!); + final rules = await statusProvider.blockUnblockDomain( + domain: domain, + newStatus: newStatus + ); - if (rules['result'] == 'success') { - FilteringStatus oldStatus = serversProvider.filteringStatus!; + processModal.close(); - List newRules = rules['data'].userRules.where((domain) => !domain.contains(log.question.name)).toList(); - if (newStatus == 'block') { - newRules.add("||${log.question.name}^"); - } - else if (newStatus == 'unblock') { - newRules.add("@@||${log.question.name}^"); - } - FilteringStatus newObj = serversProvider.filteringStatus!; - newObj.userRules = newRules; - serversProvider.setFilteringStatus(newObj); - - final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); - - processModal.close(); - - if (result['result'] == 'success') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesUpdated), - backgroundColor: Colors.green, - ) - ); - } - else { - appConfigProvider.addLog(result['log']); - serversProvider.setFilteringStatus(oldStatus); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) - ); - } + if (rules == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesUpdated, + color: Colors.green + ); } else { - appConfigProvider.addLog(rules['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, + color: Colors.red ); } } @@ -266,7 +239,12 @@ class LogDetailsScreen extends StatelessWidget { Row( children: [ IconButton( - onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), + onPressed: log.question.name != null + ? () => blockUnblock( + log.question.name!, + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' + ) + : null, icon: Icon( getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? Icons.check_circle_rounded @@ -298,8 +276,13 @@ class LogDetailsScreen extends StatelessWidget { centerTitle: false, title: Text(AppLocalizations.of(context)!.logDetails), actions: [ - if (serversProvider.filteringStatus != null) IconButton( - onPressed: () => blockUnblock(log, getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block'), + if (statusProvider.filteringStatus != null) IconButton( + onPressed: log.question.name != null + ? () => blockUnblock( + log.question.name!, + getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? 'unblock' : 'block' + ) + : null, icon: Icon( getFilteredStatus(context, appConfigProvider, log.reason, true)['filtered'] == true ? Icons.check_circle_rounded diff --git a/lib/screens/logs/logs.dart b/lib/screens/logs/logs.dart index c88cd0e..a48024c 100644 --- a/lib/screens/logs/logs.dart +++ b/lib/screens/logs/logs.dart @@ -15,160 +15,61 @@ import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/logs.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class Logs extends StatelessWidget { +class Logs extends StatefulWidget { const Logs({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - final logsProvider = Provider.of(context); - - return LogsWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - logsProvider: logsProvider, - selectedResultStatus: logsProvider.appliedFilters.selectedResultStatus, - searchText: logsProvider.appliedFilters.searchText, - ); - } + State createState() => _LogsState(); } -class LogsWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - final LogsProvider logsProvider; - final String selectedResultStatus; - final String? searchText; - - const LogsWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - required this.logsProvider, - required this.selectedResultStatus, - required this.searchText, - }) : super(key: key); - - @override - State createState() => _LogsWidgetState(); -} - -class _LogsWidgetState extends State { +class _LogsState extends State { late ScrollController scrollController; - - bool isLoadingMore = false; bool showDivider = true; Log? selectedLog; - Future fetchLogs({ - int? inOffset, - bool? loadingMore, - String? responseStatus, - String? searchText, - }) async { - int offst = inOffset ?? widget.logsProvider.offset; - - String resStatus = responseStatus ?? widget.selectedResultStatus; - String? search = searchText ?? widget.searchText; - - if (loadingMore != null && loadingMore == true) { - setState(() => isLoadingMore = true); - } - - final result = await getLogs( - server: widget.serversProvider.selectedServer!, - count: widget.logsProvider.logsQuantity, - offset: offst, - olderThan: widget.logsProvider.logsOlderThan, - responseStatus: resStatus, - search: search - ); - - if (loadingMore != null && loadingMore == true) { - setState(() => isLoadingMore = false); - } - - if (mounted) { - if (result['result'] == 'success') { - widget.logsProvider.setOffset(inOffset != null ? inOffset+widget.logsProvider.logsQuantity : widget.logsProvider.offset+widget.logsProvider.logsQuantity); - if (loadingMore != null && loadingMore == true && widget.logsProvider.logsData != null) { - LogsData newLogsData = result['data']; - newLogsData.data = [...widget.logsProvider.logsData!.data, ...result['data'].data]; - if (widget.logsProvider.appliedFilters.clients != null) { - newLogsData.data = newLogsData.data.where( - (item) => widget.logsProvider.appliedFilters.clients!.contains(item.client) - ).toList(); - } - widget.logsProvider.setLogsData(newLogsData); - } - else { - LogsData newLogsData = result['data']; - if (widget.logsProvider.appliedFilters.clients != null) { - newLogsData.data = newLogsData.data.where( - (item) => widget.logsProvider.appliedFilters.clients!.contains(item.client) - ).toList(); - } - widget.logsProvider.setLogsData(newLogsData); - } - widget.logsProvider.setLoadStatus(1); - } - else { - widget.logsProvider.setLoadStatus(2); - widget.appConfigProvider.addLog(result['log']); - } - } - } - void fetchFilteringRules() async { - final result = await getFilteringRules(server: widget.serversProvider.selectedServer!); - if (mounted) { - if (result['result'] == 'success') { - widget.serversProvider.setFilteringStatus(result['data']); - } - else { - widget.appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.couldntGetFilteringStatus), - backgroundColor: Colors.red, - ) - ); - } + final appConfigProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); + + final result = await statusProvider.getFilteringRules(); + if (mounted && result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.couldntGetFilteringStatus, + color: Colors.red + ); } } Future fetchClients() async { - final result = await getClients(widget.serversProvider.selectedServer!); - if (mounted) { - if (result['result'] == 'success') { - widget.logsProvider.setClientsLoadStatus(1); - widget.logsProvider.setClients(result['data'].autoClientsData); - } - else { - widget.logsProvider.setClientsLoadStatus(2); - widget.appConfigProvider.addLog(result['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.couldntGetFilteringStatus), - backgroundColor: Colors.red, - ) - ); - } + final clientsProvider = Provider.of(context, listen: false); + final appConfigProvider = Provider.of(context, listen: false); + + final result = await clientsProvider.fetchClients(); + if (mounted && result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.couldntGetFilteringStatus, + color: Colors.red + ); } } void scrollListener() { - if (scrollController.position.extentAfter < 500 && isLoadingMore == false) { - fetchLogs(loadingMore: true); + final logsProvider = Provider.of(context, listen: false); + + if (scrollController.position.extentAfter < 500 && logsProvider.isLoadingMore == false) { + logsProvider.fetchLogs(loadingMore: true); } if (scrollController.position.pixels > 0) { setState(() => showDivider = false); @@ -180,8 +81,10 @@ class _LogsWidgetState extends State { @override void initState() { + final logsProvider = Provider.of(context, listen: false); + scrollController = ScrollController()..addListener(scrollListener); - fetchLogs(inOffset: 0); + logsProvider.fetchLogs(inOffset: 0); fetchFilteringRules(); fetchClients(); super.initState(); @@ -190,6 +93,7 @@ class _LogsWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -200,12 +104,12 @@ class _LogsWidgetState extends State { processModal.open(AppLocalizations.of(context)!.updatingSettings); final result = serverVersionIsAhead( - currentVersion: widget.serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true - ? await updateQueryLogParameters(server: serversProvider.selectedServer!, data: data) - : await updateQueryLogParametersLegacy(server: serversProvider.selectedServer!, data: data); + ? await serversProvider.apiClient!.updateQueryLogParameters(data: data) + : await serversProvider.apiClient!.updateQueryLogParametersLegacy(data: data); processModal.close(); @@ -231,7 +135,7 @@ class _LogsWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.updatingSettings); - final result = await clearLogs(server: serversProvider.selectedServer!); + final result = await serversProvider.apiClient!.clearLogs(); processModal.close(); @@ -243,8 +147,6 @@ class _LogsWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.logsNotCleared, @@ -289,7 +191,7 @@ class _LogsWidgetState extends State { Widget generateBody() { switch (logsProvider.loadStatus) { - case 0: + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -309,20 +211,20 @@ class _LogsWidgetState extends State { ), ); - case 1: + case LoadStatus.loaded: return RefreshIndicator( onRefresh: () async { - await fetchLogs(inOffset: 0); + await logsProvider.fetchLogs(inOffset: 0); }, child: logsProvider.logsData!.data.isNotEmpty ? ListView.builder( controller: scrollController, padding: const EdgeInsets.only(top: 0), - itemCount: isLoadingMore == true + itemCount: logsProvider.isLoadingMore == true ? logsProvider.logsData!.data.length+1 : logsProvider.logsData!.data.length, itemBuilder: (context, index) { - if (isLoadingMore == true && index == logsProvider.logsData!.data.length) { + if (logsProvider.isLoadingMore == true && index == logsProvider.logsData!.data.length) { return const Padding( padding: EdgeInsets.symmetric(vertical: 20), child: Center( @@ -385,7 +287,7 @@ class _LogsWidgetState extends State { ) ); - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( @@ -421,11 +323,11 @@ class _LogsWidgetState extends State { centerTitle: false, actions: [ if (!(Platform.isAndroid || Platform.isIOS)) IconButton( - onPressed: () => fetchLogs(inOffset: 0), + onPressed: () => logsProvider.fetchLogs(inOffset: 0), icon: const Icon(Icons.refresh_rounded), tooltip: AppLocalizations.of(context)!.refresh, ), - logsProvider.loadStatus == 1 + logsProvider.loadStatus == LoadStatus.loaded ? IconButton( onPressed: openFilersModal, icon: const Icon(Icons.filter_list_rounded), @@ -442,7 +344,7 @@ class _LogsWidgetState extends State { onConfirm: updateConfig, onClear: clearQueries, dialog: true, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, ), barrierDismissible: false ) @@ -454,7 +356,7 @@ class _LogsWidgetState extends State { onConfirm: updateConfig, onClear: clearQueries, dialog: false, - serverVersion: serversProvider.serverStatus.data!.serverVersion, + serverVersion: statusProvider.serverStatus!.serverVersion, ), backgroundColor: Colors.transparent, isScrollControlled: true @@ -510,7 +412,7 @@ class _LogsWidgetState extends State { ) ); logsProvider.setSearchText(null); - fetchLogs( + logsProvider.fetchLogs( inOffset: 0, searchText: '' ); @@ -543,7 +445,7 @@ class _LogsWidgetState extends State { ) ); logsProvider.setSelectedResultStatus('all'); - fetchLogs( + logsProvider.fetchLogs( inOffset: 0, responseStatus: 'all' ); @@ -578,7 +480,7 @@ class _LogsWidgetState extends State { ) ); logsProvider.setSelectedClients(null); - fetchLogs( + logsProvider.fetchLogs( inOffset: 0, responseStatus: logsProvider.appliedFilters.selectedResultStatus ); diff --git a/lib/screens/logs/logs_config_modal.dart b/lib/screens/logs/logs_config_modal.dart index 26ef299..2f16721 100644 --- a/lib/screens/logs/logs_config_modal.dart +++ b/lib/screens/logs/logs_config_modal.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -74,13 +73,15 @@ class _LogsConfigModalWidgetState extends State { int loadStatus = 0; void loadData() async { + final serversProvider = Provider.of(context, listen: false); + final result = serverVersionIsAhead( currentVersion: widget.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true - ? await getQueryLogInfo(server: widget.serversProvider.selectedServer!) - : await getQueryLogInfoLegacy(server: widget.serversProvider.selectedServer!); + ? await serversProvider.apiClient!.getQueryLogInfo() + : await serversProvider.apiClient!.getQueryLogInfoLegacy(); if (mounted) { if (result['result'] == 'success') { diff --git a/lib/screens/logs/logs_filters_modal.dart b/lib/screens/logs/logs_filters_modal.dart index 19ba0c0..6b040d3 100644 --- a/lib/screens/logs/logs_filters_modal.dart +++ b/lib/screens/logs/logs_filters_modal.dart @@ -10,11 +10,8 @@ import 'package:adguard_home_manager/screens/logs/clients_modal.dart'; import 'package:adguard_home_manager/screens/logs/filter_status_modal.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/models/logs.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/models/applied_filters.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; class LogsFiltersModal extends StatelessWidget { @@ -62,8 +59,7 @@ class _LogsFiltersModalWidgetState extends State { @override Widget build(BuildContext context) { final logsProvider = Provider.of(context); - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -78,38 +74,6 @@ class _LogsFiltersModalWidgetState extends State { "safe_search": AppLocalizations.of(context)!.blockedSafeSearchRow, }; - void resetFilters() async { - setState(() { - searchController.text = ''; - }); - - logsProvider.setLoadStatus(0); - - logsProvider.resetFilters(); - - final result = await getLogs( - server: serversProvider.selectedServer!, - count: logsProvider.logsQuantity - ); - - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: 'all', - searchText: null, - clients: null - ) - ); - - if (result['result'] == 'success') { - logsProvider.setLogsData(result['data']); - logsProvider.setLoadStatus(1); - } - else { - appConfigProvider.addLog(result['log']); - logsProvider.setLoadStatus(2); - } - } - void openSelectFilterStatus() { if (width > 700 || !(Platform.isAndroid || Platform.isIOS)) { showDialog( @@ -158,45 +122,6 @@ class _LogsFiltersModalWidgetState extends State { } } - void filterLogs() async { - Navigator.pop(context); - - logsProvider.setLoadStatus(0); - - logsProvider.setOffset(0); - - final result = await getLogs( - server: serversProvider.selectedServer!, - count: logsProvider.logsQuantity, - olderThan: logsProvider.logsOlderThan, - responseStatus: logsProvider.selectedResultStatus, - search: logsProvider.searchText, - ); - - logsProvider.setAppliedFilters( - AppliedFiters( - selectedResultStatus: logsProvider.selectedResultStatus, - searchText: logsProvider.searchText, - clients: logsProvider.selectedClients - ) - ); - - if (result['result'] == 'success') { - LogsData newLogsData = result['data']; - if (widget.logsProvider.appliedFilters.clients != null) { - newLogsData.data = newLogsData.data.where( - (item) => widget.logsProvider.appliedFilters.clients!.contains(item.client) - ).toList(); - } - logsProvider.setLogsData(newLogsData); - logsProvider.setLoadStatus(1); - } - else { - appConfigProvider.addLog(result['log']); - logsProvider.setLoadStatus(2); - } - } - Widget content() { return Column( mainAxisSize: MainAxisSize.min, @@ -273,13 +198,13 @@ class _LogsFiltersModalWidgetState extends State { subtitle: logsProvider.selectedClients != null ? "${logsProvider.selectedClients!.length} ${AppLocalizations.of(context)!.clientsSelected}" : AppLocalizations.of(context)!.all, - onTap: logsProvider.clientsLoadStatus == 1 + onTap: clientsProvider.loadStatus == LoadStatus.loaded ? openSelectClients : null, - disabled: logsProvider.clientsLoadStatus != 1 , + disabled: clientsProvider.loadStatus != LoadStatus.loaded, icon: Icons.smartphone_rounded, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), - trailing: logsProvider.clientsLoadStatus == 0 + trailing: clientsProvider.loadStatus == LoadStatus.loading ? const SizedBox( width: 20, height: 20, @@ -287,7 +212,7 @@ class _LogsFiltersModalWidgetState extends State { strokeWidth: 2, ), ) - : logsProvider.clientsLoadStatus == 2 + : clientsProvider.loadStatus == LoadStatus.error ? const Icon( Icons.error_rounded, color: Colors.red, @@ -311,11 +236,17 @@ class _LogsFiltersModalWidgetState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton( - onPressed: resetFilters, + onPressed: () { + searchController.text = ""; + logsProvider.requestResetFilters(); + }, child: Text(AppLocalizations.of(context)!.resetFilters) ), TextButton( - onPressed: () => filterLogs(), + onPressed: () { + Navigator.pop(context); + logsProvider.filterLogs(); + }, child: Text(AppLocalizations.of(context)!.apply) ), ], diff --git a/lib/screens/settings/access_settings/access_settings.dart b/lib/screens/settings/access_settings/access_settings.dart index 9f03328..beb34fd 100644 --- a/lib/screens/settings/access_settings/access_settings.dart +++ b/lib/screens/settings/access_settings/access_settings.dart @@ -7,62 +7,22 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/access_settings/clients_list.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; -class AccessSettings extends StatelessWidget { +class AccessSettings extends StatefulWidget { const AccessSettings({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return AccessSettingsWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _AccessSettingsState(); } -class AccessSettingsWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const AccessSettingsWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider, - }) : super(key: key); - - @override - State createState() => _AccessSettingsWidgetState(); -} - -class _AccessSettingsWidgetState extends State with TickerProviderStateMixin { +class _AccessSettingsState extends State with TickerProviderStateMixin { final ScrollController scrollController = ScrollController(); late TabController tabController; - Future fetchClients() async { - widget.serversProvider.setClientsLoadStatus(LoadStatus.loading, false); - final result = await getClients(widget.serversProvider.selectedServer!); - if (mounted) { - if (result['result'] == 'success') { - widget.serversProvider.setClientsData(result['data']); - widget.serversProvider.setClientsLoadStatus(LoadStatus.loaded, true); - } - else { - widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setClientsLoadStatus(LoadStatus.error, true); - } - } - } - - @override void initState() { - fetchClients(); + Provider.of(context, listen: false).fetchClients(updateLoading: true); super.initState(); tabController = TabController( initialIndex: 0, @@ -73,7 +33,7 @@ class _AccessSettingsWidgetState extends State with Ticker @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final clientsProvider = Provider.of(context); Widget body() { return TabBarView( @@ -82,26 +42,23 @@ class _AccessSettingsWidgetState extends State with Ticker ClientsList( type: 'allowed', scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.allowedClients : [], - fetchClients: fetchClients + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.allowedClients : [], ), ClientsList( type: 'disallowed', scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.disallowedClients : [], - fetchClients: fetchClients + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.disallowedClients : [], ), ClientsList( type: 'domains', scrollController: scrollController, - loadStatus: serversProvider.clients.loadStatus, - data: serversProvider.clients.loadStatus == LoadStatus.loaded - ? serversProvider.clients.data!.clientsAllowedBlocked!.blockedHosts : [], - fetchClients: fetchClients + loadStatus: clientsProvider.loadStatus, + data: clientsProvider.loadStatus == LoadStatus.loaded + ? clientsProvider.clients!.clientsAllowedBlocked!.blockedHosts : [], ), ] ); diff --git a/lib/screens/settings/access_settings/clients_list.dart b/lib/screens/settings/access_settings/clients_list.dart index bc3646f..2466e11 100644 --- a/lib/screens/settings/access_settings/clients_list.dart +++ b/lib/screens/settings/access_settings/clients_list.dart @@ -13,10 +13,8 @@ import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/models/clients_allowed_blocked.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/constants/enums.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; +import 'package:adguard_home_manager/providers/clients_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; class ClientsList extends StatefulWidget { @@ -24,7 +22,6 @@ class ClientsList extends StatefulWidget { final ScrollController scrollController; final LoadStatus loadStatus; final List data; - final Future Function() fetchClients; const ClientsList({ Key? key, @@ -32,7 +29,6 @@ class ClientsList extends StatefulWidget { required this.scrollController, required this.loadStatus, required this.data, - required this.fetchClients }) : super(key: key); @override @@ -67,16 +63,27 @@ class _ClientsListState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); + final clientsProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; + Future refetchClients() async { + final result = await clientsProvider.fetchClients(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientsNotLoaded, + color: Colors.red + ); + } + } + void confirmRemoveItem(String client, String type) async { Map> body = { - "allowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.allowedClients ?? [], - "disallowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.disallowedClients ?? [], - "blocked_hosts": serversProvider.clients.data!.clientsAllowedBlocked?.blockedHosts ?? [], + "allowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.allowedClients ?? [], + "disallowed_clients": clientsProvider.clients!.clientsAllowedBlocked?.disallowedClients ?? [], + "blocked_hosts": clientsProvider.clients!.clientsAllowedBlocked?.blockedHosts ?? [], }; if (type == 'allowed') { @@ -92,20 +99,18 @@ class _ClientsListState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); - final result = await requestAllowedBlockedClientsHosts(serversProvider.selectedServer!, body); + final result = await clientsProvider.removeClientList(client, type); processModal.close(); - if (result['result'] == 'success') { - serversProvider.setAllowedDisallowedClientsBlockedDomains( - ClientsAllowedBlocked( - allowedClients: body['allowed_clients'] ?? [], - disallowedClients: body['disallowed_clients'] ?? [], - blockedHosts: body['blocked_hosts'] ?? [], - ) + if (result['success'] == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientRemovedSuccessfully, + color: Colors.green ); } - else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + else if (result['success'] == false && result['error'] == 'client_another_list') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, @@ -113,50 +118,32 @@ class _ClientsListState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.clientNotRemoved, + label: type == 'allowed' || type == 'blocked' + ? AppLocalizations.of(context)!.clientNotRemoved + : AppLocalizations.of(context)!.domainNotAdded, color: Colors.red ); } } void confirmAddItem(String item, String type) async { - Map> body = { - "allowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.allowedClients ?? [], - "disallowed_clients": serversProvider.clients.data!.clientsAllowedBlocked?.disallowedClients ?? [], - "blocked_hosts": serversProvider.clients.data!.clientsAllowedBlocked?.blockedHosts ?? [], - }; - - if (type == 'allowed') { - body['allowed_clients']!.add(item); - } - else if (type == 'disallowed') { - body['disallowed_clients']!.add(item); - } - else if (type == 'domains') { - body['blocked_hosts']!.add(item); - } - ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.removingClient); - final result = await requestAllowedBlockedClientsHosts(serversProvider.selectedServer!, body); + final result = await clientsProvider.addClientList(item, type); processModal.close(); - if (result['result'] == 'success') { - serversProvider.setAllowedDisallowedClientsBlockedDomains( - ClientsAllowedBlocked( - allowedClients: body['allowed_clients'] ?? [], - disallowedClients: body['disallowed_clients'] ?? [], - blockedHosts: body['blocked_hosts'] ?? [], - ) + if (result['success'] == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.clientAddedSuccessfully, + color: Colors.green ); } - else if (result['result'] == 'error' && result['message'] == 'client_another_list') { + else if (result['success'] == false && result['error'] == 'client_another_list') { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.clientAnotherList, @@ -164,8 +151,6 @@ class _ClientsListState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: type == 'allowed' || type == 'blocked' @@ -325,7 +310,7 @@ class _ClientsListState extends State { ), const SizedBox(height: 30), TextButton.icon( - onPressed: widget.fetchClients, + onPressed: refetchClients, icon: const Icon(Icons.refresh_rounded), label: Text(AppLocalizations.of(context)!.refresh), ) @@ -359,7 +344,7 @@ class _ClientsListState extends State { ), ), loadStatus: widget.loadStatus, - onRefresh: widget.fetchClients, + onRefresh: refetchClients, refreshIndicatorOffset: 0, fab: FloatingActionButton( onPressed: () { diff --git a/lib/screens/settings/advanced_setings.dart b/lib/screens/settings/advanced_setings.dart index 2ed0ee4..66ff49b 100644 --- a/lib/screens/settings/advanced_setings.dart +++ b/lib/screens/settings/advanced_setings.dart @@ -1,14 +1,10 @@ // ignore_for_file: use_build_context_synchronously -import 'dart:io'; - import 'package:flutter/material.dart'; -import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; -import 'package:adguard_home_manager/screens/settings/app_logs/app_logs.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -20,8 +16,6 @@ class AdvancedSettings extends StatelessWidget { Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); - final width = MediaQuery.of(context).size.width; - Future updateSettings({ required bool newStatus, required Future Function(bool) function @@ -71,29 +65,6 @@ class AdvancedSettings extends StatelessWidget { right: 10 ) ), - CustomListTile( - icon: Icons.list_rounded, - title: AppLocalizations.of(context)!.logs, - subtitle: AppLocalizations.of(context)!.checkAppLogs, - onTap: () => { - if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { - SplitView.of(context).push(const AppLogs()) - } - else { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const AppLogs() - ) - ) - } - }, - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - left: 20, - right: 10 - ) - ), ], ) ); diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index c45dfd7..49ab29c 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -13,42 +13,21 @@ import 'package:adguard_home_manager/screens/settings/dhcp/dhcp_leases.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/select_interface_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; -class Dhcp extends StatelessWidget { - const Dhcp({Key? key}) : super(key: key); +class DhcpScreen extends StatefulWidget { + const DhcpScreen({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return DhcpWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider - ); - } + State createState() => _DhcpScreenState(); } -class DhcpWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const DhcpWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _DhcpWidgetState(); -} - -class _DhcpWidgetState extends State { +class _DhcpScreenState extends State { NetworkInterface? selectedInterface; bool enabled = false; @@ -74,31 +53,22 @@ class _DhcpWidgetState extends State { bool dataValid = false; void loadDhcpStatus() async { - widget.serversProvider.setDhcpLoadStatus(0, false); - - final result = await getDhcpData(server: widget.serversProvider.selectedServer!); - - if (mounted) { - if (result['result'] == 'success') { - widget.serversProvider.setDhcpLoadStatus(1, true); - widget.serversProvider.setDhcpData(result['data']); + final result = await Provider.of(context, listen: false).loadDhcpStatus(); + if (mounted && result == true) { + final dhcpProvider = Provider.of(context, listen: false); + if (dhcpProvider.dhcp != null) { setState(() { - if (result['data'].dhcpStatus.interfaceName != '') { - selectedInterface = result['data'].networkInterfaces.firstWhere((interface) => interface.name == result['data'].dhcpStatus.interfaceName); - - enabled = result['data'].dhcpStatus.enabled; - ipv4StartRangeController.text = result['data'].dhcpStatus.v4.rangeStart; - ipv4StartRangeController.text = result['data'].dhcpStatus.v4.rangeStart; - ipv4EndRangeController.text = result['data'].dhcpStatus.v4.rangeEnd; - ipv4SubnetMaskController.text = result['data'].dhcpStatus.v4.subnetMask; - ipv4GatewayController.text = result['data'].dhcpStatus.v4.gatewayIp; - ipv4LeaseTimeController.text = result['data'].dhcpStatus.v4.leaseDuration.toString(); + if (dhcpProvider.dhcp!.dhcpStatus.interfaceName != '') { + selectedInterface = dhcpProvider.dhcp!.networkInterfaces.firstWhere((iface) => iface.name == dhcpProvider.dhcp!.dhcpStatus.interfaceName); + enabled = dhcpProvider.dhcp!.dhcpStatus.enabled; + ipv4StartRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeStart; + ipv4EndRangeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.rangeEnd ?? ''; + ipv4SubnetMaskController.text = dhcpProvider.dhcp!.dhcpStatus.v4.subnetMask ?? ''; + ipv4GatewayController.text = dhcpProvider.dhcp!.dhcpStatus.v4.gatewayIp ?? ''; + ipv4LeaseTimeController.text = dhcpProvider.dhcp!.dhcpStatus.v4.leaseDuration.toString(); } }); } - else { - widget.serversProvider.setDhcpLoadStatus(2, true); - } } checkDataValid(); } @@ -213,6 +183,7 @@ class _DhcpWidgetState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dhcpProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -221,22 +192,24 @@ class _DhcpWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingSettings); - final result = await saveDhcpConfig(server: serversProvider.selectedServer!, data: { - "enabled": enabled, - "interface_name": selectedInterface!.name, - if (selectedInterface!.ipv4Addresses.isNotEmpty) "v4": { - "gateway_ip": ipv4GatewayController.text, - "subnet_mask": ipv4SubnetMaskController.text, - "range_start": ipv4StartRangeController.text, - "range_end": ipv4EndRangeController.text, - "lease_duration": ipv4LeaseTimeController.text != '' ? int.parse(ipv4LeaseTimeController.text) : null - }, - if (selectedInterface!.ipv6Addresses.isNotEmpty) "v6": { - "range_start": ipv6StartRangeController.text, - "range_end": ipv6EndRangeController.text, - "lease_duration": ipv6LeaseTimeController.text != '' ? int.parse(ipv6LeaseTimeController.text) : null + final result = await serversProvider.apiClient!.saveDhcpConfig( + data: { + "enabled": enabled, + "interface_name": selectedInterface!.name, + if (selectedInterface!.ipv4Addresses.isNotEmpty) "v4": { + "gateway_ip": ipv4GatewayController.text, + "subnet_mask": ipv4SubnetMaskController.text, + "range_start": ipv4StartRangeController.text, + "range_end": ipv4EndRangeController.text, + "lease_duration": ipv4LeaseTimeController.text != '' ? int.parse(ipv4LeaseTimeController.text) : null + }, + if (selectedInterface!.ipv6Addresses.isNotEmpty) "v6": { + "range_start": ipv6StartRangeController.text, + "range_end": ipv6EndRangeController.text, + "lease_duration": ipv6LeaseTimeController.text != '' ? int.parse(ipv6LeaseTimeController.text) : null + } } - }); + ); processModal.close(); @@ -248,8 +221,6 @@ class _DhcpWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsNotSaved, @@ -263,7 +234,7 @@ class _DhcpWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.restoringConfig); - final result = await resetDhcpConfig(server: serversProvider.selectedServer!); + final result = await serversProvider.apiClient!.resetDhcpConfig(); processModal.close(); @@ -277,8 +248,6 @@ class _DhcpWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.configNotRestored, @@ -293,15 +262,15 @@ class _DhcpWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.restoringLeases); - final result = await restoreAllLeases(server: serversProvider.selectedServer!); + final result = await serversProvider.apiClient!.restoreAllLeases(); processModal.close(); if (result['result'] == 'success') { - DhcpData data = serversProvider.dhcp.data!; + DhcpModel data = dhcpProvider.dhcp!; data.dhcpStatus.staticLeases = []; data.dhcpStatus.leases = []; - serversProvider.setDhcpData(data); + dhcpProvider.setDhcpData(data); showSnacbkar( appConfigProvider: appConfigProvider, @@ -310,8 +279,6 @@ class _DhcpWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.leasesNotRestored, @@ -356,7 +323,7 @@ class _DhcpWidgetState extends State { showDialog( context: context, builder: (context) => SelectInterfaceModal( - interfaces: serversProvider.dhcp.data!.networkInterfaces, + interfaces: dhcpProvider.dhcp!.networkInterfaces, onSelect: (interface) => setState(() { clearAll(); selectedInterface = interface; @@ -369,7 +336,7 @@ class _DhcpWidgetState extends State { showModalBottomSheet( context: context, builder: (context) => SelectInterfaceModal( - interfaces: serversProvider.dhcp.data!.networkInterfaces, + interfaces: dhcpProvider.dhcp!.networkInterfaces, onSelect: (i) => setState(() { clearAll(); selectedInterface = i; @@ -383,8 +350,8 @@ class _DhcpWidgetState extends State { } Widget generateBody() { - switch (serversProvider.dhcp.loadStatus) { - case 0: + switch (dhcpProvider.loadStatus) { + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -404,7 +371,7 @@ class _DhcpWidgetState extends State { ), ); - case 1: + case LoadStatus.loaded: if (selectedInterface != null) { return SingleChildScrollView( child: Wrap( @@ -683,7 +650,7 @@ class _DhcpWidgetState extends State { onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus.leases, staticLeases: false, ) )); @@ -716,7 +683,7 @@ class _DhcpWidgetState extends State { onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, staticLeases: true, ) )); @@ -751,7 +718,7 @@ class _DhcpWidgetState extends State { if (!(Platform.isAndroid || Platform.isIOS)) { SplitView.of(context).push( DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus.leases, staticLeases: false, ) ); @@ -759,7 +726,7 @@ class _DhcpWidgetState extends State { else { Navigator.push(context, MaterialPageRoute( builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.leases, + items: dhcpProvider.dhcp!.dhcpStatus.leases, staticLeases: false, ) )); @@ -778,7 +745,7 @@ class _DhcpWidgetState extends State { if (!(Platform.isAndroid || Platform.isIOS)) { SplitView.of(context).push( DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, staticLeases: true, ) ); @@ -786,7 +753,7 @@ class _DhcpWidgetState extends State { else { Navigator.push(context, MaterialPageRoute( builder: (context) => DhcpLeases( - items: serversProvider.dhcp.data!.dhcpStatus.staticLeases, + items: dhcpProvider.dhcp!.dhcpStatus.staticLeases, staticLeases: true, ) )); @@ -840,7 +807,7 @@ class _DhcpWidgetState extends State { ); } - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/settings/dhcp/dhcp_leases.dart b/lib/screens/settings/dhcp/dhcp_leases.dart index 39a3303..3763704 100644 --- a/lib/screens/settings/dhcp/dhcp_leases.dart +++ b/lib/screens/settings/dhcp/dhcp_leases.dart @@ -10,12 +10,11 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/delete_static_lease_modal.dart'; import 'package:adguard_home_manager/screens/settings/dhcp/add_static_lease_modal.dart'; +import 'package:adguard_home_manager/providers/dhcp_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/models/dhcp.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class DhcpLeases extends StatelessWidget { final List items; @@ -29,7 +28,7 @@ class DhcpLeases extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final dhcpProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -38,19 +37,11 @@ class DhcpLeases extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deleting); - final result = await deleteStaticLease(server: serversProvider.selectedServer!, data: { - "mac": lease.mac, - "ip": lease.ip, - "hostname": lease.hostname - }); + final result = await dhcpProvider.deleteLease(lease); processModal.close(); - if (result['result'] == 'success') { - DhcpData data = serversProvider.dhcp.data!; - data.dhcpStatus.staticLeases = data.dhcpStatus.staticLeases.where((l) => l.mac != lease.mac).toList(); - serversProvider.setDhcpData(data); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseDeleted, @@ -58,7 +49,6 @@ class DhcpLeases extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseNotDeleted, @@ -71,35 +61,25 @@ class DhcpLeases extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.creating); - final result = await createStaticLease(server: serversProvider.selectedServer!, data: { - "mac": lease.mac, - "ip": lease.ip, - "hostname": lease.hostname, - }); + final result = await dhcpProvider.createLease(lease); processModal.close(); - if (result['result'] == 'success') { - DhcpData data = serversProvider.dhcp.data!; - data.dhcpStatus.staticLeases.add(lease); - serversProvider.setDhcpData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseCreated, color: Colors.green ); } - else if (result['result'] == 'error' && result['message'] == 'already_exists' ) { - appConfigProvider.addLog(result['log']); + else if (result['success'] == false && result['error'] == 'already_exists' ) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseExists, color: Colors.red ); } - else if (result['result'] == 'error' && result['message'] == 'server_not_configured' ) { - appConfigProvider.addLog(result['log']); + else if (result['success'] == false && result['error'] == 'server_not_configured' ) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverNotConfigured, @@ -107,7 +87,6 @@ class DhcpLeases extends StatelessWidget { ); } else { - appConfigProvider.addLog(result['log']); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.staticLeaseNotCreated, diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index fa538dd..055042d 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -4,20 +4,13 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class BootstrapDnsScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const BootstrapDnsScreen({ - Key? key, - required this.serversProvider, - }) : super(key: key); + const BootstrapDnsScreen({Key? key}) : super(key: key); @override State createState() => _BootstrapDnsScreenState(); @@ -54,7 +47,9 @@ class _BootstrapDnsScreenState extends State { @override void initState() { - for (var item in widget.serversProvider.dnsInfo.data!.bootstrapDns) { + final dnsProvider = Provider.of(context, listen: false); + + for (var item in dnsProvider.dnsInfo!.bootstrapDns) { final controller = TextEditingController(); controller.text = item; bootstrapControllers.add({ @@ -68,33 +63,27 @@ class _BootstrapDnsScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + final result = await dnsProvider.saveBootstrapDnsConfig({ "bootstrap_dns": bootstrapControllers.map((e) => e['controller'].text).toList(), }); processModal.close(); - if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; - data.bootstrapDns = List.from(bootstrapControllers.map((e) => e['controller'].text)); - serversProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -102,8 +91,6 @@ class _BootstrapDnsScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, diff --git a/lib/screens/settings/dns/cache_config.dart b/lib/screens/settings/dns/cache_config.dart index 32ae872..cd2968b 100644 --- a/lib/screens/settings/dns/cache_config.dart +++ b/lib/screens/settings/dns/cache_config.dart @@ -8,21 +8,14 @@ import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; import 'package:adguard_home_manager/screens/settings/dns/clear_dns_cache_dialog.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; - +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/clear_dns_cache.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class CacheConfigDnsScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const CacheConfigDnsScreen({ - Key? key, - required this.serversProvider - }) : super(key: key); + const CacheConfigDnsScreen({Key? key}) : super(key: key); @override State createState() => _CacheConfigDnsScreenState(); @@ -60,10 +53,12 @@ class _CacheConfigDnsScreenState extends State { @override void initState() { - cacheSizeController.text = widget.serversProvider.dnsInfo.data!.cacheSize.toString(); - overrideMinTtlController.text = widget.serversProvider.dnsInfo.data!.cacheTtlMin.toString(); - overrideMaxTtlController.text = widget.serversProvider.dnsInfo.data!.cacheTtlMax.toString(); - optimisticCache = widget.serversProvider.dnsInfo.data!.cacheOptimistic; + final dnsProvider = Provider.of(context, listen: false); + + cacheSizeController.text = dnsProvider.dnsInfo!.cacheSize.toString(); + overrideMinTtlController.text = dnsProvider.dnsInfo!.cacheTtlMin.toString(); + overrideMaxTtlController.text = dnsProvider.dnsInfo!.cacheTtlMax.toString(); + optimisticCache = dnsProvider.dnsInfo!.cacheOptimistic; validData = true; super.initState(); } @@ -71,13 +66,14 @@ class _CacheConfigDnsScreenState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + final result = await dnsProvider.saveCacheCacheConfig({ "cache_size": int.parse(cacheSizeController.text), "cache_ttl_min": int.parse(overrideMinTtlController.text), "cache_ttl_max": int.parse(overrideMaxTtlController.text), @@ -86,23 +82,14 @@ class _CacheConfigDnsScreenState extends State { processModal.close(); - if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; - data.cacheSize = int.parse(cacheSizeController.text); - data.cacheTtlMin = int.parse(overrideMinTtlController.text); - data.cacheTtlMax = int.parse(overrideMaxTtlController.text); - data.cacheOptimistic = optimisticCache; - serversProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -110,8 +97,6 @@ class _CacheConfigDnsScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, diff --git a/lib/screens/settings/dns/dns.dart b/lib/screens/settings/dns/dns.dart index be7eb79..eac3c2c 100644 --- a/lib/screens/settings/dns/dns.dart +++ b/lib/screens/settings/dns/dns.dart @@ -2,6 +2,8 @@ import 'dart:io'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:flutter/material.dart'; import 'package:flutter_split_view/flutter_split_view.dart'; import 'package:provider/provider.dart'; @@ -19,64 +21,25 @@ import 'package:adguard_home_manager/functions/clear_dns_cache.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; -class DnsSettings extends StatelessWidget { +class DnsSettings extends StatefulWidget { const DnsSettings({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return DnsSettingsWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } -} -class DnsSettingsWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const DnsSettingsWidget({ - required this.serversProvider, - required this.appConfigProvider, - Key? key - }) : super(key: key); - - @override - State createState() => _DnsSettingsWidgetState(); + State createState() => _DnsSettingsState(); } -class _DnsSettingsWidgetState extends State { - - void fetchData({bool? showRefreshIndicator}) async { - widget.serversProvider.setDnsInfoLoadStatus(0, showRefreshIndicator ?? false); - - final result = await getDnsInfo(server: widget.serversProvider.selectedServer!); - - if (mounted) { - if (result['result'] == 'success') { - widget.serversProvider.setDnsInfoData(result['data']); - widget.serversProvider.setDnsInfoLoadStatus(1, true); - } - else { - widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setDnsInfoLoadStatus(2, true); - } - } - } - +class _DnsSettingsState extends State { @override void initState() { - fetchData(); + Provider.of(context, listen: false).fetchDnsData(showLoading: true); super.initState(); } @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -93,8 +56,8 @@ class _DnsSettingsWidgetState extends State { } Widget generateBody() { - switch (widget.serversProvider.dnsInfo.loadStatus) { - case 0: + switch (dnsProvider.loadStatus) { + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -115,63 +78,43 @@ class _DnsSettingsWidgetState extends State { ) ); - case 1: + case LoadStatus.loaded: return ListView( children: [ CustomListTile( title: AppLocalizations.of(context)!.upstreamDns, subtitle: AppLocalizations.of(context)!.upstreamDnsDescription, - onTap: () => navigate( - UpstreamDnsScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const UpstreamDnsScreen()), icon: Icons.upload_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.bootstrapDns, subtitle: AppLocalizations.of(context)!.bootstrapDnsDescription, - onTap: () => navigate( - BootstrapDnsScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const BootstrapDnsScreen()), icon: Icons.dns_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.privateReverseDnsServers, subtitle: AppLocalizations.of(context)!.privateReverseDnsDescription, - onTap: () => navigate( - PrivateReverseDnsServersScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const PrivateReverseDnsServersScreen()), icon: Icons.person_rounded, ), CustomListTile( title: AppLocalizations.of(context)!.dnsServerSettings, subtitle: AppLocalizations.of(context)!.dnsServerSettingsDescription, - onTap: () => navigate( - DnsServerSettingsScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const DnsServerSettingsScreen()), icon: Icons.settings, ), CustomListTile( title: AppLocalizations.of(context)!.dnsCacheConfig, subtitle: AppLocalizations.of(context)!.dnsCacheConfigDescription, - onTap: () => navigate( - CacheConfigDnsScreen( - serversProvider: serversProvider - ) - ), + onTap: () => navigate(const CacheConfigDnsScreen()), icon: Icons.storage_rounded, ), ], ); - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( @@ -226,7 +169,7 @@ class _DnsSettingsWidgetState extends State { PopupMenuButton( itemBuilder: (context) => [ PopupMenuItem( - onTap: () => fetchData(showRefreshIndicator: true), + onTap: () => dnsProvider.fetchDnsData(), child: Row( children: [ const Icon(Icons.refresh_rounded), diff --git a/lib/screens/settings/dns/dns_server_settings.dart b/lib/screens/settings/dns/dns_server_settings.dart index d0d3ecd..9169408 100644 --- a/lib/screens/settings/dns/dns_server_settings.dart +++ b/lib/screens/settings/dns/dns_server_settings.dart @@ -8,20 +8,13 @@ import 'package:adguard_home_manager/widgets/custom_radio_list_tile.dart'; import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class DnsServerSettingsScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const DnsServerSettingsScreen({ - Key? key, - required this.serversProvider - }) : super(key: key); + const DnsServerSettingsScreen({Key? key}) : super(key: key); @override State createState() => _DnsServerSettingsScreenState(); @@ -89,56 +82,48 @@ class _DnsServerSettingsScreenState extends State { @override void initState() { - limitRequestsController.text = widget.serversProvider.dnsInfo.data!.ratelimit.toString(); - enableEdns = widget.serversProvider.dnsInfo.data!.ednsCsEnabled; - enableDnssec = widget.serversProvider.dnsInfo.data!.dnssecEnabled; - disableIpv6Resolving = widget.serversProvider.dnsInfo.data!.disableIpv6; - blockingMode = widget.serversProvider.dnsInfo.data!.blockingMode; - ipv4controller.text = widget.serversProvider.dnsInfo.data!.blockingIpv4; - ipv6controller.text = widget.serversProvider.dnsInfo.data!.blockingIpv6; + final dnsProvider = Provider.of(context, listen: false); + + limitRequestsController.text = dnsProvider.dnsInfo!.ratelimit.toString(); + enableEdns = dnsProvider.dnsInfo!.ednsCsEnabled; + enableDnssec = dnsProvider.dnsInfo!.dnssecEnabled; + disableIpv6Resolving = dnsProvider.dnsInfo!.disableIpv6; + blockingMode = dnsProvider.dnsInfo!.blockingMode; + ipv4controller.text = dnsProvider.dnsInfo!.blockingIpv4; + ipv6controller.text = dnsProvider.dnsInfo!.blockingIpv6; isDataValid = true; super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + final result = await dnsProvider.saveDnsServerConfig({ "ratelimit": int.parse(limitRequestsController.text), "edns_cs_enabled": enableEdns, "dnssec_enabled": enableDnssec, "disable_ipv6": disableIpv6Resolving, - "blocking_mode": blockingMode + "blocking_mode": blockingMode, + "blocking_ipv4": ipv4controller.text, + "blocking_ipv6": ipv6controller.text }); processModal.close(); - if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; - data.ratelimit = int.parse(limitRequestsController.text); - data.ednsCsEnabled = enableEdns; - data.dnssecEnabled = enableDnssec; - data.disableIpv6 = disableIpv6Resolving; - data.blockingMode = blockingMode; - data.blockingIpv4 = ipv4controller.text; - data.blockingIpv6 = ipv6controller.text; - serversProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -146,8 +131,6 @@ class _DnsServerSettingsScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, diff --git a/lib/screens/settings/dns/private_reverse_servers.dart b/lib/screens/settings/dns/private_reverse_servers.dart index 6081278..bf6f63b 100644 --- a/lib/screens/settings/dns/private_reverse_servers.dart +++ b/lib/screens/settings/dns/private_reverse_servers.dart @@ -6,20 +6,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_switch_list_tile.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; +import 'package:adguard_home_manager/providers/dns_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/dns_info.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class PrivateReverseDnsServersScreen extends StatefulWidget { - final ServersProvider serversProvider; - - const PrivateReverseDnsServersScreen({ - Key? key, - required this.serversProvider, - }) : super(key: key); + const PrivateReverseDnsServersScreen({Key? key}) : super(key: key); @override State createState() => _PrivateReverseDnsServersScreenState(); @@ -69,10 +62,12 @@ class _PrivateReverseDnsServersScreenState extends State(context, listen: false); + + for (var item in dnsProvider.dnsInfo!.defaultLocalPtrUpstreams) { defaultReverseResolvers.add(item); } - for (var item in widget.serversProvider.dnsInfo.data!.localPtrUpstreams) { + for (var item in dnsProvider.dnsInfo!.localPtrUpstreams) { final controller = TextEditingController(); controller.text = item; reverseResolversControllers = [{ @@ -80,54 +75,46 @@ class _PrivateReverseDnsServersScreenState extends State(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveData() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: editReverseResolvers == true - ? { - "local_ptr_upstreams": List.from(reverseResolversControllers.map((e) => e['controller'].text)), - "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, - "resolve_clients": enableReverseResolve - } : { - "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, - "resolve_clients": enableReverseResolve - }); + final result = await dnsProvider.savePrivateReverseServersConfig( + editReverseResolvers == true + ? { + "local_ptr_upstreams": List.from(reverseResolversControllers.map((e) => e['controller'].text)), + "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, + "resolve_clients": enableReverseResolve + } : { + "use_private_ptr_resolvers": usePrivateReverseDnsResolvers, + "resolve_clients": enableReverseResolve + } + ); processModal.close(); - if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; - if (editReverseResolvers == true) { - data.localPtrUpstreams = List.from(reverseResolversControllers.map((e) => e['controller'].text)); - } - data.usePrivatePtrResolvers = usePrivateReverseDnsResolvers; - data.resolveClients = enableReverseResolve; - serversProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -135,8 +122,6 @@ class _PrivateReverseDnsServersScreenState extends State createState() => _UpstreamDnsScreenState(); @@ -50,7 +43,9 @@ class _UpstreamDnsScreenState extends State { @override void initState() { - for (var item in widget.serversProvider.dnsInfo.data!.upstreamDns) { + final dnsProvider = Provider.of(context, listen: false); + + for (var item in dnsProvider.dnsInfo!.upstreamDns) { if (item == '#') { dnsServers.add({ 'comment': item @@ -64,14 +59,14 @@ class _UpstreamDnsScreenState extends State { }); } } - upstreamMode = widget.serversProvider.dnsInfo.data!.upstreamMode; + upstreamMode = dnsProvider.dnsInfo!.upstreamMode; validValues = true; super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final dnsProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -146,28 +141,21 @@ class _UpstreamDnsScreenState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await setDnsConfig(server: serversProvider.selectedServer!, data: { + final result = await dnsProvider.saveUpstreamDnsConfig({ "upstream_dns": dnsServers.map((e) => e['controller'] != null ? e['controller'].text : e['comment']).toList(), "upstream_mode": upstreamMode }); processModal.close(); - if (result['result'] == 'success') { - DnsInfoData data = serversProvider.dnsInfo.data!; - data.upstreamDns = List.from(dnsServers.map((e) => e['controller'] != null ? e['controller'].text : e['comment'])); - data.upstreamMode = upstreamMode; - serversProvider.setDnsInfoData(data); - + if (result['success'] == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigSaved, color: Colors.green ); } - else if (result['log'] != null && result['log'].statusCode == '400') { - appConfigProvider.addLog(result['log']); - + else if (result['success'] == false && result['error'] == 400) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.someValueNotValid, @@ -175,8 +163,6 @@ class _UpstreamDnsScreenState extends State { ); } else { - appConfigProvider.addLog(result['log']); - showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsConfigNotSaved, diff --git a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart index edff851..24ee717 100644 --- a/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart @@ -6,7 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; class AddDnsRewriteModal extends StatefulWidget { - final void Function(RewriteRulesData) onConfirm; + final void Function(RewriteRules) onConfirm; final bool dialog; const AddDnsRewriteModal({ @@ -143,7 +143,7 @@ class _AddDnsRewriteModalState extends State { ? () { Navigator.pop(context); widget.onConfirm( - RewriteRulesData( + RewriteRules( domain: domainController.text, answer: answerController.text ) diff --git a/lib/screens/settings/dns_rewrites/dns_rewrites.dart b/lib/screens/settings/dns_rewrites/dns_rewrites.dart index 203c068..d2ec726 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrites.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrites.dart @@ -9,87 +9,43 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/dns_rewrites/add_dns_rewrite_modal.dart'; import 'package:adguard_home_manager/screens/settings/dns_rewrites/delete_dns_rewrite.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/rewrite_rules_provider.dart'; import 'package:adguard_home_manager/models/rewrite_rules.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -class DnsRewrites extends StatelessWidget { - const DnsRewrites({Key? key}) : super(key: key); +class DnsRewritesScreen extends StatefulWidget { + const DnsRewritesScreen({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return DnsRewritesWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _DnsRewritesScreenState(); } -class DnsRewritesWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const DnsRewritesWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _DnsRewritesWidgetState(); -} - -class _DnsRewritesWidgetState extends State { - Future fetchData() async { - widget.serversProvider.setRewriteRulesLoadStatus(0, false); - - final result = await getDnsRewriteRules(server: widget.serversProvider.selectedServer!); - - if (result['result'] == 'success') { - widget.serversProvider.setRewriteRulesData(result['data']); - widget.serversProvider.setRewriteRulesLoadStatus(1, true); - } - else { - widget.appConfigProvider.addLog(result['log']); - widget.serversProvider.setRewriteRulesLoadStatus(2, true); - } - } - +class _DnsRewritesScreenState extends State { @override void initState() { - fetchData(); + Provider.of(context, listen: false).fetchRules(); super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final rewriteRulesProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; - void deleteDnsRewrite(RewriteRulesData rule) async { + void deleteDnsRewrite(RewriteRules rule) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.deleting); - final result = await deleteDnsRewriteRule(server: serversProvider.selectedServer!, data: { - "domain": rule.domain, - "answer": rule.answer - }); + final result = await rewriteRulesProvider.deleteDnsRewrite(rule); processModal.close(); - if (result['result'] == 'success') { - List data = serversProvider.rewriteRules.data!; - data = data.where((item) => item.domain != rule.domain).toList(); - serversProvider.setRewriteRulesData(data); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleDeleted, @@ -97,7 +53,6 @@ class _DnsRewritesWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotDeleted, @@ -106,22 +61,15 @@ class _DnsRewritesWidgetState extends State { } } - void addDnsRewrite(RewriteRulesData rule) async { + void addDnsRewrite(RewriteRules rule) async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.addingRewrite); - final result = await addDnsRewriteRule(server: serversProvider.selectedServer!, data: { - "domain": rule.domain, - "answer": rule.answer - }); + final result = await rewriteRulesProvider.addDnsRewrite(rule); processModal.close(); - if (result['result'] == 'success') { - List data = serversProvider.rewriteRules.data!; - data.add(rule); - serversProvider.setRewriteRulesData(data); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleAdded, @@ -129,7 +77,6 @@ class _DnsRewritesWidgetState extends State { ); } else { - appConfigProvider.addLog(result['log']); showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.dnsRewriteRuleNotAdded, @@ -139,8 +86,8 @@ class _DnsRewritesWidgetState extends State { } Widget generateBody() { - switch (serversProvider.rewriteRules.loadStatus) { - case 0: + switch (rewriteRulesProvider.loadStatus) { + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -160,15 +107,22 @@ class _DnsRewritesWidgetState extends State { ), ); - case 1: - if (serversProvider.rewriteRules.data!.isNotEmpty) { + case LoadStatus.loaded: + if (rewriteRulesProvider.rewriteRules!.isNotEmpty) { return RefreshIndicator( onRefresh: () async { - await fetchData(); + final result = await rewriteRulesProvider.fetchRules(); + if (result == false) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.rewriteRulesNotLoaded, + color: Colors.red + ); + } }, child: ListView.builder( padding: const EdgeInsets.only(top: 0), - itemCount: serversProvider.rewriteRules.data!.length, + itemCount: rewriteRulesProvider.rewriteRules!.length, itemBuilder: (context, index) => Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10), decoration: BoxDecoration( @@ -195,7 +149,7 @@ class _DnsRewritesWidgetState extends State { ), ), Text( - serversProvider.rewriteRules.data![index].domain, + rewriteRulesProvider.rewriteRules![index].domain, style: TextStyle( color: Theme.of(context).colorScheme.onSurface ), @@ -213,7 +167,7 @@ class _DnsRewritesWidgetState extends State { ), ), Text( - serversProvider.rewriteRules.data![index].answer, + rewriteRulesProvider.rewriteRules![index].answer, style: TextStyle( color: Theme.of(context).colorScheme.onSurface ), @@ -227,7 +181,7 @@ class _DnsRewritesWidgetState extends State { showDialog( context: context, builder: (context) => DeleteDnsRewrite( - onConfirm: () => deleteDnsRewrite(serversProvider.rewriteRules.data![index]) + onConfirm: () => deleteDnsRewrite(rewriteRulesProvider.rewriteRules![index]) ) ) }, @@ -251,7 +205,7 @@ class _DnsRewritesWidgetState extends State { ); } - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/settings/encryption/encryption.dart b/lib/screens/settings/encryption/encryption.dart index b99efd7..1282279 100644 --- a/lib/screens/settings/encryption/encryption.dart +++ b/lib/screens/settings/encryption/encryption.dart @@ -16,7 +16,6 @@ import 'package:adguard_home_manager/screens/settings/encryption/error_message.d import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/base64.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -98,7 +97,7 @@ class _EncryptionSettingsWidgetState extends State { void fetchData({bool? showRefreshIndicator}) async { setState(() => loadStatus = 0); - final result = await getEncryptionSettings(server: widget.serversProvider.selectedServer!); + final result = await Provider.of(context, listen: false).apiClient!.getEncryptionSettings(); if (mounted) { if (result['result'] == 'success') { @@ -141,19 +140,21 @@ class _EncryptionSettingsWidgetState extends State { Future checkValidDataApi({Map? data}) async { setState(() => certKeyValidApi = 0); - final result = await checkEncryptionSettings(server: widget.serversProvider.selectedServer!, data: data ?? { - "enabled": enabled, - "server_name": domainNameController.text, - "force_https": redirectHttps, - "port_https": httpsPortController.text != '' ? int.parse(httpsPortController.text) : null, - "port_dns_over_tls": tlsPortController.text != '' ? int.parse(tlsPortController.text) : null, - "port_dns_over_quic": dnsOverQuicPortController.text != '' ? int.parse(dnsOverQuicPortController.text) : null, - if (certificateOption == 1) "certificate_chain": encodeBase64(certificateContentController.text), - if (privateKeyOption == 1 && usePreviouslySavedKey == false) "private_key": encodeBase64(pastePrivateKeyController.text), - "private_key_saved": usePreviouslySavedKey, - if (certificateOption == 0) "certificate_path": certificatePathController.text, - if (privateKeyOption == 0) "private_key_path": privateKeyPathController.text, - }); + final result = await Provider.of(context, listen: false).apiClient!.checkEncryptionSettings( + data: data ?? { + "enabled": enabled, + "server_name": domainNameController.text, + "force_https": redirectHttps, + "port_https": httpsPortController.text != '' ? int.parse(httpsPortController.text) : null, + "port_dns_over_tls": tlsPortController.text != '' ? int.parse(tlsPortController.text) : null, + "port_dns_over_quic": dnsOverQuicPortController.text != '' ? int.parse(dnsOverQuicPortController.text) : null, + if (certificateOption == 1) "certificate_chain": encodeBase64(certificateContentController.text), + if (privateKeyOption == 1 && usePreviouslySavedKey == false) "private_key": encodeBase64(pastePrivateKeyController.text), + "private_key_saved": usePreviouslySavedKey, + if (certificateOption == 0) "certificate_path": certificatePathController.text, + if (privateKeyOption == 0) "private_key_path": privateKeyPathController.text, + } + ); if (mounted) { if (result['result'] == 'success') { @@ -224,19 +225,21 @@ class _EncryptionSettingsWidgetState extends State { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingConfig); - final result = await saveEncryptionSettings(server: serversProvider.selectedServer!, data: { - "enabled": enabled, - "server_name": domainNameController.text, - "force_https": redirectHttps, - "port_https": int.tryParse(httpsPortController.text), - "port_dns_over_tls": int.tryParse(tlsPortController.text), - "port_dns_over_quic": int.tryParse(dnsOverQuicPortController.text), - "certificate_chain": encodeBase64(certificateContentController.text), - "private_key": encodeBase64(pastePrivateKeyController.text), - "private_key_saved": usePreviouslySavedKey, - "certificate_path": certificatePathController.text, - "private_key_path": privateKeyPathController.text, - }); + final result = await serversProvider.apiClient!.saveEncryptionSettings( + data: { + "enabled": enabled, + "server_name": domainNameController.text, + "force_https": redirectHttps, + "port_https": int.tryParse(httpsPortController.text), + "port_dns_over_tls": int.tryParse(tlsPortController.text), + "port_dns_over_quic": int.tryParse(dnsOverQuicPortController.text), + "certificate_chain": encodeBase64(certificateContentController.text), + "private_key": encodeBase64(pastePrivateKeyController.text), + "private_key_saved": usePreviouslySavedKey, + "certificate_path": certificatePathController.text, + "private_key_path": privateKeyPathController.text, + } + ); processModal.close(); diff --git a/lib/screens/settings/general_settings.dart b/lib/screens/settings/general_settings.dart index d237d3c..e68aae3 100644 --- a/lib/screens/settings/general_settings.dart +++ b/lib/screens/settings/general_settings.dart @@ -2,20 +2,19 @@ import 'dart:io'; -import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:store_checker/store_checker.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/widgets/section_label.dart'; +import 'package:adguard_home_manager/functions/check_app_updates.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/functions/app_update_download_link.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/functions/compare_versions.dart'; class GeneralSettings extends StatefulWidget { const GeneralSettings({Key? key}) : super(key: key); @@ -56,16 +55,16 @@ class _GeneralSettingsState extends State { Future checkUpdatesAvailable() async { setState(() => appUpdatesStatus = AppUpdatesStatus.checking); - final result = await checkAppUpdatesGitHub(); - if (result['result'] == 'success') { - final update = gitHubUpdateExists(appConfigProvider.getAppInfo!.version, result['body'].tagName); - if (update == true) { - appConfigProvider.setAppUpdatesAvailable(result['body']); - setState(() => appUpdatesStatus = AppUpdatesStatus.available); - } - else { - setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); - } + + final res = await checkAppUpdates( + currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, + setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + installationSource: appConfigProvider.installationSource, + isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), + ); + + if (res != null) { + setState(() => appUpdatesStatus = AppUpdatesStatus.available); } else { setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); diff --git a/lib/screens/settings/safe_search_settings.dart b/lib/screens/settings/safe_search_settings.dart index 7dbbbfc..461b6a6 100644 --- a/lib/screens/settings/safe_search_settings.dart +++ b/lib/screens/settings/safe_search_settings.dart @@ -7,42 +7,19 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/custom_checkbox_list_tile.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; -import 'package:adguard_home_manager/models/server_status.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -class SafeSearchSettingsScreen extends StatelessWidget { +class SafeSearchSettingsScreen extends StatefulWidget { const SafeSearchSettingsScreen({Key? key}) : super(key: key); @override - Widget build(BuildContext context) { - final serversProvider = Provider.of(context); - final appConfigProvider = Provider.of(context); - - return SafeSearchSettingsScreenWidget( - serversProvider: serversProvider, - appConfigProvider: appConfigProvider, - ); - } + State createState() => _SafeSearchSettingsScreenState(); } -class SafeSearchSettingsScreenWidget extends StatefulWidget { - final ServersProvider serversProvider; - final AppConfigProvider appConfigProvider; - - const SafeSearchSettingsScreenWidget({ - Key? key, - required this.serversProvider, - required this.appConfigProvider - }) : super(key: key); - - @override - State createState() => _SafeSearchSettingsScreenWidgetState(); -} - -class _SafeSearchSettingsScreenWidgetState extends State { +class _SafeSearchSettingsScreenState extends State { bool generalEnabled = false; bool bingEnabled = false; bool duckduckgoEnabled = false; @@ -50,85 +27,66 @@ class _SafeSearchSettingsScreenWidgetState extends State(context, listen: false).getServerStatus(); + if (mounted && result == true) { + final statusProvider = Provider.of(context, listen: false); + if (statusProvider.serverStatus != null) { + setState(() { + generalEnabled = statusProvider.serverStatus!.safeSearchEnabled; + bingEnabled = statusProvider.serverStatus!.safeSeachBing ?? false; + duckduckgoEnabled = statusProvider.serverStatus!.safeSearchDuckduckgo ?? false; + googleEnabled = statusProvider.serverStatus!.safeSearchGoogle ?? false; + pixabayEnabled = statusProvider.serverStatus!.safeSearchPixabay ?? false; + yandexEnabled = statusProvider.serverStatus!.safeSearchYandex ?? false; + youtubeEnabled = statusProvider.serverStatus!.safeSearchYoutube ?? false; + }); } } } @override void initState() { - if (widget.serversProvider.serverStatus.loadStatus == 0) { + final statusProvider = Provider.of(context, listen: false); + + if (statusProvider.loadStatus == LoadStatus.loading) { requestSafeSearchSettings(); } - else if (widget.serversProvider.serverStatus.loadStatus == 1) { - generalEnabled = widget.serversProvider.serverStatus.data!.safeSearchEnabled; - bingEnabled = widget.serversProvider.serverStatus.data!.safeSeachBing!; - duckduckgoEnabled = widget.serversProvider.serverStatus.data!.safeSearchDuckduckgo!; - googleEnabled = widget.serversProvider.serverStatus.data!.safeSearchGoogle!; - pixabayEnabled = widget.serversProvider.serverStatus.data!.safeSearchPixabay!; - yandexEnabled = widget.serversProvider.serverStatus.data!.safeSearchYandex!; - youtubeEnabled = widget.serversProvider.serverStatus.data!.safeSearchYoutube!; + else if (statusProvider.loadStatus == LoadStatus.loaded) { + generalEnabled = statusProvider.serverStatus!.safeSearchEnabled; + bingEnabled = statusProvider.serverStatus!.safeSeachBing!; + duckduckgoEnabled = statusProvider.serverStatus!.safeSearchDuckduckgo!; + googleEnabled = statusProvider.serverStatus!.safeSearchGoogle!; + pixabayEnabled = statusProvider.serverStatus!.safeSearchPixabay!; + yandexEnabled = statusProvider.serverStatus!.safeSearchYandex!; + youtubeEnabled = statusProvider.serverStatus!.safeSearchYoutube!; } super.initState(); } @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void saveConfig() async { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingSettings); - final result = await updateSafeSearchSettings( - server: serversProvider.selectedServer!, - body: { - "enabled": generalEnabled, - "bing": bingEnabled, - "duckduckgo": duckduckgoEnabled, - "google": googleEnabled, - "pixabay": pixabayEnabled, - "yandex": yandexEnabled, - "youtube": youtubeEnabled - } - ); + final result = await statusProvider.updateSafeSearchConfig({ + "enabled": generalEnabled, + "bing": bingEnabled, + "duckduckgo": duckduckgoEnabled, + "google": googleEnabled, + "pixabay": pixabayEnabled, + "yandex": yandexEnabled, + "youtube": youtubeEnabled + }); processModal.close(); - if (result['result'] == 'success') { - ServerStatusData data = serversProvider.serverStatus.data!; - data.safeSearchEnabled = generalEnabled; - data.safeSeachBing = bingEnabled; - data.safeSearchDuckduckgo = duckduckgoEnabled; - data.safeSearchGoogle = googleEnabled; - data.safeSearchPixabay = pixabayEnabled; - data.safeSearchYandex = yandexEnabled; - data.safeSearchYoutube = youtubeEnabled; - - serversProvider.setServerStatusData(data); - + if (result == true) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.settingsUpdatedSuccessfully, @@ -137,7 +95,6 @@ class _SafeSearchSettingsScreenWidgetState extends State saveConfig() : null, icon: const Icon(Icons.save_rounded), diff --git a/lib/screens/settings/server_info/server_info.dart b/lib/screens/settings/server_info/server_info.dart index 607e822..35bbd82 100644 --- a/lib/screens/settings/server_info/server_info.dart +++ b/lib/screens/settings/server_info/server_info.dart @@ -1,3 +1,4 @@ +import 'package:adguard_home_manager/constants/enums.dart'; import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -7,7 +8,6 @@ import 'package:adguard_home_manager/screens/settings/server_info/dns_addresses_ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/server_info.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; @@ -41,20 +41,19 @@ class ServerInformationWidget extends StatefulWidget { } class _ServerInformationWidgetState extends State { - ServerInfo serverInfo = ServerInfo(loadStatus: 0); + ServerInfo serverInfo = ServerInfo(loadStatus: LoadStatus.loading); void fetchServerInfo() async { - final result = await getServerInfo(server: widget.serversProvider.selectedServer!); + final result = await Provider.of(context, listen: false).apiClient!.getServerInfo(); if (mounted) { if (result['result'] == 'success') { setState(() { - serverInfo.loadStatus = 1; + serverInfo.loadStatus = LoadStatus.loaded; serverInfo.data = result['data']; }); } else { - widget.appConfigProvider.addLog(result['log']); - setState(() => serverInfo.loadStatus = 2); + setState(() => serverInfo.loadStatus = LoadStatus.loaded); } } } @@ -69,7 +68,7 @@ class _ServerInformationWidgetState extends State { Widget build(BuildContext context) { Widget generateBody() { switch (serverInfo.loadStatus) { - case 0: + case LoadStatus.loading: return SizedBox( width: double.maxFinite, child: Column( @@ -93,7 +92,7 @@ class _ServerInformationWidgetState extends State { ), ); - case 1: + case LoadStatus.loaded: return ListView( children: [ CustomListTile( @@ -145,7 +144,7 @@ class _ServerInformationWidgetState extends State { ] ); - case 2: + case LoadStatus.error: return SizedBox( width: double.maxFinite, child: Column( diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 8565e2f..b0763f6 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -27,6 +27,7 @@ import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/functions/compare_versions.dart'; import 'package:adguard_home_manager/constants/urls.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/servers_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; @@ -67,8 +68,9 @@ class SettingsWidget extends StatelessWidget { @override Widget build(BuildContext context) { - final appConfigProvider = Provider.of(context); final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); + final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -129,10 +131,14 @@ class SettingsWidget extends StatelessWidget { ], body: ListView( children: [ - if (serversProvider.selectedServer != null && serversProvider.serverStatus.data != null) ...[ + if ( + serversProvider.selectedServer != null && + statusProvider.serverStatus != null && + serversProvider.apiClient != null + ) ...[ SectionLabel(label: AppLocalizations.of(context)!.serverSettings), if (serverVersionIsAhead( - currentVersion: serversProvider.serverStatus.data!.serverVersion, + currentVersion: statusProvider.serverStatus!.serverVersion, referenceVersion: 'v0.107.28', referenceVersionBeta: 'v0.108.0-b.33' ) == true) settingsTile( @@ -154,7 +160,7 @@ class SettingsWidget extends StatelessWidget { title: AppLocalizations.of(context)!.dhcpSettings, subtitle: AppLocalizations.of(context)!.dhcpSettingsDescription, thisItem: 2, - screenToNavigate: const Dhcp(), + screenToNavigate: const DhcpScreen(), ), settingsTile( icon: Icons.dns_rounded, @@ -175,7 +181,7 @@ class SettingsWidget extends StatelessWidget { title: AppLocalizations.of(context)!.dnsRewrites, subtitle: AppLocalizations.of(context)!.dnsRewritesDescription, thisItem: 5, - screenToNavigate: const DnsRewrites(), + screenToNavigate: const DnsRewritesScreen(), ), if (serversProvider.updateAvailable.data != null) settingsTile( icon: Icons.system_update_rounded, @@ -217,7 +223,7 @@ class SettingsWidget extends StatelessWidget { icon: Icons.storage_rounded, title: AppLocalizations.of(context)!.servers, subtitle: serversProvider.selectedServer != null - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? "${AppLocalizations.of(context)!.connectedTo} ${serversProvider.selectedServer!.name}" : "${AppLocalizations.of(context)!.selectedServer} ${serversProvider.selectedServer!.name}" : AppLocalizations.of(context)!.noServerSelected, diff --git a/lib/screens/settings/update_server/update.dart b/lib/screens/settings/update_server/update.dart index 5e88a2e..f84e01a 100644 --- a/lib/screens/settings/update_server/update.dart +++ b/lib/screens/settings/update_server/update.dart @@ -10,7 +10,6 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; @@ -36,7 +35,7 @@ class UpdateScreen extends StatelessWidget { ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.requestingUpdate); - final result = await requestUpdateServer(server: serversProvider.selectedServer!); + final result = await serversProvider.apiClient!.requestUpdateServer(); processModal.close(); @@ -56,7 +55,6 @@ class UpdateScreen extends StatelessWidget { color: Colors.red, labelColor: Colors.white, ); - appConfigProvider.addLog(result['log']); } } @@ -92,8 +90,8 @@ class UpdateScreen extends StatelessWidget { child: Column( children: [ serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? Column( - children: const [ + ? const Column( + children: [ CircularProgressIndicator(), SizedBox(height: 4) ], diff --git a/lib/screens/top_items/top_items.dart b/lib/screens/top_items/top_items.dart index 643e8be..6e9af74 100644 --- a/lib/screens/top_items/top_items.dart +++ b/lib/screens/top_items/top_items.dart @@ -12,11 +12,10 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; class TopItemsScreen extends StatefulWidget { final String type; @@ -57,7 +56,7 @@ class _TopItemsScreenState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -130,12 +129,8 @@ class _TopItemsScreenState extends State { ), body: RefreshIndicator( onRefresh: () async { - final result = await getServerStatus(serversProvider.selectedServer!); - if (result['result'] == 'success') { - serversProvider.setServerStatusData(result['data']); - } - else { - appConfigProvider.addLog(result['log']); + final result = await statusProvider.getServerStatus(); + if (result == false) { showSnacbkar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.serverStatusNotRefreshed, @@ -150,7 +145,7 @@ class _TopItemsScreenState extends State { String? name; if (widget.isClient != null && widget.isClient == true) { try { - name = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; } catch (e) { // ---- // } diff --git a/lib/screens/top_items/top_items_modal.dart b/lib/screens/top_items/top_items_modal.dart index 3c98679..845459a 100644 --- a/lib/screens/top_items/top_items_modal.dart +++ b/lib/screens/top_items/top_items_modal.dart @@ -13,8 +13,8 @@ import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/models/applied_filters.dart'; import 'package:adguard_home_manager/providers/logs_provider.dart'; import 'package:adguard_home_manager/functions/number_format.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; class TopItemsModal extends StatefulWidget { final String type; @@ -55,7 +55,7 @@ class _TopItemsModalState extends State { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); @@ -122,7 +122,7 @@ class _TopItemsModalState extends State { String? name; if (widget.isClient != null && widget.isClient == true) { try { - name = serversProvider.serverStatus.data!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; + name = statusProvider.serverStatus!.clients.firstWhere((c) => c.ids.contains(screenData[index].keys.toList()[0])).name; } catch (e) { // ---- // } diff --git a/lib/services/http_requests.dart b/lib/services/http_requests.dart index 35b542f..4d129ae 100644 --- a/lib/services/http_requests.dart +++ b/lib/services/http_requests.dart @@ -23,7 +23,7 @@ import 'package:adguard_home_manager/constants/urls.dart'; Future> apiRequest({ - required Server server, + required Server server, required String method, required String urlPath, dynamic body, @@ -262,81 +262,101 @@ Future loginHA(Server server) async { } } -Future getServerVersion(Server server) async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/status', - type: 'get_server_version' - ); +class ApiClient { + final Server server; - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200 && result['body'] != null) { - return { - 'result': 'success', - 'data': jsonDecode(result['body'])['version'] - }; + ApiClient({ + required this.server + }); + + Future getServerVersion() async { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/status', + type: 'get_server_version' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200 && result['body'] != null) { + return { + 'result': 'success', + 'data': jsonDecode(result['body'])['version'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_version', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_server_version', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } } - else { - return result; - } -} -Future getServerStatus(Server server) async { - final result = await Future.wait([ - apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/filtering/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/safesearch/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/safebrowsing/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/parental/status', type: 'server_status'), - apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'server_status'), - ]); + Future getServerStatus() async { + final result = await Future.wait([ + apiRequest(server: server, method: 'get', urlPath: '/stats', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/filtering/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/safesearch/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/safebrowsing/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/parental/status', type: 'server_status'), + apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'server_status'), + ]); - if ( - result[0]['hasResponse'] == true && - result[1]['hasResponse'] == true && - result[2]['hasResponse'] == true && - result[3]['hasResponse'] == true && - result[4]['hasResponse'] == true && - result[5]['hasResponse'] == true && - result[6]['hasResponse'] == true - ) { if ( - result[0]['statusCode'] == 200 && - result[1]['statusCode'] == 200 && - result[2]['statusCode'] == 200 && - result[3]['statusCode'] == 200 && - result[4]['statusCode'] == 200 && - result[5]['statusCode'] == 200 && - result[6]['statusCode'] == 200 + result[0]['hasResponse'] == true && + result[1]['hasResponse'] == true && + result[2]['hasResponse'] == true && + result[3]['hasResponse'] == true && + result[4]['hasResponse'] == true && + result[5]['hasResponse'] == true && + result[6]['hasResponse'] == true ) { - final Map mappedData = { - 'stats': jsonDecode(result[0]['body']), - 'clients': jsonDecode(result[6]['body'])['clients'], - 'status': jsonDecode(result[1]['body']), - 'filtering': jsonDecode(result[2]['body']), - 'safeSearch': jsonDecode(result[3]['body']), - 'safeBrowsingEnabled': jsonDecode(result[4]['body']), - 'parentalControlEnabled': jsonDecode(result[5]['body']), - }; - return { - 'result': 'success', - 'data': ServerStatusData.fromJson(mappedData) - }; + if ( + result[0]['statusCode'] == 200 && + result[1]['statusCode'] == 200 && + result[2]['statusCode'] == 200 && + result[3]['statusCode'] == 200 && + result[4]['statusCode'] == 200 && + result[5]['statusCode'] == 200 && + result[6]['statusCode'] == 200 + ) { + final Map mappedData = { + 'stats': jsonDecode(result[0]['body']), + 'clients': jsonDecode(result[6]['body'])['clients'], + 'status': jsonDecode(result[1]['body']), + 'filtering': jsonDecode(result[2]['body']), + 'safeSearch': jsonDecode(result[3]['body']), + 'safeBrowsingEnabled': jsonDecode(result[4]['body']), + 'parentalControlEnabled': jsonDecode(result[5]['body']), + }; + return { + 'result': 'success', + 'data': ServerStatus.fromJson(mappedData) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_server_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode']).toString(), + resBody: result.map((res) => res['body']).toString() + ) + }; + } } else { return { @@ -344,259 +364,257 @@ Future getServerStatus(Server server) async { 'log': AppLog( type: 'get_server_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result.map((res) => res['statusCode']).toString(), - resBody: result.map((res) => res['body']).toString() + message: 'no_response', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString() ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_server_status', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString() - ) - }; - } -} -Future updateFiltering({ - required Server server, - required bool enable, -}) async { - final result = await apiRequest( - urlPath: '/filtering/config', - method: 'post', - server: server, - body: { - 'enabled': enable - }, - type: 'update_filtering' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_filtering', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateSafeSearchLegacy(Server server, bool enable) async { - final result = enable == true - ? await apiRequest( - urlPath: '/safesearch/enable', - method: 'post', - server: server, - type: 'enable_safe_search' - ) - : await apiRequest( - urlPath: '/safesearch/disable', - method: 'post', - server: server, - type: 'disable_safe_search' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'safe_search', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateSafeBrowsing(Server server, bool enable) async { - final result = enable == true - ? await apiRequest( - urlPath: '/safebrowsing/enable', - method: 'post', - server: server, - type: 'enable_safe_browsing' - ) - : await apiRequest( - urlPath: '/safebrowsing/disable', - method: 'post', - server: server, - type: 'disable_safe_browsing' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'safe_browsing', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateParentalControl(Server server, bool enable) async { - final result = enable == true - ? await apiRequest( - urlPath: '/parental/enable', - method: 'post', - server: server, - type: 'enable_parental_control' - ) - : await apiRequest( - urlPath: '/parental/disable', - method: 'post', - server: server, - type: 'disable_parental_control' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'parental_control', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateGeneralProtection({ - required Server server, - required bool enable, - int? time -}) async { + Future updateFiltering({ + required bool enable, + }) async { final result = await apiRequest( - urlPath: '/protection', - method: 'post', - server: server, - body: { - 'enabled': enable, - 'duration': time - }, - type: 'general_protection' - ); + urlPath: '/filtering/config', + method: 'post', + server: server, + body: { + 'enabled': enable + }, + type: 'update_filtering' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_filtering', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'general_protection', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } } - else { - return result; - } -} -Future updateGeneralProtectionLegacy(Server server, bool enable) async { - final result = await apiRequest( - urlPath: '/dns_config', - method: 'post', - server: server, - body: { - 'protection_enabled': enable - }, - type: 'general_protection' - ); + Future updateSafeSearchLegacy(bool enable) async { + final result = enable == true + ? await apiRequest( + urlPath: '/safesearch/enable', + method: 'post', + server: server, + type: 'enable_safe_search' + ) + : await apiRequest( + urlPath: '/safesearch/disable', + method: 'post', + server: server, + type: 'disable_safe_search' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'safe_search', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'general_protection', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; + return result; } } - else { - return result; + + Future updateSafeBrowsing(bool enable) async { + final result = enable == true + ? await apiRequest( + urlPath: '/safebrowsing/enable', + method: 'post', + server: server, + type: 'enable_safe_browsing' + ) + : await apiRequest( + urlPath: '/safebrowsing/disable', + method: 'post', + server: server, + type: 'disable_safe_browsing' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'safe_browsing', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } } -} -Future getClients(Server server) async { - final result = await Future.wait([ - apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'get_clients'), - apiRequest(server: server, method: 'get', urlPath: '/access/list', type: 'get_clients'), - ]); + Future updateParentalControl(bool enable) async { + final result = enable == true + ? await apiRequest( + urlPath: '/parental/enable', + method: 'post', + server: server, + type: 'enable_parental_control' + ) + : await apiRequest( + urlPath: '/parental/disable', + method: 'post', + server: server, + type: 'disable_parental_control' + ); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - final clients = ClientsData.fromJson(jsonDecode(result[0]['body'])); - clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(result[1]['body'])); - return { - 'result': 'success', - 'data': clients - }; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'parental_control', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future updateGeneralProtection({ + required bool enable, + int? time + }) async { + final result = await apiRequest( + urlPath: '/protection', + method: 'post', + server: server, + body: { + 'enabled': enable, + 'duration': time + }, + type: 'general_protection' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'general_protection', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future updateGeneralProtectionLegacy(bool enable) async { + final result = await apiRequest( + urlPath: '/dns_config', + method: 'post', + server: server, + body: { + 'protection_enabled': enable + }, + type: 'general_protection' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'general_protection', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getClients() async { + final result = await Future.wait([ + apiRequest(server: server, method: 'get', urlPath: '/clients', type: 'get_clients'), + apiRequest(server: server, method: 'get', urlPath: '/access/list', type: 'get_clients'), + ]); + + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + final clients = Clients.fromJson(jsonDecode(result[0]['body'])); + clients.clientsAllowedBlocked = ClientsAllowedBlocked.fromJson(jsonDecode(result[1]['body'])); + return { + 'result': 'success', + 'data': clients + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_clients', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -604,304 +622,295 @@ Future getClients(Server server) async { 'log': AppLog( type: 'get_clients', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: 'no_response', statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_clients', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } -} -Future requestAllowedBlockedClientsHosts(Server server, Map?> body) async { - final result = await apiRequest( - urlPath: '/access/set', - method: 'post', - server: server, - body: body, - type: 'get_clients' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - if (result['statusCode'] == 400) { - return { - 'result': 'error', - 'message': 'client_another_list' - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_clients', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future getLogs({ - required Server server, - required int count, - int? offset, - DateTime? olderThan, - String? responseStatus, - String? search -}) async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', - type: 'get_logs' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': LogsData.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_logs', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future getFilteringRules({ - required Server server, -}) async { - final result = await apiRequest( - server: server, - method: 'get', - urlPath: '/filtering/status', - type: 'get_filtering_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': FilteringStatus.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future postFilteringRules({ - required Server server, - required Map> data, -}) async { + Future requestAllowedBlockedClientsHosts(Map?> body) async { final result = await apiRequest( - urlPath: '/filtering/set_rules', - method: 'post', - server: server, - body: data, - type: 'post_filering_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'post_filtering_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future postAddClient({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/clients/add', - method: 'post', - server: server, - body: data, - type: 'add_client' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'add_client', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future postUpdateClient({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/clients/update', - method: 'post', - server: server, - body: data, - type: 'update_client' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_client', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future postDeleteClient({ - required Server server, - required String name, -}) async { - final result = await apiRequest( - urlPath: '/clients/delete', - method: 'post', - server: server, - body: {'name': name}, - type: 'remove_client' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'remove_client', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future getFiltering({ - required Server server, -}) async { - final result = await Future.wait([ - apiRequest( - urlPath: '/filtering/status', - method: 'get', + urlPath: '/access/set', + method: 'post', server: server, - type: 'get_filtering_status' - ), - apiRequest( - urlPath: '/blocked_services/list', - method: 'get', - server: server, - type: 'get_filtering_status' - ), - ]); + body: body, + type: 'get_clients' + ); - if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { - return { - 'result': 'success', - 'data': FilteringData.fromJson({ - ...jsonDecode(result[0]['body']), - "blocked_services": result[1]['body'] != null - ? jsonDecode(result[1]['body']) - : [] - }) - }; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + if (result['statusCode'] == 400) { + return { + 'result': 'error', + 'message': 'client_another_list' + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_clients', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getLogs({ + required int count, + int? offset, + DateTime? olderThan, + String? responseStatus, + String? search + }) async { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/querylog?limit=$count${offset != null ? '&offset=$offset' : ''}${olderThan != null ? '&older_than=${olderThan.toIso8601String()}' : ''}${responseStatus != null ? '&response_status=$responseStatus' : ''}${search != null ? '&search=$search' : ''}', + type: 'get_logs' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': LogsData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_logs', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getFilteringRules() async { + final result = await apiRequest( + server: server, + method: 'get', + urlPath: '/filtering/status', + type: 'get_filtering_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': FilteringStatus.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future postFilteringRules({ + required Map> data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/set_rules', + method: 'post', + server: server, + body: data, + type: 'post_filering_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'post_filtering_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future postAddClient({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/clients/add', + method: 'post', + server: server, + body: data, + type: 'add_client' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'add_client', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future postUpdateClient({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/clients/update', + method: 'post', + server: server, + body: data, + type: 'update_client' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_client', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future postDeleteClient({ + required String name, + }) async { + final result = await apiRequest( + urlPath: '/clients/delete', + method: 'post', + server: server, + body: {'name': name}, + type: 'remove_client' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'remove_client', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getFiltering() async { + final result = await Future.wait([ + apiRequest( + urlPath: '/filtering/status', + method: 'get', + server: server, + type: 'get_filtering_status' + ), + apiRequest( + urlPath: '/blocked_services/list', + method: 'get', + server: server, + type: 'get_filtering_status' + ), + ]); + + if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { + return { + 'result': 'success', + 'data': Filtering.fromJson({ + ...jsonDecode(result[0]['body']), + "blocked_services": result[1]['body'] != null + ? jsonDecode(result[1]['body']) + : [] + }) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -909,230 +918,222 @@ Future getFiltering({ 'log': AppLog( type: 'get_filtering_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: 'no_response', statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_status', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } -} -Future setCustomRules({ - required Server server, - required List rules, -}) async { - final result = await apiRequest( - urlPath: '/filtering/set_rules', - method: 'post', - server: server, - body: {'rules': rules}, - type: 'set_custom_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'set_custom_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } - -} - -Future addFilteringList({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/filtering/add_url', - method: 'post', - server: server, - body: data, - type: 'add_filtering_url' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': result['body'] - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'add_filtering_url', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateFilterList({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/filtering/set_url', - method: 'post', - server: server, - body: data, - type: 'update_filter_list' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_filter_list', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future deleteFilterList({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/filtering/remove_url', - method: 'post', - server: server, - body: data, - type: 'delete_filter_list' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'delete_filter_list', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future getServerInfo({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/status', - method: 'get', - server: server, - type: 'server_info' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': ServerInfoData.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'server_info', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'] - ) - }; - } - } - else { - return result; - } -} - -Future updateLists({ - required Server server, -}) async { - final result = await Future.wait([ - apiRequest( - urlPath: '/filtering/refresh', + Future setCustomRules({ + required List rules, + }) async { + final result = await apiRequest( + urlPath: '/filtering/set_rules', method: 'post', server: server, - body: {'whitelist': true}, - type: 'update_lists', - overrideTimeout: true - ), - apiRequest( - urlPath: '/filtering/refresh', + body: {'rules': rules}, + type: 'set_custom_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'set_custom_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + + } + + Future addFilteringList({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/add_url', method: 'post', server: server, - body: {'whitelist': false}, - type: 'update_lists', - overrideTimeout: true - ), - ]); + body: data, + type: 'add_filtering_url' + ); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - return { - 'result': 'success', - 'data': {'updated': jsonDecode(result[0]['body'])['updated']+jsonDecode(result[1]['body'])['updated']} - }; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': result['body'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'add_filtering_url', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future updateFilterList({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/set_url', + method: 'post', + server: server, + body: data, + type: 'update_filter_list' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_filter_list', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future deleteFilterList({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/remove_url', + method: 'post', + server: server, + body: data, + type: 'delete_filter_list' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'delete_filter_list', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future getServerInfo() async { + final result = await apiRequest( + urlPath: '/status', + method: 'get', + server: server, + type: 'server_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': ServerInfoData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'server_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'] + ) + }; + } + } + else { + return result; + } + } + + Future updateLists() async { + final result = await Future.wait([ + apiRequest( + urlPath: '/filtering/refresh', + method: 'post', + server: server, + body: {'whitelist': true}, + type: 'update_lists', + overrideTimeout: true + ), + apiRequest( + urlPath: '/filtering/refresh', + method: 'post', + server: server, + body: {'whitelist': false}, + type: 'update_lists', + overrideTimeout: true + ), + ]); + + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + return { + 'result': 'success', + 'data': {'updated': jsonDecode(result[0]['body'])['updated']+jsonDecode(result[1]['body'])['updated']} + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_lists', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { @@ -1140,920 +1141,1070 @@ Future updateLists({ 'log': AppLog( type: 'update_lists', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: [result[0]['message'], result[1]['message']].toString(), statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_lists', - dateTime: DateTime.now(), - message: [result[0]['message'], result[1]['message']].toString(), - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } -} -Future checkHostFiltered({ - required Server server, - required String host, -}) async { - final result = await apiRequest( - urlPath: '/filtering/check_host?name=$host', - method: 'get', - server: server, - type: 'check_host_filtered' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': jsonDecode(result['body']) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_lists', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future requestChangeUpdateFrequency({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/filtering/config', - method: 'post', - server: server, - body: data, - type: 'change_update_frequency' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'change_update_frequency', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future setBlockedServices({ - required Server server, - required List data, -}) async { - final result = await apiRequest( - urlPath: '/blocked_services/set', - method: 'post', - server: server, - body: data, - type: 'update_blocked_services' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_blocked_services', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getDhcpData({ - required Server server, -}) async { - final result = await Future.wait([ - apiRequest( - urlPath: '/dhcp/interfaces', + Future checkHostFiltered({ + required String host, + }) async { + final result = await apiRequest( + urlPath: '/filtering/check_host?name=$host', method: 'get', server: server, - type: 'get_dhcp_data' - ), - apiRequest( - urlPath: '/dhcp/status', - method: 'get', + type: 'check_host_filtered' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_lists', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future requestChangeUpdateFrequency({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/filtering/config', + method: 'post', server: server, - type: 'get_dhcp_data' - ), - ]); + body: data, + type: 'change_update_frequency' + ); - if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { - List interfaces = List.from(jsonDecode(result[0]['body']).entries.map((entry) => NetworkInterface.fromJson(entry.value))); + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'change_update_frequency', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } - return { - 'result': 'success', - 'data': DhcpData( - networkInterfaces: interfaces, - dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) - ) - }; + Future setBlockedServices({ + required List data, + }) async { + final result = await apiRequest( + urlPath: '/blocked_services/set', + method: 'post', + server: server, + body: data, + type: 'update_blocked_services' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_blocked_services', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getDhcpData() async { + final result = await Future.wait([ + apiRequest( + urlPath: '/dhcp/interfaces', + method: 'get', + server: server, + type: 'get_dhcp_data' + ), + apiRequest( + urlPath: '/dhcp/status', + method: 'get', + server: server, + type: 'get_dhcp_data' + ), + ]); + + if (result[0]['hasResponse'] == true && result[1]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[1]['statusCode'] == 200) { + List interfaces = List.from(jsonDecode(result[0]['body']).entries.map((entry) => NetworkInterface.fromJson(entry.value))); + + return { + 'result': 'success', + 'data': DhcpModel( + networkInterfaces: interfaces, + dhcpStatus: DhcpStatus.fromJson(jsonDecode(result[1]['body'])) + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_dhcp_data', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { 'result': 'error', 'log': AppLog( - type: 'get_dhcp_data', + type: 'get_dhpc_data', dateTime: DateTime.now(), - message: 'error_code_not_expected', + message: [result[0]['log'].message, result[1]['log'].message].toString(), statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_dhpc_data', - dateTime: DateTime.now(), - message: [result[0]['log'].message, result[1]['log'].message].toString(), - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; + + Future saveDhcpConfig({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/dhcp/set_config', + method: 'post', + server: server, + body: data, + type: 'save_dhcp_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'save_dhcp_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } } -} -Future saveDhcpConfig({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/dhcp/set_config', - method: 'post', - server: server, - body: data, - type: 'save_dhcp_config' - ); + Future resetDhcpConfig() async { + final result = await apiRequest( + urlPath: '/dhcp/reset', + method: 'post', + server: server, + body: {}, + type: 'reset_dhcp_config' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'reset_dhcp_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future deleteStaticLease({ + required Map data + }) async { + final result = await apiRequest( + urlPath: '/dhcp/remove_static_lease', + method: 'post', + server: server, + body: data, + type: 'remove_static_lease' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'remove_static_lease', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future createStaticLease({ + required Map data + }) async { + final result = await apiRequest( + urlPath: '/dhcp/add_static_lease', + method: 'post', + server: server, + body: data, + type: 'add_static_lease' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else if (result['statusCode'] == 400 && result['body'].contains('static lease already exists')) { + return { + 'result': 'error', + 'message': 'already_exists', + 'log': AppLog( + type: 'add_static_lease', + dateTime: DateTime.now(), + message: 'already_exists', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + else if (result['statusCode'] == 400 && result['body'].contains('server is unconfigured')) { + return { + 'result': 'error', + 'message': 'server_not_configured', + 'log': AppLog( + type: 'add_static_lease', + dateTime: DateTime.now(), + message: 'server_not_configured', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'add_static_lease', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future restoreAllLeases() async { + final result = await apiRequest( + urlPath: '/dhcp/reset_leases', + method: 'post', + server: server, + body: {}, + type: 'restore_all_leases' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return {'result': 'success'}; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'restore_all_leases', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getDnsRewriteRules() async { + final result = await apiRequest( + urlPath: '/rewrite/list', + method: 'get', + server: server, + type: 'get_dns_rewrite_rules' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + final List data = List.from( + jsonDecode(result['body']).map((item) => RewriteRules.fromJson(item)) + ); + + return { + 'result': 'success', + 'data': data + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_dns_rewrite_rules', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future deleteDnsRewriteRule({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/rewrite/delete', + method: 'post', + server: server, + body: data, + type: 'delete_dns_rewrite_rule' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'delete_dns_rewrite_rule', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future addDnsRewriteRule({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/rewrite/add', + method: 'post', + server: server, + body: data, + type: 'add_dns_rewrite_rule' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'add_dns_rewrite_rule', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getQueryLogInfo() async { + final result = await apiRequest( + urlPath: '/querylog/config', + method: 'get', + server: server, + type: 'get_query_log_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_query_log_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getQueryLogInfoLegacy() async { + final result = await apiRequest( + urlPath: '/querylog_info', + method: 'get', + server: server, + type: 'get_query_log_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_query_log_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future updateQueryLogParameters({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/querylog/config/update', + method: 'put', + server: server, + body: data, + type: 'update_query_log_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_query_log_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future updateQueryLogParametersLegacy({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/querylog_config', + method: 'post', + server: server, + body: data, + type: 'update_query_log_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_query_log_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future clearLogs() async { + final result = await apiRequest( + urlPath: '/querylog_clear', + method: 'post', + server: server, + body: {}, + type: 'clear_query_logs' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'clear_query_logs', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getDnsInfo() async { + final result = await apiRequest( + urlPath: '/dns_info', + method: 'get', + server: server, + type: 'get_dns_info' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success' , + 'data': DnsInfo.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_dns_info', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future setDnsConfig({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/dns_config', + method: 'post', + server: server, + body: data, + type: 'set_dns_config' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + if (result['statusCode'] == 400) { + return { + 'result': 'error', + 'log': AppLog( + type: 'set_dns_config', + dateTime: DateTime.now(), + message: 'data_not_valid', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'set_dns_config', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getEncryptionSettings() async { + final result = await apiRequest( + urlPath: '/tls/status', + method: 'get', + server: server, + type: 'get_encryption_settings' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': EncryptionData.fromJson(jsonDecode(result['body'])) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future getBlockedServices() async { + final result = await apiRequest( + urlPath: '/blocked_services/all', + method: 'get', + server: server, + type: 'get_blocked_services' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': List.from( + BlockedServicesFromApi.fromJson(jsonDecode(result['body'])).blockedServices + ) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future checkEncryptionSettings({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/tls/validate', + method: 'post', + server: server, + body: data, + type: 'check_encryption_settings' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { + 'result': 'success', + 'data': jsonDecode(result['body']) + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'check_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future saveEncryptionSettings({ + required Map data, + }) async { + final result = await apiRequest( + urlPath: '/tls/configure', + method: 'post', + server: server, + body: data, + type: 'update_encryption_settings' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future resetDnsCache() async { + final result = await apiRequest( + urlPath: '/cache_clear', + method: 'post', + server: server, + type: 'clear_dns_cache' + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'clear_dns_cache', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } + } + else { + return result; + } + } + + Future checkServerUpdates() async { + final result = await Future.wait([ + apiRequest( + urlPath: '/version.json', + method: 'get', + server: server, + type: 'check_server_updates', + body: json.encode({ + "recheck_now": true + }) + ), + apiRequest( + urlPath: '/status', + method: 'get', + server: server, + type: 'check_server_updates', + body: json.encode({ + "recheck_now": true + }) + ), + ]); + + if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { + if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { + final Map obj = { + ...jsonDecode(result[0]['body']), + 'current_version': jsonDecode(result[1]['body'])['version'] + }; + return { + 'result': 'success', + 'data': obj + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'get_filtering_status', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), + ) + }; + } } else { return { 'result': 'error', 'log': AppLog( - type: 'save_dhcp_config', + type: 'get_filtering_status', dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], + message: 'no_response', + statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), + resBody: result.map((res) => res['body'] ?? 'null').toString(), ) }; } } - else { - return result; + + Future getUpdateChangelog({ + required String releaseTag + }) async { + try { + HttpClient httpClient = HttpClient(); + HttpClientRequest request = await httpClient.getUrl(Uri.parse("${Urls.adGuardHomeReleasesTags}/$releaseTag")); + HttpClientResponse response = await request.close(); + String reply = await response.transform(utf8.decoder).join(); + httpClient.close(); + if (response.statusCode == 200) { + return { + 'result': 'success', + 'hasResponse': true, + 'error': false, + 'statusCode': response.statusCode, + 'body': jsonDecode(reply)['body'] + }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_encryption_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: response.statusCode.toString(), + resBody: reply, + ) + }; + } + } on SocketException { + return { + 'result': 'no_connection', + 'message': 'SocketException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'SocketException' + ) + }; + } on TimeoutException { + return { + 'result': 'no_connection', + 'message': 'TimeoutException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'TimeoutException' + ) + }; + } on HandshakeException { + return { + 'result': 'ssl_error', + 'message': 'HandshakeException', + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: 'HandshakeException' + ) + }; + } catch (e) { + return { + 'result': 'error', + 'message': e.toString(), + 'log': AppLog( + type: 'check_latest_release_github', + dateTime: DateTime.now(), + message: e.toString() + ) + }; + } } -} -Future resetDhcpConfig({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/dhcp/reset', - method: 'post', - server: server, - body: {}, - type: 'reset_dhcp_config' - ); + Future requestUpdateServer() async { + final result = await apiRequest( + urlPath: '/update', + method: 'post', + server: server, + type: 'update_server' + ); - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'update_server', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'reset_dhcp_config', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; + return result; } } - else { - return result; - } -} -Future deleteStaticLease({ - required Server server, - required Map data -}) async { - final result = await apiRequest( - urlPath: '/dhcp/remove_static_lease', - method: 'post', - server: server, - body: data, - type: 'remove_static_lease' - ); + Future updateSafeSearchSettings({ - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; + required Map body + }) async { + final result = await apiRequest( + urlPath: '/safesearch/settings', + method: 'put', + server: server, + type: 'safesearch_settings', + body: body + ); + + if (result['hasResponse'] == true) { + if (result['statusCode'] == 200) { + return { 'result': 'success' }; + } + else { + return { + 'result': 'error', + 'log': AppLog( + type: 'safesearch_settings', + dateTime: DateTime.now(), + message: 'error_code_not_expected', + statusCode: result['statusCode'].toString(), + resBody: result['body'], + ) + }; + } } else { - return { - 'result': 'error', - 'log': AppLog( - type: 'remove_static_lease', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; + return result; } } - else { - return result; - } -} - -Future createStaticLease({ - required Server server, - required Map data -}) async { - final result = await apiRequest( - urlPath: '/dhcp/add_static_lease', - method: 'post', - server: server, - body: data, - type: 'add_static_lease' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else if (result['statusCode'] == 400 && result['body'].contains('static lease already exists')) { - return { - 'result': 'error', - 'message': 'already_exists', - 'log': AppLog( - type: 'add_static_lease', - dateTime: DateTime.now(), - message: 'already_exists', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - else if (result['statusCode'] == 400 && result['body'].contains('server is unconfigured')) { - return { - 'result': 'error', - 'message': 'server_not_configured', - 'log': AppLog( - type: 'add_static_lease', - dateTime: DateTime.now(), - message: 'server_not_configured', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'add_static_lease', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future restoreAllLeases({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/dhcp/reset_leases', - method: 'post', - server: server, - body: {}, - type: 'restore_all_leases' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return {'result': 'success'}; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'restore_all_leases', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getDnsRewriteRules({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/rewrite/list', - method: 'get', - server: server, - type: 'get_dns_rewrite_rules' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - final List data = List.from( - jsonDecode(result['body']).map((item) => RewriteRulesData.fromJson(item)) - ); - - return { - 'result': 'success', - 'data': data - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_dns_rewrite_rules', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future deleteDnsRewriteRule({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/rewrite/delete', - method: 'post', - server: server, - body: data, - type: 'delete_dns_rewrite_rule' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'delete_dns_rewrite_rule', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future addDnsRewriteRule({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/rewrite/add', - method: 'post', - server: server, - body: data, - type: 'add_dns_rewrite_rule' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'add_dns_rewrite_rule', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getQueryLogInfo({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/querylog/config', - method: 'get', - server: server, - type: 'get_query_log_info' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': jsonDecode(result['body']) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_query_log_info', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getQueryLogInfoLegacy({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/querylog_info', - method: 'get', - server: server, - type: 'get_query_log_info' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': jsonDecode(result['body']) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_query_log_info', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future updateQueryLogParameters({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/querylog/config/update', - method: 'put', - server: server, - body: data, - type: 'update_query_log_config' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_query_log_config', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future updateQueryLogParametersLegacy({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/querylog_config', - method: 'post', - server: server, - body: data, - type: 'update_query_log_config' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_query_log_config', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future clearLogs({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/querylog_clear', - method: 'post', - server: server, - body: {}, - type: 'clear_query_logs' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'clear_query_logs', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getDnsInfo({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/dns_info', - method: 'get', - server: server, - type: 'get_dns_info' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success' , - 'data': DnsInfoData.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_dns_info', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future setDnsConfig({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/dns_config', - method: 'post', - server: server, - body: data, - type: 'set_dns_config' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - if (result['statusCode'] == 400) { - return { - 'result': 'error', - 'log': AppLog( - type: 'set_dns_config', - dateTime: DateTime.now(), - message: 'data_not_valid', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'set_dns_config', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getEncryptionSettings({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/tls/status', - method: 'get', - server: server, - type: 'get_encryption_settings' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': EncryptionData.fromJson(jsonDecode(result['body'])) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future getBlockedServices({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/blocked_services/all', - method: 'get', - server: server, - type: 'get_blocked_services' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': List.from( - BlockedServicesFromApi.fromJson(jsonDecode(result['body'])).blockedServices - ) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future checkEncryptionSettings({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/tls/validate', - method: 'post', - server: server, - body: data, - type: 'check_encryption_settings' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { - 'result': 'success', - 'data': jsonDecode(result['body']) - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'check_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future saveEncryptionSettings({ - required Server server, - required Map data, -}) async { - final result = await apiRequest( - urlPath: '/tls/configure', - method: 'post', - server: server, - body: data, - type: 'update_encryption_settings' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future resetDnsCache({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/cache_clear', - method: 'post', - server: server, - type: 'clear_dns_cache' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'clear_dns_cache', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } } Future checkAppUpdatesGitHub() async { try { HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.checkLatestReleaseUrl)); + HttpClientRequest request = await httpClient.getUrl(Uri.parse(Urls.getReleasesGitHub)); HttpClientResponse response = await request.close(); String reply = await response.transform(utf8.decoder).join(); httpClient.close(); @@ -2063,7 +2214,7 @@ Future checkAppUpdatesGitHub() async { 'hasResponse': true, 'error': false, 'statusCode': response.statusCode, - 'body': GitHubRelease.fromJson(jsonDecode(reply)) + 'body': List.from(jsonDecode(reply).map((entry) => GitHubRelease.fromJson(entry))) }; } else { @@ -2119,206 +2270,4 @@ Future checkAppUpdatesGitHub() async { ) }; } -} - -Future checkServerUpdates({ - required Server server, -}) async { - final result = await Future.wait([ - apiRequest( - urlPath: '/version.json', - method: 'get', - server: server, - type: 'check_server_updates', - body: json.encode({ - "recheck_now": true - }) - ), - apiRequest( - urlPath: '/status', - method: 'get', - server: server, - type: 'check_server_updates', - body: json.encode({ - "recheck_now": true - }) - ), - ]); - - if (result[0]['hasResponse'] == true && result[0]['hasResponse'] == true) { - if (result[0]['statusCode'] == 200 && result[0]['statusCode'] == 200) { - final Map obj = { - ...jsonDecode(result[0]['body']), - 'current_version': jsonDecode(result[1]['body'])['version'] - }; - return { - 'result': 'success', - 'data': obj - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_status', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'get_filtering_status', - dateTime: DateTime.now(), - message: 'no_response', - statusCode: result.map((res) => res['statusCode'] ?? 'null').toString(), - resBody: result.map((res) => res['body'] ?? 'null').toString(), - ) - }; - } -} - -Future getUpdateChangelog({ - required Server server, - required String releaseTag -}) async { - try { - HttpClient httpClient = HttpClient(); - HttpClientRequest request = await httpClient.getUrl(Uri.parse("${Urls.adGuardHomeReleasesTags}/$releaseTag")); - HttpClientResponse response = await request.close(); - String reply = await response.transform(utf8.decoder).join(); - httpClient.close(); - if (response.statusCode == 200) { - return { - 'result': 'success', - 'hasResponse': true, - 'error': false, - 'statusCode': response.statusCode, - 'body': jsonDecode(reply)['body'] - }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_encryption_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: response.statusCode.toString(), - resBody: reply, - ) - }; - } - } on SocketException { - return { - 'result': 'no_connection', - 'message': 'SocketException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'SocketException' - ) - }; - } on TimeoutException { - return { - 'result': 'no_connection', - 'message': 'TimeoutException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'TimeoutException' - ) - }; - } on HandshakeException { - return { - 'result': 'ssl_error', - 'message': 'HandshakeException', - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: 'HandshakeException' - ) - }; - } catch (e) { - return { - 'result': 'error', - 'message': e.toString(), - 'log': AppLog( - type: 'check_latest_release_github', - dateTime: DateTime.now(), - message: e.toString() - ) - }; - } -} - -Future requestUpdateServer({ - required Server server, -}) async { - final result = await apiRequest( - urlPath: '/update', - method: 'post', - server: server, - type: 'update_server' - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'update_server', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } -} - -Future updateSafeSearchSettings({ - required Server server, - required Map body -}) async { - final result = await apiRequest( - urlPath: '/safesearch/settings', - method: 'put', - server: server, - type: 'safesearch_settings', - body: body - ); - - if (result['hasResponse'] == true) { - if (result['statusCode'] == 200) { - return { 'result': 'success' }; - } - else { - return { - 'result': 'error', - 'log': AppLog( - type: 'safesearch_settings', - dateTime: DateTime.now(), - message: 'error_code_not_expected', - statusCode: result['statusCode'].toString(), - resBody: result['body'], - ) - }; - } - } - else { - return result; - } } \ No newline at end of file diff --git a/lib/widgets/add_server_modal.dart b/lib/widgets/add_server_modal.dart index 70ca410..51d8b22 100644 --- a/lib/widgets/add_server_modal.dart +++ b/lib/widgets/add_server_modal.dart @@ -7,6 +7,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/functions/base64.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/app_log.dart'; @@ -217,6 +219,7 @@ class _AddServerModalState extends State { @override Widget build(BuildContext context) { final serversProvider = Provider.of(context, listen: false); + final statusProvider = Provider.of(context, listen: false); final appConfigProvider = Provider.of(context, listen: false); final mediaQuery = MediaQuery.of(context); @@ -257,13 +260,18 @@ class _AddServerModalState extends State { } final serverCreated = await serversProvider.createServer(serverObj); if (serverCreated == null) { - serversProvider.setServerStatusLoad(0); + statusProvider.setServerStatusLoad(LoadStatus.loading); + + final ApiClient apiClient = ApiClient(server: serverObj); - final serverStatus = await getServerStatus(serverObj); + final serverStatus = await apiClient.getServerStatus(); if (serverStatus['result'] == 'success') { - serversProvider.setServerStatusData(serverStatus['data']); - serversProvider.setServerStatusLoad(1); + statusProvider.setServerStatusData( + data: serverStatus['data'] + ); + serversProvider.setApiClient(apiClient); + statusProvider.setServerStatusLoad(LoadStatus.loaded); if (serverStatus['data'].serverVersion.contains('a') || serverStatus['data'].serverVersion.contains('b')) { Navigator.pop(context); widget.onUnsupportedVersion(serverStatus['data'].serverVersion); @@ -274,7 +282,7 @@ class _AddServerModalState extends State { } else { appConfigProvider.addLog(serverStatus['log']); - serversProvider.setServerStatusLoad(2); + statusProvider.setServerStatusLoad(LoadStatus.error); Navigator.pop(context); } } @@ -377,7 +385,8 @@ class _AddServerModalState extends State { final serverSaved = await serversProvider.editServer(serverObj); if (serverSaved == null) { - final version = await getServerVersion(serverObj); + final ApiClient apiClient = ApiClient(server: serverObj); + final version = await apiClient.getServerVersion(); if ( version['result'] == 'success' && (version['data'].contains('a') || version['data'].contains('b')) // alpha or beta diff --git a/lib/widgets/bottom_nav_bar.dart b/lib/widgets/bottom_nav_bar.dart index 36abbbe..8465844 100644 --- a/lib/widgets/bottom_nav_bar.dart +++ b/lib/widgets/bottom_nav_bar.dart @@ -17,11 +17,10 @@ class BottomNavBar extends StatelessWidget { final appConfigProvider = Provider.of(context); final logsProvider = Provider.of(context); - List screens = serversProvider.selectedServer != null + List screens = serversProvider.selectedServer != null && serversProvider.apiClient != null ? screensServerConnected : screensSelectServer; - String translatedName(String key) { switch (key) { case 'home': @@ -47,8 +46,14 @@ class BottomNavBar extends StatelessWidget { } } + if ((serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1) { + appConfigProvider.setSelectedScreen(0); + } + return NavigationBar( - selectedIndex: appConfigProvider.selectedScreen, + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 + ? 0 + : appConfigProvider.selectedScreen, destinations: screens.map((screen) => NavigationDestination( icon: Stack( children: [ diff --git a/lib/widgets/domain_options.dart b/lib/widgets/domain_options.dart index 1612390..58409d9 100644 --- a/lib/widgets/domain_options.dart +++ b/lib/widgets/domain_options.dart @@ -9,11 +9,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/widgets/options_modal.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; +import 'package:adguard_home_manager/functions/snackbar.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; -import 'package:adguard_home_manager/models/filtering_status.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; -import 'package:adguard_home_manager/providers/servers_provider.dart'; -import 'package:adguard_home_manager/services/http_requests.dart'; import 'package:adguard_home_manager/models/menu_option.dart'; class DomainOptions extends StatelessWidget { @@ -36,59 +35,33 @@ class DomainOptions extends StatelessWidget { @override Widget build(BuildContext context) { - final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); void blockUnblock(String domain, String newStatus) async { final ProcessModal processModal = ProcessModal(context: context); processModal.open(AppLocalizations.of(context)!.savingUserFilters); - final rules = await getFilteringRules(server: serversProvider.selectedServer!); + final rules = await statusProvider.blockUnblockDomain( + domain: domain, + newStatus: newStatus + ); - if (rules['result'] == 'success') { - FilteringStatus oldStatus = serversProvider.serverStatus.data!.filteringStatus; + processModal.close(); - List newRules = rules['data'].userRules.where((d) => !d.contains(domain)).toList(); - if (newStatus == 'block') { - newRules.add("||$domain^"); - } - else if (newStatus == 'unblock') { - newRules.add("@@||$domain^"); - } - FilteringStatus newObj = serversProvider.serverStatus.data!.filteringStatus; - newObj.userRules = newRules; - serversProvider.setFilteringStatus(newObj); - - final result = await postFilteringRules(server: serversProvider.selectedServer!, data: {'rules': newRules}); - - processModal.close(); - - if (result['result'] == 'success') { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesUpdated), - backgroundColor: Colors.green, - ) - ); - } - else { - appConfigProvider.addLog(result['log']); - serversProvider.setFilteringStatus(oldStatus); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) - ); - } + if (rules == true) { + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesUpdated, + color: Colors.green + ); } else { - appConfigProvider.addLog(rules['log']); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(AppLocalizations.of(context)!.userFilteringRulesNotUpdated), - backgroundColor: Colors.red, - ) + showSnacbkar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.userFilteringRulesNotUpdated, + color: Colors.red + ); } } diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart index 6dc028f..063993c 100644 --- a/lib/widgets/navigation_rail.dart +++ b/lib/widgets/navigation_rail.dart @@ -46,8 +46,14 @@ class SideNavigationRail extends StatelessWidget { } } + if ((serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1) { + appConfigProvider.setSelectedScreen(0); + } + return NavigationRail( - selectedIndex: appConfigProvider.selectedScreen, + selectedIndex: (serversProvider.selectedServer == null || serversProvider.apiClient == null) && appConfigProvider.selectedScreen > 1 + ? 0 + : appConfigProvider.selectedScreen, destinations: screens.map((screen) => NavigationRailDestination( icon: Icon( screen.icon, diff --git a/lib/widgets/servers_list/servers_list_item.dart b/lib/widgets/servers_list/servers_list_item.dart index 614c2ca..fb3364e 100644 --- a/lib/widgets/servers_list/servers_list_item.dart +++ b/lib/widgets/servers_list/servers_list_item.dart @@ -11,6 +11,8 @@ import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -69,6 +71,7 @@ class _ServersListItemState extends State with SingleTickerProv @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -132,18 +135,22 @@ class _ServersListItemState extends State with SingleTickerProv : await login(server); if (result['result'] == 'success') { + final ApiClient apiClient = ApiClient(server: server); + serversProvider.setApiClient(apiClient); serversProvider.setSelectedServer(server); - serversProvider.setServerStatusLoad(0); - final serverStatus = await getServerStatus(server); + statusProvider.setServerStatusLoad(LoadStatus.loading); + final serverStatus = await apiClient.getServerStatus(); if (serverStatus['result'] == 'success') { - serversProvider.setServerStatusData(serverStatus['data']); + statusProvider.setServerStatusData( + data: serverStatus['data'] + ); serversProvider.checkServerUpdatesAvailable(server); - serversProvider.setServerStatusLoad(1); + statusProvider.setServerStatusLoad(LoadStatus.loaded); } else { appConfigProvider.addLog(serverStatus['log']); - serversProvider.setServerStatusLoad(2); + statusProvider.setServerStatusLoad(LoadStatus.error); } process.close(); @@ -192,7 +199,7 @@ class _ServersListItemState extends State with SingleTickerProv Icon( Icons.storage_rounded, color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? Colors.green : Colors.orange : null, @@ -225,7 +232,7 @@ class _ServersListItemState extends State with SingleTickerProv return Icon( Icons.storage_rounded, color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? Colors.green : Colors.orange : null, @@ -344,7 +351,7 @@ class _ServersListItemState extends State with SingleTickerProv margin: const EdgeInsets.only(right: 12), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( - color: serversProvider.serverStatus.data != null + color: statusProvider.serverStatus != null ? Colors.green : Colors.orange, borderRadius: BorderRadius.circular(30) @@ -352,14 +359,14 @@ class _ServersListItemState extends State with SingleTickerProv child: Row( children: [ Icon( - serversProvider.serverStatus.data != null + statusProvider.serverStatus != null ? Icons.check : Icons.warning, color: Colors.white, ), const SizedBox(width: 10), Text( - serversProvider.serverStatus.data != null + statusProvider.serverStatus != null ? AppLocalizations.of(context)!.connected : AppLocalizations.of(context)!.selectedDisconnected, style: const TextStyle( diff --git a/lib/widgets/servers_list/servers_tile_item.dart b/lib/widgets/servers_list/servers_tile_item.dart index 8145b5e..fd274d6 100644 --- a/lib/widgets/servers_list/servers_tile_item.dart +++ b/lib/widgets/servers_list/servers_tile_item.dart @@ -10,6 +10,8 @@ import 'package:adguard_home_manager/widgets/servers_list/delete_modal.dart'; import 'package:adguard_home_manager/classes/process_modal.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; +import 'package:adguard_home_manager/constants/enums.dart'; +import 'package:adguard_home_manager/providers/status_provider.dart'; import 'package:adguard_home_manager/models/app_log.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; import 'package:adguard_home_manager/services/http_requests.dart'; @@ -36,6 +38,7 @@ class _ServersTileItemState extends State with SingleTickerProv @override Widget build(BuildContext context) { final serversProvider = Provider.of(context); + final statusProvider = Provider.of(context); final appConfigProvider = Provider.of(context); final width = MediaQuery.of(context).size.width; @@ -99,18 +102,22 @@ class _ServersTileItemState extends State with SingleTickerProv : await login(server); if (result['result'] == 'success') { + final ApiClient apiClient = ApiClient(server: server); + serversProvider.setApiClient(apiClient); serversProvider.setSelectedServer(server); - serversProvider.setServerStatusLoad(0); - final serverStatus = await getServerStatus(server); + statusProvider.setServerStatusLoad(LoadStatus.loading); + final serverStatus = await apiClient.getServerStatus(); if (serverStatus['result'] == 'success') { - serversProvider.setServerStatusData(serverStatus['data']); + statusProvider.setServerStatusData( + data: serverStatus['data'] + ); serversProvider.checkServerUpdatesAvailable(server); - serversProvider.setServerStatusLoad(1); + statusProvider.setServerStatusLoad(LoadStatus.loaded); } else { appConfigProvider.addLog(serverStatus['log']); - serversProvider.setServerStatusLoad(2); + statusProvider.setServerStatusLoad(LoadStatus.error); } process.close(); @@ -159,7 +166,7 @@ class _ServersTileItemState extends State with SingleTickerProv Icon( Icons.storage_rounded, color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? Colors.green : Colors.orange : null, @@ -192,7 +199,7 @@ class _ServersTileItemState extends State with SingleTickerProv return Icon( Icons.storage_rounded, color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id - ? serversProvider.serverStatus.data != null + ? statusProvider.serverStatus != null ? Colors.green : Colors.orange : null, @@ -305,13 +312,13 @@ class _ServersTileItemState extends State with SingleTickerProv ), SizedBox( child: serversProvider.selectedServer != null && - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null && + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null && serversProvider.selectedServer?.id == server.id ? Container( margin: const EdgeInsets.only(right: 12), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), decoration: BoxDecoration( - color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + color: serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null ? Colors.green : Colors.orange, borderRadius: BorderRadius.circular(30) @@ -319,14 +326,14 @@ class _ServersTileItemState extends State with SingleTickerProv child: Row( children: [ Icon( - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null ? Icons.check : Icons.warning, color: Colors.white, ), const SizedBox(width: 10), Text( - serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && serversProvider.serverStatus.data != null + serversProvider.selectedServer != null && serversProvider.selectedServer?.id == server.id && statusProvider.serverStatus != null ? AppLocalizations.of(context)!.connected : AppLocalizations.of(context)!.selectedDisconnected, style: const TextStyle( diff --git a/lib/widgets/update_modal.dart b/lib/widgets/update_modal.dart index d8f164f..5b99b66 100644 --- a/lib/widgets/update_modal.dart +++ b/lib/widgets/update_modal.dart @@ -60,7 +60,7 @@ class _UpdateModalState extends State { ), const SizedBox(height: 10), Text( - "${AppLocalizations.of(context)!.newVersion}: ${widget.gitHubRelease.tagName}", + "${AppLocalizations.of(context)!.newVersion}: ${widget.gitHubRelease.name.replaceAll('v', '')}", style: TextStyle( color: Theme.of(context).colorScheme.onSurfaceVariant ), @@ -101,7 +101,9 @@ class _UpdateModalState extends State { ), actions: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: downloadLink != null + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.end, children: [ if (downloadLink != null) TextButton( onPressed: () { diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 5bf52bf..03d00fd 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -421,7 +421,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 61; + CURRENT_PROJECT_VERSION = 63; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -429,7 +429,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.4.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -554,7 +554,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 61; + CURRENT_PROJECT_VERSION = 63; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -562,7 +562,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.4.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager"; @@ -581,7 +581,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 61; + CURRENT_PROJECT_VERSION = 63; DEVELOPMENT_TEAM = 38Z3B9TJTR; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "AdGuard Home Manager"; @@ -589,7 +589,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.4.0; PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.adguard-home-manager"; PRODUCT_COPYRIGHT = "Copyright © 2023 JGeek00. All rights reserved."; PRODUCT_NAME = "AdGuard Home Manager";