diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml new file mode 100644 index 0000000..3ded1c1 --- /dev/null +++ b/.github/workflows/release-beta.yaml @@ -0,0 +1,121 @@ +name: Compile and release beta build + +on: + workflow_dispatch: + +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 + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} + steps: + - uses: actions/checkout@v3 + with: + ref: beta + - 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: Read pubspec.yaml + uses: adore-me/read-yaml@v1.0.0 + id: read_pubspec + with: + file: './pubspec.yaml' + key-path: '["version"]' + - name: Save version on env variable + id: save_version + run: | + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT + - 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_${{ env.VERSION_NAME }}_Android.apk + - name: Rename aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab + - name: Copy apk to project root + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk + - name: Copy aab to project root + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: android + path: | + AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab + AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk + release-builds-github: + name: Release beta build to GitHub + runs-on: ubuntu-latest + needs: [build-android] + env: + VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} + VERSION_NUMBER: ${{ needs.build-android.outputs.VERSION_NUMBER }} + steps: + - uses: actions/checkout@v3 + with: + ref: beta + - 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: '${{ env.VERSION_NAME }}_(${{ env.VERSION_NUMBER }})' + name: v${{ env.VERSION_NAME }} + 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] + env: + VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} + steps: + - uses: actions/checkout@v3 + with: + ref: beta + - 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_${{ env.VERSION_NAME }}_Android.aab + track: beta + status: draft + releaseName: ${{ env.VERSION_NAME }} \ No newline at end of file diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml new file mode 100644 index 0000000..01630ac --- /dev/null +++ b/.github/workflows/release-stable.yaml @@ -0,0 +1,300 @@ +name: Compile and release production build + +on: + workflow_dispatch: + +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 + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} + 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: Read pubspec.yaml + uses: jbutcher5/read-yaml@1.6 + id: read_pubspec + with: + file: './pubspec.yaml' # File to read from + key-path: '["version"]' + - name: Save version on env variable + id: save_version + run: | + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT + - 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_${{ env.VERSION_NAME }}_Android.apk + - name: Rename aab + run: mv $ANDROID_AAB_RELEASE_PATH/app-release.aab $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab + - name: Copy apk to project root + run: cp $ANDROID_APK_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk + - name: Copy aab to project root + run: cp $ANDROID_AAB_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: android + path: | + AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.aab + AdGuardHomeManager_${{ env.VERSION_NAME }}_Android.apk + build-macos: + name: Build macOS .dmg + runs-on: macos-latest + env: + MACOS_APP_RELEASE_PATH: build/macos/Build/Products/Release + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} + steps: + - uses: actions/checkout@v3 + - name: Decode .env + run: echo "${{ secrets.ENV }}" | base64 --decode > .env + - name: Read pubspec.yaml + uses: jbutcher5/read-yaml@1.6 + id: read_pubspec + with: + file: './pubspec.yaml' + key-path: '["version"]' + - name: Save version on env variable + id: save_version + run: | + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT + - uses: subosito/flutter-action@v2 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build macos --release + - name: Install the Apple certificate and sign the application + env: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PWD: ${{ secrets.APPLE_CERTIFICATE_PWD }} + APPLE_KEYCHAIN_PWD: ${{ secrets.APPLE_KEYCHAIN_PWD }} + APPLE_IDENTITY_ID: ${{ secrets.APPLE_IDENTITY_ID }} + run: | + echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12 + security create-keychain -p $APPLE_KEYCHAIN_PWD build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p $APPLE_KEYCHAIN_PWD build.keychain + security import certificate.p12 -k build.keychain -P $APPLE_CERTIFICATE_PWD -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $APPLE_KEYCHAIN_PWD build.keychain + /usr/bin/codesign --force -s "$APPLE_IDENTITY_ID" $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager.app -v + - name: Create folder to build dmg + run: mkdir $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager + - name: Copy app into folder + run: cp -r $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager.app $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager/AdGuard\ Home\ Manager.app + - name: Generate symbolic link to Applications dir + run: ln -s /Applications $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager + - name: Generate dmg + run: hdiutil create -srcfolder $MACOS_APP_RELEASE_PATH/AdGuard\ Home\ Manager $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg + - name: Copy dmg to project root + run: cp $MACOS_APP_RELEASE_PATH/AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: macos + path: AdGuardHomeManager_${{ env.VERSION_NAME }}_macOS_Universal.dmg + build-linux: + name: Build Linux .tar.gz and .deb + runs-on: ubuntu-latest + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} + steps: + - uses: actions/checkout@v3 + - name: Decode .env + run: echo "${{ secrets.ENV }}" | base64 --decode > .env + - name: Read pubspec.yaml + uses: jbutcher5/read-yaml@1.6 + id: read_pubspec + with: + file: './pubspec.yaml' + key-path: '["version"]' + - name: Save version on env variable + id: save_version + run: | + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT + - name: Update version in debian.yaml + run: sed -i 's//${{ env.VERSION_NAME }}/g' debian/debian.yaml + - name: Update dependencies list + run: sudo apt-get update + - name: Install dependencies + run: sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev + - uses: subosito/flutter-action@v2 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build linux --release + - name: Install flutter_to_debian + run: dart pub global activate flutter_to_debian + - name: Generate .deb package + run: flutter_to_debian + - name: Move .deb package to project root + run: mv build/linux/x64/release/debian/AdGuardHomeManager_${{ env.VERSION_NAME }}_amd64.deb AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux_amd64.deb + - name: Generate .tar.gz package + uses: a7ul/tar-action@v1.1.3 + id: compress + with: + command: c + cwd: build/linux/x64/release/bundle + files: | + ./data + ./lib + ./AdGuardHomeManager + outPath: AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux.tar.gz + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: linux + path: | + AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux_amd64.deb + AdGuardHomeManager_${{ env.VERSION_NAME }}_Linux.tar.gz + build-windows: + name: Build Windows installer + runs-on: windows-latest + outputs: + VERSION_NAME: ${{ steps.save_version.outputs.version_name }} + VERSION_NUMBER: ${{ steps.save_version.outputs.version_number }} + steps: + - uses: actions/checkout@v3 + - name: Decode .env + shell: pwsh + run: | + [IO.File]::WriteAllBytes('.env', [Convert]::FromBase64String('${{ secrets.ENV }}')) + - name: Read pubspec.yaml + uses: jbutcher5/read-yaml@1.6 + id: read_pubspec + with: + file: './pubspec.yaml' + key-path: '["version"]' + - name: Save version on env variable + shell: bash + id: save_version + run: | + version=${{ steps.read_pubspec.outputs.data }} + IFS='+' + read -r -a split <<< "$version" + echo "VERSION_NAME=$(echo ${split[0]})" >> $GITHUB_ENV + echo "version_name=${split[0]}" >> $GITHUB_OUTPUT + echo "version_number=${split[1]}" >> $GITHUB_OUTPUT + - name: Update version in innosetup config file + shell: pwsh + run: | + (Get-Content windows/innosetup_installer_builder.iss) -replace '', '${{ env.VERSION_NAME }}' | Out-File -encoding ASCII windows/innosetup_installer_builder.iss + - uses: subosito/flutter-action@v2 + with: + channel: "stable" + - run: flutter clean + - run: flutter pub get + - run: flutter build windows --release + - name: Build installer witn innosetup + run: iscc /Q windows/innosetup_installer_builder.iss + - name: Move installer file to root directory + run: move build/windows/aghm_installer.exe AdGuardHomeManager_${{ env.VERSION_NAME }}_Windows_x64.exe + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: windows + path: AdGuardHomeManager_${{ env.VERSION_NAME }}_Windows_x64.exe + release-builds-github: + name: Release builds to GitHub + runs-on: ubuntu-latest + needs: [build-android, build-macos, build-linux, build-windows] + env: + VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} + VERSION_NUMBER: ${{ needs.build-android.outputs.VERSION_NUMBER }} + 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: Download macOS artifacts + uses: actions/download-artifact@v3 + with: + name: macos + path: releases/ + - name: Download Linux artifacts + uses: actions/download-artifact@v3 + with: + name: linux + path: releases/ + - name: Download Windows artifacts + uses: actions/download-artifact@v3 + with: + name: windows + path: releases/ + - name: Release to GitHub + uses: ncipollo/release-action@v1 + with: + artifacts: "releases/*" + token: ${{ secrets.GH_TOKEN }} + tag: '${{ env.VERSION_NAME }}_(${{ env.VERSION_NUMBER }})' + name: v${{ env.VERSION_NAME }} + draft: true + prerelease: false + commit: ${{ github.sha }} + release-build-google-play: + name: Release Android build to the Google Play Store + runs-on: ubuntu-latest + needs: [build-android, build-macos, build-linux, build-windows] + env: + VERSION_NAME: ${{ needs.build-android.outputs.VERSION_NAME }} + 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_${{ env.VERSION_NAME }}_Android.aab + track: production + status: draft + releaseName: ${{ env.VERSION_NAME }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index e9d1504..6f4a17f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,11 +5,9 @@ *.swp .DS_Store .atom/ -.build/ .buildlog/ .history .svn/ -.swiftpm/ migrate_working_dir/ # Env @@ -50,6 +48,4 @@ app.*.map.json /debian/packages -untranslated.json - -android/app/.cxx +untranslated.json \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index fab9821..791c93f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,9 +12,5 @@ "editor.formatOnSave": false, "editor.formatOnPaste": false, "editor.formatOnType": false - }, - "cSpell.ignorePaths": [ - "/pubspec.yaml", - "/.github/workflows" - ], + } } \ No newline at end of file diff --git a/README.md b/README.md index 1dcbc67..d46c921 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ If you like the project and you want to contribute with the development, you can - [expandable](https://pub.dev/packages/expandable) - [package info plus](https://pub.dev/packages/package_info_plus) - [flutter phoenix](https://pub.dev/packages/flutter_phoenix) +- [flutter displaymode](https://pub.dev/packages/flutter_displaymode) - [flutter launcher icons](https://pub.dev/packages/flutter_launcher_icons) - [flutter native splash](https://pub.dev/packages/flutter_native_splash) - [intl](https://pub.dev/packages/intl) @@ -141,6 +142,7 @@ If you like the project and you want to contribute with the development, you can - [flutter custom tabs](https://pub.dev/packages/flutter_custom_tabs) - [shared preferences](https://pub.dev/packages/shared_preferences) - [window manager](https://pub.dev/packages/window_manager) +- [install referrer](https://pub.dev/packages/install_referrer)
diff --git a/android/app/build.gradle b/android/app/build.gradle index ab6291c..29785d0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -29,9 +29,8 @@ if (keystorePropertiesFile.exists()) { } android { - namespace "com.jgeek00.adguard_home_manager" - compileSdkVersion 35 - ndkVersion "26.1.10909125" + compileSdkVersion 34 + ndkVersion flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -47,9 +46,12 @@ android { } defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.jgeek00.adguard_home_manager" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. minSdkVersion 26 - targetSdkVersion 35 + targetSdkVersion 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 19cfad9..3c472b9 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index e8481f5..b14b9f7 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.6.0' apply false + id "com.android.application" version '7.4.2' apply false id "org.jetbrains.kotlin.android" version "1.8.20" apply false } diff --git a/debian/debian.yaml b/debian/debian.yaml index 43a90f9..876c66e 100644 --- a/debian/debian.yaml +++ b/debian/debian.yaml @@ -5,7 +5,7 @@ flutter_app: control: Package: AdGuardHomeManager - Version: 2.20.1 + Version: Architecture: amd64 Essential: no Priority: optional diff --git a/lib/config/theme.dart b/lib/config/theme.dart index eba0b9c..93b5365 100644 --- a/lib/config/theme.dart +++ b/lib/config/theme.dart @@ -27,12 +27,11 @@ ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( dialogTheme: DialogTheme( surfaceTintColor: dynamicColorScheme?.surfaceTint ), - // DISABLE PREDICTIVE BACK GESTURE - // pageTransitionsTheme: const PageTransitionsTheme( - // builders: { - // TargetPlatform.android: PredictiveBackPageTransitionsBuilder() - // } - // ) + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + } + ) ); ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( @@ -63,12 +62,11 @@ ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( dialogTheme: DialogTheme( surfaceTintColor: dynamicColorScheme?.surfaceTint ), - // DISABLE PREDICTIVE BACK GESTURE - // pageTransitionsTheme: const PageTransitionsTheme( - // builders: { - // TargetPlatform.android: PredictiveBackPageTransitionsBuilder() - // } - // ) + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + } + ) ); ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( @@ -87,12 +85,11 @@ ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( iconColor: Color.fromRGBO(117, 117, 117, 1), ), brightness: Brightness.light, - // DISABLE PREDICTIVE BACK GESTURE - // pageTransitionsTheme: const PageTransitionsTheme( - // builders: { - // TargetPlatform.android: PredictiveBackPageTransitionsBuilder() - // } - // ) + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + } + ) ); ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( @@ -114,10 +111,9 @@ ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( iconColor: Color.fromRGBO(187, 187, 187, 1), ), brightness: Brightness.dark, - // DISABLE PREDICTIVE BACK GESTURE - // pageTransitionsTheme: const PageTransitionsTheme( - // builders: { - // TargetPlatform.android: PredictiveBackPageTransitionsBuilder() - // } - // ) + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + } + ) ); \ No newline at end of file diff --git a/lib/constants/enums.dart b/lib/constants/enums.dart index 569db37..f54e665 100644 --- a/lib/constants/enums.dart +++ b/lib/constants/enums.dart @@ -1,3 +1,2 @@ enum LoadStatus { loading, loaded, error } -enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients, topUpstreams, avgUpstreamResponseTime } -enum CustomRulesSorting { topBottom, bottomTop } \ No newline at end of file +enum HomeTopItems { queriedDomains, blockedDomains, recurrentClients, topUpstreams, avgUpstreamResponseTime } \ No newline at end of file diff --git a/lib/constants/regexps.dart b/lib/constants/regexps.dart deleted file mode 100644 index e882913..0000000 --- a/lib/constants/regexps.dart +++ /dev/null @@ -1,12 +0,0 @@ -class Regexps { - static final wildcardDomain = RegExp(r'^(\*\.)?(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,10}$'); - static final domain = RegExp(r'^((?:(?:[a-zA-Z]{1})|(?:[a-zA-Z]{1}[a-zA-Z]{1})|(?:[a-zA-Z]{1}[0-9]{1})|(?:[0-9]{1}[a-zA-Z]{1})|(?:[a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.)+([a-zA-Z]{2,10}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,10})$'); - static final ipv4Address = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); - static final ipv6Address = RegExp(r'(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))'); - static final subroute = RegExp(r'^\/\b([A-Za-z0-9_\-~/]*)[^\/|\.|\:]$'); - static final macAddress = RegExp(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'); - static final url = RegExp(r'^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})$'); - static final certificate = RegExp(r'(-{3,}(\bBEGIN CERTIFICATE\b))|(-{3,}-{3,}(\END CERTIFICATE\b)-{3,})', multiLine: true); - static final privateKey = RegExp(r'(-{3,}(\bBEGIN\b).*(PRIVATE KEY\b))|(-{3,}-{3,}(\bEND\b).*(PRIVATE KEY\b)-{3,})', multiLine: true); - static final path = RegExp(r'^(\/{0,1}(?!\/))[A-Za-z0-9\/\-_]+(\.([a-zA-Z]+))?$'); -} \ No newline at end of file diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart index 0a8ece3..b7eb069 100644 --- a/lib/constants/urls.dart +++ b/lib/constants/urls.dart @@ -7,6 +7,4 @@ class Urls { static const String adGuardHomeReleasesTags = "https://api.github.com/repos/AdGuardTeam/AdGuardHome/releases/tags"; static const String googleSearchUrl = "https://www.google.com/search"; static const String connectionInstructions = "https://github.com/JGeek00/adguard-home-manager/wiki/Create-a-connection"; - static const String appDetailsWebpage = "https://apps.jgeek00.com/jlfed8mcgyz6laf"; - static const String jgeek00AppsWebpage = "https://apps.jgeek00.com"; } \ 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..e6137d7 --- /dev/null +++ b/lib/functions/check_app_updates.dart @@ -0,0 +1,57 @@ +import 'dart:io'; + +import 'package:install_referrer/install_referrer.dart'; + +import 'package:adguard_home_manager/functions/compare_versions.dart'; +import 'package:adguard_home_manager/services/external_requests.dart'; +import 'package:adguard_home_manager/models/github_release.dart'; + +Future checkAppUpdates({ + required String currentBuildNumber, + required void Function(GitHubRelease?) setUpdateAvailable, + required InstallationAppReferrer? installationSource, + required bool isBeta +}) async { + var result = isBeta + ? await ExternalRequests.getReleasesGitHub() + : await ExternalRequests.getReleaseData(); + + if (result.successful == true) { + late GitHubRelease gitHubRelease; + if (isBeta) { + gitHubRelease = (result.content as List).firstWhere((r) => r.prerelease == true); + } + else { + gitHubRelease = result.content as GitHubRelease; + } + + final update = gitHubUpdateExists( + currentBuildNumber: currentBuildNumber, + gitHubRelease: gitHubRelease, + isBeta: isBeta + ); + + if (update == true) { + setUpdateAvailable(gitHubRelease); + + if (Platform.isAndroid) { + if (installationSource == InstallationAppReferrer.androidManually) { + return gitHubRelease; + } + else { + return null; + } + } + else if (Platform.isIOS) { + return null; + } + else { + return gitHubRelease; + } + } + else { + setUpdateAvailable(null); + } + } + return null; +} \ No newline at end of file diff --git a/lib/functions/is_ip.dart b/lib/functions/is_ip.dart index 73ee1e9..667bf0b 100644 --- a/lib/functions/is_ip.dart +++ b/lib/functions/is_ip.dart @@ -1,7 +1,7 @@ -import 'package:adguard_home_manager/constants/regexps.dart'; - bool isIpAddress(String value) { - if (Regexps.ipv4Address.hasMatch(value) || Regexps.ipv6Address.hasMatch(value)) { + final ipv4Regexp = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$'); + final ipv6Regexp = RegExp(r'(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))'); + if (ipv4Regexp.hasMatch(value) || ipv6Regexp.hasMatch(value)) { return true; } else { diff --git a/lib/functions/open_url.dart b/lib/functions/open_url.dart index 599eea0..00cfc17 100644 --- a/lib/functions/open_url.dart +++ b/lib/functions/open_url.dart @@ -5,15 +5,6 @@ import 'package:url_launcher/url_launcher.dart' as url_launcher; import 'package:sentry_flutter/sentry_flutter.dart'; void openUrl(String url) async { - if (!(url.startsWith("http") || url.startsWith("https"))) { - try { - url_launcher.launchUrl(Uri.parse(url)); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - } - return; - } - if (Platform.isAndroid || Platform.isIOS) { try { await flutter_custom_tabs.launchUrl( @@ -29,7 +20,6 @@ void openUrl(String url) async { ), ); } catch (e, stackTrace) { - url_launcher.launchUrl(Uri.parse(url)); Sentry.captureException(e, stackTrace: stackTrace); } } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f923e8b..609c616 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -797,14 +797,5 @@ "dnsServerAddressCopied": "DNS server address copied to the clipboard", "select": "Select", "liveLogs": "Live logs", - "hereWillAppearRealtimeLogs": "Here there will appear the logs on realtime.", - "applicationDetails": "Application details", - "applicationDetailsDescription": "App repository, stores where it's available, and more", - "myOtherApps": "My other apps", - "myOtherAppsDescription": "Check my other apps, make a donation, contact support, and more", - "topToBottom": "From top to bottom", - "bottomToTop": "From bottom to top", - "upstreamTimeout": "Upstream timeout", - "upstreamTimeoutHelper": "Specifies the number of seconds to wait for a response from the upstream server", - "fieldCannotBeEmpty": "This field cannot be empty" + "hereWillAppearRealtimeLogs": "Here there will appear the logs on realtime." } \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index c93c501..231eeaf 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -403,7 +403,7 @@ "dnsRewriteRuleDeleted": "Reescritura DNS eliminada correctamente", "dnsRewriteRuleNotDeleted": "La reescritura DNS no pudo ser eliminada", "addDnsRewrite": "Añadir reescritura DNS", - "addingRewrite": "Añadiendo reescritura...", + "addingRewrite": "Añadiend reescritura...", "dnsRewriteRuleAdded": "Regla de reescritura DNS añadida correctamente", "dnsRewriteRuleNotAdded": "La regla de reescritura DNS no ha podido ser añadida", "logsSettings": "Ajustes de registros", @@ -797,14 +797,5 @@ "dnsServerAddressCopied": "Dirección del servidor DNS copiada al portapapeles", "select": "Seleccionar", "liveLogs": "Registros en directo", - "hereWillAppearRealtimeLogs": "Aquí aparecerán los registros en tiempo real.", - "applicationDetails": "Detalles de la aplicación", - "applicationDetailsDescription": "Repositorio de la app, tiendas donde está disponible, y más", - "myOtherApps": "Mis otras apps", - "myOtherAppsDescription": "Comprueba mis otras apps, hacer una donación, contactar al soporte, y más", - "topToBottom": "Desde arriba hacia abajo", - "bottomToTop": "Desde abajo hacia arriba", - "upstreamTimeout": "Tiempo de espera del upstream", - "upstreamTimeoutHelper": "Especifica el número de segundos que se debe esperar para recibir una respuesta del servidor upstream", - "fieldCannotBeEmpty": "El campo no puede estar vacío" + "hereWillAppearRealtimeLogs": "Aquí aparecerán los registros en tiempo real." } \ No newline at end of file diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index d0f26c5..423dfa3 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -791,20 +791,5 @@ "clientDisallowedSuccessfully": "İstemci başarıyla reddedildi", "changesNotSaved": "Değişiklikler kaydedilemedi", "allowingClient": "İstemciye izin veriliyor...", - "disallowingClient": "İstemci reddediliyor...", - "clientIpCopied": "İstemci IP'si panoya kopyalandı", - "clientNameCopied": "İstemci adı panoya kopyalandı", - "dnsServerAddressCopied": "DNS sunucu adresi panoya kopyalandı", - "select": "Seç", - "liveLogs": "Canlı günlükler", - "hereWillAppearRealtimeLogs": "Burada gerçek zamanlı günlükler görünecek.", - "applicationDetails": "Uygulama detayları", - "applicationDetailsDescription": "Uygulama deposu, mevcut olduğu mağazalar ve daha fazlası", - "myOtherApps": "Diğer uygulamalarım", - "myOtherAppsDescription": "Diğer uygulamalarımı kontrol et, bağış yap, destekle iletişime geç ve daha fazlası", - "topToBottom": "Yukarıdan aşağıya", - "bottomToTop": "Aşağıdan yukarıya", - "upstreamTimeout": "Üst sunucu zaman aşımı", - "upstreamTimeoutHelper": "Üst DNS sunucusundan yanıt bekleme süresini saniye cinsinden belirtir", - "fieldCannotBeEmpty": "Bu alan boş olamaz" -} + "disallowingClient": "İstemci reddediliyor..." +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 6402b70..ecd9f7e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,7 +4,9 @@ import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:install_referrer/install_referrer.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -77,6 +79,11 @@ void main() async { HttpOverrides.global = MyHttpOverrides(); } + if (Platform.isAndroid || Platform.isIOS) { + InstallationAppReferrer installationSource = await InstallReferrer.referrer; + appConfigProvider.setInstallationSource(installationSource); + } + final dbData = await loadDb(); serversProvider.setDbInstance(dbData['dbInstance']); serversProvider.saveFromDb(dbData['servers']); @@ -162,31 +169,6 @@ void main() async { (options) { options.dsn = dotenv.env['SENTRY_DSN']; options.sendDefaultPii = false; - options.beforeSend = (event, hint) { - if (event.throwable is HttpException) { - return null; - } - - if (event.message?.formatted.contains("HttpException") == true) { - return null; - } - - if ( - event.message?.formatted.contains("Unexpected character") ?? false || - (event.throwable != null && event.throwable!.toString().contains("Unexpected character")) - ) { - return null; - } - - if ( - event.message?.formatted.contains("Unexpected end of input") ?? false || - (event.throwable != null && event.throwable!.toString().contains("Unexpected end of input")) - ) { - return null; - } - - return event; - }; }, appRunner: () => startApp() ); @@ -196,9 +178,37 @@ void main() async { } } -class Main extends StatelessWidget { +class Main extends StatefulWidget { const Main({super.key}); + @override + State
createState() => _MainState(); +} + +class _MainState extends State
{ + List modes = []; + DisplayMode? active; + DisplayMode? preferred; + + Future displayMode() async { + try { + modes = await FlutterDisplayMode.supported; + preferred = await FlutterDisplayMode.preferred; + active = await FlutterDisplayMode.active; + await FlutterDisplayMode.setHighRefreshRate(); + setState(() {}); + } catch (_) { + // ---- // + } + } + + @override + void initState() { + displayMode(); + + super.initState(); + } + @override Widget build(BuildContext context) { final appConfigProvider = Provider.of(context); diff --git a/lib/models/dns_info.dart b/lib/models/dns_info.dart index 7007644..5a53023 100644 --- a/lib/models/dns_info.dart +++ b/lib/models/dns_info.dart @@ -26,7 +26,6 @@ class DnsInfo { int? ratelimitSubnetLenIpv4; int? ratelimitSubnetLenIpv6; List? ratelimitWhitelist; - int? upstreamTimeout; DnsInfo({ required this.upstreamDns, @@ -56,7 +55,6 @@ class DnsInfo { required this.ratelimitSubnetLenIpv4, required this.ratelimitSubnetLenIpv6, required this.ratelimitWhitelist, - required this.upstreamTimeout, }); factory DnsInfo.fromJson(Map json) => DnsInfo( @@ -87,7 +85,6 @@ class DnsInfo { ratelimitSubnetLenIpv4: json["ratelimit_subnet_len_ipv4"], ratelimitSubnetLenIpv6: json["ratelimit_subnet_len_ipv6"], ratelimitWhitelist: json["ratelimit_whitelist"] != null ? List.from(json["ratelimit_whitelist"].map((x) => x)) : [], - upstreamTimeout: json["upstream_timeout"], ); Map toJson() => { @@ -118,6 +115,5 @@ class DnsInfo { "ratelimit_subnet_len_ipv4": ratelimitSubnetLenIpv4, "ratelimit_subnet_len_ipv6": ratelimitSubnetLenIpv6, "ratelimit_whitelist": ratelimitWhitelist != null ? List.from(ratelimitWhitelist!.map((x) => x)) : null, - "upstream_timeout": upstreamTimeout, }; } diff --git a/lib/models/dns_statistics.dart b/lib/models/dns_statistics.dart index ed787ce..f279886 100644 --- a/lib/models/dns_statistics.dart +++ b/lib/models/dns_statistics.dart @@ -5,7 +5,7 @@ DnsStatistics dnsStatisticsFromJson(String str) => DnsStatistics.fromJson(json.d String dnsStatisticsToJson(DnsStatistics data) => json.encode(data.toJson()); class DnsStatistics { - final String? timeUnits; + final String timeUnits; final List> topQueriedDomains; final List> topClients; final List> topBlockedDomains; @@ -43,9 +43,9 @@ class DnsStatistics { factory DnsStatistics.fromJson(Map json) => DnsStatistics( timeUnits: json["time_units"], - topQueriedDomains: json["top_queried_domains"] != null ? List>.from(json["top_queried_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : [], - topClients: json["top_clients"] != null ? List>.from(json["top_clients"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : [], - topBlockedDomains: json["top_blocked_domains"] != null ? List>.from(json["top_blocked_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))): [], + topQueriedDomains: List>.from(json["top_queried_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), + topClients: List>.from(json["top_clients"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), + topBlockedDomains: List>.from(json["top_blocked_domains"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))), topUpstreamResponses: json["top_upstreams_responses"] != null ? List>.from(json["top_upstreams_responses"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : null, topUpstreamsAvgTime: json["top_upstreams_avg_time"] != null ? List>.from(json["top_upstreams_avg_time"].map((x) => Map.from(x).map((k, v) => MapEntry(k, v)))) : null, dnsQueries: List.from(json["dns_queries"].map((x) => x)), diff --git a/lib/providers/app_config_provider.dart b/lib/providers/app_config_provider.dart index bb6887c..3b843b9 100644 --- a/lib/providers/app_config_provider.dart +++ b/lib/providers/app_config_provider.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/scheduler.dart'; +import 'package:install_referrer/install_referrer.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -57,6 +58,8 @@ class AppConfigProvider with ChangeNotifier { GitHubRelease? _appUpdatesAvailable; + InstallationAppReferrer? _installationSource; + PackageInfo? get getAppInfo { return _appInfo; } @@ -159,6 +162,10 @@ class AppConfigProvider with ChangeNotifier { return _appUpdatesAvailable; } + InstallationAppReferrer? get installationSource { + return _installationSource; + } + List get homeTopItemsOrder { return _homeTopItemsOrder; } @@ -220,6 +227,11 @@ class AppConfigProvider with ChangeNotifier { notifyListeners(); } + void setInstallationSource(InstallationAppReferrer value) { + _installationSource = value; + notifyListeners(); + } + Future setOverrideSslCheck(bool status) async { try { sharedPreferencesInstance.setBool('overrideSslCheck', status); diff --git a/lib/providers/dns_provider.dart b/lib/providers/dns_provider.dart index a59c3c5..198053b 100644 --- a/lib/providers/dns_provider.dart +++ b/lib/providers/dns_provider.dart @@ -151,26 +151,20 @@ class DnsProvider with ChangeNotifier { final result = await _serversProvider!.apiClient2!.setDnsConfig( data: value ); - - void updateValue(dynamic parameter, dynamic value) { - if (value != null) { - parameter = value; - } - } if (result.successful == true) { DnsInfo data = dnsInfo!; - updateValue(data.ratelimit, value['ratelimit']); - updateValue(data.ednsCsEnabled, value['edns_cs_enabled']); - updateValue(data.dnssecEnabled, value['dnssec_enabled']); - updateValue(data.disableIpv6, value['disable_ipv6']); - updateValue(data.blockingMode, value['blocking_mode']); - updateValue(data.blockingIpv4, value['blocking_ipv4']); - updateValue(data.blockingIpv6, value['blocking_ipv6']); - updateValue(data.blockedResponseTtl, value['blocked_response_ttl']); - updateValue(data.ratelimitSubnetLenIpv4, value['ratelimit_subnet_len_ipv4']); - updateValue(data.ratelimitSubnetLenIpv6, value['ratelimit_subnet_len_ipv6']); - updateValue(data.ratelimitWhitelist, value['ratelimit_whitelist']); + 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']; + data.blockedResponseTtl = value['blocked_response_ttl']; + data.ratelimitSubnetLenIpv4 = value['ratelimit_subnet_len_ipv4']; + data.ratelimitSubnetLenIpv6 = value['ratelimit_subnet_len_ipv6']; + data.ratelimitWhitelist = value['ratelimit_whitelist']; setDnsInfoData(data); return result; } diff --git a/lib/screens/clients/fab.dart b/lib/screens/clients/fab.dart index 9571ae3..383a2f3 100644 --- a/lib/screens/clients/fab.dart +++ b/lib/screens/clients/fab.dart @@ -25,14 +25,10 @@ class ClientsFab extends StatelessWidget { final width = MediaQuery.of(context).size.width; void confirmAddClient(Client client) async { - if (!context.mounted) return; - ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingClient); final result = await clientsProvider.addClient(client); - - if (!context.mounted) return; processModal.close(); diff --git a/lib/screens/filters/add_button.dart b/lib/screens/filters/add_button.dart index e2de2ff..2eca7d4 100644 --- a/lib/screens/filters/add_button.dart +++ b/lib/screens/filters/add_button.dart @@ -33,8 +33,6 @@ class AddFiltersButton extends StatelessWidget { final width = MediaQuery.of(context).size.width; void confirmAddRule(String rule) async { - if (!context.mounted) return; - ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingRule); @@ -60,8 +58,6 @@ class AddFiltersButton extends StatelessWidget { } void confirmEditCustomRules(List rules) async { - if (!context.mounted) return; - ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingCustomRules); @@ -141,8 +137,6 @@ class AddFiltersButton extends StatelessWidget { } void confirmAddList({required String name, required String url, required String type}) async { - if (!context.mounted) return; - ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingList); diff --git a/lib/screens/filters/custom_rules_list.dart b/lib/screens/filters/custom_rules_list.dart index 284e15f..304972f 100644 --- a/lib/screens/filters/custom_rules_list.dart +++ b/lib/screens/filters/custom_rules_list.dart @@ -6,7 +6,6 @@ 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/screens/filters/modals/custom_rules/sort_rules.dart'; import 'package:adguard_home_manager/widgets/tab_content_list.dart'; import 'package:adguard_home_manager/functions/snackbar.dart'; @@ -35,8 +34,6 @@ class CustomRulesList extends StatefulWidget { class _CustomRulesListState extends State { late bool isVisible; - CustomRulesSorting _sortingMethod = CustomRulesSorting.topBottom; - @override initState(){ super.initState(); @@ -63,8 +60,6 @@ class _CustomRulesListState extends State { final filteringProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - final renderData = _sortingMethod == CustomRulesSorting.bottomTop ? widget.data.reversed.toList() : widget.data.toList(); - bool checkIfComment(String value) { final regex = RegExp(r'^(!|#).*$'); if (regex.hasMatch(value)) { @@ -109,16 +104,6 @@ class _CustomRulesListState extends State { } } - void showSortingMethodModal() { - showDialog( - context: context, - builder: (ctx) => SortCustomRulesModal( - sortingMethod: _sortingMethod, - onSelect: (value) => setState(() => _sortingMethod = value), - ), - ); - } - return CustomTabContentList( loadingGenerator: () => SizedBox( width: double.maxFinite, @@ -139,10 +124,10 @@ class _CustomRulesListState extends State { ], ), ), - itemsCount: renderData.length, + itemsCount: widget.data.length, contentWidget: (index) => ListTile( title: Text( - renderData[index], + widget.data[index], style: TextStyle( color: checkIfComment(widget.data[index]) == true ? Theme.of(context).colorScheme.onSurface.withOpacity(0.6) @@ -150,9 +135,9 @@ class _CustomRulesListState extends State { fontWeight: FontWeight.normal, ), ), - subtitle: generateSubtitle(renderData[index]), + subtitle: generateSubtitle(widget.data[index]), trailing: IconButton( - onPressed: () => widget.onRemoveCustomRule(renderData[index]), + onPressed: () => widget.onRemoveCustomRule(widget.data[index]), icon: const Icon(Icons.delete) ), ), @@ -177,7 +162,7 @@ class _CustomRulesListState extends State { TextButton.icon( onPressed: () async { final result = await filteringProvider.fetchFilters(); - if (result == false && context.mounted) { + if (result == false) { showSnackbar( appConfigProvider: appConfigProvider, label: AppLocalizations.of(context)!.errorLoadFilters, @@ -227,11 +212,6 @@ class _CustomRulesListState extends State { }, fab: Column( children: [ - FloatingActionButton.small( - onPressed: showSortingMethodModal, - child: Icon(Icons.sort_rounded), - ), - const SizedBox(height: 16), AddFiltersButton( type: 'edit_custom_rule', widget: (fn) => FloatingActionButton.small( @@ -249,7 +229,7 @@ class _CustomRulesListState extends State { ), ], ), - heightFabHidden: -180, + heightFabHidden: -120, fabVisible: isVisible, ); } diff --git a/lib/screens/filters/details/add_list_modal.dart b/lib/screens/filters/details/add_list_modal.dart index f153224..d5579a6 100644 --- a/lib/screens/filters/details/add_list_modal.dart +++ b/lib/screens/filters/details/add_list_modal.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -98,7 +97,8 @@ class _ContentState extends State<_Content> { } void validateUrl(String value) { - if (Regexps.url.hasMatch(value)) { + final urlRegex = RegExp(r'^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})$'); + if (urlRegex.hasMatch(value)) { setState(() => urlError = null); } else { diff --git a/lib/screens/filters/details/check_host_modal.dart b/lib/screens/filters/details/check_host_modal.dart index be0efce..3065588 100644 --- a/lib/screens/filters/details/check_host_modal.dart +++ b/lib/screens/filters/details/check_host_modal.dart @@ -1,6 +1,5 @@ // ignore_for_file: use_build_context_synchronously -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -64,7 +63,8 @@ class _ContentState extends State<_Content> { Widget? resultWidget; void validateDomain(String value) { - if (Regexps.domain.hasMatch(value)) { + final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); + if (domainRegex.hasMatch(value)) { setState(() => domainError = null); } else { diff --git a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart index 674c200..b528c02 100644 --- a/lib/screens/filters/modals/custom_rules/add_custom_rule.dart +++ b/lib/screens/filters/modals/custom_rules/add_custom_rule.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:segmented_button_slide/segmented_button_slide.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -42,7 +41,8 @@ class _AddCustomRuleState extends State { } void validateDomain(String value) { - if (Regexps.domain.hasMatch(value)) { + final domainRegex = RegExp(r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$'); + if (domainRegex.hasMatch(value)) { setState(() => _domainError = null); } else { diff --git a/lib/screens/filters/modals/custom_rules/sort_rules.dart b/lib/screens/filters/modals/custom_rules/sort_rules.dart deleted file mode 100644 index 7ae0870..0000000 --- a/lib/screens/filters/modals/custom_rules/sort_rules.dart +++ /dev/null @@ -1,128 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - -import 'package:adguard_home_manager/constants/enums.dart'; - -class SortCustomRulesModal extends StatelessWidget { - final CustomRulesSorting sortingMethod; - final void Function(CustomRulesSorting) onSelect; - - const SortCustomRulesModal({ - super.key, - required this.sortingMethod, - required this.onSelect, - }); - - @override - Widget build(BuildContext context) { - return AlertDialog( - contentPadding: const EdgeInsets.symmetric(vertical: 16), - scrollable: true, - title: Column( - children: [ - Icon( - Icons.sort_rounded, - size: 24, - color: Theme.of(context).listTileTheme.iconColor - ), - const SizedBox(height: 16), - Text( - AppLocalizations.of(context)!.sortingOptions, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface - ), - ) - ], - ), - content: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 500 - ), - child: Column( - children: [ - _CustomListTileDialog( - title: AppLocalizations.of(context)!.topToBottom, - icon: Icons.arrow_downward_rounded, - onTap: () { - Navigator.pop(context); - onSelect(CustomRulesSorting.topBottom); - }, - isSelected: sortingMethod == CustomRulesSorting.topBottom - ), - _CustomListTileDialog( - title: AppLocalizations.of(context)!.bottomToTop, - icon: Icons.arrow_upward_rounded, - onTap: () { - Navigator.pop(context); - onSelect(CustomRulesSorting.bottomTop); - }, - isSelected: sortingMethod == CustomRulesSorting.bottomTop - ), - ] - ), - ), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(AppLocalizations.of(context)!.close) - ) - ], - ) - ], - ); - } -} - -class _CustomListTileDialog extends StatelessWidget { - final String title; - final IconData? icon; - final void Function()? onTap; - final bool isSelected; - - const _CustomListTileDialog({ - required this.title, - required this.icon, - required this.onTap, - required this.isSelected, - }); - - @override - Widget build(BuildContext context) { - return Material( - color: Colors.transparent, - child: InkWell( - onTap: onTap, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), - child: Row( - children: [ - Icon( - icon, - color: Theme.of(context).colorScheme.onSurface, - ), - const SizedBox(width: 24), - Flexible( - child: Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ), - const SizedBox(width: 24), - Icon( - isSelected == true ? Icons.radio_button_checked_rounded : Icons.radio_button_unchecked_rounded, - color: Theme.of(context).colorScheme.primary, - ) - ], - ), - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/screens/home/appbar.dart b/lib/screens/home/appbar.dart index d4b447c..5cd481f 100644 --- a/lib/screens/home/appbar.dart +++ b/lib/screens/home/appbar.dart @@ -34,7 +34,6 @@ class HomeAppBar extends StatelessWidget { void navigateServers() { Future.delayed(const Duration(milliseconds: 0), (() { - if (!context.mounted) return; Navigator.of(context).push( MaterialPageRoute(builder: (context) => const Servers()) ); diff --git a/lib/screens/logs/filters/clients_modal.dart b/lib/screens/logs/filters/clients_modal.dart index 05b7213..403f098 100644 --- a/lib/screens/logs/filters/clients_modal.dart +++ b/lib/screens/logs/filters/clients_modal.dart @@ -114,12 +114,10 @@ class _ClientsModalState extends State { } void searchAddedClient(_ClientLog client) { - final ips = client.ids?.where((e) => isIpAddress(e) == true).toList(); - if (ips == null || ips.isEmpty) return; - logsProvider.setSearchText(ips[0]); - logsProvider.filterLogs(); + final notIps = client.ids?.where((e) => isIpAddress(e) == false).toList(); + if (notIps == null) return; + logsProvider.setSearchText('"${notIps[0]}"'); Navigator.of(context).pop(); - Navigator.pop(context); } if (widget.dialog == true) { @@ -304,7 +302,7 @@ class _ClientsModalState extends State { subtitle: _selectedList == 0 ? _filteredClients[index].name : _filteredClients[index].ids?.join(", "), checkboxActive: logsProvider.selectedClients.contains(_filteredClients[index].ip), isAddedClient: _selectedList == 1, - onSearchAddedClient: _filteredClients[index].ids != null && _filteredClients[index].ids!.where((e) => isIpAddress(e) == true).isNotEmpty ? () => searchAddedClient(_filteredClients[index]) : null, + onSearchAddedClient: () => searchAddedClient(_filteredClients[index]), onChanged: (isSelected) { if (isSelected == true) { logsProvider.setSelectedClients([ @@ -378,7 +376,7 @@ class _ListItem extends StatelessWidget { final bool checkboxActive; final void Function(bool) onChanged; final bool isAddedClient; - final void Function()? onSearchAddedClient; + final void Function() onSearchAddedClient; const _ListItem({ required this.title, diff --git a/lib/screens/logs/log_tile.dart b/lib/screens/logs/log_tile.dart index dc33048..bed2e40 100644 --- a/lib/screens/logs/log_tile.dart +++ b/lib/screens/logs/log_tile.dart @@ -96,8 +96,6 @@ class LogTile extends StatelessWidget { } void blockUnblock({required String domain, required String newStatus}) async { - if (!context.mounted) return; - final ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.savingUserFilters); @@ -126,8 +124,6 @@ class LogTile extends StatelessWidget { } void confirmAddClient(Client client) async { - if (!context.mounted) return; - ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingClient); @@ -154,8 +150,6 @@ class LogTile extends StatelessWidget { } void blockUnblockRuleClient() async { - if (!context.mounted) return; - ProcessModal processModal = ProcessModal(); processModal.open(AppLocalizations.of(context)!.addingRule); diff --git a/lib/screens/logs/logs_list_appbar.dart b/lib/screens/logs/logs_list_appbar.dart index 21e03b1..2a052f6 100644 --- a/lib/screens/logs/logs_list_appbar.dart +++ b/lib/screens/logs/logs_list_appbar.dart @@ -89,7 +89,6 @@ class LogsListAppBar extends StatelessWidget { } void openLiveLogsScreen() { - if (!context.mounted) return; Navigator.of(context).push( MaterialPageRoute( builder: (context) => MultiProvider( diff --git a/lib/screens/settings/dhcp/add_static_lease_modal.dart b/lib/screens/settings/dhcp/add_static_lease_modal.dart index d40c506..c80e848 100644 --- a/lib/screens/settings/dhcp/add_static_lease_modal.dart +++ b/lib/screens/settings/dhcp/add_static_lease_modal.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -68,7 +67,8 @@ class __ContentState extends State<_Content> { bool validData = false; void validateMac(String value) { - if (Regexps.macAddress.hasMatch(value)) { + final RegExp macRegex = RegExp(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$'); + if (macRegex.hasMatch(value)) { setState(() => macError = null); } else { @@ -78,7 +78,8 @@ class __ContentState extends State<_Content> { } void validateIp(String value) { - if (Regexps.ipv4Address.hasMatch(value) == true) { + RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); + if (ipAddress.hasMatch(value) == true) { setState(() => ipError = null); } else { diff --git a/lib/screens/settings/dhcp/dhcp.dart b/lib/screens/settings/dhcp/dhcp.dart index 76867ef..449b063 100644 --- a/lib/screens/settings/dhcp/dhcp.dart +++ b/lib/screens/settings/dhcp/dhcp.dart @@ -2,7 +2,6 @@ import 'dart:io'; -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -101,8 +100,8 @@ class _DhcpScreenState extends State { break; } } - - if (Regexps.ipv4Address.hasMatch(value)) { + final regex = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$'); + if (regex.hasMatch(value)) { setValue(null); } else { @@ -127,8 +126,8 @@ class _DhcpScreenState extends State { break; } } - - if (Regexps.ipv6Address.hasMatch(value)) { + final regex = RegExp(r'^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$'); + if (regex.hasMatch(value)) { setValue(null); } else { diff --git a/lib/screens/settings/dns/bootstrap_dns.dart b/lib/screens/settings/dns/bootstrap_dns.dart index dba929a..833396d 100644 --- a/lib/screens/settings/dns/bootstrap_dns.dart +++ b/lib/screens/settings/dns/bootstrap_dns.dart @@ -1,6 +1,5 @@ // ignore_for_file: use_build_context_synchronously -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -24,7 +23,8 @@ class _BootstrapDnsScreenState extends State { bool validValues = false; void validateIp(Map field, String value) { - if (Regexps.ipv4Address.hasMatch(value) == true || Regexps.ipv6Address.hasMatch(value) == true) { + RegExp ipAddress = RegExp(r'(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$)'); + if (ipAddress.hasMatch(value) == true) { setState(() => field['error'] = null); } else { diff --git a/lib/screens/settings/dns/fallback_dns.dart b/lib/screens/settings/dns/fallback_dns.dart index 6c8d8ce..19040ed 100644 --- a/lib/screens/settings/dns/fallback_dns.dart +++ b/lib/screens/settings/dns/fallback_dns.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:adguard_home_manager/screens/settings/dns/comment_modal.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -25,7 +24,9 @@ class _FallbackDnsScreenState extends State { bool validValues = false; void validateIp(Map field, String value) { - if (Regexps.ipv4Address.hasMatch(value) == true || Regexps.ipv6Address.hasMatch(value) || Regexps.url.hasMatch(value) == true) { + RegExp ipAddress = RegExp(r'(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$)'); + RegExp url = RegExp(r'(https?|tls):\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'); + if (ipAddress.hasMatch(value) == true || url.hasMatch(value) == true) { setState(() => field['error'] = null); } else { diff --git a/lib/screens/settings/dns/rate_limit_allowlist_modal.dart b/lib/screens/settings/dns/rate_limit_allowlist_modal.dart index 2c2fed8..e5b678e 100644 --- a/lib/screens/settings/dns/rate_limit_allowlist_modal.dart +++ b/lib/screens/settings/dns/rate_limit_allowlist_modal.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -34,7 +33,8 @@ class _RateLimitAllowlistModalState extends State { List<_IpListItemController> _controllersList = []; void _validateIp(String value, _IpListItemController item) { - if (Regexps.ipv4Address.hasMatch(value)) { + final regexp = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); + if (regexp.hasMatch(value)) { setState(() => _controllersList = _controllersList.map((e) { if (e.id == item.id) { return _IpListItemController( diff --git a/lib/screens/settings/dns/upstream_dns.dart b/lib/screens/settings/dns/upstream_dns.dart index 1ae8c5e..33818a1 100644 --- a/lib/screens/settings/dns/upstream_dns.dart +++ b/lib/screens/settings/dns/upstream_dns.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'dart:io'; import 'package:flutter/material.dart'; @@ -28,9 +30,6 @@ class _UpstreamDnsScreenState extends State { bool validValues = false; - final upstreamTimeoutController = TextEditingController(); - String? upstreamTimeoutError = null; - checkValidValues() { if ( dnsServers.isNotEmpty && @@ -62,7 +61,6 @@ class _UpstreamDnsScreenState extends State { } } upstreamMode = dnsProvider.dnsInfo!.upstreamMode ?? ""; - upstreamTimeoutController.text = dnsProvider.dnsInfo!.upstreamTimeout != null ? dnsProvider.dnsInfo!.upstreamTimeout.toString() : ""; validValues = true; super.initState(); } @@ -74,23 +72,6 @@ class _UpstreamDnsScreenState extends State { final width = MediaQuery.of(context).size.width; - void validateTimeout(String value) { - if (value != '' && int.tryParse(value) != null && int.parse(value) > 0) { - setState(() { - upstreamTimeoutError = null; - validValues = true; - }); - } - else { - setState(() { - upstreamTimeoutError = value == '' - ? AppLocalizations.of(context)!.fieldCannotBeEmpty - : AppLocalizations.of(context)!.invalidValue; - validValues = false; - }); - } - } - void openAddCommentModal() { if (width > 900 || !(Platform.isAndroid || Platform.isIOS)) { showDialog( @@ -165,13 +146,11 @@ class _UpstreamDnsScreenState extends State { final result = await dnsProvider.saveUpstreamDnsConfig({ "upstream_dns": dnsServers.map((e) => e['controller'] != null ? e['controller'].text : e['comment']).toList(), - "upstream_mode": upstreamMode, - "upstream_timeout": int.tryParse(upstreamTimeoutController.text) + "upstream_mode": upstreamMode }); processModal.close(); - if (!context.mounted) return; if (result.successful == true) { showSnackbar( appConfigProvider: appConfigProvider, @@ -333,27 +312,6 @@ class _UpstreamDnsScreenState extends State { subtitle: AppLocalizations.of(context)!.fastestIpAddressDescription, onChanged: (value) => setState(() => upstreamMode = value), ), - const SizedBox(height: 16), - SectionLabel(label: AppLocalizations.of(context)!.others), - Padding( - padding: const EdgeInsets.all(16), - child: TextFormField( - controller: upstreamTimeoutController, - onChanged: validateTimeout, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.timer_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.upstreamTimeout, - helperText: AppLocalizations.of(context)!.upstreamTimeoutHelper, - helperMaxLines: 2, - errorText: upstreamTimeoutError - ) - ), - ), ], ), ), diff --git a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart index 42524fa..439455c 100644 --- a/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart +++ b/lib/screens/settings/dns_rewrites/dns_rewrite_modal.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -83,7 +82,8 @@ class _ContentState extends State<_Content> { bool validData = false; void validateDomain(String value) { - if (Regexps.wildcardDomain.hasMatch(value)) { + final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); + if (domainRegex.hasMatch(value)) { setState(() => domainError = null); } else { diff --git a/lib/screens/settings/encryption/encryption_functions.dart b/lib/screens/settings/encryption/encryption_functions.dart index c7700e4..c9c0c4b 100644 --- a/lib/screens/settings/encryption/encryption_functions.dart +++ b/lib/screens/settings/encryption/encryption_functions.dart @@ -1,11 +1,11 @@ -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/providers/app_config_provider.dart'; String? validateDomain(BuildContext context, String domain) { - if (Regexps.domain.hasMatch(domain)) { + RegExp regExp = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); + if (regExp.hasMatch(domain)) { return null; } else { @@ -23,7 +23,8 @@ String? validatePort(BuildContext context, String value) { } String? validateCertificate(BuildContext context, String cert) { - if (Regexps.certificate.hasMatch(cert.replaceAll('\n', ''))) { + final regExp = RegExp(r'(-{3,}(\bBEGIN CERTIFICATE\b))|(-{3,}-{3,}(\END CERTIFICATE\b)-{3,})', multiLine: true); + if (regExp.hasMatch(cert.replaceAll('\n', ''))) { return null; } else { @@ -32,7 +33,8 @@ String? validateCertificate(BuildContext context, String cert) { } String? validatePrivateKey(BuildContext context, String cert) { - if (Regexps.privateKey.hasMatch(cert.replaceAll('\n', ''))) { + final regExp = RegExp(r'(-{3,}(\bBEGIN\b).*(PRIVATE KEY\b))|(-{3,}-{3,}(\bEND\b).*(PRIVATE KEY\b)-{3,})', multiLine: true); + if (regExp.hasMatch(cert.replaceAll('\n', ''))) { return null; } else { @@ -41,7 +43,8 @@ String? validatePrivateKey(BuildContext context, String cert) { } String? validatePath(BuildContext context, String cert) { - if (Regexps.path.hasMatch(cert)) { + final regExp = RegExp(r'^(\/{0,1}(?!\/))[A-Za-z0-9\/\-_]+(\.([a-zA-Z]+))?$'); + if (regExp.hasMatch(cert)) { return null; } else { diff --git a/lib/screens/settings/general_settings/general_settings.dart b/lib/screens/settings/general_settings/general_settings.dart index f32446d..0029752 100644 --- a/lib/screens/settings/general_settings/general_settings.dart +++ b/lib/screens/settings/general_settings/general_settings.dart @@ -1,4 +1,9 @@ +// ignore_for_file: use_build_context_synchronously + +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:install_referrer/install_referrer.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -8,8 +13,11 @@ import 'package:adguard_home_manager/screens/settings/general_settings/top_items 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/desktop_mode.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/providers/app_config_provider.dart'; class GeneralSettings extends StatefulWidget { @@ -40,7 +48,6 @@ class _GeneralSettingsState extends State { required Future Function(bool) function }) async { final result = await function(newStatus); - if (!context.mounted) return; if (result == true) { showSnackbar( appConfigProvider: appConfigProvider, @@ -57,60 +64,60 @@ class _GeneralSettingsState extends State { } } - // Future checkUpdatesAvailable() async { - // setState(() => appUpdatesStatus = AppUpdatesStatus.checking); + Future checkUpdatesAvailable() async { + setState(() => appUpdatesStatus = AppUpdatesStatus.checking); - // final res = await checkAppUpdates( - // currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, - // setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, - // installationSource: appConfigProvider.installationSource, - // isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), - // ); + final res = await checkAppUpdates( + currentBuildNumber: appConfigProvider.getAppInfo!.buildNumber, + setUpdateAvailable: appConfigProvider.setAppUpdatesAvailable, + installationSource: appConfigProvider.installationSource, + isBeta: appConfigProvider.getAppInfo!.version.contains('beta'), + ); - // if (!mounted) return; - // if (res != null) { - // setState(() => appUpdatesStatus = AppUpdatesStatus.available); - // } - // else { - // setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); - // } - // } + if (!mounted) return; + if (res != null) { + setState(() => appUpdatesStatus = AppUpdatesStatus.available); + } + else { + setState(() => appUpdatesStatus = AppUpdatesStatus.recheck); + } + } - // Widget generateAppUpdateStatus() { - // if (appUpdatesStatus == AppUpdatesStatus.available) { - // return IconButton( - // onPressed: appConfigProvider.appUpdatesAvailable != null - // ? () async { - // final link = getAppUpdateDownloadLink(appConfigProvider.appUpdatesAvailable!); - // if (link != null) { - // openUrl(link); - // } - // } - // : null, - // icon: const Icon(Icons.download_rounded), - // tooltip: AppLocalizations.of(context)!.downloadUpdate, - // ); - // } - // else if (appUpdatesStatus == AppUpdatesStatus.checking) { - // return const Padding( - // padding: EdgeInsets.only(right: 16), - // child: SizedBox( - // width: 24, - // height: 24, - // child: CircularProgressIndicator( - // strokeWidth: 3, - // ) - // ), - // ); - // } - // else { - // return IconButton( - // onPressed: checkUpdatesAvailable, - // icon: const Icon(Icons.refresh_rounded), - // tooltip: AppLocalizations.of(context)!.checkUpdates, - // ); - // } - // } + Widget generateAppUpdateStatus() { + if (appUpdatesStatus == AppUpdatesStatus.available) { + return IconButton( + onPressed: appConfigProvider.appUpdatesAvailable != null + ? () async { + final link = getAppUpdateDownloadLink(appConfigProvider.appUpdatesAvailable!); + if (link != null) { + openUrl(link); + } + } + : null, + icon: const Icon(Icons.download_rounded), + tooltip: AppLocalizations.of(context)!.downloadUpdate, + ); + } + else if (appUpdatesStatus == AppUpdatesStatus.checking) { + return const Padding( + padding: EdgeInsets.only(right: 16), + child: SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator( + strokeWidth: 3, + ) + ), + ); + } + else { + return IconButton( + onPressed: checkUpdatesAvailable, + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.checkUpdates, + ); + } + } return Scaffold( appBar: AppBar( @@ -246,17 +253,17 @@ class _GeneralSettingsState extends State { right: 10 ) ), - // if (!(Platform.isAndroid || Platform.isIOS) || (Platform.isAndroid && (appConfigProvider.installationSource == InstallationAppReferrer.androidManually ))) ...[ - // SectionLabel(label: AppLocalizations.of(context)!.application), - // CustomListTile( - // icon: Icons.system_update_rounded, - // title: AppLocalizations.of(context)!.appUpdates, - // subtitle: appConfigProvider.appUpdatesAvailable != null - // ? AppLocalizations.of(context)!.updateAvailable - // : AppLocalizations.of(context)!.usingLatestVersion, - // trailing: generateAppUpdateStatus() - // ) - // ] + if (!(Platform.isAndroid || Platform.isIOS) || (Platform.isAndroid && (appConfigProvider.installationSource == InstallationAppReferrer.androidManually ))) ...[ + SectionLabel(label: AppLocalizations.of(context)!.application), + CustomListTile( + icon: Icons.system_update_rounded, + title: AppLocalizations.of(context)!.appUpdates, + subtitle: appConfigProvider.appUpdatesAvailable != null + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.usingLatestVersion, + trailing: generateAppUpdateStatus() + ) + ] ], ), ) diff --git a/lib/screens/settings/logs_settings/config_widgets.dart b/lib/screens/settings/logs_settings/config_widgets.dart index 066f779..002fd96 100644 --- a/lib/screens/settings/logs_settings/config_widgets.dart +++ b/lib/screens/settings/logs_settings/config_widgets.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -13,16 +12,13 @@ class LogsConfigOptions extends StatelessWidget { final void Function(bool) updateGeneralSwitch; final bool anonymizeClientIp; final void Function(bool) updateAnonymizeClientIp; - final List retentionItems; - final String? retentionTime; - final void Function(String?) updateRetentionTime; + final List retentionItems; + final double? retentionTime; + final void Function(double?) updateRetentionTime; final void Function() onClear; final void Function() onConfirm; final List ignoredDomainsControllers; final void Function(List) updateIgnoredDomainsControllers; - final TextEditingController customTimeController; - final String? customTimeError; - final void Function(String) validateCustomTime; const LogsConfigOptions({ super.key, @@ -36,10 +32,7 @@ class LogsConfigOptions extends StatelessWidget { required this.onClear, required this.onConfirm, required this.ignoredDomainsControllers, - required this.updateIgnoredDomainsControllers, - required this.customTimeController, - required this.customTimeError, - required this.validateCustomTime, + required this.updateIgnoredDomainsControllers }); @override @@ -47,7 +40,6 @@ class LogsConfigOptions extends StatelessWidget { const Uuid uuid = Uuid(); final List dropdownItemTranslation = [ - AppLocalizations.of(context)!.custom, AppLocalizations.of(context)!.hours6, AppLocalizations.of(context)!.hours24, AppLocalizations.of(context)!.days7, @@ -56,8 +48,9 @@ class LogsConfigOptions extends StatelessWidget { ]; void validateDomain(String value, String id) { + final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); bool error = false; - if (Regexps.domain.hasMatch(value)) { + if (domainRegex.hasMatch(value)) { error = false; } else { @@ -74,7 +67,7 @@ class LogsConfigOptions extends StatelessWidget { }).toList() ); } -print(retentionTime); + return ListView( children: [ const SizedBox(height: 16), @@ -99,7 +92,7 @@ print(retentionTime); child: Text(dropdownItemTranslation[item.key]), )).toList(), value: retentionTime, - onChanged: (value) => updateRetentionTime(value.toString()), + onChanged: (value) => updateRetentionTime(double.tryParse(value.toString())), decoration: InputDecoration( border: const OutlineInputBorder( borderRadius: BorderRadius.all( @@ -111,24 +104,6 @@ print(retentionTime); borderRadius: BorderRadius.circular(20), ), ), - if (retentionTime == "custom") Padding( - padding: const EdgeInsets.only(top: 24, left: 16, right: 16), - child: TextFormField( - controller: customTimeController, - onChanged: validateCustomTime, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.schedule_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10) - ) - ), - labelText: AppLocalizations.of(context)!.customTimeInHours, - errorText: customTimeError - ), - keyboardType: TextInputType.number, - ), - ), Padding( padding: const EdgeInsets.only(top: 24, bottom: 8), child: Row( diff --git a/lib/screens/settings/logs_settings/logs_settings.dart b/lib/screens/settings/logs_settings/logs_settings.dart index c31304f..0d55ce5 100644 --- a/lib/screens/settings/logs_settings/logs_settings.dart +++ b/lib/screens/settings/logs_settings/logs_settings.dart @@ -37,18 +37,15 @@ class _LogsSettingsState extends State { bool generalSwitch = false; bool anonymizeClientIp = false; - String? retentionTime; + double? retentionTime; List _ignoredDomainsControllers = []; - final _customTimeController = TextEditingController(); - String? _customTimeError = null; - List retentionItems = [ - "custom", - "21600000", - "86400000", - "604800000", - "2592000000", - "7776000000" + List retentionItems = [ + 21600000, + 86400000, + 604800000, + 2592000000, + 7776000000 ]; LoadStatus loadStatus = LoadStatus.loading; @@ -64,10 +61,9 @@ class _LogsSettingsState extends State { setState(() { generalSwitch = data.enabled ?? false; anonymizeClientIp = data.anonymizeClientIp ?? false; - retentionTime = retentionItems.contains(data.interval.toString()) ? data.interval.toString() : "custom"; - if (data.interval != null && !retentionItems.contains(data.interval.toString())) { - _customTimeController.text = (data.interval!/3.6e+6).toInt().toString(); - } + retentionTime = data.interval != null + ? double.parse(data.interval.toString()) + : null; if (data.ignored != null) { _ignoredDomainsControllers = data.ignored!.map((e) => DomainListItemController( id: uuid.v4(), @@ -83,34 +79,6 @@ class _LogsSettingsState extends State { } } - void validateCustomTime(String value) { - try { - final regex = RegExp(r'^\d+$'); - final parsed = int.parse(value); - if (!regex.hasMatch(value)) { - setState(() => _customTimeError = AppLocalizations.of(context)!.invalidTime); - } - else if (parsed < 1) { - setState(() => _customTimeError = AppLocalizations.of(context)!.notLess1Hour); - } - else { - setState(() => _customTimeError = null); - } - } catch (_) { - setState(() => _customTimeError = AppLocalizations.of(context)!.invalidTime); - } - } - - bool checkValidValues() { - if (_ignoredDomainsControllers.where((d) => d.controller.text == "" || d.error == true).isNotEmpty) { - return false; - } - if (retentionTime == "custom" && (_customTimeError != null || _customTimeController.text == "")) { - return false; - } - return true; - } - @override void initState() { loadData(); @@ -122,7 +90,9 @@ class _LogsSettingsState extends State { final serversProvider = Provider.of(context); final appConfigProvider = Provider.of(context); - final validValues = checkValidValues(); + final validValues = _ignoredDomainsControllers.where( + (d) => d.controller.text == "" || d.error == true + ).isEmpty; void clearQueries() async { ProcessModal processModal = ProcessModal(); @@ -157,7 +127,7 @@ class _LogsSettingsState extends State { final result = await serversProvider.apiClient2!.updateQueryLogParameters( data: { "enabled": generalSwitch, - "interval": retentionTime == "custom" ? int.parse(_customTimeController.text)*3.6e+6 : int.parse(retentionTime!) , + "interval": retentionTime, "anonymize_client_ip": anonymizeClientIp, "ignored": _ignoredDomainsControllers.map((e) => e.controller.text).toList() } @@ -228,9 +198,6 @@ class _LogsSettingsState extends State { onConfirm: updateConfig, ignoredDomainsControllers: _ignoredDomainsControllers, updateIgnoredDomainsControllers: (v) => setState(() => _ignoredDomainsControllers = v), - customTimeController: _customTimeController, - customTimeError: _customTimeError, - validateCustomTime: validateCustomTime, ); case LoadStatus.error: diff --git a/lib/screens/settings/settings.dart b/lib/screens/settings/settings.dart index 6c388cf..0f55b89 100644 --- a/lib/screens/settings/settings.dart +++ b/lib/screens/settings/settings.dart @@ -1,6 +1,8 @@ +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:adguard_home_manager/screens/settings/server_info/server_info.dart'; @@ -23,6 +25,7 @@ import 'package:adguard_home_manager/widgets/section_label.dart'; import 'package:adguard_home_manager/widgets/custom_list_tile.dart'; import 'package:adguard_home_manager/functions/desktop_mode.dart'; +import 'package:adguard_home_manager/constants/strings.dart'; import 'package:adguard_home_manager/functions/open_url.dart'; import 'package:adguard_home_manager/constants/urls.dart'; import 'package:adguard_home_manager/providers/status_provider.dart'; @@ -270,18 +273,37 @@ class _SettingsWidgetState extends State<_SettingsWidget> { subtitle: appConfigProvider.getAppInfo!.version, ), CustomListTile( - title: AppLocalizations.of(context)!.applicationDetails, - subtitle: AppLocalizations.of(context)!.applicationDetailsDescription, - trailing: Icon(Icons.open_in_new_rounded), - onTap: () => openUrl(Urls.appDetailsWebpage), + title: AppLocalizations.of(context)!.createdBy, + subtitle: Strings.createdBy, ), - CustomListTile( - title: AppLocalizations.of(context)!.myOtherApps, - subtitle: AppLocalizations.of(context)!.myOtherAppsDescription, - trailing: Icon(Icons.open_in_new_rounded), - onTap: () => openUrl(Urls.jgeek00AppsWebpage), - ), - SizedBox(height: 16) + Padding( + padding: const EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if (Platform.isAndroid) IconButton( + onPressed: () => openUrl(Urls.playStore), + icon: SvgPicture.asset( + 'assets/resources/google-play.svg', + color: Theme.of(context).colorScheme.onSurfaceVariant, + width: 30, + height: 30, + ), + tooltip: AppLocalizations.of(context)!.visitGooglePlay, + ), + IconButton( + onPressed: () => openUrl(Urls.gitHub), + icon: SvgPicture.asset( + 'assets/resources/github.svg', + color: Theme.of(context).colorScheme.onSurfaceVariant, + width: 30, + height: 30, + ), + tooltip: AppLocalizations.of(context)!.gitHub, + ), + ], + ), + ) ], ) ], diff --git a/lib/screens/settings/statistics_settings/statistics_settings.dart b/lib/screens/settings/statistics_settings/statistics_settings.dart index 84439b1..67a2989 100644 --- a/lib/screens/settings/statistics_settings/statistics_settings.dart +++ b/lib/screens/settings/statistics_settings/statistics_settings.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; import 'package:provider/provider.dart'; @@ -92,8 +91,9 @@ class _StatisticsSettingsState extends State { void validateDomain(String value, String id) { + final domainRegex = RegExp(r'^([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+$'); bool error = false; - if (Regexps.domain.hasMatch(value)) { + if (domainRegex.hasMatch(value)) { error = false; } else { @@ -138,7 +138,7 @@ class _StatisticsSettingsState extends State { "enabled": _generalSwitch, "interval": _retentionTime == "custom" ? Duration(hours: int.parse(_customTimeController.text)).inMilliseconds - : int.parse(_retentionTime ?? _retentionItems[0]), + : int.parse(_retentionTime!), "ignored": _ignoredDomainsControllers.map((e) => e.controller.text).toList() } ); diff --git a/lib/screens/settings/update_server/update_screen.dart b/lib/screens/settings/update_server/update_screen.dart index ae894f8..4ddc959 100644 --- a/lib/screens/settings/update_server/update_screen.dart +++ b/lib/screens/settings/update_server/update_screen.dart @@ -218,110 +218,101 @@ class _Header extends SliverPersistentHeaderDelegate { final iconBottom = _iconMinBottomPositionExent + (iconMaxBottomPositionExent-iconMinBottomPositionExent)*(1-iconPercentage); return LayoutBuilder( - builder: (context, constraints) => Stack( - children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - ), - ), - Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceTint.withOpacity(0.075), - ), - child: Align( - alignment: Alignment.topLeft, - child: SafeArea( - bottom: false, - child: Stack( - fit: StackFit.expand, - alignment: Alignment.center, - children: [ - if (Navigator.of(context).canPop()) Positioned( - top: 8, - left: 0, - child: BackButton( - onPressed: () => Navigator.pop(context), - ), - ), - Positioned( - top: 8, - right: 0, - child: IconButton( - onPressed: onRefresh, - icon: const Icon(Icons.refresh_rounded), - tooltip: AppLocalizations.of(context)!.refresh, - ) - ), - Positioned( - bottom: iconBottom, - left: (constraints.maxWidth/2)-(_iconSize/2), - child: Opacity( - opacity: 1-iconPercentage, - child: serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? const Column( - children: [ - CircularProgressIndicator(), - SizedBox(height: 4) - ], - ) - : Icon( - serversProvider.updateAvailable.data!.canAutoupdate == true - ? Icons.system_update_rounded - : Icons.system_security_update_good_rounded, - size: _iconSize, - color: Theme.of(context).colorScheme.primary, - ), - ), - ), - Positioned( - bottom: mainText, - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: constraints.maxWidth-100 - ), - child: Text( - serversProvider.updateAvailable.loadStatus == LoadStatus.loading - ? AppLocalizations.of(context)!.checkingUpdates - : serversProvider.updateAvailable.data!.canAutoupdate == true - ? AppLocalizations.of(context)!.updateAvailable - : AppLocalizations.of(context)!.serverUpdated, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: textFontSize, - fontWeight: FontWeight.w400 - ), - ), - ) - ), - Positioned( - bottom: versionText, - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: constraints.maxWidth-100 - ), - child: Opacity( - opacity: 1-iconPercentage, - child: Text( - serversProvider.updateAvailable.data!.canAutoupdate == true - ? "${AppLocalizations.of(context)!.newVersion}: ${serversProvider.updateAvailable.data!.newVersion ?? 'N/A'}" - : "${AppLocalizations.of(context)!.installedVersion}: ${serversProvider.updateAvailable.data!.currentVersion}", - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - color: Theme.of(context).colorScheme.onSurfaceVariant - ), - ), - ), - ) - ) - ], + builder: (context, constraints) => Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainerHighest, + ), + child: Align( + alignment: Alignment.topLeft, + child: SafeArea( + bottom: false, + child: Stack( + fit: StackFit.expand, + alignment: Alignment.center, + children: [ + if (Navigator.of(context).canPop()) Positioned( + top: 8, + left: 0, + child: BackButton( + onPressed: () => Navigator.pop(context), + ), ), - ), + Positioned( + top: 8, + right: 0, + child: IconButton( + onPressed: onRefresh, + icon: const Icon(Icons.refresh_rounded), + tooltip: AppLocalizations.of(context)!.refresh, + ) + ), + Positioned( + bottom: iconBottom, + left: (constraints.maxWidth/2)-(_iconSize/2), + child: Opacity( + opacity: 1-iconPercentage, + child: serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? const Column( + children: [ + CircularProgressIndicator(), + SizedBox(height: 4) + ], + ) + : Icon( + serversProvider.updateAvailable.data!.canAutoupdate == true + ? Icons.system_update_rounded + : Icons.system_security_update_good_rounded, + size: _iconSize, + color: Theme.of(context).colorScheme.primary, + ), + ), + ), + Positioned( + bottom: mainText, + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth-100 + ), + child: Text( + serversProvider.updateAvailable.loadStatus == LoadStatus.loading + ? AppLocalizations.of(context)!.checkingUpdates + : serversProvider.updateAvailable.data!.canAutoupdate == true + ? AppLocalizations.of(context)!.updateAvailable + : AppLocalizations.of(context)!.serverUpdated, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: textFontSize, + fontWeight: FontWeight.w400 + ), + ), + ) + ), + Positioned( + bottom: versionText, + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: constraints.maxWidth-100 + ), + child: Opacity( + opacity: 1-iconPercentage, + child: Text( + serversProvider.updateAvailable.data!.canAutoupdate == true + ? "${AppLocalizations.of(context)!.newVersion}: ${serversProvider.updateAvailable.data!.newVersion ?? 'N/A'}" + : "${AppLocalizations.of(context)!.installedVersion}: ${serversProvider.updateAvailable.data!.currentVersion}", + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + color: Theme.of(context).colorScheme.onSurfaceVariant + ), + ), + ), + ) + ) + ], ), ), - ], + ), ), ); } diff --git a/lib/widgets/add_server/add_server_functions.dart b/lib/widgets/add_server/add_server_functions.dart index bbb88fd..6dd9c38 100644 --- a/lib/widgets/add_server/add_server_functions.dart +++ b/lib/widgets/add_server/add_server_functions.dart @@ -1,4 +1,3 @@ -import 'package:adguard_home_manager/constants/regexps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -50,7 +49,8 @@ String? validateSubroute({ required String? value }) { if (value != null && value != '') { - if (Regexps.subroute.hasMatch(value) == true) { + RegExp subrouteRegexp = RegExp(r'^\/\b([A-Za-z0-9_\-~/]*)[^\/|\.|\:]$'); + if (subrouteRegexp.hasMatch(value) == true) { return null; } else { @@ -67,7 +67,9 @@ String? validateAddress({ required String? value }) { if (value != null && value != '') { - if (Regexps.ipv4Address.hasMatch(value) == true || Regexps.domain.hasMatch(value) == true) { + RegExp ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); + RegExp domain = RegExp(r'^(([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+)$'); + if (ipAddress.hasMatch(value) == true || domain.hasMatch(value) == true) { return null; } else { diff --git a/lib/widgets/add_server/add_server_modal.dart b/lib/widgets/add_server/add_server_modal.dart index a7fc768..ec00ff6 100644 --- a/lib/widgets/add_server/add_server_modal.dart +++ b/lib/widgets/add_server/add_server_modal.dart @@ -142,7 +142,6 @@ class _AddServerModalState extends State { port: portController.text != '' ? int.parse(portController.text) : null, user: userController.text != "" ? userController.text : null, password: passwordController.text != "" ? passwordController.text : null, - path: pathController.text != "" ? pathController.text : null, defaultServer: defaultServer, authToken: homeAssistant == true ? encodeBase64UserPass(userController.text, passwordController.text) @@ -175,8 +174,6 @@ class _AddServerModalState extends State { final ApiClientV2 apiClient2 = ApiClientV2(server: serverObj); final serverStatus = await apiClient2.getServerStatus(); - if (!context.mounted) return; - // If something goes wrong when fetching server status if (serverStatus.successful == false) { statusProvider.setServerStatusLoad(LoadStatus.error); @@ -205,16 +202,16 @@ class _AddServerModalState extends State { final serverCreated = await serversProvider.createServer(serverObj); - if (!context.mounted) return; - // If something goes wrong when saving the connection on the db if (serverCreated != null) { - setState(() => isConnecting = false); - showSnackbar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionNotCreated, - color: Colors.red - ); + if (mounted) setState(() => isConnecting = false); + if (mounted) { + showSnackbar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionNotCreated, + color: Colors.red + ); + } return; } @@ -297,12 +294,10 @@ class _AddServerModalState extends State { } final serverSaved = await serversProvider.editServer(serverObj); - - if (!mounted) return; // If something goes wrong when saving the connection on the db if (serverSaved != null) { - setState(() => isConnecting = false); + if (mounted) setState(() => isConnecting = false); appConfigProvider.addLog( AppLog( type: 'save_connection_db', @@ -310,11 +305,13 @@ class _AddServerModalState extends State { message: serverSaved.toString() ) ); - showSnackbar( - appConfigProvider: appConfigProvider, - label: AppLocalizations.of(context)!.connectionNotCreated, - color: Colors.red - ); + if (mounted) { + showSnackbar( + appConfigProvider: appConfigProvider, + label: AppLocalizations.of(context)!.connectionNotCreated, + color: Colors.red + ); + } return; } diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index 119bee1..9a42415 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -1,10 +1,14 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:adguard_home_manager/widgets/update_modal.dart'; import 'package:adguard_home_manager/widgets/system_ui_overlay_style.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/providers/app_config_provider.dart'; import 'package:adguard_home_manager/config/app_screens.dart'; import 'package:adguard_home_manager/config/sizes.dart'; @@ -33,23 +37,23 @@ class _LayoutState extends State with WidgetsBindingObserver { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { - // if (kDebugMode) return; // Don't check for app updates on debug mode - // 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 && appConfigProvider.doNotRememberVersion != result.tagName && mounted) { - // await showDialog( - // context: context, - // builder: (context) => UpdateModal( - // gitHubRelease: result, - // onDownload: (link, version) => openUrl(link), - // ), - // ); - // } + if (kDebugMode) return; // Don't check for app updates on debug mode + 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 && appConfigProvider.doNotRememberVersion != result.tagName && mounted) { + await showDialog( + context: context, + builder: (context) => UpdateModal( + gitHubRelease: result, + onDownload: (link, version) => openUrl(link), + ), + ); + } }); } diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 4fbee04..fd3f3f5 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,7 +7,7 @@ #include "generated_plugin_registrant.h" #include -#include +#include #include #include #include @@ -17,9 +17,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); - g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin"); - screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar); + g_autoptr(FlPluginRegistrar) screen_retriever_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin"); + screen_retriever_plugin_register_with_registrar(screen_retriever_registrar); g_autoptr(FlPluginRegistrar) sentry_flutter_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin"); sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 787cc64..307410d 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,7 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color - screen_retriever_linux + screen_retriever sentry_flutter sqlite3_flutter_libs url_launcher_linux diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 69e9dbc..28ea475 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,10 +8,10 @@ import Foundation import device_info_plus import dynamic_color import package_info_plus -import screen_retriever_macos +import screen_retriever import sentry_flutter import shared_preferences_foundation -import sqflite_darwin +import sqflite import sqlite3_flutter_libs import url_launcher_macos import window_manager @@ -20,7 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) - ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin")) + ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index ae5c12f..54fe2f5 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -6,38 +6,39 @@ PODS: - FlutterMacOS (1.0.0) - package_info_plus (0.0.1): - FlutterMacOS - - screen_retriever_macos (0.0.1): + - screen_retriever (0.0.1): - FlutterMacOS - - Sentry/HybridSDK (8.44.0) - - sentry_flutter (8.13.2): + - Sentry/HybridSDK (8.35.1) + - sentry_flutter (8.8.0): - Flutter - FlutterMacOS - - Sentry/HybridSDK (= 8.44.0) + - Sentry/HybridSDK (= 8.35.1) - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - sqflite_darwin (0.0.4): + - sqflite (0.0.3): - Flutter - FlutterMacOS - - sqlite3 (3.49.1): - - sqlite3/common (= 3.49.1) - - sqlite3/common (3.49.1) - - sqlite3/dbstatvtab (3.49.1): + - "sqlite3 (3.46.1+1)": + - "sqlite3/common (= 3.46.1+1)" + - "sqlite3/common (3.46.1+1)" + - "sqlite3/dbstatvtab (3.46.1+1)": - sqlite3/common - - sqlite3/fts5 (3.49.1): + - "sqlite3/fts5 (3.46.1+1)": - sqlite3/common - - sqlite3/perf-threadsafe (3.49.1): + - "sqlite3/perf-threadsafe (3.46.1+1)": - sqlite3/common - - sqlite3/rtree (3.49.1): + - "sqlite3/rtree (3.46.1+1)": - sqlite3/common - sqlite3_flutter_libs (0.0.1): - - Flutter - FlutterMacOS - - sqlite3 (~> 3.49.1) + - "sqlite3 (~> 3.46.0+1)" - sqlite3/dbstatvtab - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree + - store_checker (0.0.1): + - FlutterMacOS - url_launcher_macos (0.0.1): - FlutterMacOS - window_manager (0.2.0): @@ -48,11 +49,12 @@ DEPENDENCIES: - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - - screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`) + - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) - sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) - - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`) + - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) + - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) + - store_checker (from `Flutter/ephemeral/.symlinks/plugins/store_checker/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) @@ -70,34 +72,37 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral package_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos - screen_retriever_macos: - :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos + screen_retriever: + :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos sentry_flutter: :path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin - sqflite_darwin: - :path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin + sqflite: + :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin sqlite3_flutter_libs: - :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin + :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos + store_checker: + :path: Flutter/ephemeral/.symlinks/plugins/store_checker/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_manager: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: - device_info_plus: 1b14eed9bf95428983aed283a8d51cce3d8c4215 + device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720 dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b - screen_retriever_macos: 776e0fa5d42c6163d2bf772d22478df4b302b161 - Sentry: 0f9bc9adfc0b960e7f3bb5ec67e9a3d8193f3bdb - sentry_flutter: 64a43fb39ab4c7f67d8a4cad52b49e22439e58b7 + package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c + screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 + Sentry: 1fe34e9c2cbba1e347623610d26db121dcb569f1 + sentry_flutter: a39c2a2d67d5e5b9cb0b94a4985c76dd5b3fc737 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d - sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983 - sqlite3_flutter_libs: cc304edcb8e1d8c595d1b08c7aeb46a47691d9db - url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb + sqlite3_flutter_libs: 5ca46c1a04eddfbeeb5b16566164aa7ad1616e7b + store_checker: 387169de0dffe57b6370d54cc027e9f95051b57f + url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index dcd4e29..6982a10 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -48,7 +48,6 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" - enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift index b3c1761..8e02df2 100644 --- a/macos/Runner/AppDelegate.swift +++ b/macos/Runner/AppDelegate.swift @@ -6,8 +6,4 @@ class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } } diff --git a/pubspec.lock b/pubspec.lock index 207783c..e7c67eb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,42 +29,42 @@ packages: dependency: transitive description: name: archive - sha256: "7dcbd0f87fe5f61cb28da39a1a8b70dbc106e2fe0516f7836eb7bb2948481a12" + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "4.0.5" + version: "3.6.1" args: dependency: transitive description: name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.5.0" async: dependency: "direct main" description: name: async - sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.12.0" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" characters: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.0" checked_yaml: dependency: transitive description: @@ -77,26 +77,26 @@ packages: dependency: transitive description: name: cli_util - sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 url: "https://pub.dev" source: hosted - version: "0.4.2" + version: "0.4.1" clock: dependency: transitive description: name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.1" collection: dependency: transitive description: name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.19.1" + version: "1.18.0" contextmenu: dependency: "direct main" description: @@ -109,18 +109,18 @@ packages: dependency: transitive description: name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.5" csslib: dependency: transitive description: name: csslib - sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "0.17.3" cupertino_icons: dependency: "direct main" description: @@ -133,18 +133,18 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "306b78788d1bb569edb7c55d622953c2414ca12445b41c9117963e03afc5c513" + sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 url: "https://pub.dev" source: hosted - version: "11.3.3" + version: "10.1.2" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2" + sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" url: "https://pub.dev" source: hosted - version: "7.0.2" + version: "7.0.1" dynamic_color: dependency: "direct main" description: @@ -157,10 +157,10 @@ packages: dependency: transitive description: name: equatable - sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.5" expandable: dependency: "direct main" description: @@ -173,42 +173,42 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.1" ffi: dependency: transitive description: name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.3" file: dependency: transitive description: name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "7.0.0" fixnum: dependency: transitive description: name: fixnum - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.0" fl_chart: dependency: "direct main" description: name: fl_chart - sha256: "5276944c6ffc975ae796569a826c38a62d2abcf264e26b88fa6f482e107f4237" + sha256: "94307bef3a324a0d329d3ab77b2f0c6e5ed739185ffc029ed28c0f9b019ea7ef" url: "https://pub.dev" source: hosted - version: "0.70.2" + version: "0.69.0" flutter: dependency: "direct main" description: flutter @@ -254,38 +254,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + flutter_displaymode: + dependency: "direct main" + description: + name: flutter_displaymode + sha256: "42c5e9abd13d28ed74f701b60529d7f8416947e58256e6659c5550db719c57ef" + url: "https://pub.dev" + source: hosted + version: "0.6.0" flutter_dotenv: dependency: "direct main" description: name: flutter_dotenv - sha256: b7c7be5cd9f6ef7a78429cabd2774d3c4af50e79cb2b7593e3d5d763ef95c61b + sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77" url: "https://pub.dev" source: hosted - version: "5.2.1" + version: "5.1.0" flutter_html: dependency: "direct main" description: name: flutter_html - sha256: "38a2fd702ffdf3243fb7441ab58aa1bc7e6922d95a50db76534de8260638558d" + sha256: "02ad69e813ecfc0728a455e4bf892b9379983e050722b1dce00192ee2e41d1ee" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.0-beta.2" flutter_launcher_icons: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: bfa04787c85d80ecb3f8777bde5fc10c3de809240c48fa061a2c2bf15ea5211c + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" url: "https://pub.dev" source: hosted - version: "0.14.3" + version: "0.13.1" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "4.0.0" flutter_localizations: dependency: "direct main" description: flutter @@ -295,18 +303,18 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: e7bbc718adc9476aa14cfddc1ef048d2e21e4e8f18311aaac723266db9f9e7b5 + sha256: a23c41ee57573e62fc2190a1f36a0480c4d90bde3a8a8d7126e5d5992fb53fb7 url: "https://pub.dev" source: hosted - version: "0.7.6+2" + version: "0.7.3+1" flutter_native_splash: dependency: "direct dev" description: name: flutter_native_splash - sha256: edb09c35ee9230c4b03f13dd45bb3a276d0801865f0a4650b7e2a3bba61a803a + sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840 url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.4.1" flutter_reorderable_list: dependency: "direct main" description: @@ -319,10 +327,10 @@ packages: dependency: "direct main" description: name: flutter_svg - sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -337,34 +345,42 @@ packages: dependency: "direct main" description: name: html - sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec" + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" url: "https://pub.dev" source: hosted - version: "0.15.5" + version: "0.15.4" http: dependency: "direct main" description: name: http - sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.2.2" http_parser: dependency: transitive description: name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" url: "https://pub.dev" source: hosted - version: "4.1.2" + version: "4.0.2" image: dependency: transitive description: name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" url: "https://pub.dev" source: hosted - version: "4.5.4" + version: "4.2.0" + install_referrer: + dependency: "direct main" + description: + name: install_referrer + sha256: "901c56d24ee3c3010dfd0bbebf305ed6b4b0f3fe969192081c167590a64cd78b" + url: "https://pub.dev" + source: hosted + version: "1.2.1" intl: dependency: "direct main" description: @@ -385,18 +401,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -409,10 +425,10 @@ packages: dependency: transitive description: name: lints - sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "4.0.0" list_counter: dependency: transitive description: @@ -425,18 +441,18 @@ packages: dependency: "direct main" description: name: markdown - sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" + sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051 url: "https://pub.dev" source: hosted - version: "7.3.0" + version: "7.2.2" matcher: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: @@ -449,10 +465,10 @@ packages: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.15.0" nested: dependency: transitive description: @@ -465,34 +481,34 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" + sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918 url: "https://pub.dev" source: hosted - version: "8.3.0" + version: "8.0.2" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" + sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.0.1" path: dependency: transitive description: name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.9.0" path_parsing: dependency: transitive description: name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.0.1" path_provider_linux: dependency: transitive description: @@ -521,18 +537,18 @@ packages: dependency: "direct main" description: name: percent_indicator - sha256: "0d77d5c6fa9b7f60202cedf748b568ba9ba38d3f30405d6ceae4da76f5185462" + sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "4.2.3" petitparser: dependency: transitive description: name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.0.2" pie_chart: dependency: "direct main" description: @@ -545,10 +561,10 @@ packages: dependency: transitive description: name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.6" + version: "3.1.5" plugin_platform_interface: dependency: transitive description: @@ -557,14 +573,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - posix: - dependency: transitive - description: - name: posix - sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a - url: "https://pub.dev" - source: hosted - version: "6.0.1" provider: dependency: "direct main" description: @@ -577,42 +585,10 @@ packages: dependency: transitive description: name: screen_retriever - sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" + sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90" url: "https://pub.dev" source: hosted - version: "0.2.0" - screen_retriever_linux: - dependency: transitive - description: - name: screen_retriever_linux - sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_macos: - dependency: transitive - description: - name: screen_retriever_macos - sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_platform_interface: - dependency: transitive - description: - name: screen_retriever_platform_interface - sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 - url: "https://pub.dev" - source: hosted - version: "0.2.0" - screen_retriever_windows: - dependency: transitive - description: - name: screen_retriever_windows - sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" - url: "https://pub.dev" - source: hosted - version: "0.2.0" + version: "0.1.9" segmented_button_slide: dependency: "direct main" description: @@ -625,42 +601,42 @@ packages: dependency: transitive description: name: sentry - sha256: "3a64dd001bff768ce5ab6fc3608deef4dde22acd4b5d947763557b20db9e2a32" + sha256: "1af8308298977259430d118ab25be8e1dda626cdefa1e6ce869073d530d39271" url: "https://pub.dev" source: hosted - version: "8.14.0" + version: "8.8.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "3d361f2d5f805783e2e4ed1bd475ef126b36cf525b359dc3627a765a3fb7424d" + sha256: "18fe4d125c2d529bd6127200f0d2895768266a8c60b4fb50b2086fd97e1a4ab2" url: "https://pub.dev" source: hosted - version: "8.14.0" + version: "8.8.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a" + sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.3.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "3ec7210872c4ba945e3244982918e502fa2bfb5230dff6832459ca0e1879b7ad" + sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" url: "https://pub.dev" source: hosted - version: "2.4.8" + version: "2.3.2" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f url: "https://pub.dev" source: hosted - version: "2.5.4" + version: "2.5.2" shared_preferences_linux: dependency: transitive description: @@ -681,10 +657,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.2" shared_preferences_windows: dependency: transitive description: @@ -697,15 +673,15 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.0" + version: "0.0.99" source_span: dependency: transitive description: name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.10.1" + version: "1.10.0" sprintf: dependency: transitive description: @@ -718,130 +694,106 @@ packages: dependency: "direct main" description: name: sqflite - sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d url: "https://pub.dev" source: hosted - version: "2.4.2" - sqflite_android: - dependency: transitive - description: - name: sqflite_android - sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b" - url: "https://pub.dev" - source: hosted - version: "2.4.1" + version: "2.3.3+1" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "84731e8bfd8303a3389903e01fb2141b6e59b5973cacbb0929021df08dddbe8b" + sha256: "7b41b6c3507854a159e24ae90a8e3e9cc01eb26a477c118d6dca065b5f55453e" url: "https://pub.dev" source: hosted - version: "2.5.5" + version: "2.5.4+2" sqflite_common_ffi: dependency: "direct main" description: name: sqflite_common_ffi - sha256: "1f3ef3888d3bfbb47785cc1dda0dc7dd7ebd8c1955d32a9e8e9dae1e38d1c4c1" + sha256: "4d6137c29e930d6e4a8ff373989dd9de7bac12e3bc87bce950f6e844e8ad3bb5" url: "https://pub.dev" source: hosted - version: "2.3.5" - sqflite_darwin: - dependency: transitive - description: - name: sqflite_darwin - sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" - url: "https://pub.dev" - source: hosted - version: "2.4.2" - sqflite_platform_interface: - dependency: transitive - description: - name: sqflite_platform_interface - sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" - url: "https://pub.dev" - source: hosted - version: "2.4.0" + version: "2.3.3" sqlite3: dependency: transitive description: name: sqlite3 - sha256: "310af39c40dd0bb2058538333c9d9840a2725ae0b9f77e4fd09ad6696aa8f66e" + sha256: "45f168ae2213201b54e09429ed0c593dc2c88c924a1488d6f9c523a255d567cb" url: "https://pub.dev" source: hosted - version: "2.7.5" + version: "2.4.6" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - sha256: "1a96b59227828d9eb1463191d684b37a27d66ee5ed7597fcf42eee6452c88a14" + sha256: "62bbb4073edbcdf53f40c80775f33eea01d301b7b81417e5b3fb7395416258c1" url: "https://pub.dev" source: hosted - version: "0.5.32" + version: "0.5.24" stack_trace: dependency: transitive description: name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.12.1" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.2" string_scanner: dependency: transitive description: name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.2.0" synchronized: dependency: transitive description: name: synchronized - sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6" + sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.2.0" term_glyph: dependency: transitive description: name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.2" timezone: dependency: "direct main" description: name: timezone - sha256: ffc9d5f4d1193534ef051f9254063fa53d588609418c84299956c3db9383587d + sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" url: "https://pub.dev" source: hosted - version: "0.10.0" + version: "0.9.4" typed_data: dependency: transitive description: name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.2" universal_io: dependency: transitive description: @@ -854,42 +806,42 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.0" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "1d0eae19bd7606ef60fe69ef3b312a437a16549476c42321d5dc1506c9ca3bf4" + sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab url: "https://pub.dev" source: hosted - version: "6.3.15" + version: "6.3.10" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e url: "https://pub.dev" source: hosted - version: "6.3.2" + version: "6.3.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.0" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.2.0" url_launcher_platform_interface: dependency: transitive description: @@ -902,50 +854,50 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.3.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.2" uuid: dependency: "direct main" description: name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "4.5.0" vector_graphics: dependency: transitive description: name: vector_graphics - sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de" + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" url: "https://pub.dev" source: hosted - version: "1.1.18" + version: "1.1.11+1" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da url: "https://pub.dev" source: hosted - version: "1.1.13" + version: "1.1.11+1" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" url: "https://pub.dev" source: hosted - version: "1.1.16" + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -958,50 +910,50 @@ packages: dependency: transitive description: name: vm_service - sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.3.1" + version: "14.2.5" web: dependency: transitive description: name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.0.0" win32: dependency: transitive description: name: win32 - sha256: dc6ecaa00a7c708e5b4d10ee7bec8c270e9276dfcab1783f57e9962d7884305f + sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a" url: "https://pub.dev" source: hosted - version: "5.12.0" + version: "5.5.4" win32_registry: dependency: transitive description: name: win32_registry - sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae" + sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "1.1.4" window_manager: dependency: "direct main" description: name: window_manager - sha256: "732896e1416297c63c9e3fb95aea72d0355f61390263982a47fd519169dc5059" + sha256: ab8b2a7f97543d3db2b506c9d875e637149d48ee0c6a5cb5f5fd6e0dac463792 url: "https://pub.dev" source: hosted - version: "0.4.3" + version: "0.4.2" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.0.4" xml: dependency: transitive description: @@ -1014,10 +966,10 @@ packages: dependency: transitive description: name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.2" sdks: - dart: ">=3.7.0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index 2fffd97..f821dbf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 2.20.4+151 +version: 2.19.0+143 environment: sdk: '>=2.18.1 <3.0.0' @@ -42,12 +42,13 @@ dependencies: provider: ^6.1.1 sqflite: ^2.3.0 package_info_plus: ^8.0.0 + flutter_displaymode: ^0.6.0 dynamic_color: ^1.7.0 animations: ^2.0.10 - device_info_plus: ^11.2.1 + device_info_plus: ^10.1.0 uuid: ^4.2.1 expandable: ^5.0.1 - fl_chart: ^0.70.2 + fl_chart: ^0.69.0 flutter_svg: ^2.0.9 percent_indicator: ^4.2.3 flutter_markdown: ^0.7.1 @@ -64,11 +65,12 @@ dependencies: pie_chart: ^5.4.0 segmented_button_slide: ^2.0.0 http: ^1.1.2 - timezone: ^0.10.0 + timezone: ^0.9.2 flutter_custom_tabs: ^2.0.0+1 url_launcher: ^6.2.4 shared_preferences: ^2.2.2 window_manager: ^0.4.2 + install_referrer: ^1.2.1 dev_dependencies: flutter_test: @@ -79,8 +81,8 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^5.0.0 - flutter_launcher_icons: ^0.14.1 + flutter_lints: ^4.0.0 + flutter_launcher_icons: ^0.13.1 flutter_native_splash: ^2.3.8 # For information on the generic Dart part of this file, see the diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index b0ea5ac..683e616 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,7 +7,7 @@ #include "generated_plugin_registrant.h" #include -#include +#include #include #include #include @@ -16,8 +16,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { DynamicColorPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); - ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); + ScreenRetrieverPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); SentryFlutterPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("SentryFlutterPlugin")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 5ab1216..b2ba396 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,7 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color - screen_retriever_windows + screen_retriever sentry_flutter sqlite3_flutter_libs url_launcher_windows diff --git a/windows/innosetup_installer_builder.iss b/windows/innosetup_installer_builder.iss index ed5df88..b2a93ce 100644 --- a/windows/innosetup_installer_builder.iss +++ b/windows/innosetup_installer_builder.iss @@ -41,6 +41,7 @@ Source: "..\build\windows\x64\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Source: "..\build\windows\x64\runner\Release\dynamic_color_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\screen_retriever_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\build\windows\x64\runner\Release\sentry_flutter_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\sqlite3_flutter_libs_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\build\windows\x64\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion