Merge pull request #707 from revanced/dev
chore: merge branch `dev` to `flutter`
114
.github/workflows/commit-build.yml
vendored
@ -1,35 +1,104 @@
|
|||||||
name: "Android CI Actions"
|
name: Android Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "**"
|
- "**"
|
||||||
tags-ignore:
|
tags-ignore:
|
||||||
- "v*" # Ignore tags that start with "v" (e.g. v1.0.0) because they are handled by release-build.yml
|
- "v*"
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- "**"
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
version:
|
||||||
|
name: Create version number
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set env
|
|
||||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
|
||||||
- name: Set up JDK 12
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
with:
|
||||||
java-version: '12'
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Fetch all history for all tags and branches
|
||||||
|
run: |
|
||||||
|
git config remote.origin.url https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
|
||||||
|
git fetch --prune --depth=10000
|
||||||
|
|
||||||
|
- name: Install GitVersion
|
||||||
|
uses: gittools/actions/gitversion/setup@v0.9.7
|
||||||
|
with:
|
||||||
|
versionSpec: "5.x"
|
||||||
|
|
||||||
|
- name: Use GitVersion
|
||||||
|
id: gitversion
|
||||||
|
uses: gittools/actions/gitversion/execute@v0.9.7
|
||||||
|
|
||||||
|
- name: Create version.txt with nuGetVersion
|
||||||
|
run: echo ${{ steps.gitversion.outputs.nuGetVersion }} > version.txt
|
||||||
|
|
||||||
|
- name: Upload version.txt
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: gitversion
|
||||||
|
path: version.txt
|
||||||
|
|
||||||
|
build:
|
||||||
|
name: Create Android Build
|
||||||
|
needs: version
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Get version.txt
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: gitversion
|
||||||
|
|
||||||
|
- name: Create new file without newline char from version.txt
|
||||||
|
run: tr -d '\n' < version.txt > version1.txt
|
||||||
|
|
||||||
|
- name: Read version
|
||||||
|
id: version
|
||||||
|
uses: juliangruber/read-file-action@v1
|
||||||
|
with:
|
||||||
|
path: version1.txt
|
||||||
|
|
||||||
|
- name: Update version in YAML
|
||||||
|
run: sed -i 's/99.99.99+99/${{ steps.version.outputs.content }}+${{ github.run_number }}/g' pubspec.yaml
|
||||||
|
|
||||||
|
- name: Download Android keystore
|
||||||
|
id: android_keystore
|
||||||
|
uses: timheuer/base64-to-file@v1.0.3
|
||||||
|
with:
|
||||||
|
fileName: upload-keystore.jks
|
||||||
|
encodedString: ${{ secrets.SIGNING_KEYSTORE }}
|
||||||
|
|
||||||
|
- name: Create key.properties
|
||||||
|
run: |
|
||||||
|
echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > android/key.properties
|
||||||
|
echo "storePassword=${{ secrets.SIGNING_KEYSTORE_PASSWORD }}" >> android/key.properties
|
||||||
|
echo "keyPassword=${{ secrets.SIGNING_KEY_PASSWORD }}" >> android/key.properties
|
||||||
|
echo "keyAlias=${{ secrets.SIGNING_KEY_ALIAS }}" >> android/key.properties
|
||||||
|
|
||||||
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
distribution: 'zulu'
|
distribution: 'zulu'
|
||||||
|
java-version: "12.x"
|
||||||
|
cache: gradle
|
||||||
|
|
||||||
- uses: subosito/flutter-action@v2
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
- name: Set environment variables
|
cache: true
|
||||||
run: echo $SECRETS | base64 -d > lib/utils/environment.dart
|
|
||||||
env:
|
- name: Get dependencies
|
||||||
SECRETS: ${{ secrets.SECRETS }}
|
|
||||||
- name: Set up Flutter
|
|
||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
|
|
||||||
- name: Generate files with Builder
|
- name: Generate files with Builder
|
||||||
run: flutter packages pub run build_runner build --delete-conflicting-outputs
|
run: flutter packages pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
- name: Build with Flutter
|
- name: Build with Flutter
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@ -37,6 +106,7 @@ jobs:
|
|||||||
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
|
SIGNING_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }}
|
||||||
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }}
|
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }}
|
||||||
run: flutter build apk
|
run: flutter build apk
|
||||||
|
|
||||||
- name: Sign APK
|
- name: Sign APK
|
||||||
id: sign_apk
|
id: sign_apk
|
||||||
uses: ilharp/sign-android-release@v1
|
uses: ilharp/sign-android-release@v1
|
||||||
@ -46,10 +116,26 @@ jobs:
|
|||||||
keyStorePassword: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }}
|
keyStorePassword: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }}
|
||||||
keyAlias: ${{ secrets.SIGNING_KEY_ALIAS }}
|
keyAlias: ${{ secrets.SIGNING_KEY_ALIAS }}
|
||||||
keyPassword: ${{ secrets.SIGNING_KEY_PASSWORD }}
|
keyPassword: ${{ secrets.SIGNING_KEY_PASSWORD }}
|
||||||
|
|
||||||
- name: Add version to APK
|
- name: Add version to APK
|
||||||
run: mv ${{ steps.sign_apk.outputs.signedFile }} revanced-manager-${{ env.RELEASE_VERSION }}.apk
|
run: mv ${{ steps.sign_apk.outputs.signedFile }} revanced-manager-${{ env.RELEASE_VERSION }}.apk
|
||||||
|
|
||||||
- name: Upload APK
|
- name: Upload APK
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: revanced-manager-${{ env.RELEASE_VERSION }}
|
name: revanced-manager-${{ env.RELEASE_VERSION }}
|
||||||
path: revanced-manager-${{ env.RELEASE_VERSION }}.apk
|
path: revanced-manager-${{ env.RELEASE_VERSION }}.apk
|
||||||
|
|
||||||
|
# deploy:
|
||||||
|
# name: Deploy Android Build
|
||||||
|
# needs: build
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v1
|
||||||
|
# - name: Get Android Build from artifacts
|
||||||
|
# uses: actions/download-artifact@v2
|
||||||
|
# with:
|
||||||
|
# name: android-release
|
||||||
|
|
||||||
|
env:
|
||||||
|
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||||
|
4
.github/workflows/pull-request-build.yml
vendored
@ -20,10 +20,6 @@ jobs:
|
|||||||
- uses: subosito/flutter-action@v2
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
- name: Set environment variables
|
|
||||||
run: echo $SECRETS | base64 -d > lib/utils/environment.dart
|
|
||||||
env:
|
|
||||||
SECRETS: ${{ secrets.SECRETS }}
|
|
||||||
- name: Set up Flutter
|
- name: Set up Flutter
|
||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
- name: Generate files with Builder
|
- name: Generate files with Builder
|
||||||
|
4
.github/workflows/release-build.yml
vendored
@ -20,10 +20,6 @@ jobs:
|
|||||||
- uses: subosito/flutter-action@v2
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: 'stable'
|
channel: 'stable'
|
||||||
- name: Set environment variables
|
|
||||||
run: echo $SECRETS | base64 -d > lib/utils/environment.dart
|
|
||||||
env:
|
|
||||||
SECRETS: ${{ secrets.SECRETS }}
|
|
||||||
- name: Set up Flutter
|
- name: Set up Flutter
|
||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
- name: Generate files with Builder
|
- name: Generate files with Builder
|
||||||
|
@ -71,7 +71,7 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
|
||||||
// ReVanced
|
// ReVanced
|
||||||
implementation "app.revanced:revanced-patcher:6.4.3"
|
implementation "app.revanced:revanced-patcher:7.0.0"
|
||||||
|
|
||||||
// Signing & aligning
|
// Signing & aligning
|
||||||
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
|
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
|
||||||
|
@ -43,7 +43,6 @@ class MainActivity : FlutterActivity() {
|
|||||||
val integrationsPath = call.argument<String>("integrationsPath")
|
val integrationsPath = call.argument<String>("integrationsPath")
|
||||||
val selectedPatches = call.argument<List<String>>("selectedPatches")
|
val selectedPatches = call.argument<List<String>>("selectedPatches")
|
||||||
val cacheDirPath = call.argument<String>("cacheDirPath")
|
val cacheDirPath = call.argument<String>("cacheDirPath")
|
||||||
val mergeIntegrations = call.argument<Boolean>("mergeIntegrations")
|
|
||||||
val keyStoreFilePath = call.argument<String>("keyStoreFilePath")
|
val keyStoreFilePath = call.argument<String>("keyStoreFilePath")
|
||||||
if (patchBundleFilePath != null &&
|
if (patchBundleFilePath != null &&
|
||||||
originalFilePath != null &&
|
originalFilePath != null &&
|
||||||
@ -53,7 +52,6 @@ class MainActivity : FlutterActivity() {
|
|||||||
integrationsPath != null &&
|
integrationsPath != null &&
|
||||||
selectedPatches != null &&
|
selectedPatches != null &&
|
||||||
cacheDirPath != null &&
|
cacheDirPath != null &&
|
||||||
mergeIntegrations != null &&
|
|
||||||
keyStoreFilePath != null
|
keyStoreFilePath != null
|
||||||
) {
|
) {
|
||||||
runPatcher(
|
runPatcher(
|
||||||
@ -66,7 +64,6 @@ class MainActivity : FlutterActivity() {
|
|||||||
integrationsPath,
|
integrationsPath,
|
||||||
selectedPatches,
|
selectedPatches,
|
||||||
cacheDirPath,
|
cacheDirPath,
|
||||||
mergeIntegrations,
|
|
||||||
keyStoreFilePath
|
keyStoreFilePath
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -88,7 +85,6 @@ class MainActivity : FlutterActivity() {
|
|||||||
integrationsPath: String,
|
integrationsPath: String,
|
||||||
selectedPatches: List<String>,
|
selectedPatches: List<String>,
|
||||||
cacheDirPath: String,
|
cacheDirPath: String,
|
||||||
mergeIntegrations: Boolean,
|
|
||||||
keyStoreFilePath: String
|
keyStoreFilePath: String
|
||||||
) {
|
) {
|
||||||
val originalFile = File(originalFilePath)
|
val originalFile = File(originalFilePath)
|
||||||
@ -139,19 +135,17 @@ class MainActivity : FlutterActivity() {
|
|||||||
mapOf("progress" to 0.3, "header" to "", "log" to "")
|
mapOf("progress" to 0.3, "header" to "", "log" to "")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (mergeIntegrations) {
|
handler.post {
|
||||||
handler.post {
|
installerChannel.invokeMethod(
|
||||||
installerChannel.invokeMethod(
|
"update",
|
||||||
"update",
|
mapOf(
|
||||||
mapOf(
|
"progress" to 0.4,
|
||||||
"progress" to 0.4,
|
"header" to "Merging integrations...",
|
||||||
"header" to "Merging integrations...",
|
"log" to "Merging integrations"
|
||||||
"log" to "Merging integrations"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
patcher.addFiles(listOf(integrations)) {}
|
|
||||||
}
|
}
|
||||||
|
patcher.addIntegrations(listOf(integrations)) {}
|
||||||
|
|
||||||
handler.post {
|
handler.post {
|
||||||
installerChannel.invokeMethod(
|
installerChannel.invokeMethod(
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 814 B After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 9.2 KiB |
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="ic_launcher_background">#1B1B1B</color>
|
|
||||||
</resources>
|
|
@ -1,6 +1,6 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.cronetVersion = '102.5005.125'
|
ext.cronetVersion = '102.5005.125'
|
||||||
ext.kotlin_version = '1.8.0'
|
ext.kotlin_version = '1.7.10'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#Mon May 09 12:07:41 MSK 2022
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-rc-1-bin.zip
|
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
@ -79,8 +79,11 @@
|
|||||||
"searchBarHint": "Search patches",
|
"searchBarHint": "Search patches",
|
||||||
"doneButton": "Done",
|
"doneButton": "Done",
|
||||||
"recommended": "Recommended",
|
"recommended": "Recommended",
|
||||||
|
"recommendedTooltip": "Select all recommended patches",
|
||||||
"all": "All",
|
"all": "All",
|
||||||
|
"allTooltip": "Select all patches",
|
||||||
"none": "None",
|
"none": "None",
|
||||||
|
"noneTooltip": "Deselect all patches",
|
||||||
"loadPatchesSelection": "Load patches selection",
|
"loadPatchesSelection": "Load patches selection",
|
||||||
"noSavedPatches": "No saved patches for the selected app.\nPress Done to save current selection.",
|
"noSavedPatches": "No saved patches for the selected app.\nPress Done to save current selection.",
|
||||||
"noPatchesFound": "No patches found for the selected app",
|
"noPatchesFound": "No patches found for the selected app",
|
||||||
@ -145,8 +148,6 @@
|
|||||||
"exportSectionTitle": "Import & export",
|
"exportSectionTitle": "Import & export",
|
||||||
"aboutLabel": "About",
|
"aboutLabel": "About",
|
||||||
"snackbarMessage": "Copied to clipboard",
|
"snackbarMessage": "Copied to clipboard",
|
||||||
"sentryLabel": "Sentry logging",
|
|
||||||
"sentryHint": "Send anonymous logs to help us improve ReVanced Manager",
|
|
||||||
"restartAppForChanges": "Restart the app to apply changes",
|
"restartAppForChanges": "Restart the app to apply changes",
|
||||||
"deleteKeystoreLabel": "Delete keystore",
|
"deleteKeystoreLabel": "Delete keystore",
|
||||||
"deleteKeystoreHint": "Delete the keystore used to sign the app",
|
"deleteKeystoreHint": "Delete the keystore used to sign the app",
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:revanced_manager/services/crowdin_api.dart';
|
|
||||||
import 'package:revanced_manager/services/github_api.dart';
|
import 'package:revanced_manager/services/github_api.dart';
|
||||||
import 'package:revanced_manager/services/manager_api.dart';
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/services/patcher_api.dart';
|
import 'package:revanced_manager/services/patcher_api.dart';
|
||||||
@ -38,7 +37,6 @@ import 'package:stacked_services/stacked_services.dart';
|
|||||||
LazySingleton(classType: PatcherAPI),
|
LazySingleton(classType: PatcherAPI),
|
||||||
LazySingleton(classType: RevancedAPI),
|
LazySingleton(classType: RevancedAPI),
|
||||||
LazySingleton(classType: GithubAPI),
|
LazySingleton(classType: GithubAPI),
|
||||||
LazySingleton(classType: CrowdinAPI),
|
|
||||||
LazySingleton(classType: Toast),
|
LazySingleton(classType: Toast),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -4,15 +4,12 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:revanced_manager/app/app.locator.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/services/crowdin_api.dart';
|
|
||||||
import 'package:revanced_manager/services/github_api.dart';
|
import 'package:revanced_manager/services/github_api.dart';
|
||||||
import 'package:revanced_manager/services/manager_api.dart';
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/services/patcher_api.dart';
|
import 'package:revanced_manager/services/patcher_api.dart';
|
||||||
import 'package:revanced_manager/services/revanced_api.dart';
|
import 'package:revanced_manager/services/revanced_api.dart';
|
||||||
import 'package:revanced_manager/ui/theme/dynamic_theme_builder.dart';
|
import 'package:revanced_manager/ui/theme/dynamic_theme_builder.dart';
|
||||||
import 'package:revanced_manager/ui/views/navigation/navigation_view.dart';
|
import 'package:revanced_manager/ui/views/navigation/navigation_view.dart';
|
||||||
import 'package:revanced_manager/utils/environment.dart';
|
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:stacked_themes/stacked_themes.dart';
|
import 'package:stacked_themes/stacked_themes.dart';
|
||||||
import 'package:timezone/data/latest.dart' as tz;
|
import 'package:timezone/data/latest.dart' as tz;
|
||||||
@ -25,36 +22,12 @@ Future main() async {
|
|||||||
await locator<ManagerAPI>().initialize();
|
await locator<ManagerAPI>().initialize();
|
||||||
final String apiUrl = locator<ManagerAPI>().getApiUrl();
|
final String apiUrl = locator<ManagerAPI>().getApiUrl();
|
||||||
await locator<RevancedAPI>().initialize(apiUrl);
|
await locator<RevancedAPI>().initialize(apiUrl);
|
||||||
await locator<CrowdinAPI>().initialize();
|
|
||||||
final bool isSentryEnabled = locator<ManagerAPI>().isSentryEnabled();
|
|
||||||
final String repoUrl = locator<ManagerAPI>().getRepoUrl();
|
final String repoUrl = locator<ManagerAPI>().getRepoUrl();
|
||||||
locator<GithubAPI>().initialize(repoUrl);
|
locator<GithubAPI>().initialize(repoUrl);
|
||||||
await locator<PatcherAPI>().initialize();
|
await locator<PatcherAPI>().initialize();
|
||||||
tz.initializeTimeZones();
|
tz.initializeTimeZones();
|
||||||
prefs = await SharedPreferences.getInstance();
|
prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
await SentryFlutter.init(
|
|
||||||
(options) {
|
|
||||||
options
|
|
||||||
..dsn = isSentryEnabled ? Environment.sentryDSN : ''
|
|
||||||
..environment = 'alpha'
|
|
||||||
..release = '0.1'
|
|
||||||
..tracesSampleRate = 1.0
|
|
||||||
..anrEnabled = true
|
|
||||||
..enableOutOfMemoryTracking = true
|
|
||||||
..sampleRate = isSentryEnabled ? 1.0 : 0.0
|
|
||||||
..beforeSend = (event, hint) {
|
|
||||||
if (isSentryEnabled) {
|
|
||||||
return event;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} as BeforeSendCallback?;
|
|
||||||
},
|
|
||||||
appRunner: () {
|
|
||||||
runApp(const MyApp());
|
|
||||||
},
|
|
||||||
);
|
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:dio_http_cache_lts/dio_http_cache_lts.dart';
|
|
||||||
import 'package:injectable/injectable.dart' hide Environment;
|
|
||||||
import 'package:revanced_manager/utils/environment.dart';
|
|
||||||
import 'package:sentry_dio/sentry_dio.dart';
|
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
|
|
||||||
@lazySingleton
|
|
||||||
class CrowdinAPI {
|
|
||||||
late Dio _dio = Dio();
|
|
||||||
final DioCacheManager _dioCacheManager = DioCacheManager(CacheConfig());
|
|
||||||
final apiKey = Environment.crowdinKEY;
|
|
||||||
|
|
||||||
Future<void> initialize() async {
|
|
||||||
try {
|
|
||||||
_dio = Dio(
|
|
||||||
BaseOptions(
|
|
||||||
baseUrl: 'https://api.crowdin.com/api/v2',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
_dio.interceptors.add(_dioCacheManager.interceptor);
|
|
||||||
_dio.addSentry(
|
|
||||||
captureFailedRequests: true,
|
|
||||||
);
|
|
||||||
} on Exception catch (e, s) {
|
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> clearAllCache() async {
|
|
||||||
try {
|
|
||||||
await _dioCacheManager.clearAll();
|
|
||||||
} on Exception catch (e, s) {
|
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List> getLanguages() async {
|
|
||||||
try {
|
|
||||||
final response = await _dio.get(
|
|
||||||
'/projects',
|
|
||||||
options: buildCacheOptions(
|
|
||||||
const Duration(hours: 6),
|
|
||||||
maxStale: const Duration(days: 1),
|
|
||||||
options: Options(
|
|
||||||
headers: {
|
|
||||||
'Authorization': 'Bearer $apiKey',
|
|
||||||
},
|
|
||||||
contentType: 'application/json',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
final List targetLanguages =
|
|
||||||
await response.data['data'][0]['data']['targetLanguages'];
|
|
||||||
|
|
||||||
return targetLanguages;
|
|
||||||
} on Exception catch (e, s) {
|
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,11 +4,10 @@ import 'dart:io';
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio_http_cache_lts/dio_http_cache_lts.dart';
|
import 'package:dio_http_cache_lts/dio_http_cache_lts.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
import 'package:revanced_manager/models/patch.dart';
|
import 'package:revanced_manager/models/patch.dart';
|
||||||
import 'package:sentry_dio/sentry_dio.dart';
|
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
|
|
||||||
@lazySingleton
|
@lazySingleton
|
||||||
class GithubAPI {
|
class GithubAPI {
|
||||||
@ -38,19 +37,20 @@ class GithubAPI {
|
|||||||
);
|
);
|
||||||
|
|
||||||
_dio.interceptors.add(_dioCacheManager.interceptor);
|
_dio.interceptors.add(_dioCacheManager.interceptor);
|
||||||
_dio.addSentry(
|
} on Exception catch (e) {
|
||||||
captureFailedRequests: true,
|
if (kDebugMode) {
|
||||||
);
|
print(e);
|
||||||
} on Exception catch (e, s) {
|
}
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> clearAllCache() async {
|
Future<void> clearAllCache() async {
|
||||||
try {
|
try {
|
||||||
await _dioCacheManager.clearAll();
|
await _dioCacheManager.clearAll();
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,8 +61,10 @@ class GithubAPI {
|
|||||||
options: _cacheOptions,
|
options: _cacheOptions,
|
||||||
);
|
);
|
||||||
return response.data[0];
|
return response.data[0];
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,10 +94,12 @@ class GithubAPI {
|
|||||||
'\n' as String,
|
'\n' as String,
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
return List.empty();
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> getLatestReleaseFile(String extension, String repoName) async {
|
Future<File?> getLatestReleaseFile(String extension, String repoName) async {
|
||||||
@ -112,9 +116,10 @@ class GithubAPI {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
return null;
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -127,10 +132,12 @@ class GithubAPI {
|
|||||||
final List<dynamic> list = jsonDecode(f.readAsStringSync());
|
final List<dynamic> list = jsonDecode(f.readAsStringSync());
|
||||||
patches = list.map((patch) => Patch.fromJson(patch)).toList();
|
patches = list.map((patch) => Patch.fromJson(patch)).toList();
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
return List.empty();
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return patches;
|
return patches;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,9 +149,12 @@ class GithubAPI {
|
|||||||
} else {
|
} else {
|
||||||
return 'Unknown';
|
return 'Unknown';
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
return '';
|
print(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Unknown';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:device_apps/device_apps.dart';
|
import 'package:device_apps/device_apps.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
@ -10,7 +11,6 @@ import 'package:revanced_manager/models/patched_application.dart';
|
|||||||
import 'package:revanced_manager/services/github_api.dart';
|
import 'package:revanced_manager/services/github_api.dart';
|
||||||
import 'package:revanced_manager/services/revanced_api.dart';
|
import 'package:revanced_manager/services/revanced_api.dart';
|
||||||
import 'package:revanced_manager/services/root_api.dart';
|
import 'package:revanced_manager/services/root_api.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
@lazySingleton
|
@lazySingleton
|
||||||
@ -98,14 +98,6 @@ class ManagerAPI {
|
|||||||
await _prefs.setBool('useDarkTheme', value);
|
await _prefs.setBool('useDarkTheme', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSentryEnabled() {
|
|
||||||
return _prefs.getBool('sentryEnabled') ?? true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setSentryStatus(bool value) async {
|
|
||||||
await _prefs.setBool('sentryEnabled', value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool areUniversalPatchesEnabled() {
|
bool areUniversalPatchesEnabled() {
|
||||||
return _prefs.getBool('universalPatchesEnabled') ?? false;
|
return _prefs.getBool('universalPatchesEnabled') ?? false;
|
||||||
}
|
}
|
||||||
@ -179,8 +171,10 @@ class ManagerAPI {
|
|||||||
try {
|
try {
|
||||||
_revancedAPI.clearAllCache();
|
_revancedAPI.clearAllCache();
|
||||||
_githubAPI.clearAllCache();
|
_githubAPI.clearAllCache();
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,8 +190,10 @@ class ManagerAPI {
|
|||||||
} else {
|
} else {
|
||||||
return await _githubAPI.getPatches(repoName);
|
return await _githubAPI.getPatches(repoName);
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,8 +209,10 @@ class ManagerAPI {
|
|||||||
} else {
|
} else {
|
||||||
return await _githubAPI.getLatestReleaseFile('.jar', repoName);
|
return await _githubAPI.getLatestReleaseFile('.jar', repoName);
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,8 +228,10 @@ class ManagerAPI {
|
|||||||
} else {
|
} else {
|
||||||
return await _githubAPI.getLatestReleaseFile('.apk', repoName);
|
return await _githubAPI.getLatestReleaseFile('.apk', repoName);
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import 'package:revanced_manager/models/patch.dart';
|
|||||||
import 'package:revanced_manager/models/patched_application.dart';
|
import 'package:revanced_manager/models/patched_application.dart';
|
||||||
import 'package:revanced_manager/services/manager_api.dart';
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/services/root_api.dart';
|
import 'package:revanced_manager/services/root_api.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
import 'package:share_extend/share_extend.dart';
|
import 'package:share_extend/share_extend.dart';
|
||||||
|
|
||||||
@lazySingleton
|
@lazySingleton
|
||||||
@ -49,8 +48,10 @@ class PatcherAPI {
|
|||||||
if (_patches.isEmpty) {
|
if (_patches.isEmpty) {
|
||||||
_patches = await _managerAPI.getPatches();
|
_patches = await _managerAPI.getPatches();
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
_patches = List.empty();
|
_patches = List.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,9 +92,10 @@ class PatcherAPI {
|
|||||||
filteredApps.add(app);
|
filteredApps.add(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
continue;
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,25 +124,6 @@ class PatcherAPI {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dependencyNeedsIntegrations(String name) {
|
|
||||||
return name.contains('integrations') ||
|
|
||||||
_patches.any(
|
|
||||||
(patch) =>
|
|
||||||
patch.name == name &&
|
|
||||||
(patch.dependencies.any(
|
|
||||||
(dep) => dependencyNeedsIntegrations(dep),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> needsIntegrations(List<Patch> selectedPatches) async {
|
|
||||||
return selectedPatches.any(
|
|
||||||
(patch) => patch.dependencies.any(
|
|
||||||
(dep) => dependencyNeedsIntegrations(dep),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> needsResourcePatching(List<Patch> selectedPatches) async {
|
Future<bool> needsResourcePatching(List<Patch> selectedPatches) async {
|
||||||
return selectedPatches.any(
|
return selectedPatches.any(
|
||||||
(patch) => patch.dependencies.any(
|
(patch) => patch.dependencies.any(
|
||||||
@ -170,8 +153,10 @@ class PatcherAPI {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return originalFilePath;
|
return originalFilePath;
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return originalFilePath;
|
return originalFilePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,7 +166,6 @@ class PatcherAPI {
|
|||||||
String originalFilePath,
|
String originalFilePath,
|
||||||
List<Patch> selectedPatches,
|
List<Patch> selectedPatches,
|
||||||
) async {
|
) async {
|
||||||
final bool mergeIntegrations = await needsIntegrations(selectedPatches);
|
|
||||||
final bool includeSettings = await needsSettingsPatch(selectedPatches);
|
final bool includeSettings = await needsSettingsPatch(selectedPatches);
|
||||||
if (includeSettings) {
|
if (includeSettings) {
|
||||||
try {
|
try {
|
||||||
@ -193,16 +177,14 @@ class PatcherAPI {
|
|||||||
if (settingsPatch != null) {
|
if (settingsPatch != null) {
|
||||||
selectedPatches.add(settingsPatch);
|
selectedPatches.add(settingsPatch);
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
// ignore
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final File? patchBundleFile = await _managerAPI.downloadPatches();
|
final File? patchBundleFile = await _managerAPI.downloadPatches();
|
||||||
File? integrationsFile;
|
final File? integrationsFile = await _managerAPI.downloadIntegrations();
|
||||||
if (mergeIntegrations) {
|
|
||||||
integrationsFile = await _managerAPI.downloadIntegrations();
|
|
||||||
}
|
|
||||||
if (patchBundleFile != null) {
|
if (patchBundleFile != null) {
|
||||||
_dataDir.createSync();
|
_dataDir.createSync();
|
||||||
_tmpDir.createSync();
|
_tmpDir.createSync();
|
||||||
@ -224,18 +206,16 @@ class PatcherAPI {
|
|||||||
'inputFilePath': inputFile.path,
|
'inputFilePath': inputFile.path,
|
||||||
'patchedFilePath': patchedFile.path,
|
'patchedFilePath': patchedFile.path,
|
||||||
'outFilePath': _outFile!.path,
|
'outFilePath': _outFile!.path,
|
||||||
'integrationsPath': mergeIntegrations ? integrationsFile!.path : '',
|
'integrationsPath': integrationsFile!.path,
|
||||||
'selectedPatches': selectedPatches.map((p) => p.name).toList(),
|
'selectedPatches': selectedPatches.map((p) => p.name).toList(),
|
||||||
'cacheDirPath': cacheDir.path,
|
'cacheDirPath': cacheDir.path,
|
||||||
'mergeIntegrations': mergeIntegrations,
|
|
||||||
'keyStoreFilePath': _keyStoreFile.path,
|
'keyStoreFilePath': _keyStoreFile.path,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print(e);
|
print(e);
|
||||||
}
|
}
|
||||||
throw await Sentry.captureException(e, stackTrace: s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,8 +236,10 @@ class PatcherAPI {
|
|||||||
await AppInstaller.installApk(_outFile!.path);
|
await AppInstaller.installApk(_outFile!.path);
|
||||||
return await DeviceApps.isAppInstalled(patchedApp.packageName);
|
return await DeviceApps.isAppInstalled(patchedApp.packageName);
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,11 +250,17 @@ class PatcherAPI {
|
|||||||
try {
|
try {
|
||||||
if (_outFile != null) {
|
if (_outFile != null) {
|
||||||
final String newName = _getFileName(appName, version);
|
final String newName = _getFileName(appName, version);
|
||||||
CRFileSaver.saveFileWithDialog(SaveFileDialogParams(
|
CRFileSaver.saveFileWithDialog(
|
||||||
sourceFilePath: _outFile!.path, destinationFileName: newName,),);
|
SaveFileDialogParams(
|
||||||
|
sourceFilePath: _outFile!.path,
|
||||||
|
destinationFileName: newName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} on Exception catch (e) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
|
||||||
Sentry.captureException(e, stackTrace: s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,8 +274,10 @@ class PatcherAPI {
|
|||||||
final File shareFile = _outFile!.copySync(newPath);
|
final File shareFile = _outFile!.copySync(newPath);
|
||||||
ShareExtend.share(shareFile.path, 'file');
|
ShareExtend.share(shareFile.path, 'file');
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,13 +4,12 @@ import 'dart:io';
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio_http_cache_lts/dio_http_cache_lts.dart';
|
import 'package:dio_http_cache_lts/dio_http_cache_lts.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
import 'package:native_dio_client/native_dio_client.dart';
|
import 'package:native_dio_client/native_dio_client.dart';
|
||||||
import 'package:revanced_manager/models/patch.dart';
|
import 'package:revanced_manager/models/patch.dart';
|
||||||
import 'package:revanced_manager/utils/check_for_gms.dart';
|
import 'package:revanced_manager/utils/check_for_gms.dart';
|
||||||
import 'package:sentry_dio/sentry_dio.dart';
|
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
import 'package:timeago/timeago.dart';
|
import 'package:timeago/timeago.dart';
|
||||||
|
|
||||||
@lazySingleton
|
@lazySingleton
|
||||||
@ -42,19 +41,20 @@ class RevancedAPI {
|
|||||||
log('ReVanced API: Using CronetEngine + $isGMSInstalled');
|
log('ReVanced API: Using CronetEngine + $isGMSInstalled');
|
||||||
}
|
}
|
||||||
_dio.interceptors.add(_dioCacheManager.interceptor);
|
_dio.interceptors.add(_dioCacheManager.interceptor);
|
||||||
_dio.addSentry(
|
} on Exception catch (e) {
|
||||||
captureFailedRequests: true,
|
if (kDebugMode) {
|
||||||
);
|
print(e);
|
||||||
} on Exception catch (e, s) {
|
}
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> clearAllCache() async {
|
Future<void> clearAllCache() async {
|
||||||
try {
|
try {
|
||||||
await _dioCacheManager.clearAll();
|
await _dioCacheManager.clearAll();
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,8 +67,10 @@ class RevancedAPI {
|
|||||||
final String name = repo['name'];
|
final String name = repo['name'];
|
||||||
contributors[name] = repo['contributors'];
|
contributors[name] = repo['contributors'];
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return contributors;
|
return contributors;
|
||||||
@ -79,8 +81,10 @@ class RevancedAPI {
|
|||||||
final response = await _dio.get('/patches', options: _cacheOptions);
|
final response = await _dio.get('/patches', options: _cacheOptions);
|
||||||
final List<dynamic> patches = response.data;
|
final List<dynamic> patches = response.data;
|
||||||
return patches.map((patch) => Patch.fromJson(patch)).toList();
|
return patches.map((patch) => Patch.fromJson(patch)).toList();
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return List.empty();
|
return List.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,8 +101,10 @@ class RevancedAPI {
|
|||||||
t['repository'] == repoName &&
|
t['repository'] == repoName &&
|
||||||
(t['name'] as String).endsWith(extension),
|
(t['name'] as String).endsWith(extension),
|
||||||
);
|
);
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,8 +121,10 @@ class RevancedAPI {
|
|||||||
if (release != null) {
|
if (release != null) {
|
||||||
return release['version'];
|
return release['version'];
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -132,8 +140,10 @@ class RevancedAPI {
|
|||||||
final String url = release['browser_download_url'];
|
final String url = release['browser_download_url'];
|
||||||
return await DefaultCacheManager().getSingleFile(url);
|
return await DefaultCacheManager().getSingleFile(url);
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -153,8 +163,10 @@ class RevancedAPI {
|
|||||||
DateTime.parse(release['timestamp'] as String);
|
DateTime.parse(release['timestamp'] as String);
|
||||||
return format(timestamp, locale: 'en_short');
|
return format(timestamp, locale: 'en_short');
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:root/root.dart';
|
import 'package:root/root.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
|
|
||||||
class RootAPI {
|
class RootAPI {
|
||||||
final String _managerDirPath = '/data/local/tmp/revanced-manager';
|
final String _managerDirPath = '/data/local/tmp/revanced-manager';
|
||||||
@ -10,8 +10,10 @@ class RootAPI {
|
|||||||
try {
|
try {
|
||||||
final bool? isRooted = await Root.isRootAvailable();
|
final bool? isRooted = await Root.isRootAvailable();
|
||||||
return isRooted != null && isRooted;
|
return isRooted != null && isRooted;
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,8 +26,10 @@ class RootAPI {
|
|||||||
return isRooted != null && isRooted;
|
return isRooted != null && isRooted;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,8 +82,10 @@ class RootAPI {
|
|||||||
apps.removeWhere((pack) => pack.isEmpty);
|
apps.removeWhere((pack) => pack.isEmpty);
|
||||||
return apps.map((pack) => pack.trim()).toList();
|
return apps.map((pack) => pack.trim()).toList();
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return List.empty();
|
return List.empty();
|
||||||
}
|
}
|
||||||
return List.empty();
|
return List.empty();
|
||||||
@ -125,8 +131,10 @@ class RootAPI {
|
|||||||
await installApk(packageName, patchedFilePath);
|
await installApk(packageName, patchedFilePath);
|
||||||
await mountApk(packageName, originalFilePath);
|
await mountApk(packageName, originalFilePath);
|
||||||
return true;
|
return true;
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ var lightCustomTheme = ThemeData(
|
|||||||
navigationBarTheme: NavigationBarThemeData(
|
navigationBarTheme: NavigationBarThemeData(
|
||||||
labelTextStyle: MaterialStateProperty.all(
|
labelTextStyle: MaterialStateProperty.all(
|
||||||
TextStyle(
|
TextStyle(
|
||||||
color: lightCustomColorScheme.secondary,
|
color: lightCustomColorScheme.onSurface,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -33,13 +33,12 @@ var darkCustomTheme = ThemeData(
|
|||||||
navigationBarTheme: NavigationBarThemeData(
|
navigationBarTheme: NavigationBarThemeData(
|
||||||
labelTextStyle: MaterialStateProperty.all(
|
labelTextStyle: MaterialStateProperty.all(
|
||||||
TextStyle(
|
TextStyle(
|
||||||
color: darkCustomColorScheme.secondary,
|
color: darkCustomColorScheme.onSurface,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
canvasColor: const Color(0xff1B1A1D),
|
canvasColor: const Color(0xff1B1A1D),
|
||||||
scaffoldBackgroundColor: const Color(0xff1B1A1D),
|
scaffoldBackgroundColor: const Color(0xff1B1A1D),
|
||||||
toggleableActiveColor: const Color(0xffA5CAFF),
|
|
||||||
textTheme: GoogleFonts.robotoTextTheme(ThemeData.dark().textTheme),
|
textTheme: GoogleFonts.robotoTextTheme(ThemeData.dark().textTheme),
|
||||||
);
|
);
|
||||||
|
@ -23,48 +23,28 @@ class DynamicThemeBuilder extends StatelessWidget {
|
|||||||
builder: (lightColorScheme, darkColorScheme) {
|
builder: (lightColorScheme, darkColorScheme) {
|
||||||
final ThemeData lightDynamicTheme = ThemeData(
|
final ThemeData lightDynamicTheme = ThemeData(
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
canvasColor: lightColorScheme?.surface,
|
|
||||||
navigationBarTheme: NavigationBarThemeData(
|
navigationBarTheme: NavigationBarThemeData(
|
||||||
backgroundColor: lightColorScheme?.surface,
|
|
||||||
indicatorColor: lightColorScheme?.secondaryContainer,
|
|
||||||
labelTextStyle: MaterialStateProperty.all(
|
labelTextStyle: MaterialStateProperty.all(
|
||||||
GoogleFonts.roboto(
|
GoogleFonts.roboto(
|
||||||
color: lightColorScheme?.onSurface,
|
color: lightColorScheme?.onSurface,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
iconTheme: MaterialStateProperty.all(
|
|
||||||
IconThemeData(
|
|
||||||
color: lightColorScheme?.onSecondaryContainer,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
scaffoldBackgroundColor: lightColorScheme?.surface,
|
|
||||||
colorScheme: lightColorScheme?.harmonized(),
|
colorScheme: lightColorScheme?.harmonized(),
|
||||||
toggleableActiveColor: lightColorScheme?.primary,
|
|
||||||
textTheme: GoogleFonts.robotoTextTheme(ThemeData.light().textTheme),
|
textTheme: GoogleFonts.robotoTextTheme(ThemeData.light().textTheme),
|
||||||
);
|
);
|
||||||
final ThemeData darkDynamicTheme = ThemeData(
|
final ThemeData darkDynamicTheme = ThemeData(
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
canvasColor: darkColorScheme?.surface,
|
|
||||||
navigationBarTheme: NavigationBarThemeData(
|
navigationBarTheme: NavigationBarThemeData(
|
||||||
backgroundColor: darkColorScheme?.surface,
|
|
||||||
indicatorColor: darkColorScheme?.secondaryContainer,
|
|
||||||
labelTextStyle: MaterialStateProperty.all(
|
labelTextStyle: MaterialStateProperty.all(
|
||||||
GoogleFonts.roboto(
|
GoogleFonts.roboto(
|
||||||
color: darkColorScheme?.onSurface,
|
color: darkColorScheme?.onSurface,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
iconTheme: MaterialStateProperty.all(
|
|
||||||
IconThemeData(
|
|
||||||
color: darkColorScheme?.onSecondaryContainer,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
scaffoldBackgroundColor: darkColorScheme?.surface,
|
|
||||||
colorScheme: darkColorScheme?.harmonized(),
|
colorScheme: darkColorScheme?.harmonized(),
|
||||||
toggleableActiveColor: darkColorScheme?.primary,
|
|
||||||
textTheme: GoogleFonts.robotoTextTheme(ThemeData.dark().textTheme),
|
textTheme: GoogleFonts.robotoTextTheme(ThemeData.dark().textTheme),
|
||||||
);
|
);
|
||||||
return DynamicTheme(
|
return DynamicTheme(
|
||||||
@ -90,4 +70,4 @@ class DynamicThemeBuilder extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,14 +41,14 @@ class _AppSelectorViewState extends State<AppSelectorView> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.arrow_back,
|
Icons.arrow_back,
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
|
@ -2,6 +2,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:device_apps/device_apps.dart';
|
import 'package:device_apps/device_apps.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:revanced_manager/app/app.locator.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/models/patched_application.dart';
|
import 'package:revanced_manager/models/patched_application.dart';
|
||||||
@ -9,7 +10,6 @@ import 'package:revanced_manager/services/manager_api.dart';
|
|||||||
import 'package:revanced_manager/services/patcher_api.dart';
|
import 'package:revanced_manager/services/patcher_api.dart';
|
||||||
import 'package:revanced_manager/services/toast.dart';
|
import 'package:revanced_manager/services/toast.dart';
|
||||||
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
class AppSelectorViewModel extends BaseViewModel {
|
class AppSelectorViewModel extends BaseViewModel {
|
||||||
@ -87,8 +87,10 @@ class AppSelectorViewModel extends BaseViewModel {
|
|||||||
locator<PatcherViewModel>().loadLastSelectedPatches();
|
locator<PatcherViewModel>().loadLastSelectedPatches();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
_toast.showBottom('appSelectorView.errorMessage');
|
_toast.showBottom('appSelectorView.errorMessage');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ class ContributorsView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -7,7 +7,6 @@ import 'package:revanced_manager/ui/views/home/home_viewmodel.dart';
|
|||||||
import 'package:revanced_manager/ui/widgets/homeView/available_updates_card.dart';
|
import 'package:revanced_manager/ui/widgets/homeView/available_updates_card.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/homeView/installed_apps_card.dart';
|
import 'package:revanced_manager/ui/widgets/homeView/installed_apps_card.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/homeView/latest_commit_card.dart';
|
import 'package:revanced_manager/ui/widgets/homeView/latest_commit_card.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/shared/custom_chip.dart';
|
|
||||||
import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart';
|
import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
@ -22,8 +21,6 @@ class HomeView extends StatelessWidget {
|
|||||||
viewModelBuilder: () => locator<HomeViewModel>(),
|
viewModelBuilder: () => locator<HomeViewModel>(),
|
||||||
builder: (context, model, child) => Scaffold(
|
builder: (context, model, child) => Scaffold(
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
|
||||||
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
|
||||||
onRefresh: () => model.forceRefresh(context),
|
onRefresh: () => model.forceRefresh(context),
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: <Widget>[
|
slivers: <Widget>[
|
||||||
@ -34,7 +31,7 @@ class HomeView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -48,7 +45,7 @@ class HomeView extends StatelessWidget {
|
|||||||
'homeView.updatesSubtitle',
|
'homeView.updatesSubtitle',
|
||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: Theme.of(context).textTheme.headline6,
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
@ -61,27 +58,53 @@ class HomeView extends StatelessWidget {
|
|||||||
'homeView.patchedSubtitle',
|
'homeView.patchedSubtitle',
|
||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: Theme.of(context).textTheme.headline6,
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
CustomChip(
|
ActionChip(
|
||||||
|
avatar: const Icon(Icons.grid_view),
|
||||||
label: I18nText('homeView.installed'),
|
label: I18nText('homeView.installed'),
|
||||||
isSelected: !model.showUpdatableApps,
|
side: BorderSide(
|
||||||
onSelected: (value) {
|
color: model.showUpdatableApps
|
||||||
|
? Theme.of(context).colorScheme.outline
|
||||||
|
: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondaryContainer,
|
||||||
|
width: model.showUpdatableApps ? 1 : 1,
|
||||||
|
),
|
||||||
|
backgroundColor: model.showUpdatableApps
|
||||||
|
? Theme.of(context).colorScheme.background
|
||||||
|
: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondaryContainer,
|
||||||
|
onPressed: () {
|
||||||
model.toggleUpdatableApps(false);
|
model.toggleUpdatableApps(false);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
CustomChip(
|
ActionChip(
|
||||||
|
avatar: const Icon(Icons.update),
|
||||||
label: I18nText('homeView.updatesAvailable'),
|
label: I18nText('homeView.updatesAvailable'),
|
||||||
isSelected: model.showUpdatableApps,
|
side: BorderSide(
|
||||||
onSelected: (value) {
|
color: !model.showUpdatableApps
|
||||||
|
? Theme.of(context).colorScheme.outline
|
||||||
|
: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondaryContainer,
|
||||||
|
width: !model.showUpdatableApps ? 1 : 1,
|
||||||
|
),
|
||||||
|
backgroundColor: !model.showUpdatableApps
|
||||||
|
? Theme.of(context).colorScheme.background
|
||||||
|
: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondaryContainer,
|
||||||
|
onPressed: () {
|
||||||
model.toggleUpdatableApps(true);
|
model.toggleUpdatableApps(true);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 14),
|
const SizedBox(height: 14),
|
||||||
|
@ -4,6 +4,7 @@ import 'dart:io';
|
|||||||
import 'package:app_installer/app_installer.dart';
|
import 'package:app_installer/app_installer.dart';
|
||||||
import 'package:cross_connectivity/cross_connectivity.dart';
|
import 'package:cross_connectivity/cross_connectivity.dart';
|
||||||
import 'package:device_apps/device_apps.dart';
|
import 'package:device_apps/device_apps.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
@ -18,7 +19,6 @@ import 'package:revanced_manager/services/toast.dart';
|
|||||||
import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/homeView/update_confirmation_dialog.dart';
|
import 'package:revanced_manager/ui/widgets/homeView/update_confirmation_dialog.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
import 'package:timezone/timezone.dart' as tz;
|
import 'package:timezone/timezone.dart' as tz;
|
||||||
@ -95,8 +95,10 @@ class HomeViewModel extends BaseViewModel {
|
|||||||
final int currentVersionInt =
|
final int currentVersionInt =
|
||||||
int.parse(currentVersion.replaceAll(RegExp('[^0-9]'), ''));
|
int.parse(currentVersion.replaceAll(RegExp('[^0-9]'), ''));
|
||||||
return latestVersionInt > currentVersionInt;
|
return latestVersionInt > currentVersionInt;
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,8 +139,10 @@ class HomeViewModel extends BaseViewModel {
|
|||||||
} else {
|
} else {
|
||||||
_toast.showBottom('homeView.errorDownloadMessage');
|
_toast.showBottom('homeView.errorDownloadMessage');
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
_toast.showBottom('homeView.errorInstallMessage');
|
_toast.showBottom('homeView.errorInstallMessage');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class InstallerView extends StatelessWidget {
|
|||||||
title: Text(
|
title: Text(
|
||||||
model.headerLogs,
|
model.headerLogs,
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onBackButtonPressed: () => model.onWillPop(context),
|
onBackButtonPressed: () => model.onWillPop(context),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
import 'package:device_apps/device_apps.dart';
|
import 'package:device_apps/device_apps.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_background/flutter_background.dart';
|
import 'package:flutter_background/flutter_background.dart';
|
||||||
@ -14,7 +15,6 @@ import 'package:revanced_manager/services/root_api.dart';
|
|||||||
import 'package:revanced_manager/services/toast.dart';
|
import 'package:revanced_manager/services/toast.dart';
|
||||||
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart';
|
import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
|
|
||||||
@ -56,9 +56,10 @@ class InstallerViewModel extends BaseViewModel {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
).then((value) => FlutterBackground.enableBackgroundExecution());
|
).then((value) => FlutterBackground.enableBackgroundExecution());
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
// ignore
|
print(e);
|
||||||
|
} // ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Wakelock.enable();
|
await Wakelock.enable();
|
||||||
@ -131,14 +132,15 @@ class InstallerViewModel extends BaseViewModel {
|
|||||||
_app.apkFilePath,
|
_app.apkFilePath,
|
||||||
_patches,
|
_patches,
|
||||||
);
|
);
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
update(
|
update(
|
||||||
-100.0,
|
-100.0,
|
||||||
'Aborting...',
|
'Aborting...',
|
||||||
'An error occurred! Aborting\nError:\n$e',
|
'An error occurred! Aborting\nError:\n$e',
|
||||||
);
|
);
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
throw await Sentry.captureException(e, stackTrace: s);
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
update(-100.0, 'Aborting...', 'No app or patches selected! Aborting');
|
update(-100.0, 'Aborting...', 'No app or patches selected! Aborting');
|
||||||
@ -146,14 +148,17 @@ class InstallerViewModel extends BaseViewModel {
|
|||||||
if (FlutterBackground.isBackgroundExecutionEnabled) {
|
if (FlutterBackground.isBackgroundExecutionEnabled) {
|
||||||
try {
|
try {
|
||||||
FlutterBackground.disableBackgroundExecution();
|
FlutterBackground.disableBackgroundExecution();
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
// ignore
|
print(e);
|
||||||
|
} // ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Wakelock.disable();
|
await Wakelock.disable();
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,24 +216,30 @@ class InstallerViewModel extends BaseViewModel {
|
|||||||
await _managerAPI.savePatchedApp(_app);
|
await _managerAPI.savePatchedApp(_app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void exportResult() {
|
void exportResult() {
|
||||||
try {
|
try {
|
||||||
_patcherAPI.exportPatchedFile(_app.name, _app.version);
|
_patcherAPI.exportPatchedFile(_app.name, _app.version);
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shareResult() {
|
void shareResult() {
|
||||||
try {
|
try {
|
||||||
_patcherAPI.sharePatchedFile(_app.name, _app.version);
|
_patcherAPI.sharePatchedFile(_app.name, _app.version);
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,8 +253,10 @@ class InstallerViewModel extends BaseViewModel {
|
|||||||
locator<PatcherViewModel>().selectedApp = null;
|
locator<PatcherViewModel>().selectedApp = null;
|
||||||
locator<PatcherViewModel>().selectedPatches.clear();
|
locator<PatcherViewModel>().selectedPatches.clear();
|
||||||
locator<PatcherViewModel>().notifyListeners();
|
locator<PatcherViewModel>().notifyListeners();
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@ class NavigationView extends StatelessWidget {
|
|||||||
context,
|
context,
|
||||||
'navigationView.dashboardTab',
|
'navigationView.dashboardTab',
|
||||||
),
|
),
|
||||||
tooltip: '',
|
|
||||||
),
|
),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: model.isIndexSelected(1)
|
icon: model.isIndexSelected(1)
|
||||||
@ -52,7 +51,6 @@ class NavigationView extends StatelessWidget {
|
|||||||
context,
|
context,
|
||||||
'navigationView.patcherTab',
|
'navigationView.patcherTab',
|
||||||
),
|
),
|
||||||
tooltip: '',
|
|
||||||
),
|
),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: model.isIndexSelected(2)
|
icon: model.isIndexSelected(2)
|
||||||
@ -62,7 +60,6 @@ class NavigationView extends StatelessWidget {
|
|||||||
context,
|
context,
|
||||||
'navigationView.settingsTab',
|
'navigationView.settingsTab',
|
||||||
),
|
),
|
||||||
tooltip: '',
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -34,7 +34,7 @@ class PatcherView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -52,31 +52,33 @@ class PatcherViewModel extends BaseViewModel {
|
|||||||
|
|
||||||
Future<void> showPatchConfirmationDialog(BuildContext context) async {
|
Future<void> showPatchConfirmationDialog(BuildContext context) async {
|
||||||
final bool isValid = await isValidPatchConfig();
|
final bool isValid = await isValidPatchConfig();
|
||||||
if (isValid) {
|
if (context.mounted) {
|
||||||
navigateToInstaller();
|
if (isValid) {
|
||||||
} else {
|
navigateToInstaller();
|
||||||
return showDialog(
|
} else {
|
||||||
context: context,
|
return showDialog(
|
||||||
builder: (context) => AlertDialog(
|
context: context,
|
||||||
title: I18nText('warning'),
|
builder: (context) => AlertDialog(
|
||||||
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
title: I18nText('warning'),
|
||||||
content: I18nText('patcherView.patchDialogText'),
|
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
actions: <Widget>[
|
content: I18nText('patcherView.patchDialogText'),
|
||||||
CustomMaterialButton(
|
actions: <Widget>[
|
||||||
isFilled: false,
|
CustomMaterialButton(
|
||||||
label: I18nText('noButton'),
|
isFilled: false,
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
label: I18nText('noButton'),
|
||||||
),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
CustomMaterialButton(
|
),
|
||||||
label: I18nText('yesButton'),
|
CustomMaterialButton(
|
||||||
onPressed: () {
|
label: I18nText('yesButton'),
|
||||||
Navigator.of(context).pop();
|
onPressed: () {
|
||||||
navigateToInstaller();
|
Navigator.of(context).pop();
|
||||||
},
|
navigateToInstaller();
|
||||||
)
|
},
|
||||||
],
|
)
|
||||||
),
|
],
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +116,8 @@ class PatcherViewModel extends BaseViewModel {
|
|||||||
await _managerAPI.getSelectedPatches(selectedApp!.originalPackageName);
|
await _managerAPI.getSelectedPatches(selectedApp!.originalPackageName);
|
||||||
final List<Patch> patches =
|
final List<Patch> patches =
|
||||||
_patcherAPI.getFilteredPatches(selectedApp!.originalPackageName);
|
_patcherAPI.getFilteredPatches(selectedApp!.originalPackageName);
|
||||||
this.selectedPatches
|
this
|
||||||
|
.selectedPatches
|
||||||
.addAll(patches.where((patch) => selectedPatches.contains(patch.name)));
|
.addAll(patches.where((patch) => selectedPatches.contains(patch.name)));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||||
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/patchesSelectorView/patch_item.dart';
|
import 'package:revanced_manager/ui/widgets/patchesSelectorView/patch_item.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/shared/custom_chip.dart';
|
|
||||||
import 'package:revanced_manager/ui/widgets/shared/custom_popup_menu.dart';
|
import 'package:revanced_manager/ui/widgets/shared/custom_popup_menu.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/shared/search_bar.dart';
|
import 'package:revanced_manager/ui/widgets/shared/search_bar.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
@ -50,14 +49,14 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.arrow_back,
|
Icons.arrow_back,
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
@ -74,7 +73,7 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
model.patchesVersion!,
|
model.patchesVersion!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -135,27 +134,36 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
CustomChip(
|
ActionChip(
|
||||||
label:
|
label: I18nText('patchesSelectorView.recommended'),
|
||||||
I18nText('patchesSelectorView.recommended'),
|
tooltip: FlutterI18n.translate(
|
||||||
onSelected: (value) {
|
context,
|
||||||
|
'patchesSelectorView.recommendedTooltip',
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
model.selectRecommendedPatches();
|
model.selectRecommendedPatches();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
CustomChip(
|
ActionChip(
|
||||||
label: I18nText('patchesSelectorView.all'),
|
label: I18nText('patchesSelectorView.all'),
|
||||||
onSelected: (value) {
|
tooltip: FlutterI18n.translate(
|
||||||
if (value) {
|
context,
|
||||||
model.selectAllPatcherWarning(context);
|
'patchesSelectorView.allTooltip',
|
||||||
}
|
),
|
||||||
|
onPressed: () {
|
||||||
|
model.selectAllPatcherWarning(context);
|
||||||
model.selectAllPatches(true);
|
model.selectAllPatches(true);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
CustomChip(
|
ActionChip(
|
||||||
label: I18nText('patchesSelectorView.none'),
|
label: I18nText('patchesSelectorView.none'),
|
||||||
onSelected: (value) {
|
tooltip: FlutterI18n.translate(
|
||||||
|
context,
|
||||||
|
'patchesSelectorView.noneTooltip',
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
model.clearPatches();
|
model.clearPatches();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -152,8 +152,6 @@ class SManageSources extends BaseViewModel {
|
|||||||
_managerAPI.setPatchesRepo('');
|
_managerAPI.setPatchesRepo('');
|
||||||
_managerAPI.setIntegrationsRepo('');
|
_managerAPI.setIntegrationsRepo('');
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Navigator.of(context).pop();
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||||
import 'package:revanced_manager/app/app.locator.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/main.dart';
|
import 'package:revanced_manager/main.dart';
|
||||||
import 'package:revanced_manager/services/crowdin_api.dart';
|
|
||||||
import 'package:revanced_manager/services/toast.dart';
|
import 'package:revanced_manager/services/toast.dart';
|
||||||
import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
||||||
@ -16,7 +15,6 @@ import 'package:timeago/timeago.dart' as timeago;
|
|||||||
final _settingViewModel = SettingsViewModel();
|
final _settingViewModel = SettingsViewModel();
|
||||||
|
|
||||||
class SUpdateLanguage extends BaseViewModel {
|
class SUpdateLanguage extends BaseViewModel {
|
||||||
final CrowdinAPI _crowdinAPI = locator<CrowdinAPI>();
|
|
||||||
final Toast _toast = locator<Toast>();
|
final Toast _toast = locator<Toast>();
|
||||||
late SharedPreferences _prefs;
|
late SharedPreferences _prefs;
|
||||||
String selectedLanguage = 'English';
|
String selectedLanguage = 'English';
|
||||||
@ -43,7 +41,6 @@ class SUpdateLanguage extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> initLang() async {
|
Future<void> initLang() async {
|
||||||
languages = await _crowdinAPI.getLanguages();
|
|
||||||
languages.sort((a, b) => a['name'].compareTo(b['name']));
|
languages.sort((a, b) => a['name'].compareTo(b['name']));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
@ -7,7 +7,6 @@ import 'package:flutter_i18n/widgets/I18nText.dart';
|
|||||||
import 'package:revanced_manager/app/app.locator.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/services/manager_api.dart';
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/custom_switch_tile.dart';
|
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
|
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
@ -64,8 +63,8 @@ class SUpdateThemeUI extends StatelessWidget {
|
|||||||
return SettingsSection(
|
return SettingsSection(
|
||||||
title: 'settingsView.appearanceSectionTitle',
|
title: 'settingsView.appearanceSectionTitle',
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
CustomSwitchTile(
|
SwitchListTile(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
title: I18nText(
|
title: I18nText(
|
||||||
'settingsView.darkThemeLabel',
|
'settingsView.darkThemeLabel',
|
||||||
child: const Text(
|
child: const Text(
|
||||||
@ -78,7 +77,7 @@ class SUpdateThemeUI extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
subtitle: I18nText('settingsView.darkThemeHint'),
|
subtitle: I18nText('settingsView.darkThemeHint'),
|
||||||
value: SUpdateTheme().getDarkThemeStatus(),
|
value: SUpdateTheme().getDarkThemeStatus(),
|
||||||
onTap: (value) => SUpdateTheme().setUseDarkTheme(
|
onChanged: (value) => SUpdateTheme().setUseDarkTheme(
|
||||||
context,
|
context,
|
||||||
value,
|
value,
|
||||||
),
|
),
|
||||||
@ -88,8 +87,8 @@ class SUpdateThemeUI extends StatelessWidget {
|
|||||||
builder: (context, snapshot) => Visibility(
|
builder: (context, snapshot) => Visibility(
|
||||||
visible:
|
visible:
|
||||||
snapshot.hasData && snapshot.data! >= ANDROID_12_SDK_VERSION,
|
snapshot.hasData && snapshot.data! >= ANDROID_12_SDK_VERSION,
|
||||||
child: CustomSwitchTile(
|
child: SwitchListTile(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
title: I18nText(
|
title: I18nText(
|
||||||
'settingsView.dynamicThemeLabel',
|
'settingsView.dynamicThemeLabel',
|
||||||
child: const Text(
|
child: const Text(
|
||||||
@ -102,11 +101,12 @@ class SUpdateThemeUI extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
subtitle: I18nText('settingsView.dynamicThemeHint'),
|
subtitle: I18nText('settingsView.dynamicThemeHint'),
|
||||||
value: _settingViewModel.sUpdateTheme.getDynamicThemeStatus(),
|
value: _settingViewModel.sUpdateTheme.getDynamicThemeStatus(),
|
||||||
onTap: (value) =>
|
onChanged: (value) => {
|
||||||
_settingViewModel.sUpdateTheme.setUseDynamicTheme(
|
_settingViewModel.sUpdateTheme.setUseDynamicTheme(
|
||||||
context,
|
context,
|
||||||
value,
|
value,
|
||||||
),
|
),
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
@ -3,7 +3,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settingsFragement/settings_update_theme.dart';
|
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_update_theme.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_advanced_section.dart';
|
import 'package:revanced_manager/ui/widgets/settingsView/settings_advanced_section.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_export_section.dart';
|
import 'package:revanced_manager/ui/widgets/settingsView/settings_export_section.dart';
|
||||||
@ -32,7 +32,7 @@ class SettingsView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -49,8 +49,6 @@ class SettingsView extends StatelessWidget {
|
|||||||
_settingsDivider,
|
_settingsDivider,
|
||||||
SExportSection(),
|
SExportSection(),
|
||||||
_settingsDivider,
|
_settingsDivider,
|
||||||
// SLoggingSection(),
|
|
||||||
// _settingsDivider,
|
|
||||||
SInfoSection(),
|
SInfoSection(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -2,6 +2,7 @@ import 'dart:io';
|
|||||||
import 'package:cr_file_saver/file_saver.dart';
|
import 'package:cr_file_saver/file_saver.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:logcat/logcat.dart';
|
import 'package:logcat/logcat.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:revanced_manager/app/app.locator.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
@ -9,9 +10,8 @@ import 'package:revanced_manager/app/app.router.dart';
|
|||||||
import 'package:revanced_manager/services/manager_api.dart';
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/services/toast.dart';
|
import 'package:revanced_manager/services/toast.dart';
|
||||||
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settingsFragement/settings_update_language.dart';
|
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_update_language.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settingsFragement/settings_update_theme.dart';
|
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_update_theme.dart';
|
||||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
||||||
import 'package:share_extend/share_extend.dart';
|
import 'package:share_extend/share_extend.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
@ -28,16 +28,6 @@ class SettingsViewModel extends BaseViewModel {
|
|||||||
_navigationService.navigateTo(Routes.contributorsView);
|
_navigationService.navigateTo(Routes.contributorsView);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSentryEnabled() {
|
|
||||||
return _managerAPI.isSentryEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
void useSentry(bool value) {
|
|
||||||
_managerAPI.setSentryStatus(value);
|
|
||||||
_toast.showBottom('settingsView.restartAppForChanges');
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool areUniversalPatchesEnabled() {
|
bool areUniversalPatchesEnabled() {
|
||||||
return _managerAPI.areUniversalPatchesEnabled();
|
return _managerAPI.areUniversalPatchesEnabled();
|
||||||
}
|
}
|
||||||
@ -74,14 +64,20 @@ class SettingsViewModel extends BaseViewModel {
|
|||||||
if (outFile.existsSync()) {
|
if (outFile.existsSync()) {
|
||||||
final String dateTime =
|
final String dateTime =
|
||||||
DateTime.now().toString().replaceAll(' ', '_').split('.').first;
|
DateTime.now().toString().replaceAll(' ', '_').split('.').first;
|
||||||
await CRFileSaver.saveFileWithDialog(SaveFileDialogParams(
|
await CRFileSaver.saveFileWithDialog(
|
||||||
sourceFilePath: outFile.path, destinationFileName: 'selected_patches_$dateTime.json',),);
|
SaveFileDialogParams(
|
||||||
|
sourceFilePath: outFile.path,
|
||||||
|
destinationFileName: 'selected_patches_$dateTime.json',
|
||||||
|
),
|
||||||
|
);
|
||||||
_toast.showBottom('settingsView.exportedPatches');
|
_toast.showBottom('settingsView.exportedPatches');
|
||||||
} else {
|
} else {
|
||||||
_toast.showBottom('settingsView.noExportFileFound');
|
_toast.showBottom('settingsView.noExportFileFound');
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,8 +96,10 @@ class SettingsViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
_toast.showBottom('settingsView.importedPatches');
|
_toast.showBottom('settingsView.importedPatches');
|
||||||
}
|
}
|
||||||
} on Exception catch (e, s) {
|
} on Exception catch (e) {
|
||||||
await Sentry.captureException(e, stackTrace: s);
|
if (kDebugMode) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
_toast.showBottom('settingsView.jsonSelectorErrorMessage');
|
_toast.showBottom('settingsView.jsonSelectorErrorMessage');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class AppInfoView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -51,13 +51,13 @@ class AppInfoView extends StatelessWidget {
|
|||||||
Text(
|
Text(
|
||||||
app.name,
|
app.name,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.headline6,
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
app.version,
|
app.version,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.subtitle1,
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -28,7 +28,7 @@ class AvailableUpdatesCard extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.subtitle1!.copyWith(
|
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -53,7 +53,7 @@ class AvailableUpdatesCard extends StatelessWidget {
|
|||||||
// child: Text(
|
// child: Text(
|
||||||
// '',
|
// '',
|
||||||
// textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
// style: Theme.of(context).textTheme.subtitle1!.copyWith(
|
// style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||||
// color: Theme.of(context).colorScheme.secondary,
|
// color: Theme.of(context).colorScheme.secondary,
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
|
@ -30,7 +30,7 @@ class InstalledAppsCard extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'',
|
'',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.subtitle1!.copyWith(
|
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -61,7 +61,7 @@ class OptionsFilePicker extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'Select File',
|
'Select File',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).textTheme.bodyText1?.color,
|
color: Theme.of(context).textTheme.bodyLarge?.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_i18n/widgets/I18nText.dart';
|
import 'package:flutter_i18n/widgets/I18nText.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settingsFragement/settings_manage_api_url.dart';
|
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_api_url.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settingsFragement/settings_manage_sources.dart';
|
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_patches.dart';
|
import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_patches.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_universal_patches.dart';
|
import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_universal_patches.dart';
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_i18n/widgets/I18nText.dart';
|
import 'package:flutter_i18n/widgets/I18nText.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/custom_switch_tile.dart';
|
|
||||||
|
|
||||||
class SExperimentalPatches extends StatefulWidget {
|
class SExperimentalPatches extends StatefulWidget {
|
||||||
const SExperimentalPatches({super.key});
|
const SExperimentalPatches({super.key});
|
||||||
@ -15,8 +14,8 @@ final _settingsViewModel = SettingsViewModel();
|
|||||||
class _SExperimentalPatchesState extends State<SExperimentalPatches> {
|
class _SExperimentalPatchesState extends State<SExperimentalPatches> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomSwitchTile(
|
return SwitchListTile(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
title: I18nText(
|
title: I18nText(
|
||||||
'settingsView.experimentalPatchesLabel',
|
'settingsView.experimentalPatchesLabel',
|
||||||
child: const Text(
|
child: const Text(
|
||||||
@ -29,7 +28,7 @@ class _SExperimentalPatchesState extends State<SExperimentalPatches> {
|
|||||||
),
|
),
|
||||||
subtitle: I18nText('settingsView.experimentalPatchesHint'),
|
subtitle: I18nText('settingsView.experimentalPatchesHint'),
|
||||||
value: _settingsViewModel.areExperimentalPatchesEnabled(),
|
value: _settingsViewModel.areExperimentalPatchesEnabled(),
|
||||||
onTap: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_settingsViewModel.useExperimentalPatches(value);
|
_settingsViewModel.useExperimentalPatches(value);
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_i18n/widgets/I18nText.dart';
|
import 'package:flutter_i18n/widgets/I18nText.dart';
|
||||||
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/custom_switch_tile.dart';
|
|
||||||
|
|
||||||
class SExperimentalUniversalPatches extends StatefulWidget {
|
class SExperimentalUniversalPatches extends StatefulWidget {
|
||||||
const SExperimentalUniversalPatches({super.key});
|
const SExperimentalUniversalPatches({super.key});
|
||||||
@ -17,8 +16,8 @@ class _SExperimentalUniversalPatchesState
|
|||||||
extends State<SExperimentalUniversalPatches> {
|
extends State<SExperimentalUniversalPatches> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomSwitchTile(
|
return SwitchListTile(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
title: I18nText(
|
title: I18nText(
|
||||||
'settingsView.experimentalUniversalPatchesLabel',
|
'settingsView.experimentalUniversalPatchesLabel',
|
||||||
child: const Text(
|
child: const Text(
|
||||||
@ -31,7 +30,7 @@ class _SExperimentalUniversalPatchesState
|
|||||||
),
|
),
|
||||||
subtitle: I18nText('settingsView.experimentalUniversalPatchesHint'),
|
subtitle: I18nText('settingsView.experimentalUniversalPatchesHint'),
|
||||||
value: _settingsViewModel.areUniversalPatchesEnabled(),
|
value: _settingsViewModel.areUniversalPatchesEnabled(),
|
||||||
onTap: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_settingsViewModel.showUniversalPatches(value);
|
_settingsViewModel.showUniversalPatches(value);
|
||||||
});
|
});
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_i18n/widgets/I18nText.dart';
|
|
||||||
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
|
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/custom_switch_tile.dart';
|
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
|
|
||||||
|
|
||||||
final _settingsViewModel = SettingsViewModel();
|
|
||||||
|
|
||||||
class SLoggingSection extends StatelessWidget {
|
|
||||||
const SLoggingSection({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return SettingsSection(
|
|
||||||
title: 'settingsView.logsSectionTitle',
|
|
||||||
children: <Widget>[
|
|
||||||
CustomSwitchTile(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
|
||||||
title: I18nText(
|
|
||||||
'settingsView.sentryLabel',
|
|
||||||
child: const Text(
|
|
||||||
'',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
subtitle: I18nText('settingsView.sentryHint'),
|
|
||||||
value: _settingsViewModel.isSentryEnabled(),
|
|
||||||
onTap: (value) => _settingsViewModel.useSentry(value),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,7 +17,7 @@ class CustomChip extends StatelessWidget {
|
|||||||
showCheckmark: false,
|
showCheckmark: false,
|
||||||
label: label,
|
label: label,
|
||||||
selected: isSelected,
|
selected: isSelected,
|
||||||
labelStyle: Theme.of(context).textTheme.subtitle2!.copyWith(
|
labelStyle: Theme.of(context).textTheme.titleSmall!.copyWith(
|
||||||
color: isSelected
|
color: isSelected
|
||||||
? Theme.of(context).colorScheme.primary
|
? Theme.of(context).colorScheme.primary
|
||||||
: Theme.of(context).colorScheme.secondary,
|
: Theme.of(context).colorScheme.secondary,
|
||||||
|
@ -33,7 +33,7 @@ class CustomSliverAppBar extends StatelessWidget {
|
|||||||
: IconButton(
|
: IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.arrow_back,
|
Icons.arrow_back,
|
||||||
color: Theme.of(context).textTheme.headline6!.color,
|
color: Theme.of(context).textTheme.titleLarge!.color,
|
||||||
),
|
),
|
||||||
onPressed:
|
onPressed:
|
||||||
onBackButtonPressed ?? () => Navigator.of(context).pop(),
|
onBackButtonPressed ?? () => Navigator.of(context).pop(),
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
// Dummy environment variables used for building the app locally. These automatically get set with correct values during workflow builds.
|
|
||||||
class Environment {
|
|
||||||
static const sentryDSN = '';
|
|
||||||
static const crowdinKEY = '';
|
|
||||||
}
|
|
@ -10,7 +10,6 @@ environment:
|
|||||||
sdk: ">=2.17.5 <3.0.0"
|
sdk: ">=2.17.5 <3.0.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
sentry_flutter: ^6.12.2
|
|
||||||
animations: ^2.0.4
|
animations: ^2.0.4
|
||||||
app_installer: ^1.1.0
|
app_installer: ^1.1.0
|
||||||
collection: ^1.16.0
|
collection: ^1.16.0
|
||||||
@ -73,7 +72,6 @@ dependencies:
|
|||||||
timezone: ^0.8.0
|
timezone: ^0.8.0
|
||||||
url_launcher: ^6.1.5
|
url_launcher: ^6.1.5
|
||||||
wakelock: ^0.6.2
|
wakelock: ^0.6.2
|
||||||
sentry_dio: ^6.12.2
|
|
||||||
flutter_dotenv: ^5.0.2
|
flutter_dotenv: ^5.0.2
|
||||||
pub_release: ^8.0.3
|
pub_release: ^8.0.3
|
||||||
flutter_markdown: ^0.6.13
|
flutter_markdown: ^0.6.13
|
||||||
@ -92,5 +90,4 @@ dev_dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
assets:
|
assets:
|
||||||
- assets/i18n/
|
- assets/i18n/
|
||||||
- .env
|
|