diff --git a/analysis_options.yaml b/analysis_options.yaml index 39e73350..4c75e38f 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -12,6 +12,8 @@ include: package:flutter_lints/flutter.yaml analyzer: exclude: - lib/utils/env_class.g.dart + - "**/*.locator.dart" + - "**/*.router.dart" linter: rules: diff --git a/lib/app/app.dart b/lib/app/app.dart index 2f10b09a..58f9fcc9 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -15,6 +15,7 @@ import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/views/patches_selector/patches_selector_view.dart'; import 'package:revanced_manager/ui/views/settings/settings_view.dart'; import 'package:revanced_manager/ui/widgets/appInfoView/app_info_view.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:stacked/stacked_annotations.dart'; import 'package:stacked_services/stacked_services.dart'; @@ -40,6 +41,10 @@ import 'package:stacked_services/stacked_services.dart'; LazySingleton(classType: GithubAPI), LazySingleton(classType: CrowdinAPI), LazySingleton(classType: Toast), + Presolve( + classType: SharedPreferences, + presolveUsing: SharedPreferences.getInstance, + ) ], ) class AppSetup {} diff --git a/lib/main.dart b/lib/main.dart index 9763504a..7d2ff82e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_localizations/flutter_localizations.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/manager_api.dart'; import 'package:revanced_manager/services/patcher_api.dart'; @@ -13,27 +12,25 @@ import 'package:revanced_manager/ui/theme/dynamic_theme_builder.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:stacked_themes/stacked_themes.dart'; import 'package:timezone/data/latest.dart' as tz; -late SharedPreferences prefs; Future main() async { - await ThemeManager.initialise(); - await setupLocator(); WidgetsFlutterBinding.ensureInitialized(); - await locator().initialize(); - final String apiUrl = locator().getApiUrl(); - await locator().initialize(apiUrl); - await locator().initialize(); - final bool isSentryEnabled = locator().isSentryEnabled(); - final String repoUrl = locator().getRepoUrl(); - locator().initialize(repoUrl); - await locator().initialize(); - tz.initializeTimeZones(); - prefs = await SharedPreferences.getInstance(); + await setupLocator(); + final manager = locator(); + await manager.initialize(); + final String apiUrl = manager.getApiUrl(); + final bool isSentryEnabled = manager.isSentryEnabled(); + final String repoUrl = manager.getRepoUrl(); - await SentryFlutter.init( + await Future.wait([ + locator().initialize(apiUrl), + locator().initialize(), + ]); + locator().initialize(repoUrl); + tz.initializeTimeZones(); + + return SentryFlutter.init( (options) { options ..dsn = isSentryEnabled ? Environment.sentryDSN : '' @@ -51,11 +48,8 @@ Future main() async { } } as BeforeSendCallback?; }, - appRunner: () { - runApp(const MyApp()); - }, + appRunner: () => runApp(const MyApp()), ); - runApp(const MyApp()); } class MyApp extends StatelessWidget { diff --git a/lib/services/crowdin_api.dart b/lib/services/crowdin_api.dart index 053d5a41..0b470261 100644 --- a/lib/services/crowdin_api.dart +++ b/lib/services/crowdin_api.dart @@ -7,11 +7,14 @@ import 'package:sentry_flutter/sentry_flutter.dart'; @lazySingleton class CrowdinAPI { - late Dio _dio = Dio(); - final DioCacheManager _dioCacheManager = DioCacheManager(CacheConfig()); - final apiKey = Environment.crowdinKEY; + CrowdinAPI() { + initialize(); + } + Dio _dio = Dio(); + DioCacheManager get _dioCacheManager => DioCacheManager(CacheConfig()); + String get apiKey => Environment.crowdinKEY; - Future initialize() async { + void initialize() { try { _dio = Dio( BaseOptions( @@ -24,7 +27,7 @@ class CrowdinAPI { captureFailedRequests: true, ); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -32,7 +35,7 @@ class CrowdinAPI { try { await _dioCacheManager.clearAll(); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -56,7 +59,7 @@ class CrowdinAPI { return targetLanguages; } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return []; } } diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index de4676e9..54e1a7a2 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -42,7 +42,7 @@ class GithubAPI { captureFailedRequests: true, ); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -50,7 +50,7 @@ class GithubAPI { try { await _dioCacheManager.clearAll(); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -62,7 +62,7 @@ class GithubAPI { ); return response.data[0]; } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return null; } } @@ -93,7 +93,7 @@ class GithubAPI { ) .toList(); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return List.empty(); } } @@ -113,7 +113,7 @@ class GithubAPI { } } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return null; } return null; @@ -128,7 +128,7 @@ class GithubAPI { patches = list.map((patch) => Patch.fromJson(patch)).toList(); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return List.empty(); } return patches; @@ -143,7 +143,7 @@ class GithubAPI { return 'Unknown'; } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return ''; } } diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 2c79b3bc..350e0e39 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:io'; + import 'package:device_apps/device_apps.dart'; import 'package:injectable/injectable.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -17,10 +18,10 @@ import 'package:shared_preferences/shared_preferences.dart'; class ManagerAPI { final RevancedAPI _revancedAPI = locator(); final GithubAPI _githubAPI = locator(); + final SharedPreferences _prefs = locator(); final RootAPI _rootAPI = RootAPI(); final String patcherRepo = 'revanced-patcher'; final String cliRepo = 'revanced-cli'; - late SharedPreferences _prefs; String storedPatchesFile = '/selected-patches.json'; String defaultApiUrl = 'https://releases.revanced.app/'; String defaultRepoUrl = 'https://api.github.com'; @@ -31,7 +32,6 @@ class ManagerAPI { String defaultManagerRepo = 'revanced/revanced-manager'; Future initialize() async { - _prefs = await SharedPreferences.getInstance(); storedPatchesFile = (await getApplicationDocumentsDirectory()).path + storedPatchesFile; } @@ -180,7 +180,7 @@ class ManagerAPI { _revancedAPI.clearAllCache(); _githubAPI.clearAllCache(); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -197,7 +197,7 @@ class ManagerAPI { return await _githubAPI.getPatches(repoName); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return []; } } @@ -214,7 +214,7 @@ class ManagerAPI { return await _githubAPI.getLatestReleaseFile('.jar', repoName); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return null; } } @@ -231,7 +231,7 @@ class ManagerAPI { return await _githubAPI.getLatestReleaseFile('.apk', repoName); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return null; } } diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index d5ba92b6..17bd1808 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -50,7 +50,7 @@ class PatcherAPI { _patches = await _managerAPI.getPatches(); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); _patches = List.empty(); } } @@ -92,7 +92,7 @@ class PatcherAPI { } } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); continue; } } @@ -171,7 +171,7 @@ class PatcherAPI { } return originalFilePath; } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return originalFilePath; } } @@ -194,7 +194,7 @@ class PatcherAPI { selectedPatches.add(settingsPatch); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); // ignore } } @@ -231,11 +231,11 @@ class PatcherAPI { 'keyStoreFilePath': _keyStoreFile.path, }, ); - } on Exception catch (e, s) { + } on Exception catch (e) { if (kDebugMode) { print(e); } - throw await Sentry.captureException(e, stackTrace: s); + rethrow; } } } @@ -257,7 +257,7 @@ class PatcherAPI { return await DeviceApps.isAppInstalled(patchedApp.packageName); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return false; } } @@ -268,11 +268,15 @@ class PatcherAPI { try { if (_outFile != null) { final String newName = _getFileName(appName, version); - CRFileSaver.saveFileWithDialog(SaveFileDialogParams( - sourceFilePath: _outFile!.path, destinationFileName: newName,),); + CRFileSaver.saveFileWithDialog( + SaveFileDialogParams( + sourceFilePath: _outFile!.path, + destinationFileName: newName, + ), + ); } } on Exception catch (e, s) { - Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -287,7 +291,7 @@ class PatcherAPI { ShareExtend.share(shareFile.path, 'file'); } } on Exception catch (e, s) { - Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } diff --git a/lib/services/revanced_api.dart b/lib/services/revanced_api.dart index fb78d63c..4394aad8 100644 --- a/lib/services/revanced_api.dart +++ b/lib/services/revanced_api.dart @@ -46,7 +46,7 @@ class RevancedAPI { captureFailedRequests: true, ); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -54,7 +54,7 @@ class RevancedAPI { try { await _dioCacheManager.clearAll(); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -68,7 +68,7 @@ class RevancedAPI { contributors[name] = repo['contributors']; } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return {}; } return contributors; @@ -80,7 +80,7 @@ class RevancedAPI { final List patches = response.data; return patches.map((patch) => Patch.fromJson(patch)).toList(); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return List.empty(); } } @@ -98,7 +98,7 @@ class RevancedAPI { (t['name'] as String).endsWith(extension), ); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return null; } } @@ -116,7 +116,7 @@ class RevancedAPI { return release['version']; } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return null; } return null; @@ -133,7 +133,7 @@ class RevancedAPI { return await DefaultCacheManager().getSingleFile(url); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return null; } return null; @@ -154,7 +154,7 @@ class RevancedAPI { return format(timestamp, locale: 'en_short'); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return null; } return null; diff --git a/lib/services/root_api.dart b/lib/services/root_api.dart index 0153848d..036bb3da 100644 --- a/lib/services/root_api.dart +++ b/lib/services/root_api.dart @@ -11,7 +11,7 @@ class RootAPI { final bool? isRooted = await Root.isRootAvailable(); return isRooted != null && isRooted; } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return false; } } @@ -25,7 +25,7 @@ class RootAPI { } return false; } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return false; } } @@ -79,7 +79,7 @@ class RootAPI { return apps.map((pack) => pack.trim()).toList(); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return List.empty(); } return List.empty(); @@ -126,7 +126,7 @@ class RootAPI { await mountApk(packageName, originalFilePath); return true; } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return false; } } diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart index d7019ae7..2ee25eb2 100644 --- a/lib/ui/views/app_selector/app_selector_viewmodel.dart +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -88,7 +88,7 @@ class AppSelectorViewModel extends BaseViewModel { } } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); _toast.showBottom('appSelectorView.errorMessage'); } } diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index d09ed202..fbb0f46e 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -96,7 +96,7 @@ class HomeViewModel extends BaseViewModel { int.parse(currentVersion.replaceAll(RegExp('[^0-9]'), '')); return latestVersionInt > currentVersionInt; } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); return false; } } @@ -138,7 +138,7 @@ class HomeViewModel extends BaseViewModel { _toast.showBottom('homeView.errorDownloadMessage'); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); _toast.showBottom('homeView.errorInstallMessage'); } } diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index fb891795..4b293255 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -57,7 +57,7 @@ class InstallerViewModel extends BaseViewModel { ), ).then((value) => FlutterBackground.enableBackgroundExecution()); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); // ignore } } @@ -131,14 +131,13 @@ class InstallerViewModel extends BaseViewModel { _app.apkFilePath, _patches, ); - } on Exception catch (e, s) { + } on Exception catch (e) { update( -100.0, 'Aborting...', 'An error occurred! Aborting\nError:\n$e', ); - await Sentry.captureException(e, stackTrace: s); - throw await Sentry.captureException(e, stackTrace: s); + rethrow; } } else { update(-100.0, 'Aborting...', 'No app or patches selected! Aborting'); @@ -146,14 +145,13 @@ class InstallerViewModel extends BaseViewModel { if (FlutterBackground.isBackgroundExecutionEnabled) { try { FlutterBackground.disableBackgroundExecution(); - } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); - // ignore + } on Exception { + rethrow; } } await Wakelock.disable(); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -212,7 +210,7 @@ class InstallerViewModel extends BaseViewModel { } } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -220,7 +218,7 @@ class InstallerViewModel extends BaseViewModel { try { _patcherAPI.exportPatchedFile(_app.name, _app.version); } on Exception catch (e, s) { - Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -228,7 +226,7 @@ class InstallerViewModel extends BaseViewModel { try { _patcherAPI.sharePatchedFile(_app.name, _app.version); } on Exception catch (e, s) { - Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -243,7 +241,7 @@ class InstallerViewModel extends BaseViewModel { locator().selectedPatches.clear(); locator().notifyListeners(); } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } diff --git a/lib/ui/views/navigation/navigation_viewmodel.dart b/lib/ui/views/navigation/navigation_viewmodel.dart index 0cdf582d..8d23ddb8 100644 --- a/lib/ui/views/navigation/navigation_viewmodel.dart +++ b/lib/ui/views/navigation/navigation_viewmodel.dart @@ -15,9 +15,9 @@ import 'package:stacked/stacked.dart'; @lazySingleton class NavigationViewModel extends IndexTrackingViewModel { + final prefs = locator(); Future initialize(BuildContext context) async { locator().initialize(context); - final SharedPreferences prefs = await SharedPreferences.getInstance(); if (prefs.getBool('permissionsRequested') == null) { await prefs.setBool('permissionsRequested', true); RootAPI().hasRootPermissions().then( diff --git a/lib/ui/views/settings/settingsFragment/settings_update_language.dart b/lib/ui/views/settings/settingsFragment/settings_update_language.dart index 833d4a87..3873a9d1 100644 --- a/lib/ui/views/settings/settingsFragment/settings_update_language.dart +++ b/lib/ui/views/settings/settingsFragment/settings_update_language.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.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/ui/views/navigation/navigation_viewmodel.dart'; @@ -17,23 +16,14 @@ final _settingViewModel = SettingsViewModel(); class SUpdateLanguage extends BaseViewModel { final CrowdinAPI _crowdinAPI = locator(); + final SharedPreferences _prefs = locator(); final Toast _toast = locator(); - late SharedPreferences _prefs; String selectedLanguage = 'English'; - String selectedLanguageLocale = prefs.getString('language') ?? 'en_US'; + String get selectedLanguageLocale => _prefs.getString('language') ?? 'en_US'; List languages = []; - Future initialize() async { - _prefs = await SharedPreferences.getInstance(); - selectedLanguageLocale = - _prefs.getString('language') ?? selectedLanguageLocale; - notifyListeners(); - } - Future updateLanguage(BuildContext context, String? value) async { if (value != null) { - selectedLanguageLocale = value; - _prefs = await SharedPreferences.getInstance(); await _prefs.setString('language', value); await FlutterI18n.refresh(context, Locale(value)); timeago.setLocaleMessages(value, timeago.EnMessages()); diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index 48d41c76..1e9680b5 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -1,4 +1,5 @@ import 'dart:io'; + import 'package:cr_file_saver/file_saver.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:file_picker/file_picker.dart'; @@ -74,14 +75,18 @@ class SettingsViewModel extends BaseViewModel { if (outFile.existsSync()) { final String dateTime = DateTime.now().toString().replaceAll(' ', '_').split('.').first; - await CRFileSaver.saveFileWithDialog(SaveFileDialogParams( - sourceFilePath: outFile.path, destinationFileName: 'selected_patches_$dateTime.json',),); + await CRFileSaver.saveFileWithDialog( + SaveFileDialogParams( + sourceFilePath: outFile.path, + destinationFileName: 'selected_patches_$dateTime.json', + ), + ); _toast.showBottom('settingsView.exportedPatches'); } else { _toast.showBottom('settingsView.noExportFileFound'); } } on Exception catch (e, s) { - Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); } } @@ -101,7 +106,7 @@ class SettingsViewModel extends BaseViewModel { _toast.showBottom('settingsView.importedPatches'); } } on Exception catch (e, s) { - await Sentry.captureException(e, stackTrace: s); + Sentry.captureException(e, stackTrace: s).ignore(); _toast.showBottom('settingsView.jsonSelectorErrorMessage'); } }