diff --git a/analysis_options.yaml b/analysis_options.yaml index 2be62ed6..39e73350 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -14,20 +14,149 @@ analyzer: - lib/utils/env_class.g.dart linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at - # https://dart-lang.github.io/linter/lints/index.html. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options + - always_declare_return_types + - require_trailing_commas + - always_put_control_body_on_new_line + - always_require_non_null_named_parameters + - always_use_package_imports # we do this commonly + - annotate_overrides + - avoid_bool_literals_in_conditional_expressions + - avoid_double_and_int_checks + - avoid_empty_else + - avoid_equals_and_hash_code_on_mutable_classes + - avoid_escaping_inner_quotes + - avoid_field_initializers_in_const_classes + - avoid_function_literals_in_foreach_calls + - avoid_implementing_value_types + - avoid_init_to_null + - avoid_js_rounded_ints + - avoid_null_checks_in_equality_operators + - avoid_print + - avoid_redundant_argument_values + - avoid_relative_lib_imports + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + - avoid_returning_null + - avoid_returning_null_for_future + - avoid_returning_null_for_void + - avoid_setters_without_getters + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements + - avoid_type_to_string + - avoid_types_as_parameter_names + - avoid_unnecessary_containers + - avoid_void_async + - avoid_web_libraries_in_flutter # we use web libraries in web-specific code, and our tests prevent us from using them elsewhere + - await_only_futures + - camel_case_extensions + - camel_case_types + - cancel_subscriptions + - cast_nullable_to_non_nullable + - close_sinks # not reliable enough + - control_flow_in_finally + - curly_braces_in_flow_control_structures + - depend_on_referenced_packages + - deprecated_consistency + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - eol_at_end_of_file + - exhaustive_cases + - file_names + - flutter_style_todos + - hash_and_equals + - implementation_imports + - iterable_contains_unrelated_type + - leading_newlines_in_multiline_strings + - library_names + - library_prefixes + - library_private_types_in_public_api + - list_remove_unrelated_type + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + - no_duplicate_case_values + - no_logic_in_create_state + - non_constant_identifier_names + - noop_primitive_operations + - null_check_on_nullable_type_parameter + - null_closures + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + - prefer_asserts_in_initializer_lists + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_constructors + - prefer_const_constructors_in_immutables + - prefer_const_declarations + - prefer_const_literals_to_create_immutables + - prefer_contains + - prefer_equal_for_default_values + - prefer_final_fields + - prefer_final_in_for_each + - prefer_final_locals + - prefer_for_elements_to_map_fromIterable + - prefer_foreach + - prefer_function_declarations_over_variables + - prefer_generic_function_type_aliases + - prefer_if_elements_to_conditional_expressions + - prefer_if_null_operators + - prefer_initializing_formals + - prefer_inlined_adds + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + - prefer_is_not_operator + - prefer_iterable_whereType + - prefer_mixin # Has false positives, see https://github.com/dart-lang/linter/issues/3018 + - prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere + - prefer_null_aware_operators + - prefer_single_quotes + - prefer_spread_collections + - prefer_typing_uninitialized_variables + - prefer_void_to_null + - provide_deprecation_message + - recursive_getters + - sized_box_for_whitespace + - slash_for_doc_comments + - sort_child_properties_last + - sort_constructors_first + - sort_unnamed_constructors_first + - test_types_in_equals + - throw_in_finally + - tighten_type_of_initializing_formals + - type_init_formals + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_getters_setters + - unnecessary_new + - unnecessary_null_aware_assignments + - unnecessary_null_checks + - unnecessary_null_in_if_null_operators + - unnecessary_nullable_for_final_variable_declarations + - unnecessary_overrides + - unnecessary_parenthesis + - unnecessary_statements + - unnecessary_string_escapes + - unnecessary_string_interpolations + - unnecessary_this + - unrelated_type_equality_checks + - unsafe_html + - use_build_context_synchronously + - use_full_hex_values_for_flutter_colors + - use_function_type_syntax_for_parameters + - use_if_null_to_convert_nulls_to_bools + - use_is_even_rather_than_modulo + - use_key_in_widget_constructors + - use_late_for_private_fields_and_variables + - use_named_constants + - use_raw_strings + - use_rethrow_when_possible + - use_setters_to_change_properties + - use_test_throws_matchers + - valid_regexps + - void_checks diff --git a/lib/main.dart b/lib/main.dart index 5bc27ed2..9763504a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -10,9 +12,9 @@ import 'package:revanced_manager/services/revanced_api.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/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:sentry_flutter/sentry_flutter.dart'; import 'package:timezone/data/latest.dart' as tz; late SharedPreferences prefs; @@ -21,11 +23,11 @@ Future main() async { await setupLocator(); WidgetsFlutterBinding.ensureInitialized(); await locator().initialize(); - String apiUrl = locator().getApiUrl(); + final String apiUrl = locator().getApiUrl(); await locator().initialize(apiUrl); await locator().initialize(); - bool isSentryEnabled = locator().isSentryEnabled(); - String repoUrl = locator().getRepoUrl(); + final bool isSentryEnabled = locator().isSentryEnabled(); + final String repoUrl = locator().getRepoUrl(); locator().initialize(repoUrl); await locator().initialize(); tz.initializeTimeZones(); @@ -65,7 +67,7 @@ class MyApp extends StatelessWidget { // String replaceLocale = rawLocale.replaceAll('_', '-'); // List localeList = replaceLocale.split('-'); // Locale locale = Locale(localeList[0], localeList[1]); - Locale locale = const Locale('en', 'US'); + const Locale locale = Locale('en', 'US'); return DynamicThemeBuilder( title: 'ReVanced Manager', @@ -79,8 +81,9 @@ class MyApp extends StatelessWidget { useCountryCode: true, ), missingTranslationHandler: (key, locale) { - print( - '--> Missing translation: key: $key, languageCode: ${locale?.languageCode}'); + log( + '--> Missing translation: key: $key, languageCode: ${locale?.languageCode}', + ); }, ), GlobalMaterialLocalizations.delegate, diff --git a/lib/models/patch.dart b/lib/models/patch.dart index 275a2890..1d841bc3 100644 --- a/lib/models/patch.dart +++ b/lib/models/patch.dart @@ -5,13 +5,6 @@ part 'patch.g.dart'; @JsonSerializable() class Patch { - final String name; - final String description; - final String version; - final bool excluded; - final List dependencies; - final List compatiblePackages; - Patch({ required this.name, required this.description, @@ -22,6 +15,12 @@ class Patch { }); factory Patch.fromJson(Map json) => _$PatchFromJson(json); + final String name; + final String description; + final String version; + final bool excluded; + final List dependencies; + final List compatiblePackages; Map toJson() => _$PatchToJson(this); @@ -37,9 +36,6 @@ class Patch { @JsonSerializable() class Package { - final String name; - final List versions; - Package({ required this.name, required this.versions, @@ -47,6 +43,8 @@ class Package { factory Package.fromJson(Map json) => _$PackageFromJson(json); + final String name; + final List versions; Map toJson() => _$PackageToJson(this); } diff --git a/lib/models/patched_application.dart b/lib/models/patched_application.dart index 456ece15..90bfb9a3 100644 --- a/lib/models/patched_application.dart +++ b/lib/models/patched_application.dart @@ -6,23 +6,6 @@ part 'patched_application.g.dart'; @JsonSerializable() class PatchedApplication { - String name; - String packageName; - String originalPackageName; - String version; - final String apkFilePath; - @JsonKey( - fromJson: decodeBase64, - toJson: encodeBase64, - ) - Uint8List icon; - DateTime patchDate; - bool isRooted; - bool isFromStorage; - bool hasUpdates; - List appliedPatches; - List changelog; - PatchedApplication({ required this.name, required this.packageName, @@ -40,6 +23,22 @@ class PatchedApplication { factory PatchedApplication.fromJson(Map json) => _$PatchedApplicationFromJson(json); + String name; + String packageName; + String originalPackageName; + String version; + final String apkFilePath; + @JsonKey( + fromJson: decodeBase64, + toJson: encodeBase64, + ) + Uint8List icon; + DateTime patchDate; + bool isRooted; + bool isFromStorage; + bool hasUpdates; + List appliedPatches; + List changelog; Map toJson() => _$PatchedApplicationToJson(this); diff --git a/lib/services/crowdin_api.dart b/lib/services/crowdin_api.dart index 29312ba5..053d5a41 100644 --- a/lib/services/crowdin_api.dart +++ b/lib/services/crowdin_api.dart @@ -13,9 +13,11 @@ class CrowdinAPI { Future initialize() async { try { - _dio = Dio(BaseOptions( - baseUrl: 'https://api.crowdin.com/api/v2', - )); + _dio = Dio( + BaseOptions( + baseUrl: 'https://api.crowdin.com/api/v2', + ), + ); _dio.interceptors.add(_dioCacheManager.interceptor); _dio.addSentry( @@ -36,7 +38,7 @@ class CrowdinAPI { Future getLanguages() async { try { - var response = await _dio.get( + final response = await _dio.get( '/projects', options: buildCacheOptions( const Duration(hours: 6), @@ -49,7 +51,7 @@ class CrowdinAPI { ), ), ); - List targetLanguages = + final List targetLanguages = await response.data['data'][0]['data']['targetLanguages']; return targetLanguages; diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index e8dc5321..de4676e9 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -1,13 +1,14 @@ import 'dart:convert'; import 'dart:io'; + import 'package:collection/collection.dart'; import 'package:dio/dio.dart'; import 'package:dio_http_cache_lts/dio_http_cache_lts.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:injectable/injectable.dart'; import 'package:revanced_manager/models/patch.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_dio/sentry_dio.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; @lazySingleton class GithubAPI { @@ -28,11 +29,13 @@ class GithubAPI { 'com.spotify.music': 'spotify', }; - void initialize(String repoUrl) async { + Future initialize(String repoUrl) async { try { - _dio = Dio(BaseOptions( - baseUrl: repoUrl, - )); + _dio = Dio( + BaseOptions( + baseUrl: repoUrl, + ), + ); _dio.interceptors.add(_dioCacheManager.interceptor); _dio.addSentry( @@ -53,7 +56,7 @@ class GithubAPI { Future?> getLatestRelease(String repoName) async { try { - var response = await _dio.get( + final response = await _dio.get( '/repos/$repoName/releases', options: _cacheOptions, ); @@ -69,10 +72,10 @@ class GithubAPI { String repoName, DateTime since, ) async { - String path = + final String path = 'src/main/kotlin/app/revanced/patches/${repoAppPath[packageName]}'; try { - var response = await _dio.get( + final response = await _dio.get( '/repos/$repoName/commits', queryParameters: { 'path': path, @@ -80,7 +83,7 @@ class GithubAPI { }, options: _cacheOptions, ); - List commits = response.data; + final List commits = response.data; return commits .map( (commit) => (commit['commit']['message']).split('\n')[0] + @@ -97,9 +100,9 @@ class GithubAPI { Future getLatestReleaseFile(String extension, String repoName) async { try { - Map? release = await getLatestRelease(repoName); + final Map? release = await getLatestRelease(repoName); if (release != null) { - Map? asset = + final Map? asset = (release['assets'] as List).firstWhereOrNull( (asset) => (asset['name'] as String).endsWith(extension), ); @@ -119,9 +122,9 @@ class GithubAPI { Future> getPatches(String repoName) async { List patches = []; try { - File? f = await getLatestReleaseFile('.json', repoName); + final File? f = await getLatestReleaseFile('.json', repoName); if (f != null) { - List list = jsonDecode(f.readAsStringSync()); + final List list = jsonDecode(f.readAsStringSync()); patches = list.map((patch) => Patch.fromJson(patch)).toList(); } } on Exception catch (e, s) { @@ -133,7 +136,7 @@ class GithubAPI { Future getLastestReleaseVersion(String repoName) async { try { - Map? release = await getLatestRelease(repoName); + final Map? release = await getLatestRelease(repoName); if (release != null) { return release['tag_name']; } else { diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 60c44357..2c79b3bc 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -131,14 +131,15 @@ class ManagerAPI { Future deleteKeystore() async { final File keystore = File( - '/sdcard/Android/data/app.revanced.manager.flutter/files/revanced-manager.keystore'); + '/sdcard/Android/data/app.revanced.manager.flutter/files/revanced-manager.keystore', + ); if (await keystore.exists()) { await keystore.delete(); } } List getPatchedApps() { - List apps = _prefs.getStringList('patchedApps') ?? []; + final List apps = _prefs.getStringList('patchedApps') ?? []; return apps.map((a) => PatchedApplication.fromJson(jsonDecode(a))).toList(); } @@ -146,14 +147,16 @@ class ManagerAPI { if (patchedApps.length > 1) { patchedApps.sort((a, b) => a.name.compareTo(b.name)); } - await _prefs.setStringList('patchedApps', - patchedApps.map((a) => json.encode(a.toJson())).toList()); + await _prefs.setStringList( + 'patchedApps', + patchedApps.map((a) => json.encode(a.toJson())).toList(), + ); } Future savePatchedApp(PatchedApplication app) async { - List patchedApps = getPatchedApps(); + final List patchedApps = getPatchedApps(); patchedApps.removeWhere((a) => a.packageName == app.packageName); - ApplicationWithIcon? installed = await DeviceApps.getApp( + final ApplicationWithIcon? installed = await DeviceApps.getApp( app.packageName, true, ) as ApplicationWithIcon?; @@ -167,12 +170,12 @@ class ManagerAPI { } Future deletePatchedApp(PatchedApplication app) async { - List patchedApps = getPatchedApps(); + final List patchedApps = getPatchedApps(); patchedApps.removeWhere((a) => a.packageName == app.packageName); await setPatchedApps(patchedApps); } - void clearAllData() async { + Future clearAllData() async { try { _revancedAPI.clearAllCache(); _githubAPI.clearAllCache(); @@ -187,7 +190,7 @@ class ManagerAPI { Future> getPatches() async { try { - String repoName = getPatchesRepo(); + final String repoName = getPatchesRepo(); if (repoName == defaultPatchesRepo) { return await _revancedAPI.getPatches(); } else { @@ -201,7 +204,7 @@ class ManagerAPI { Future downloadPatches() async { try { - String repoName = getPatchesRepo(); + final String repoName = getPatchesRepo(); if (repoName == defaultPatchesRepo) { return await _revancedAPI.getLatestReleaseFile( '.jar', @@ -218,7 +221,7 @@ class ManagerAPI { Future downloadIntegrations() async { try { - String repoName = getIntegrationsRepo(); + final String repoName = getIntegrationsRepo(); if (repoName == defaultIntegrationsRepo) { return await _revancedAPI.getLatestReleaseFile( '.apk', @@ -260,16 +263,16 @@ class ManagerAPI { } Future getCurrentManagerVersion() async { - PackageInfo packageInfo = await PackageInfo.fromPlatform(); + final PackageInfo packageInfo = await PackageInfo.fromPlatform(); return packageInfo.version; } Future> getAppsToRemove( List patchedApps, ) async { - List toRemove = []; - for (PatchedApplication app in patchedApps) { - bool isRemove = await isAppUninstalled(app); + final List toRemove = []; + for (final PatchedApplication app in patchedApps) { + final bool isRemove = await isAppUninstalled(app); if (isRemove) { toRemove.add(app); } @@ -280,13 +283,13 @@ class ManagerAPI { Future> getUnsavedApps( List patchedApps, ) async { - List unsavedApps = []; - bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final List unsavedApps = []; + final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { - List installedApps = await _rootAPI.getInstalledApps(); - for (String packageName in installedApps) { + final List installedApps = await _rootAPI.getInstalledApps(); + for (final String packageName in installedApps) { if (!patchedApps.any((app) => app.packageName == packageName)) { - ApplicationWithIcon? application = await DeviceApps.getApp( + final ApplicationWithIcon? application = await DeviceApps.getApp( packageName, true, ) as ApplicationWithIcon?; @@ -307,15 +310,13 @@ class ManagerAPI { } } } - List userApps = await DeviceApps.getInstalledApplications( - includeSystemApps: false, - includeAppIcons: false, - ); - for (Application app in userApps) { + final List userApps = + await DeviceApps.getInstalledApplications(); + for (final Application app in userApps) { if (app.packageName.startsWith('app.revanced') && !app.packageName.startsWith('app.revanced.manager.') && !patchedApps.any((uapp) => uapp.packageName == app.packageName)) { - ApplicationWithIcon? application = await DeviceApps.getApp( + final ApplicationWithIcon? application = await DeviceApps.getApp( app.packageName, true, ) as ApplicationWithIcon?; @@ -329,7 +330,6 @@ class ManagerAPI { apkFilePath: application.apkFilePath, icon: application.icon, patchDate: DateTime.now(), - isRooted: false, ), ); } @@ -339,24 +339,27 @@ class ManagerAPI { } Future reAssessSavedApps() async { - List patchedApps = getPatchedApps(); - List unsavedApps = await getUnsavedApps(patchedApps); + final List patchedApps = getPatchedApps(); + final List unsavedApps = + await getUnsavedApps(patchedApps); patchedApps.addAll(unsavedApps); - List toRemove = await getAppsToRemove(patchedApps); + final List toRemove = + await getAppsToRemove(patchedApps); patchedApps.removeWhere((a) => toRemove.contains(a)); - for (PatchedApplication app in patchedApps) { + for (final PatchedApplication app in patchedApps) { app.hasUpdates = await hasAppUpdates(app.originalPackageName, app.patchDate); app.changelog = await getAppChangelog(app.originalPackageName, app.patchDate); if (!app.hasUpdates) { - String? currentInstalledVersion = + final String? currentInstalledVersion = (await DeviceApps.getApp(app.packageName))?.versionName; if (currentInstalledVersion != null) { - String currentSavedVersion = app.version; - int currentInstalledVersionInt = int.parse( - currentInstalledVersion.replaceAll(RegExp('[^0-9]'), '')); - int currentSavedVersionInt = + final String currentSavedVersion = app.version; + final int currentInstalledVersionInt = int.parse( + currentInstalledVersion.replaceAll(RegExp('[^0-9]'), ''), + ); + final int currentSavedVersionInt = int.parse(currentSavedVersion.replaceAll(RegExp('[^0-9]'), '')); if (currentInstalledVersionInt > currentSavedVersionInt) { app.hasUpdates = true; @@ -369,9 +372,9 @@ class ManagerAPI { Future isAppUninstalled(PatchedApplication app) async { bool existsRoot = false; - bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName); + final bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName); if (app.isRooted) { - bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { existsRoot = await _rootAPI.isAppInstalled(app.packageName); } @@ -381,7 +384,7 @@ class ManagerAPI { } Future hasAppUpdates(String packageName, DateTime patchDate) async { - List commits = await _githubAPI.getCommits( + final List commits = await _githubAPI.getCommits( packageName, getPatchesRepo(), patchDate, @@ -390,7 +393,9 @@ class ManagerAPI { } Future> getAppChangelog( - String packageName, DateTime patchDate) async { + String packageName, + DateTime patchDate, + ) async { List newCommits = await _githubAPI.getCommits( packageName, getPatchesRepo(), @@ -418,7 +423,7 @@ class ManagerAPI { Future setSelectedPatches(String app, List patches) async { final File selectedPatchesFile = File(storedPatchesFile); - Map patchesMap = await readSelectedPatchesFile(); + final Map patchesMap = await readSelectedPatchesFile(); if (patches.isEmpty) { patchesMap.remove(app); } else { @@ -428,15 +433,19 @@ class ManagerAPI { } Future> getSelectedPatches(String app) async { - Map patchesMap = await readSelectedPatchesFile(); + final Map patchesMap = await readSelectedPatchesFile(); return List.from(patchesMap.putIfAbsent(app, () => List.empty())); } Future> readSelectedPatchesFile() async { final File selectedPatchesFile = File(storedPatchesFile); - if (!selectedPatchesFile.existsSync()) return {}; - String string = selectedPatchesFile.readAsStringSync(); - if (string.trim().isEmpty) return {}; + if (!selectedPatchesFile.existsSync()) { + return {}; + } + final String string = selectedPatchesFile.readAsStringSync(); + if (string.trim().isEmpty) { + return {}; + } return jsonDecode(string); } diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index 90070cd3..d5ba92b6 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -1,7 +1,10 @@ import 'dart:io'; + import 'package:app_installer/app_installer.dart'; import 'package:collection/collection.dart'; +import 'package:cr_file_saver/file_saver.dart'; import 'package:device_apps/device_apps.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:injectable/injectable.dart'; import 'package:path_provider/path_provider.dart'; @@ -12,7 +15,6 @@ import 'package:revanced_manager/services/manager_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:cr_file_saver/file_saver.dart'; @lazySingleton class PatcherAPI { @@ -29,7 +31,7 @@ class PatcherAPI { Future initialize() async { await _loadPatches(); - Directory appCache = await getTemporaryDirectory(); + final Directory appCache = await getTemporaryDirectory(); _dataDir = await getExternalStorageDirectory() ?? appCache; _tmpDir = Directory('${appCache.path}/patcher'); _keyStoreFile = File('${_dataDir.path}/revanced-manager.keystore'); @@ -53,18 +55,21 @@ class PatcherAPI { } } - Future> getFilteredInstalledApps(bool showUniversalPatches) async { - List filteredApps = []; - bool? allAppsIncluded = - _patches.any((patch) => patch.compatiblePackages.isEmpty) && showUniversalPatches; + Future> getFilteredInstalledApps( + bool showUniversalPatches, + ) async { + final List filteredApps = []; + final bool allAppsIncluded = + _patches.any((patch) => patch.compatiblePackages.isEmpty) && + showUniversalPatches; if (allAppsIncluded) { - var allPackages = await DeviceApps.getInstalledApplications( + final allPackages = await DeviceApps.getInstalledApplications( includeAppIcons: true, onlyAppsWithLaunchIntent: true, ); - allPackages.forEach((pkg) async { + for (final pkg in allPackages) { if (!filteredApps.any((app) => app.packageName == pkg.packageName)) { - var appInfo = await DeviceApps.getApp( + final appInfo = await DeviceApps.getApp( pkg.packageName, true, ) as ApplicationWithIcon?; @@ -72,13 +77,13 @@ class PatcherAPI { filteredApps.add(appInfo); } } - }); + } } - for (Patch patch in _patches) { - for (Package package in patch.compatiblePackages) { + for (final Patch patch in _patches) { + for (final Package package in patch.compatiblePackages) { try { if (!filteredApps.any((app) => app.packageName == package.name)) { - ApplicationWithIcon? app = await DeviceApps.getApp( + final ApplicationWithIcon? app = await DeviceApps.getApp( package.name, true, ) as ApplicationWithIcon?; @@ -97,12 +102,14 @@ class PatcherAPI { List getFilteredPatches(String packageName) { if (!filteredPatches.keys.contains(packageName)) { - List patches = _patches - .where((patch) => - patch.compatiblePackages.isEmpty || - !patch.name.contains('settings') && - patch.compatiblePackages - .any((pack) => pack.name == packageName)) + final List patches = _patches + .where( + (patch) => + patch.compatiblePackages.isEmpty || + !patch.name.contains('settings') && + patch.compatiblePackages + .any((pack) => pack.name == packageName), + ) .toList(); filteredPatches[packageName] = patches; } @@ -155,7 +162,7 @@ class PatcherAPI { String originalFilePath, ) async { try { - bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { originalFilePath = await _rootAPI.getOriginalFilePath( packageName, @@ -174,11 +181,11 @@ class PatcherAPI { String originalFilePath, List selectedPatches, ) async { - bool mergeIntegrations = await needsIntegrations(selectedPatches); - bool includeSettings = await needsSettingsPatch(selectedPatches); + final bool mergeIntegrations = await needsIntegrations(selectedPatches); + final bool includeSettings = await needsSettingsPatch(selectedPatches); if (includeSettings) { try { - Patch? settingsPatch = _patches.firstWhereOrNull( + final Patch? settingsPatch = _patches.firstWhereOrNull( (patch) => patch.name.contains('settings') && patch.compatiblePackages.any((pack) => pack.name == packageName), @@ -191,7 +198,7 @@ class PatcherAPI { // ignore } } - File? patchBundleFile = await _managerAPI.downloadPatches(); + final File? patchBundleFile = await _managerAPI.downloadPatches(); File? integrationsFile; if (mergeIntegrations) { integrationsFile = await _managerAPI.downloadIntegrations(); @@ -199,11 +206,11 @@ class PatcherAPI { if (patchBundleFile != null) { _dataDir.createSync(); _tmpDir.createSync(); - Directory workDir = _tmpDir.createTempSync('tmp-'); - File inputFile = File('${workDir.path}/base.apk'); - File patchedFile = File('${workDir.path}/patched.apk'); + final Directory workDir = _tmpDir.createTempSync('tmp-'); + final File inputFile = File('${workDir.path}/base.apk'); + final File patchedFile = File('${workDir.path}/patched.apk'); _outFile = File('${workDir.path}/out.apk'); - Directory cacheDir = Directory('${workDir.path}/cache'); + final Directory cacheDir = Directory('${workDir.path}/cache'); cacheDir.createSync(); try { await patcherChannel.invokeMethod( @@ -225,7 +232,9 @@ class PatcherAPI { }, ); } on Exception catch (e, s) { - print(e); + if (kDebugMode) { + print(e); + } throw await Sentry.captureException(e, stackTrace: s); } } @@ -235,7 +244,7 @@ class PatcherAPI { if (_outFile != null) { try { if (patchedApp.isRooted) { - bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { return _rootAPI.installApp( patchedApp.packageName, @@ -258,9 +267,9 @@ class PatcherAPI { void exportPatchedFile(String appName, String version) { try { if (_outFile != null) { - String newName = _getFileName(appName, version); + final String newName = _getFileName(appName, version); CRFileSaver.saveFileWithDialog(SaveFileDialogParams( - sourceFilePath: _outFile!.path, destinationFileName: newName)); + sourceFilePath: _outFile!.path, destinationFileName: newName,),); } } on Exception catch (e, s) { Sentry.captureException(e, stackTrace: s); @@ -270,11 +279,11 @@ class PatcherAPI { void sharePatchedFile(String appName, String version) { try { if (_outFile != null) { - String newName = _getFileName(appName, version); - int lastSeparator = _outFile!.path.lastIndexOf('/'); - String newPath = + final String newName = _getFileName(appName, version); + final int lastSeparator = _outFile!.path.lastIndexOf('/'); + final String newPath = _outFile!.path.substring(0, lastSeparator + 1) + newName; - File shareFile = _outFile!.copySync(newPath); + final File shareFile = _outFile!.copySync(newPath); ShareExtend.share(shareFile.path, 'file'); } } on Exception catch (e, s) { @@ -283,34 +292,35 @@ class PatcherAPI { } String _getFileName(String appName, String version) { - String prefix = appName.toLowerCase().replaceAll(' ', '-'); - String newName = '$prefix-revanced_v$version.apk'; + final String prefix = appName.toLowerCase().replaceAll(' ', '-'); + final String newName = '$prefix-revanced_v$version.apk'; return newName; } Future sharePatcherLog(String logs) async { - Directory appCache = await getTemporaryDirectory(); - Directory logDir = Directory('${appCache.path}/logs'); + final Directory appCache = await getTemporaryDirectory(); + final Directory logDir = Directory('${appCache.path}/logs'); logDir.createSync(); - String dateTime = DateTime.now() + final String dateTime = DateTime.now() .toIso8601String() .replaceAll('-', '') .replaceAll(':', '') .replaceAll('T', '') .replaceAll('.', ''); - File log = File('${logDir.path}/revanced-manager_patcher_$dateTime.log'); + final File log = + File('${logDir.path}/revanced-manager_patcher_$dateTime.log'); log.writeAsStringSync(logs); ShareExtend.share(log.path, 'file'); } String getRecommendedVersion(String packageName) { - Map versions = {}; - for (Patch patch in _patches) { - Package? package = patch.compatiblePackages.firstWhereOrNull( + final Map versions = {}; + for (final Patch patch in _patches) { + final Package? package = patch.compatiblePackages.firstWhereOrNull( (pack) => pack.name == packageName, ); if (package != null) { - for (String version in package.versions) { + for (final String version in package.versions) { versions.update( version, (value) => versions[version]! + 1, @@ -320,7 +330,7 @@ class PatcherAPI { } } if (versions.isNotEmpty) { - var entries = versions.entries.toList() + final entries = versions.entries.toList() ..sort((a, b) => a.value.compareTo(b.value)); versions ..clear() diff --git a/lib/services/revanced_api.dart b/lib/services/revanced_api.dart index 40794fc8..fb78d63c 100644 --- a/lib/services/revanced_api.dart +++ b/lib/services/revanced_api.dart @@ -1,15 +1,17 @@ +import 'dart:developer'; import 'dart:io'; + import 'package:collection/collection.dart'; -import 'package:native_dio_client/native_dio_client.dart'; import 'package:dio/dio.dart'; import 'package:dio_http_cache_lts/dio_http_cache_lts.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:injectable/injectable.dart'; +import 'package:native_dio_client/native_dio_client.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/utils/check_for_gms.dart'; -import 'package:timeago/timeago.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_dio/sentry_dio.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:timeago/timeago.dart'; @lazySingleton class RevancedAPI { @@ -22,19 +24,22 @@ class RevancedAPI { Future initialize(String apiUrl) async { try { - bool isGMSInstalled = await checkForGMS(); + final bool isGMSInstalled = await checkForGMS(); if (!isGMSInstalled) { - _dio = Dio(BaseOptions( - baseUrl: apiUrl, - )); - print('ReVanced API: Using default engine + $isGMSInstalled'); + _dio = Dio( + BaseOptions( + baseUrl: apiUrl, + ), + ); + log('ReVanced API: Using default engine + $isGMSInstalled'); } else { - _dio = Dio(BaseOptions( - baseUrl: apiUrl, - )) - ..httpClientAdapter = NativeAdapter(); - print('ReVanced API: Using CronetEngine + $isGMSInstalled'); + _dio = Dio( + BaseOptions( + baseUrl: apiUrl, + ), + )..httpClientAdapter = NativeAdapter(); + log('ReVanced API: Using CronetEngine + $isGMSInstalled'); } _dio.interceptors.add(_dioCacheManager.interceptor); _dio.addSentry( @@ -54,12 +59,12 @@ class RevancedAPI { } Future>> getContributors() async { - Map> contributors = {}; + final Map> contributors = {}; try { - var response = await _dio.get('/contributors', options: _cacheOptions); - List repositories = response.data['repositories']; - for (Map repo in repositories) { - String name = repo['name']; + final response = await _dio.get('/contributors', options: _cacheOptions); + final List repositories = response.data['repositories']; + for (final Map repo in repositories) { + final String name = repo['name']; contributors[name] = repo['contributors']; } } on Exception catch (e, s) { @@ -71,8 +76,8 @@ class RevancedAPI { Future> getPatches() async { try { - var response = await _dio.get('/patches', options: _cacheOptions); - List patches = response.data; + final response = await _dio.get('/patches', options: _cacheOptions); + final List patches = response.data; return patches.map((patch) => Patch.fromJson(patch)).toList(); } on Exception catch (e, s) { await Sentry.captureException(e, stackTrace: s); @@ -85,8 +90,8 @@ class RevancedAPI { String repoName, ) async { try { - var response = await _dio.get('/tools', options: _cacheOptions); - List tools = response.data['tools']; + final response = await _dio.get('/tools', options: _cacheOptions); + final List tools = response.data['tools']; return tools.firstWhereOrNull( (t) => t['repository'] == repoName && @@ -103,7 +108,7 @@ class RevancedAPI { String repoName, ) async { try { - Map? release = await _getLatestRelease( + final Map? release = await _getLatestRelease( extension, repoName, ); @@ -119,12 +124,12 @@ class RevancedAPI { Future getLatestReleaseFile(String extension, String repoName) async { try { - Map? release = await _getLatestRelease( + final Map? release = await _getLatestRelease( extension, repoName, ); if (release != null) { - String url = release['browser_download_url']; + final String url = release['browser_download_url']; return await DefaultCacheManager().getSingleFile(url); } } on Exception catch (e, s) { @@ -139,12 +144,13 @@ class RevancedAPI { String repoName, ) async { try { - Map? release = await _getLatestRelease( + final Map? release = await _getLatestRelease( extension, repoName, ); if (release != null) { - DateTime timestamp = DateTime.parse(release['timestamp'] as String); + final DateTime timestamp = + DateTime.parse(release['timestamp'] as String); return format(timestamp, locale: 'en_short'); } } on Exception catch (e, s) { diff --git a/lib/services/root_api.dart b/lib/services/root_api.dart index 478593cb..0153848d 100644 --- a/lib/services/root_api.dart +++ b/lib/services/root_api.dart @@ -8,7 +8,7 @@ class RootAPI { Future isRooted() async { try { - bool? isRooted = await Root.isRootAvailable(); + final bool? isRooted = await Root.isRootAvailable(); return isRooted != null && isRooted; } on Exception catch (e, s) { await Sentry.captureException(e, stackTrace: s); @@ -70,11 +70,11 @@ class RootAPI { Future> getInstalledApps() async { try { - String? res = await Root.exec( + final String? res = await Root.exec( cmd: 'ls "$_managerDirPath"', ); if (res != null) { - List apps = res.split('\n'); + final List apps = res.split('\n'); apps.removeWhere((pack) => pack.isEmpty); return apps.map((pack) => pack.trim()).toList(); } @@ -132,12 +132,12 @@ class RootAPI { } Future installServiceDScript(String packageName) async { - String content = '#!/system/bin/sh\n' + final String content = '#!/system/bin/sh\n' 'while [ "\$(getprop sys.boot_completed | tr -d \'"\'"\'\\\\r\'"\'"\')" != "1" ]; do sleep 3; done\n' 'base_path=$_managerDirPath/$packageName/base.apk\n' 'stock_path=\$(pm path $packageName | grep base | sed \'"\'"\'s/package://g\'"\'"\')\n' - '[ ! -z \$stock_path ] && mount -o bind \$base_path \$stock_path'; - String scriptFilePath = '$_serviceDDirPath/$packageName.sh'; + r'[ ! -z $stock_path ] && mount -o bind $base_path $stock_path'; + final String scriptFilePath = '$_serviceDDirPath/$packageName.sh'; await Root.exec( cmd: 'echo \'$content\' > "$scriptFilePath"', ); @@ -145,10 +145,10 @@ class RootAPI { } Future installPostFsDataScript(String packageName) async { - String content = '#!/system/bin/sh\n' + final String content = '#!/system/bin/sh\n' 'stock_path=\$(pm path $packageName | grep base | sed \'"\'"\'s/package://g\'"\'"\')\n' - '[ ! -z \$stock_path ] && umount -l \$stock_path'; - String scriptFilePath = '$_postFsDataDirPath/$packageName.sh'; + r'[ ! -z $stock_path ] && umount -l $stock_path'; + final String scriptFilePath = '$_postFsDataDirPath/$packageName.sh'; await Root.exec( cmd: 'echo \'$content\' > "$scriptFilePath"', ); @@ -156,7 +156,7 @@ class RootAPI { } Future installApk(String packageName, String patchedFilePath) async { - String newPatchedFilePath = '$_managerDirPath/$packageName/base.apk'; + final String newPatchedFilePath = '$_managerDirPath/$packageName/base.apk'; await Root.exec( cmd: 'cp "$patchedFilePath" "$newPatchedFilePath"', ); @@ -169,7 +169,7 @@ class RootAPI { } Future mountApk(String packageName, String originalFilePath) async { - String newPatchedFilePath = '$_managerDirPath/$packageName/base.apk'; + final String newPatchedFilePath = '$_managerDirPath/$packageName/base.apk'; await Root.exec( cmd: 'am force-stop "$packageName"', ); @@ -182,7 +182,7 @@ class RootAPI { } Future isMounted(String packageName) async { - String? res = await Root.exec( + final String? res = await Root.exec( cmd: 'cat /proc/mounts | grep $packageName', ); return res != null && res.isNotEmpty; @@ -192,7 +192,7 @@ class RootAPI { String packageName, String originalFilePath, ) async { - bool isInstalled = await isAppInstalled(packageName); + final bool isInstalled = await isAppInstalled(packageName); if (isInstalled && await isMounted(packageName)) { originalFilePath = '$_managerDirPath/$packageName/original.apk'; await setPermissions( @@ -209,7 +209,8 @@ class RootAPI { String packageName, String originalFilePath, ) async { - String originalRootPath = '$_managerDirPath/$packageName/original.apk'; + final String originalRootPath = + '$_managerDirPath/$packageName/original.apk'; await Root.exec( cmd: 'mkdir -p "$_managerDirPath/$packageName"', ); diff --git a/lib/theme.dart b/lib/theme.dart index e8530b15..8affd911 100644 --- a/lib/theme.dart +++ b/lib/theme.dart @@ -3,7 +3,6 @@ import 'package:google_fonts/google_fonts.dart'; var lightCustomColorScheme = ColorScheme.fromSeed( seedColor: Colors.blue, - brightness: Brightness.light, primary: const Color(0xff1B73E8), ); diff --git a/lib/ui/theme/dynamic_theme_builder.dart b/lib/ui/theme/dynamic_theme_builder.dart index d57cf153..54b561fb 100644 --- a/lib/ui/theme/dynamic_theme_builder.dart +++ b/lib/ui/theme/dynamic_theme_builder.dart @@ -7,22 +7,21 @@ import 'package:revanced_manager/theme.dart'; import 'package:stacked_services/stacked_services.dart'; class DynamicThemeBuilder extends StatelessWidget { - final String title; - final Widget home; - final Iterable localizationsDelegates; - const DynamicThemeBuilder({ Key? key, required this.title, required this.home, required this.localizationsDelegates, }) : super(key: key); + final String title; + final Widget home; + final Iterable localizationsDelegates; @override Widget build(BuildContext context) { return DynamicColorBuilder( builder: (lightColorScheme, darkColorScheme) { - ThemeData lightDynamicTheme = ThemeData( + final ThemeData lightDynamicTheme = ThemeData( useMaterial3: true, canvasColor: lightColorScheme?.background, navigationBarTheme: NavigationBarThemeData( @@ -45,7 +44,7 @@ class DynamicThemeBuilder extends StatelessWidget { toggleableActiveColor: lightColorScheme?.primary, textTheme: GoogleFonts.robotoTextTheme(ThemeData.light().textTheme), ); - ThemeData darkDynamicTheme = ThemeData( + final ThemeData darkDynamicTheme = ThemeData( useMaterial3: true, canvasColor: darkColorScheme?.background, navigationBarTheme: NavigationBarThemeData( diff --git a/lib/ui/views/app_selector/app_selector_view.dart b/lib/ui/views/app_selector/app_selector_view.dart index 12440006..8e661674 100644 --- a/lib/ui/views/app_selector/app_selector_view.dart +++ b/lib/ui/views/app_selector/app_selector_view.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart'; +import 'package:revanced_manager/ui/widgets/appSelectorView/app_skeleton_loader.dart'; import 'package:revanced_manager/ui/widgets/appSelectorView/installed_app_item.dart'; import 'package:revanced_manager/ui/widgets/shared/search_bar.dart'; -import 'package:revanced_manager/ui/widgets/appSelectorView/app_skeleton_loader.dart'; import 'package:stacked/stacked.dart' hide SkeletonLoader; -import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart'; class AppSelectorView extends StatefulWidget { const AppSelectorView({Key? key}) : super(key: key); @@ -19,7 +19,7 @@ class _AppSelectorViewState extends State { @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - onModelReady: (model) => model.initialize(), + onViewModelReady: (model) => model.initialize(), viewModelBuilder: () => AppSelectorViewModel(), builder: (context, model, child) => Scaffold( resizeToAvoidBottomInset: false, @@ -36,7 +36,6 @@ class _AppSelectorViewState extends State { SliverAppBar( pinned: true, floating: true, - snap: false, title: I18nText( 'appSelectorView.viewTitle', child: Text( @@ -61,7 +60,6 @@ class _AppSelectorViewState extends State { horizontal: 12.0, ), child: SearchBar( - showSelectIcon: false, hintText: FlutterI18n.translate( context, 'appSelectorView.searchBarHint', @@ -88,17 +86,19 @@ class _AppSelectorViewState extends State { child: Column( children: model .getFilteredApps(_query) - .map((app) => InstalledAppItem( - name: app.appName, - pkgName: app.packageName, - icon: app.icon, - patchesCount: - model.patchesCount(app.packageName), - onTap: () { - model.selectApp(app); - Navigator.of(context).pop(); - }, - )) + .map( + (app) => InstalledAppItem( + name: app.appName, + pkgName: app.packageName, + icon: app.icon, + patchesCount: + model.patchesCount(app.packageName), + onTap: () { + model.selectApp(app); + Navigator.of(context).pop(); + }, + ), + ) .toList(), ), ), diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart index 9b5943a5..d7019ae7 100644 --- a/lib/ui/views/app_selector/app_selector_viewmodel.dart +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -1,15 +1,16 @@ import 'dart:io'; + import 'package:device_apps/device_apps.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/models/patched_application.dart'; +import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/patcher_api.dart'; import 'package:revanced_manager/services/toast.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:stacked/stacked.dart'; -import '../../../services/manager_api.dart'; class AppSelectorViewModel extends BaseViewModel { final PatcherAPI _patcherAPI = locator(); @@ -22,16 +23,21 @@ class AppSelectorViewModel extends BaseViewModel { } Future initialize() async { - apps.addAll(await _patcherAPI.getFilteredInstalledApps(_managerAPI.areUniversalPatchesEnabled())); - apps.sort(((a, b) => _patcherAPI - .getFilteredPatches(b.packageName) - .length - .compareTo(_patcherAPI.getFilteredPatches(a.packageName).length))); + apps.addAll( + await _patcherAPI + .getFilteredInstalledApps(_managerAPI.areUniversalPatchesEnabled()), + ); + apps.sort( + (a, b) => _patcherAPI + .getFilteredPatches(b.packageName) + .length + .compareTo(_patcherAPI.getFilteredPatches(a.packageName).length), + ); noApps = apps.isEmpty; notifyListeners(); } - void selectApp(ApplicationWithIcon application) async { + Future selectApp(ApplicationWithIcon application) async { locator().selectedApp = PatchedApplication( name: application.appName, packageName: application.packageName, @@ -46,22 +52,24 @@ class AppSelectorViewModel extends BaseViewModel { Future selectAppFromStorage(BuildContext context) async { try { - FilePickerResult? result = await FilePicker.platform.pickFiles( + final FilePickerResult? result = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['apk'], ); if (result != null && result.files.single.path != null) { - File apkFile = File(result.files.single.path!); - List pathSplit = result.files.single.path!.split("/"); + final File apkFile = File(result.files.single.path!); + final List pathSplit = result.files.single.path!.split('/'); pathSplit.removeLast(); - Directory filePickerCacheDir = Directory(pathSplit.join("/")); - Iterable deletableFiles = + final Directory filePickerCacheDir = Directory(pathSplit.join('/')); + final Iterable deletableFiles = (await filePickerCacheDir.list().toList()).whereType(); - for (var file in deletableFiles) { - if (file.path != apkFile.path && file.path.endsWith(".apk")) + for (final file in deletableFiles) { + if (file.path != apkFile.path && file.path.endsWith('.apk')) { file.delete(); + } } - ApplicationWithIcon? application = await DeviceApps.getAppFromStorage( + final ApplicationWithIcon? application = + await DeviceApps.getAppFromStorage( apkFile.path, true, ) as ApplicationWithIcon?; @@ -87,10 +95,12 @@ class AppSelectorViewModel extends BaseViewModel { List getFilteredApps(String query) { return apps - .where((app) => - query.isEmpty || - query.length < 2 || - app.appName.toLowerCase().contains(query.toLowerCase())) + .where( + (app) => + query.isEmpty || + query.length < 2 || + app.appName.toLowerCase().contains(query.toLowerCase()), + ) .toList(); } } diff --git a/lib/ui/views/contributors/contributors_view.dart b/lib/ui/views/contributors/contributors_view.dart index 740c290c..ddc66267 100644 --- a/lib/ui/views/contributors/contributors_view.dart +++ b/lib/ui/views/contributors/contributors_view.dart @@ -13,7 +13,7 @@ class ContributorsView extends StatelessWidget { Widget build(BuildContext context) { return ViewModelBuilder.reactive( viewModelBuilder: () => ContributorsViewModel(), - onModelReady: (model) => model.getContributors(), + onViewModelReady: (model) => model.getContributors(), builder: (context, model, child) => Scaffold( body: CustomScrollView( slivers: [ diff --git a/lib/ui/views/contributors/contributors_viewmodel.dart b/lib/ui/views/contributors/contributors_viewmodel.dart index 92793070..c8c7975f 100644 --- a/lib/ui/views/contributors/contributors_viewmodel.dart +++ b/lib/ui/views/contributors/contributors_viewmodel.dart @@ -11,7 +11,7 @@ class ContributorsViewModel extends BaseViewModel { List managerContributors = []; Future getContributors() async { - Map> contributors = + final Map> contributors = await _managerAPI.getContributors(); patcherContributors = contributors[_managerAPI.defaultPatcherRepo] ?? []; patchesContributors = contributors[_managerAPI.getPatchesRepo()] ?? []; diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart index 21184fcf..892cab49 100644 --- a/lib/ui/views/home/home_view.dart +++ b/lib/ui/views/home/home_view.dart @@ -1,7 +1,7 @@ +import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:animations/animations.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/homeView/available_updates_card.dart'; @@ -18,7 +18,7 @@ class HomeView extends StatelessWidget { Widget build(BuildContext context) { return ViewModelBuilder.reactive( disposeViewModel: false, - onModelReady: (model) => model.initialize(context), + onViewModelReady: (model) => model.initialize(context), viewModelBuilder: () => locator(), builder: (context, model, child) => Scaffold( body: RefreshIndicator( @@ -48,7 +48,7 @@ class HomeView extends StatelessWidget { 'homeView.updatesSubtitle', child: Text( '', - style: Theme.of(context).textTheme.headline6!, + style: Theme.of(context).textTheme.headline6, ), ), const SizedBox(height: 10), @@ -61,7 +61,7 @@ class HomeView extends StatelessWidget { 'homeView.patchedSubtitle', child: Text( '', - style: Theme.of(context).textTheme.headline6!, + style: Theme.of(context).textTheme.headline6, ), ), const SizedBox(height: 8), diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index 60317247..03cb5c75 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -1,5 +1,6 @@ // ignore_for_file: use_build_context_synchronously import 'dart:io'; + import 'package:app_installer/app_installer.dart'; import 'package:cross_connectivity/cross_connectivity.dart'; import 'package:device_apps/device_apps.dart'; @@ -10,9 +11,9 @@ import 'package:injectable/injectable.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.router.dart'; import 'package:revanced_manager/models/patched_application.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'; -import 'package:revanced_manager/services/github_api.dart'; import 'package:revanced_manager/services/toast.dart'; import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; @@ -47,7 +48,7 @@ class HomeViewModel extends BaseViewModel { .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.requestPermission(); - bool isConnected = await Connectivity().checkConnection(); + final bool isConnected = await Connectivity().checkConnection(); if (!isConnected) { _toast.showBottom('homeView.noConnection'); } @@ -67,7 +68,7 @@ class HomeViewModel extends BaseViewModel { notifyListeners(); } - void navigateToPatcher(PatchedApplication app) async { + Future navigateToPatcher(PatchedApplication app) async { locator().selectedApp = app; locator().selectedPatches = await _patcherAPI.getAppliedPatches(app.appliedPatches); @@ -88,13 +89,13 @@ class HomeViewModel extends BaseViewModel { } Future hasManagerUpdates() async { - String? latestVersion = await _managerAPI.getLatestManagerVersion(); - String currentVersion = await _managerAPI.getCurrentManagerVersion(); + final String? latestVersion = await _managerAPI.getLatestManagerVersion(); + final String currentVersion = await _managerAPI.getCurrentManagerVersion(); if (latestVersion != null) { try { - int latestVersionInt = + final int latestVersionInt = int.parse(latestVersion.replaceAll(RegExp('[^0-9]'), '')); - int currentVersionInt = + final int currentVersionInt = int.parse(currentVersion.replaceAll(RegExp('[^0-9]'), '')); return latestVersionInt > currentVersionInt; } on Exception catch (e, s) { @@ -108,7 +109,7 @@ class HomeViewModel extends BaseViewModel { Future updateManager(BuildContext context) async { try { _toast.showBottom('homeView.downloadingMessage'); - File? managerApk = await _managerAPI.downloadManager(); + final File? managerApk = await _managerAPI.downloadManager(); if (managerApk != null) { await flutterLocalNotificationsPlugin.zonedSchedule( 0, diff --git a/lib/ui/views/installer/installer_view.dart b/lib/ui/views/installer/installer_view.dart index e6b5672f..d9ceda75 100644 --- a/lib/ui/views/installer/installer_view.dart +++ b/lib/ui/views/installer/installer_view.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart'; -import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; import 'package:revanced_manager/ui/widgets/installerView/gradient_progress_indicator.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; +import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_popup_menu.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; import 'package:stacked/stacked.dart'; @@ -15,7 +15,7 @@ class InstallerView extends StatelessWidget { @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - onModelReady: (model) => model.initialize(context), + onViewModelReady: (model) => model.initialize(context), viewModelBuilder: () => InstallerViewModel(), builder: (context, model, child) => WillPopScope( child: SafeArea( @@ -48,15 +48,15 @@ class InstallerView extends StatelessWidget { ), ), ), - 1: I18nText( - 'installerView.exportApkMenuOption', - child: const Text( - '', - style: TextStyle( - fontWeight: FontWeight.bold, - ), + 1: I18nText( + 'installerView.exportApkMenuOption', + child: const Text( + '', + style: TextStyle( + fontWeight: FontWeight.bold, ), ), + ), 2: I18nText( 'installerView.shareLogMenuOption', child: const Text( @@ -71,9 +71,9 @@ class InstallerView extends StatelessWidget { ), ], bottom: PreferredSize( - preferredSize: const Size(double.infinity, 1.0), - child: - GradientProgressIndicator(progress: model.progress!)), + preferredSize: const Size(double.infinity, 1.0), + child: GradientProgressIndicator(progress: model.progress), + ), ), SliverPadding( padding: const EdgeInsets.all(20.0), diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index dca72755..fb891795 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -51,10 +51,8 @@ class InstallerViewModel extends BaseViewModel { context, 'installerView.notificationText', ), - notificationImportance: AndroidNotificationImportance.Default, notificationIcon: const AndroidResource( name: 'ic_notification', - defType: 'drawable', ), ), ).then((value) => FlutterBackground.enableBackgroundExecution()); @@ -73,10 +71,10 @@ class InstallerViewModel extends BaseViewModel { switch (call.method) { case 'update': if (call.arguments != null) { - Map arguments = call.arguments; - double progress = arguments['progress']; - String header = arguments['header']; - String log = arguments['log']; + final Map arguments = call.arguments; + final double progress = arguments['progress']; + final String header = arguments['header']; + final String log = arguments['log']; update(progress, header, log); } break; @@ -159,13 +157,14 @@ class InstallerViewModel extends BaseViewModel { } } - void installResult(BuildContext context, bool installAsRoot) async { + Future installResult(BuildContext context, bool installAsRoot) async { try { _app.isRooted = installAsRoot; - bool hasMicroG = _patches.any((p) => p.name.endsWith('microg-support')); - bool rootMicroG = installAsRoot && hasMicroG; - bool rootFromStorage = installAsRoot && _app.isFromStorage; - bool ytWithoutRootMicroG = + final bool hasMicroG = + _patches.any((p) => p.name.endsWith('microg-support')); + final bool rootMicroG = installAsRoot && hasMicroG; + final bool rootFromStorage = installAsRoot && _app.isFromStorage; + final bool ytWithoutRootMicroG = !installAsRoot && !hasMicroG && _app.packageName.contains('youtube'); if (rootMicroG || rootFromStorage || ytWithoutRootMicroG) { return showDialog( diff --git a/lib/ui/views/navigation/navigation_view.dart b/lib/ui/views/navigation/navigation_view.dart index 44a132d3..d8fdd5c6 100644 --- a/lib/ui/views/navigation/navigation_view.dart +++ b/lib/ui/views/navigation/navigation_view.dart @@ -11,7 +11,7 @@ class NavigationView extends StatelessWidget { @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - onModelReady: (model) => model.initialize(context), + onViewModelReady: (model) => model.initialize(context), viewModelBuilder: () => locator(), builder: (context, model, child) => Scaffold( body: PageTransitionSwitcher( diff --git a/lib/ui/views/navigation/navigation_viewmodel.dart b/lib/ui/views/navigation/navigation_viewmodel.dart index 65b035d7..0cdf582d 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 { - void initialize(BuildContext context) async { + Future initialize(BuildContext context) async { locator().initialize(context); - SharedPreferences prefs = await SharedPreferences.getInstance(); + final SharedPreferences prefs = await SharedPreferences.getInstance(); if (prefs.getBool('permissionsRequested') == null) { await prefs.setBool('permissionsRequested', true); RootAPI().hasRootPermissions().then( @@ -27,7 +27,7 @@ class NavigationViewModel extends IndexTrackingViewModel { ); } if (prefs.getBool('useDarkTheme') == null) { - bool isDark = + final bool isDark = MediaQuery.of(context).platformBrightness != Brightness.light; await prefs.setBool('useDarkTheme', isDark); await DynamicTheme.of(context)!.setTheme(isDark ? 1 : 0); diff --git a/lib/ui/views/patcher/patcher_viewmodel.dart b/lib/ui/views/patcher/patcher_viewmodel.dart index fa6c4221..eaac984e 100644 --- a/lib/ui/views/patcher/patcher_viewmodel.dart +++ b/lib/ui/views/patcher/patcher_viewmodel.dart @@ -40,18 +40,18 @@ class PatcherViewModel extends BaseViewModel { } Future isValidPatchConfig() async { - bool needsResourcePatching = await _patcherAPI.needsResourcePatching( + final bool needsResourcePatching = await _patcherAPI.needsResourcePatching( selectedPatches, ); if (needsResourcePatching && selectedApp != null) { - bool isSplit = await _managerAPI.isSplitApk(selectedApp!); + final bool isSplit = await _managerAPI.isSplitApk(selectedApp!); return !isSplit; } return true; } Future showPatchConfirmationDialog(BuildContext context) async { - bool isValid = await isValidPatchConfig(); + final bool isValid = await isValidPatchConfig(); if (isValid) { navigateToInstaller(); } else { @@ -110,9 +110,9 @@ class PatcherViewModel extends BaseViewModel { Future loadLastSelectedPatches() async { this.selectedPatches.clear(); - List selectedPatches = + final List selectedPatches = await _managerAPI.getSelectedPatches(selectedApp!.originalPackageName); - List patches = + final List patches = _patcherAPI.getFilteredPatches(selectedApp!.originalPackageName); this.selectedPatches .addAll(patches.where((patch) => selectedPatches.contains(patch.name))); diff --git a/lib/ui/views/patches_selector/patches_selector_view.dart b/lib/ui/views/patches_selector/patches_selector_view.dart index 11365ead..c15d7879 100644 --- a/lib/ui/views/patches_selector/patches_selector_view.dart +++ b/lib/ui/views/patches_selector/patches_selector_view.dart @@ -20,7 +20,7 @@ class _PatchesSelectorViewState extends State { @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - onModelReady: (model) => model.initialize(), + onViewModelReady: (model) => model.initialize(), viewModelBuilder: () => PatchesSelectorViewModel(), builder: (context, model, child) => Scaffold( resizeToAvoidBottomInset: false, @@ -45,7 +45,6 @@ class _PatchesSelectorViewState extends State { SliverAppBar( pinned: true, floating: true, - snap: false, title: I18nText( 'patchesSelectorView.viewTitle', child: Text( diff --git a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart index 81333e95..84c87e75 100644 --- a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart +++ b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart @@ -1,4 +1,5 @@ import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_i18n/widgets/I18nText.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/models/patch.dart'; @@ -10,7 +11,6 @@ import 'package:revanced_manager/services/toast.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; import 'package:stacked/stacked.dart'; -import 'package:flutter/material.dart'; class PatchesSelectorViewModel extends BaseViewModel { final PatcherAPI _patcherAPI = locator(); @@ -26,9 +26,11 @@ class PatchesSelectorViewModel extends BaseViewModel { Future initialize() async { getPatchesVersion(); - patches.addAll(_patcherAPI.getFilteredPatches( - locator().selectedApp!.originalPackageName, - )); + patches.addAll( + _patcherAPI.getFilteredPatches( + locator().selectedApp!.originalPackageName, + ), + ); patches.sort((a, b) => a.name.compareTo(b.name)); notifyListeners(); } @@ -84,8 +86,11 @@ class PatchesSelectorViewModel extends BaseViewModel { selectedPatches.clear(); if (_managerAPI.areExperimentalPatchesEnabled() == false) { - selectedPatches.addAll(patches.where( - (element) => element.excluded == false && isPatchSupported(element))); + selectedPatches.addAll( + patches.where( + (element) => element.excluded == false && isPatchSupported(element), + ), + ); } if (_managerAPI.areExperimentalPatchesEnabled()) { @@ -117,15 +122,18 @@ class PatchesSelectorViewModel extends BaseViewModel { patchesVersion = await _githubAPI .getLastestReleaseVersion(_managerAPI.getPatchesRepo()); } + return null; } List getQueriedPatches(String query) { return patches - .where((patch) => - query.isEmpty || - query.length < 2 || - patch.name.toLowerCase().contains(query.toLowerCase()) || - patch.getSimpleName().toLowerCase().contains(query.toLowerCase())) + .where( + (patch) => + query.isEmpty || + query.length < 2 || + patch.name.toLowerCase().contains(query.toLowerCase()) || + patch.getSimpleName().toLowerCase().contains(query.toLowerCase()), + ) .toList(); } @@ -134,8 +142,8 @@ class PatchesSelectorViewModel extends BaseViewModel { } List getSupportedVersions(Patch patch) { - PatchedApplication app = locator().selectedApp!; - Package? package = patch.compatiblePackages.firstWhereOrNull( + final PatchedApplication app = locator().selectedApp!; + final Package? package = patch.compatiblePackages.firstWhereOrNull( (pack) => pack.name == app.packageName, ); if (package != null) { @@ -146,10 +154,13 @@ class PatchesSelectorViewModel extends BaseViewModel { } bool isPatchSupported(Patch patch) { - PatchedApplication app = locator().selectedApp!; - return patch.compatiblePackages.isEmpty || patch.compatiblePackages.any((pack) => - pack.name == app.packageName && - (pack.versions.isEmpty || pack.versions.contains(app.version))); + final PatchedApplication app = locator().selectedApp!; + return patch.compatiblePackages.isEmpty || + patch.compatiblePackages.any( + (pack) => + pack.name == app.packageName && + (pack.versions.isEmpty || pack.versions.contains(app.version)), + ); } void onMenuSelection(value) { @@ -161,20 +172,23 @@ class PatchesSelectorViewModel extends BaseViewModel { } Future saveSelectedPatches() async { - List selectedPatches = + final List selectedPatches = this.selectedPatches.map((patch) => patch.name).toList(); await _managerAPI.setSelectedPatches( - locator().selectedApp!.originalPackageName, - selectedPatches); + locator().selectedApp!.originalPackageName, + selectedPatches, + ); } Future loadSelectedPatches() async { - List selectedPatches = await _managerAPI.getSelectedPatches( - locator().selectedApp!.originalPackageName); + final List selectedPatches = await _managerAPI.getSelectedPatches( + locator().selectedApp!.originalPackageName, + ); if (selectedPatches.isNotEmpty) { this.selectedPatches.clear(); this.selectedPatches.addAll( - patches.where((patch) => selectedPatches.contains(patch.name))); + patches.where((patch) => selectedPatches.contains(patch.name)), + ); } else { locator().showBottom('patchesSelectorView.noSavedPatches'); } diff --git a/lib/ui/views/settings/settingsFragement/settings_manage_api_url.dart b/lib/ui/views/settings/settingsFragement/settings_manage_api_url.dart index b2600fd6..438f519b 100644 --- a/lib/ui/views/settings/settingsFragement/settings_manage_api_url.dart +++ b/lib/ui/views/settings/settingsFragement/settings_manage_api_url.dart @@ -15,7 +15,7 @@ class SManageApiUrl extends BaseViewModel { final TextEditingController _apiUrlController = TextEditingController(); Future showApiUrlDialog(BuildContext context) async { - String apiUrl = _managerAPI.getApiUrl(); + final String apiUrl = _managerAPI.getApiUrl(); _apiUrlController.text = apiUrl.replaceAll('https://', ''); return showDialog( context: context, diff --git a/lib/ui/views/settings/settingsFragement/settings_manage_sources.dart b/lib/ui/views/settings/settingsFragement/settings_manage_sources.dart index d7fdb8f2..10b3e64d 100644 --- a/lib/ui/views/settings/settingsFragement/settings_manage_sources.dart +++ b/lib/ui/views/settings/settingsFragement/settings_manage_sources.dart @@ -19,9 +19,9 @@ class SManageSources extends BaseViewModel { final TextEditingController _intSourceController = TextEditingController(); Future showSourcesDialog(BuildContext context) async { - String hostRepository = _managerAPI.getRepoUrl(); - String patchesRepo = _managerAPI.getPatchesRepo(); - String integrationsRepo = _managerAPI.getIntegrationsRepo(); + final String hostRepository = _managerAPI.getRepoUrl(); + final String patchesRepo = _managerAPI.getPatchesRepo(); + final String integrationsRepo = _managerAPI.getIntegrationsRepo(); _hostSourceController.text = hostRepository; _orgPatSourceController.text = patchesRepo.split('/')[0]; _patSourceController.text = patchesRepo.split('/')[1]; diff --git a/lib/ui/views/settings/settingsFragement/settings_update_theme.dart b/lib/ui/views/settings/settingsFragement/settings_update_theme.dart index 822af1c1..efc54042 100644 --- a/lib/ui/views/settings/settingsFragement/settings_update_theme.dart +++ b/lib/ui/views/settings/settingsFragement/settings_update_theme.dart @@ -23,9 +23,9 @@ class SUpdateTheme extends BaseViewModel { return _managerAPI.getUseDynamicTheme(); } - void setUseDynamicTheme(BuildContext context, bool value) async { + Future setUseDynamicTheme(BuildContext context, bool value) async { await _managerAPI.setUseDynamicTheme(value); - int currentTheme = DynamicTheme.of(context)!.themeId; + final int currentTheme = DynamicTheme.of(context)!.themeId; if (currentTheme.isEven) { await DynamicTheme.of(context)!.setTheme(value ? 2 : 0); } else { @@ -38,9 +38,9 @@ class SUpdateTheme extends BaseViewModel { return _managerAPI.getUseDarkTheme(); } - void setUseDarkTheme(BuildContext context, bool value) async { + Future setUseDarkTheme(BuildContext context, bool value) async { await _managerAPI.setUseDarkTheme(value); - int currentTheme = DynamicTheme.of(context)!.themeId; + final int currentTheme = DynamicTheme.of(context)!.themeId; if (currentTheme < 2) { await DynamicTheme.of(context)!.setTheme(value ? 1 : 0); } else { diff --git a/lib/ui/views/settings/settings_view.dart b/lib/ui/views/settings/settings_view.dart index ec4720bb..01d461e1 100644 --- a/lib/ui/views/settings/settings_view.dart +++ b/lib/ui/views/settings/settings_view.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:revanced_manager/ui/views/settings/settingsFragement/settings_update_language.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragement/settings_update_theme.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_advanced_section.dart'; diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index e9bf7d80..502b7a1e 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -70,12 +70,12 @@ class SettingsViewModel extends BaseViewModel { Future exportPatches() async { try { - File outFile = File(_managerAPI.storedPatchesFile); + final File outFile = File(_managerAPI.storedPatchesFile); if (outFile.existsSync()) { - String dateTime = + final String dateTime = DateTime.now().toString().replaceAll(' ', '_').split('.').first; await CRFileSaver.saveFileWithDialog(SaveFileDialogParams( - sourceFilePath: outFile.path, destinationFileName: 'selected_patches_$dateTime.json')); + sourceFilePath: outFile.path, destinationFileName: 'selected_patches_$dateTime.json',),); _toast.showBottom('settingsView.exportedPatches'); } else { _toast.showBottom('settingsView.noExportFileFound'); @@ -87,12 +87,12 @@ class SettingsViewModel extends BaseViewModel { Future importPatches() async { try { - FilePickerResult? result = await FilePicker.platform.pickFiles( + final FilePickerResult? result = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['json'], ); if (result != null && result.files.single.path != null) { - File inFile = File(result.files.single.path!); + final File inFile = File(result.files.single.path!); inFile.copySync(_managerAPI.storedPatchesFile); inFile.delete(); if (locator().selectedApp != null) { @@ -112,13 +112,13 @@ class SettingsViewModel extends BaseViewModel { } Future getSdkVersion() async { - AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo; + final AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo; return info.version.sdkInt ?? -1; } Future deleteLogs() async { - Directory appCacheDir = await getTemporaryDirectory(); - Directory logsDir = Directory('${appCacheDir.path}/logs'); + final Directory appCacheDir = await getTemporaryDirectory(); + final Directory logsDir = Directory('${appCacheDir.path}/logs'); if (logsDir.existsSync()) { logsDir.deleteSync(recursive: true); } @@ -126,17 +126,18 @@ class SettingsViewModel extends BaseViewModel { } Future exportLogcatLogs() async { - Directory appCache = await getTemporaryDirectory(); - Directory logDir = Directory('${appCache.path}/logs'); + final Directory appCache = await getTemporaryDirectory(); + final Directory logDir = Directory('${appCache.path}/logs'); logDir.createSync(); - String dateTime = DateTime.now() + final String dateTime = DateTime.now() .toIso8601String() .replaceAll('-', '') .replaceAll(':', '') .replaceAll('T', '') .replaceAll('.', ''); - File logcat = File('${logDir.path}/revanced-manager_logcat_$dateTime.log'); - String logs = await Logcat.execute(); + final File logcat = + File('${logDir.path}/revanced-manager_logcat_$dateTime.log'); + final String logs = await Logcat.execute(); logcat.writeAsStringSync(logs); ShareExtend.share(logcat.path, 'file'); } diff --git a/lib/ui/widgets/appInfoView/app_info_view.dart b/lib/ui/widgets/appInfoView/app_info_view.dart index 2c442bac..b1e0b3cb 100644 --- a/lib/ui/widgets/appInfoView/app_info_view.dart +++ b/lib/ui/widgets/appInfoView/app_info_view.dart @@ -8,12 +8,11 @@ import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; import 'package:stacked/stacked.dart'; class AppInfoView extends StatelessWidget { - final PatchedApplication app; - const AppInfoView({ Key? key, required this.app, }) : super(key: key); + final PatchedApplication app; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/appInfoView/app_info_viewmodel.dart b/lib/ui/widgets/appInfoView/app_info_viewmodel.dart index bb919465..0f6184a1 100644 --- a/lib/ui/widgets/appInfoView/app_info_viewmodel.dart +++ b/lib/ui/widgets/appInfoView/app_info_viewmodel.dart @@ -29,7 +29,7 @@ class AppInfoViewModel extends BaseViewModel { ) async { bool isUninstalled = true; if (app.isRooted) { - bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { await _rootAPI.deleteApp(app.packageName, app.apkFilePath); if (!onlyUnpatch) { @@ -45,7 +45,7 @@ class AppInfoViewModel extends BaseViewModel { } } - void navigateToPatcher(PatchedApplication app) async { + Future navigateToPatcher(PatchedApplication app) async { locator().selectedApp = app; locator().selectedPatches = await _patcherAPI.getAppliedPatches(app.appliedPatches); @@ -62,7 +62,7 @@ class AppInfoViewModel extends BaseViewModel { PatchedApplication app, bool onlyUnpatch, ) async { - bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); if (app.isRooted && !hasRootPermissions) { return showDialog( context: context, @@ -134,7 +134,8 @@ class AppInfoViewModel extends BaseViewModel { title: I18nText('appInfoView.appliedPatchesLabel'), backgroundColor: Theme.of(context).colorScheme.secondaryContainer, content: SingleChildScrollView( - child: Text(getAppliedPatchesString(app.appliedPatches))), + child: Text(getAppliedPatchesString(app.appliedPatches)), + ), actions: [ CustomMaterialButton( label: I18nText('okButton'), @@ -146,13 +147,15 @@ class AppInfoViewModel extends BaseViewModel { } String getAppliedPatchesString(List appliedPatches) { - List names = appliedPatches - .map((p) => p - .replaceAll('-', ' ') - .split('-') - .join(' ') - .toTitleCase() - .replaceFirst('Microg', 'MicroG')) + final List names = appliedPatches + .map( + (p) => p + .replaceAll('-', ' ') + .split('-') + .join(' ') + .toTitleCase() + .replaceFirst('Microg', 'MicroG'), + ) .toList(); return '\u2022 ${names.join('\n\u2022 ')}'; } diff --git a/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart b/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart index 89699c09..0c7ee017 100644 --- a/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart +++ b/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart @@ -21,7 +21,6 @@ class AppSkeletonLoader extends StatelessWidget { style: SkeletonAvatarStyle( width: screenWidth * 0.15, height: screenWidth * 0.15, - shape: BoxShape.rectangle, borderRadius: const BorderRadius.all(Radius.circular(12)), ), ), diff --git a/lib/ui/widgets/appSelectorView/installed_app_item.dart b/lib/ui/widgets/appSelectorView/installed_app_item.dart index d50820b9..839960c5 100644 --- a/lib/ui/widgets/appSelectorView/installed_app_item.dart +++ b/lib/ui/widgets/appSelectorView/installed_app_item.dart @@ -3,12 +3,6 @@ import 'package:flutter/material.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class InstalledAppItem extends StatefulWidget { - final String name; - final String pkgName; - final Uint8List icon; - final int patchesCount; - final Function()? onTap; - const InstalledAppItem({ Key? key, required this.name, @@ -17,6 +11,11 @@ class InstalledAppItem extends StatefulWidget { required this.patchesCount, this.onTap, }) : super(key: key); + final String name; + final String pkgName; + final Uint8List icon; + final int patchesCount; + final Function()? onTap; @override State createState() => _InstalledAppItemState(); @@ -48,7 +47,6 @@ class _InstalledAppItemState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( widget.name, @@ -62,8 +60,8 @@ class _InstalledAppItemState extends State { const SizedBox(width: 6), Text( widget.patchesCount == 1 - ? "${widget.patchesCount} patch" - : "${widget.patchesCount} patches", + ? '${widget.patchesCount} patch' + : '${widget.patchesCount} patches', style: TextStyle( fontSize: 8, color: Theme.of(context).colorScheme.secondary, diff --git a/lib/ui/widgets/contributorsView/contributors_card.dart b/lib/ui/widgets/contributorsView/contributors_card.dart index c02224e4..8f85f798 100644 --- a/lib/ui/widgets/contributorsView/contributors_card.dart +++ b/lib/ui/widgets/contributorsView/contributors_card.dart @@ -6,14 +6,13 @@ import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; import 'package:url_launcher/url_launcher.dart'; class ContributorsCard extends StatefulWidget { - final String title; - final List contributors; - const ContributorsCard({ Key? key, required this.title, required this.contributors, }) : super(key: key); + final String title; + final List contributors; @override State createState() => _ContributorsCardState(); diff --git a/lib/ui/widgets/homeView/available_updates_card.dart b/lib/ui/widgets/homeView/available_updates_card.dart index 2a7a6b74..db341b6f 100644 --- a/lib/ui/widgets/homeView/available_updates_card.dart +++ b/lib/ui/widgets/homeView/available_updates_card.dart @@ -3,7 +3,6 @@ import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; -import 'package:revanced_manager/ui/widgets/shared/application_item.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class AvailableUpdatesCard extends StatelessWidget { diff --git a/lib/ui/widgets/homeView/latest_commit_card.dart b/lib/ui/widgets/homeView/latest_commit_card.dart index be88a64f..f23beb07 100644 --- a/lib/ui/widgets/homeView/latest_commit_card.dart +++ b/lib/ui/widgets/homeView/latest_commit_card.dart @@ -2,16 +2,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; -import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; +import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; class LatestCommitCard extends StatefulWidget { - final Function() onPressed; - const LatestCommitCard({ Key? key, required this.onPressed, }) : super(key: key); + final Function() onPressed; @override State createState() => _LatestCommitCardState(); @@ -73,7 +72,6 @@ class _LatestCommitCardState extends State { builder: (context, snapshot) => Opacity( opacity: snapshot.hasData && snapshot.data! ? 1.0 : 0.25, child: CustomMaterialButton( - isExpanded: false, label: I18nText('latestCommitCard.updateButton'), onPressed: snapshot.hasData && snapshot.data! ? widget.onPressed diff --git a/lib/ui/widgets/homeView/update_confirmation_dialog.dart b/lib/ui/widgets/homeView/update_confirmation_dialog.dart index bee19399..2051aefc 100644 --- a/lib/ui/widgets/homeView/update_confirmation_dialog.dart +++ b/lib/ui/widgets/homeView/update_confirmation_dialog.dart @@ -14,7 +14,6 @@ class UpdateConfirmationDialog extends StatelessWidget { return DraggableScrollableSheet( expand: false, - initialChildSize: 0.5, snap: true, snapSizes: const [0.5], builder: (context, scrollController) => SingleChildScrollView( @@ -37,7 +36,11 @@ class UpdateConfirmationDialog extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.only( - top: 40.0, left: 24.0, right: 24.0, bottom: 32.0), + top: 40.0, + left: 24.0, + right: 24.0, + bottom: 32.0, + ), child: Row( children: [ Expanded( @@ -47,10 +50,11 @@ class UpdateConfirmationDialog extends StatelessWidget { I18nText( 'homeView.updateDialogTitle', child: const Text( - "", + '', style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold), + fontSize: 24, + fontWeight: FontWeight.bold, + ), ), ), const SizedBox(height: 4.0), @@ -63,7 +67,7 @@ class UpdateConfirmationDialog extends StatelessWidget { ), const SizedBox(width: 8.0), Text( - snapshot.data!["tag_name"] ?? "Unknown", + snapshot.data!['tag_name'] ?? 'Unknown', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w500, @@ -93,13 +97,14 @@ class UpdateConfirmationDialog extends StatelessWidget { child: I18nText( 'homeView.updateChangelogTitle', child: Text( - "", + '', style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer), + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), ), ), ), @@ -113,7 +118,7 @@ class UpdateConfirmationDialog extends StatelessWidget { shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.all(20.0), - data: snapshot.data!["body"] ?? "", + data: snapshot.data!['body'] ?? '', ), ), ], diff --git a/lib/ui/widgets/installerView/gradient_progress_indicator.dart b/lib/ui/widgets/installerView/gradient_progress_indicator.dart index f6d8f67e..3936810b 100644 --- a/lib/ui/widgets/installerView/gradient_progress_indicator.dart +++ b/lib/ui/widgets/installerView/gradient_progress_indicator.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; class GradientProgressIndicator extends StatefulWidget { - final double? progress; const GradientProgressIndicator({required this.progress, super.key}); + final double? progress; @override State createState() => diff --git a/lib/ui/widgets/patcherView/app_selector_card.dart b/lib/ui/widgets/patcherView/app_selector_card.dart index ae3dcb97..7c52d186 100644 --- a/lib/ui/widgets/patcherView/app_selector_card.dart +++ b/lib/ui/widgets/patcherView/app_selector_card.dart @@ -6,12 +6,11 @@ import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class AppSelectorCard extends StatelessWidget { - final Function() onPressed; - const AppSelectorCard({ Key? key, required this.onPressed, }) : super(key: key); + final Function() onPressed; @override Widget build(BuildContext context) { @@ -33,40 +32,41 @@ class AppSelectorCard extends StatelessWidget { ), ), const SizedBox(height: 8), - locator().selectedApp == null - ? I18nText('appSelectorCard.widgetSubtitle') - : Row( - children: [ - SizedBox( - height: 18.0, - child: ClipOval( - child: Image.memory( - locator().selectedApp == null - ? Uint8List(0) - : locator().selectedApp!.icon, - fit: BoxFit.cover, - ), - ), + if (locator().selectedApp == null) + I18nText('appSelectorCard.widgetSubtitle') + else + Row( + children: [ + SizedBox( + height: 18.0, + child: ClipOval( + child: Image.memory( + locator().selectedApp == null + ? Uint8List(0) + : locator().selectedApp!.icon, + fit: BoxFit.cover, ), - const SizedBox(width: 6), - Text( - locator() - .getAppSelectionString(), - style: const TextStyle(fontWeight: FontWeight.w600), - ), - ], + ), ), - locator().selectedApp == null - ? Container() - : Column( - children: [ - const SizedBox(height: 4), - Text( - locator() - .getRecommendedVersionString(context), - ), - ], + const SizedBox(width: 6), + Text( + locator().getAppSelectionString(), + style: const TextStyle(fontWeight: FontWeight.w600), ), + ], + ), + if (locator().selectedApp == null) + Container() + else + Column( + children: [ + const SizedBox(height: 4), + Text( + locator() + .getRecommendedVersionString(context), + ), + ], + ), ], ), ); diff --git a/lib/ui/widgets/patcherView/patch_selector_card.dart b/lib/ui/widgets/patcherView/patch_selector_card.dart index 2a432d66..f364a4f2 100644 --- a/lib/ui/widgets/patcherView/patch_selector_card.dart +++ b/lib/ui/widgets/patcherView/patch_selector_card.dart @@ -6,12 +6,11 @@ import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class PatchSelectorCard extends StatelessWidget { - final Function() onPressed; - const PatchSelectorCard({ Key? key, required this.onPressed, }) : super(key: key); + final Function() onPressed; @override Widget build(BuildContext context) { @@ -46,11 +45,12 @@ class PatchSelectorCard extends StatelessWidget { ], ), const SizedBox(height: 4), - locator().selectedApp == null - ? I18nText('patchSelectorCard.widgetSubtitle') - : locator().selectedPatches.isEmpty - ? I18nText('patchSelectorCard.widgetEmptySubtitle') - : Text(_getPatchesSelection()), + if (locator().selectedApp == null) + I18nText('patchSelectorCard.widgetSubtitle') + else + locator().selectedPatches.isEmpty + ? I18nText('patchSelectorCard.widgetEmptySubtitle') + : Text(_getPatchesSelection()), ], ), ); @@ -58,7 +58,7 @@ class PatchSelectorCard extends StatelessWidget { String _getPatchesSelection() { String text = ''; - for (Patch p in locator().selectedPatches) { + for (final Patch p in locator().selectedPatches) { text += '\u2022 ${p.getSimpleName()} (v${p.version})\n'; } return text.substring(0, text.length - 1); diff --git a/lib/ui/widgets/patchesSelectorView/patch_item.dart b/lib/ui/widgets/patchesSelectorView/patch_item.dart index 6471423f..e4c5b3c7 100644 --- a/lib/ui/widgets/patchesSelectorView/patch_item.dart +++ b/lib/ui/widgets/patchesSelectorView/patch_item.dart @@ -3,11 +3,24 @@ import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/toast.dart'; -import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; +import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; // ignore: must_be_immutable class PatchItem extends StatefulWidget { + PatchItem({ + Key? key, + required this.name, + required this.simpleName, + required this.description, + required this.version, + required this.packageVersion, + required this.supportedPackageVersions, + required this.isUnsupported, + required this.isSelected, + required this.onChanged, + this.child, + }) : super(key: key); final String name; final String simpleName; final String description; @@ -21,20 +34,6 @@ class PatchItem extends StatefulWidget { final toast = locator(); final _managerAPI = locator(); - PatchItem( - {Key? key, - required this.name, - required this.simpleName, - required this.description, - required this.version, - required this.packageVersion, - required this.supportedPackageVersions, - required this.isUnsupported, - required this.isSelected, - required this.onChanged, - this.child}) - : super(key: key); - @override State createState() => _PatchItemState(); } @@ -141,38 +140,37 @@ class _PatchItemState extends State { ) ], ), - widget.isUnsupported - ? Row( - children: [ - Padding( - padding: const EdgeInsets.only(top: 8), - child: TextButton.icon( - label: I18nText('warning'), - icon: const Icon(Icons.warning, size: 20.0), - onPressed: () => _showUnsupportedWarningDialog(), - style: ButtonStyle( - shape: MaterialStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: BorderSide( - width: 1, - color: - Theme.of(context).colorScheme.secondary, - ), - ), - ), - backgroundColor: MaterialStateProperty.all( - Colors.transparent, - ), - foregroundColor: MaterialStateProperty.all( - Theme.of(context).colorScheme.secondary, + if (widget.isUnsupported) + Row( + children: [ + Padding( + padding: const EdgeInsets.only(top: 8), + child: TextButton.icon( + label: I18nText('warning'), + icon: const Icon(Icons.warning, size: 20.0), + onPressed: () => _showUnsupportedWarningDialog(), + style: ButtonStyle( + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide( + color: Theme.of(context).colorScheme.secondary, ), ), ), + backgroundColor: MaterialStateProperty.all( + Colors.transparent, + ), + foregroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.secondary, + ), ), - ], - ) - : Container(), + ), + ), + ], + ) + else + Container(), widget.child ?? const SizedBox(), ], ), diff --git a/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart b/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart index 8136a38a..9cac726d 100644 --- a/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart +++ b/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart @@ -3,8 +3,8 @@ import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; class OptionsTextField extends StatelessWidget { - final String hint; const OptionsTextField({Key? key, required this.hint}) : super(key: key); + final String hint; @override Widget build(BuildContext context) { @@ -12,7 +12,7 @@ class OptionsTextField extends StatelessWidget { final sWidth = MediaQuery.of(context).size.width; return Container( margin: const EdgeInsets.only(top: 12, bottom: 6), - padding: const EdgeInsets.all(0), + padding: EdgeInsets.zero, child: TextField( decoration: InputDecoration( constraints: BoxConstraints( @@ -28,9 +28,9 @@ class OptionsTextField extends StatelessWidget { } class OptionsFilePicker extends StatelessWidget { - final String optionName; const OptionsFilePicker({Key? key, required this.optionName}) : super(key: key); + final String optionName; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/settingsView/about_widget.dart b/lib/ui/widgets/settingsView/about_widget.dart index 1f6d9325..97b10216 100644 --- a/lib/ui/widgets/settingsView/about_widget.dart +++ b/lib/ui/widgets/settingsView/about_widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/utils/about_info.dart'; -import 'package:flutter/services.dart'; class AboutWidget extends StatefulWidget { const AboutWidget({Key? key, this.padding}) : super(key: key); diff --git a/lib/ui/widgets/settingsView/custom_switch.dart b/lib/ui/widgets/settingsView/custom_switch.dart index 22a4120b..87eb266f 100644 --- a/lib/ui/widgets/settingsView/custom_switch.dart +++ b/lib/ui/widgets/settingsView/custom_switch.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; class CustomSwitch extends StatelessWidget { - final ValueChanged onChanged; - final bool value; - const CustomSwitch({ Key? key, required this.onChanged, required this.value, }) : super(key: key); + final ValueChanged onChanged; + final bool value; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/settingsView/custom_switch_tile.dart b/lib/ui/widgets/settingsView/custom_switch_tile.dart index 77521cbc..f17f9670 100644 --- a/lib/ui/widgets/settingsView/custom_switch_tile.dart +++ b/lib/ui/widgets/settingsView/custom_switch_tile.dart @@ -2,12 +2,6 @@ import 'package:flutter/material.dart'; import 'package:revanced_manager/ui/widgets/settingsView/custom_switch.dart'; class CustomSwitchTile extends StatelessWidget { - final Widget title; - final Widget subtitle; - final bool value; - final Function(bool) onTap; - final EdgeInsetsGeometry? padding; - const CustomSwitchTile({ Key? key, required this.title, @@ -16,6 +10,11 @@ class CustomSwitchTile extends StatelessWidget { required this.onTap, this.padding, }) : super(key: key); + final Widget title; + final Widget subtitle; + final bool value; + final Function(bool) onTap; + final EdgeInsetsGeometry? padding; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/settingsView/custom_text_field.dart b/lib/ui/widgets/settingsView/custom_text_field.dart index 52b7abf1..6f2b8a76 100644 --- a/lib/ui/widgets/settingsView/custom_text_field.dart +++ b/lib/ui/widgets/settingsView/custom_text_field.dart @@ -1,12 +1,6 @@ import 'package:flutter/material.dart'; class CustomTextField extends StatelessWidget { - final TextEditingController inputController; - final Widget label; - final String hint; - final Widget? leadingIcon; - final Function(String)? onChanged; - const CustomTextField({ Key? key, required this.inputController, @@ -15,6 +9,11 @@ class CustomTextField extends StatelessWidget { this.leadingIcon, required this.onChanged, }) : super(key: key); + final TextEditingController inputController; + final Widget label; + final String hint; + final Widget? leadingIcon; + final Function(String)? onChanged; @override Widget build(BuildContext context) { @@ -45,10 +44,8 @@ class CustomTextField extends StatelessWidget { border: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.primary, - width: 1.0, ), borderRadius: BorderRadius.circular(10), - gapPadding: 4.0, ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( @@ -60,14 +57,12 @@ class CustomTextField extends StatelessWidget { errorBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.error, - width: 1.0, ), borderRadius: BorderRadius.circular(10), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.primary, - width: 1.0, ), borderRadius: BorderRadius.circular(10), ), diff --git a/lib/ui/widgets/settingsView/settings_experimental_universal_patches.dart b/lib/ui/widgets/settingsView/settings_experimental_universal_patches.dart index fe255c40..c199259b 100644 --- a/lib/ui/widgets/settingsView/settings_experimental_universal_patches.dart +++ b/lib/ui/widgets/settingsView/settings_experimental_universal_patches.dart @@ -7,12 +7,14 @@ class SExperimentalUniversalPatches extends StatefulWidget { const SExperimentalUniversalPatches({super.key}); @override - State createState() => _SExperimentalUniversalPatchesState(); + State createState() => + _SExperimentalUniversalPatchesState(); } final _settingsViewModel = SettingsViewModel(); -class _SExperimentalUniversalPatchesState extends State { +class _SExperimentalUniversalPatchesState + extends State { @override Widget build(BuildContext context) { return CustomSwitchTile( diff --git a/lib/ui/widgets/settingsView/settings_section.dart b/lib/ui/widgets/settingsView/settings_section.dart index 402e2e55..74570a14 100644 --- a/lib/ui/widgets/settingsView/settings_section.dart +++ b/lib/ui/widgets/settingsView/settings_section.dart @@ -2,14 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; class SettingsSection extends StatelessWidget { - final String title; - final List children; - const SettingsSection({ Key? key, required this.title, required this.children, }) : super(key: key); + final String title; + final List children; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/settingsView/settings_tile_dialog.dart b/lib/ui/widgets/settingsView/settings_tile_dialog.dart index f4353cdd..ce3a817d 100644 --- a/lib/ui/widgets/settingsView/settings_tile_dialog.dart +++ b/lib/ui/widgets/settingsView/settings_tile_dialog.dart @@ -2,11 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; class SettingsTileDialog extends StatelessWidget { - final String title; - final String subtitle; - final Function()? onTap; - final EdgeInsetsGeometry? padding; - const SettingsTileDialog({ Key? key, required this.title, @@ -14,6 +9,10 @@ class SettingsTileDialog extends StatelessWidget { required this.onTap, this.padding, }) : super(key: key); + final String title; + final String subtitle; + final Function()? onTap; + final EdgeInsetsGeometry? padding; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/settingsView/social_media_item.dart b/lib/ui/widgets/settingsView/social_media_item.dart index 3bc28cde..86971a27 100644 --- a/lib/ui/widgets/settingsView/social_media_item.dart +++ b/lib/ui/widgets/settingsView/social_media_item.dart @@ -1,13 +1,7 @@ - import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; class SocialMediaItem extends StatelessWidget { - final Widget? icon; - final Widget title; - final Widget? subtitle; - final String? url; - const SocialMediaItem({ Key? key, this.icon, @@ -15,6 +9,10 @@ class SocialMediaItem extends StatelessWidget { this.subtitle, this.url, }) : super(key: key); + final Widget? icon; + final Widget title; + final Widget? subtitle; + final String? url; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/settingsView/social_media_widget.dart b/lib/ui/widgets/settingsView/social_media_widget.dart index 37bfd08e..9418b523 100644 --- a/lib/ui/widgets/settingsView/social_media_widget.dart +++ b/lib/ui/widgets/settingsView/social_media_widget.dart @@ -6,12 +6,11 @@ import 'package:revanced_manager/ui/widgets/settingsView/social_media_item.dart' import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class SocialMediaWidget extends StatelessWidget { - final EdgeInsetsGeometry? padding; - const SocialMediaWidget({ Key? key, this.padding, }) : super(key: key); + final EdgeInsetsGeometry? padding; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/shared/application_item.dart b/lib/ui/widgets/shared/application_item.dart index addf1bf1..24e84375 100644 --- a/lib/ui/widgets/shared/application_item.dart +++ b/lib/ui/widgets/shared/application_item.dart @@ -1,19 +1,13 @@ import 'dart:typed_data'; + +import 'package:expandable/expandable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; -import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; -import 'package:expandable/expandable.dart'; +import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; import 'package:timeago/timeago.dart'; class ApplicationItem extends StatefulWidget { - final Uint8List icon; - final String name; - final DateTime patchDate; - final List changelog; - final bool isUpdatableApp; - final Function() onPressed; - const ApplicationItem({ Key? key, required this.icon, @@ -23,6 +17,12 @@ class ApplicationItem extends StatefulWidget { required this.isUpdatableApp, required this.onPressed, }) : super(key: key); + final Uint8List icon; + final String name; + final DateTime patchDate; + final List changelog; + final bool isUpdatableApp; + final Function() onPressed; @override State createState() => _ApplicationItemState(); @@ -33,7 +33,7 @@ class _ApplicationItemState extends State late AnimationController _animationController; @override - initState() { + void initState() { super.initState(); _animationController = AnimationController( vsync: this, @@ -49,95 +49,100 @@ class _ApplicationItemState extends State @override Widget build(BuildContext context) { - ExpandableController expController = ExpandableController(); + final ExpandableController expController = ExpandableController(); return Container( - margin: const EdgeInsets.only(bottom: 16.0), - child: CustomCard( - onTap: () { - expController.toggle(); - _animationController.isCompleted - ? _animationController.reverse() - : _animationController.forward(); - }, - child: ExpandablePanel( - controller: expController, - theme: const ExpandableThemeData( - inkWellBorderRadius: BorderRadius.all(Radius.circular(16)), - tapBodyToCollapse: false, - tapBodyToExpand: false, - tapHeaderToExpand: false, - hasIcon: false, - animationDuration: Duration(milliseconds: 450), - ), - header: Row( - children: [ - SizedBox( - width: 40, - child: Image.memory(widget.icon, height: 40, width: 40), - ), - const SizedBox(width: 4), - Padding( - padding: const EdgeInsets.only(left: 15.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.name.length > 12 - ? '${widget.name.substring(0, 12)}...' - : widget.name, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - Text(format(widget.patchDate)), - ], - ), - ), - const Spacer(), - RotationTransition( - turns: Tween(begin: 0.0, end: 0.50) - .animate(_animationController), - child: const Padding( - padding: EdgeInsets.all(8.0), - child: Icon(Icons.arrow_drop_down), - ), - ), - const SizedBox(width: 8), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, + margin: const EdgeInsets.only(bottom: 16.0), + child: CustomCard( + onTap: () { + expController.toggle(); + _animationController.isCompleted + ? _animationController.reverse() + : _animationController.forward(); + }, + child: ExpandablePanel( + controller: expController, + theme: const ExpandableThemeData( + inkWellBorderRadius: BorderRadius.all(Radius.circular(16)), + tapBodyToCollapse: false, + tapBodyToExpand: false, + tapHeaderToExpand: false, + hasIcon: false, + animationDuration: Duration(milliseconds: 450), + ), + header: Row( + children: [ + SizedBox( + width: 40, + child: Image.memory(widget.icon, height: 40, width: 40), + ), + const SizedBox(width: 4), + Padding( + padding: const EdgeInsets.only(left: 15.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - CustomMaterialButton( - label: widget.isUpdatableApp - ? I18nText('applicationItem.patchButton') - : I18nText('applicationItem.infoButton'), - onPressed: widget.onPressed, + Text( + widget.name.length > 12 + ? '${widget.name.substring(0, 12)}...' + : widget.name, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), ), + Text(format(widget.patchDate)), ], ), - ], - ), - collapsed: const SizedBox(), - expanded: Padding( - padding: const EdgeInsets.only( - top: 16.0, left: 4.0, right: 4.0, bottom: 4.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + ), + const Spacer(), + RotationTransition( + turns: + Tween(begin: 0.0, end: 0.50).animate(_animationController), + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon(Icons.arrow_drop_down), + ), + ), + const SizedBox(width: 8), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, children: [ - I18nText( - 'applicationItem.changelogLabel', - child: const Text( - '', - style: TextStyle(fontWeight: FontWeight.w700), - ), + CustomMaterialButton( + label: widget.isUpdatableApp + ? I18nText('applicationItem.patchButton') + : I18nText('applicationItem.infoButton'), + onPressed: widget.onPressed, ), - const SizedBox(height: 4), - Text('\u2022 ${widget.changelog.join('\n\u2022 ')}'), ], ), + ], + ), + collapsed: const SizedBox(), + expanded: Padding( + padding: const EdgeInsets.only( + top: 16.0, + left: 4.0, + right: 4.0, + bottom: 4.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + I18nText( + 'applicationItem.changelogLabel', + child: const Text( + '', + style: TextStyle(fontWeight: FontWeight.w700), + ), + ), + const SizedBox(height: 4), + Text('\u2022 ${widget.changelog.join('\n\u2022 ')}'), + ], ), ), - )); + ), + ), + ); } } diff --git a/lib/ui/widgets/shared/custom_card.dart b/lib/ui/widgets/shared/custom_card.dart index 6e8c1be5..34b3c728 100644 --- a/lib/ui/widgets/shared/custom_card.dart +++ b/lib/ui/widgets/shared/custom_card.dart @@ -1,21 +1,20 @@ import 'package:flutter/material.dart'; class CustomCard extends StatelessWidget { + const CustomCard({ + Key? key, + this.isFilled = true, + required this.child, + this.onTap, + this.padding, + this.backgroundColor, + }) : super(key: key); final bool isFilled; final Widget child; final Function()? onTap; final EdgeInsetsGeometry? padding; final Color? backgroundColor; - const CustomCard( - {Key? key, - this.isFilled = true, - required this.child, - this.onTap, - this.padding, - this.backgroundColor}) - : super(key: key); - @override Widget build(BuildContext context) { return Material( diff --git a/lib/ui/widgets/shared/custom_chip.dart b/lib/ui/widgets/shared/custom_chip.dart index 7f4bf684..524348cd 100644 --- a/lib/ui/widgets/shared/custom_chip.dart +++ b/lib/ui/widgets/shared/custom_chip.dart @@ -1,16 +1,15 @@ import 'package:flutter/material.dart'; class CustomChip extends StatelessWidget { - final Widget label; - final bool isSelected; - final Function(bool)? onSelected; - const CustomChip({ Key? key, required this.label, this.isSelected = false, this.onSelected, }) : super(key: key); + final Widget label; + final bool isSelected; + final Function(bool)? onSelected; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/shared/custom_material_button.dart b/lib/ui/widgets/shared/custom_material_button.dart index 2442eae9..2ff80e4c 100644 --- a/lib/ui/widgets/shared/custom_material_button.dart +++ b/lib/ui/widgets/shared/custom_material_button.dart @@ -1,11 +1,6 @@ import 'package:flutter/material.dart'; class CustomMaterialButton extends StatelessWidget { - final Widget label; - final bool isFilled; - final bool isExpanded; - final Function()? onPressed; - const CustomMaterialButton({ Key? key, required this.label, @@ -13,6 +8,10 @@ class CustomMaterialButton extends StatelessWidget { this.isExpanded = false, required this.onPressed, }) : super(key: key); + final Widget label; + final bool isFilled; + final bool isExpanded; + final Function()? onPressed; @override Widget build(BuildContext context) { @@ -28,7 +27,6 @@ class CustomMaterialButton extends StatelessWidget { side: isFilled ? BorderSide.none : BorderSide( - width: 1, color: Theme.of(context).colorScheme.primary, ), ), @@ -50,12 +48,6 @@ class CustomMaterialButton extends StatelessWidget { // ignore: must_be_immutable class TimerButton extends StatefulWidget { - Widget label; - bool isFilled; - int seconds; - final bool isRunning; - final Function()? onTimerEnd; - TimerButton({ Key? key, required this.seconds, @@ -64,6 +56,11 @@ class TimerButton extends StatefulWidget { this.label = const Text(''), this.isFilled = true, }) : super(key: key); + Widget label; + bool isFilled; + int seconds; + final bool isRunning; + final Function()? onTimerEnd; @override State createState() => _TimerButtonState(); @@ -101,7 +98,6 @@ class _TimerButtonState extends State { side: widget.isFilled ? BorderSide.none : BorderSide( - width: 1, color: Theme.of(context).colorScheme.primary, ), ), diff --git a/lib/ui/widgets/shared/custom_popup_menu.dart b/lib/ui/widgets/shared/custom_popup_menu.dart index 9383d9f1..aaf24125 100644 --- a/lib/ui/widgets/shared/custom_popup_menu.dart +++ b/lib/ui/widgets/shared/custom_popup_menu.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; class CustomPopupMenu extends StatelessWidget { - final Function(dynamic) onSelected; - final Map children; - const CustomPopupMenu({ Key? key, required this.onSelected, required this.children, }) : super(key: key); + final Function(dynamic) onSelected; + final Map children; @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/shared/custom_sliver_app_bar.dart b/lib/ui/widgets/shared/custom_sliver_app_bar.dart index 798bff69..72c48ce3 100644 --- a/lib/ui/widgets/shared/custom_sliver_app_bar.dart +++ b/lib/ui/widgets/shared/custom_sliver_app_bar.dart @@ -1,12 +1,6 @@ import 'package:flutter/material.dart'; class CustomSliverAppBar extends StatelessWidget { - final Widget title; - final List? actions; - final PreferredSizeWidget? bottom; - final bool isMainView; - final Function()? onBackButtonPressed; - const CustomSliverAppBar({ Key? key, required this.title, @@ -15,13 +9,16 @@ class CustomSliverAppBar extends StatelessWidget { this.isMainView = false, this.onBackButtonPressed, }) : super(key: key); + final Widget title; + final List? actions; + final PreferredSizeWidget? bottom; + final bool isMainView; + final Function()? onBackButtonPressed; @override Widget build(BuildContext context) { return SliverAppBar( pinned: true, - snap: false, - floating: false, expandedHeight: 100.0, automaticallyImplyLeading: !isMainView, flexibleSpace: FlexibleSpaceBar( diff --git a/lib/ui/widgets/shared/open_container_wrapper.dart b/lib/ui/widgets/shared/open_container_wrapper.dart index 612beeb0..f5b1c642 100644 --- a/lib/ui/widgets/shared/open_container_wrapper.dart +++ b/lib/ui/widgets/shared/open_container_wrapper.dart @@ -2,21 +2,19 @@ import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; class OpenContainerWrapper extends StatelessWidget { - final OpenContainerBuilder openBuilder; - final CloseContainerBuilder closedBuilder; - const OpenContainerWrapper({ Key? key, required this.openBuilder, required this.closedBuilder, }) : super(key: key); + final OpenContainerBuilder openBuilder; + final CloseContainerBuilder closedBuilder; @override Widget build(BuildContext context) { return OpenContainer( openBuilder: openBuilder, closedBuilder: closedBuilder, - transitionType: ContainerTransitionType.fade, transitionDuration: const Duration(milliseconds: 400), openColor: Theme.of(context).colorScheme.primary, closedColor: Colors.transparent, diff --git a/lib/ui/widgets/shared/search_bar.dart b/lib/ui/widgets/shared/search_bar.dart index f9b8c605..e48e3031 100644 --- a/lib/ui/widgets/shared/search_bar.dart +++ b/lib/ui/widgets/shared/search_bar.dart @@ -1,10 +1,6 @@ import 'package:flutter/material.dart'; class SearchBar extends StatefulWidget { - final String? hintText; - final bool showSelectIcon; - final Function(bool)? onSelectAll; - const SearchBar({ Key? key, required this.hintText, @@ -12,6 +8,9 @@ class SearchBar extends StatefulWidget { this.onSelectAll, required this.onQueryChanged, }) : super(key: key); + final String? hintText; + final bool showSelectIcon; + final Function(bool)? onSelectAll; final Function(String) onQueryChanged; diff --git a/lib/utils/about_info.dart b/lib/utils/about_info.dart index 56da8899..bd107ced 100644 --- a/lib/utils/about_info.dart +++ b/lib/utils/about_info.dart @@ -1,6 +1,6 @@ +import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:package_info_plus/package_info_plus.dart'; -import 'package:device_info_plus/device_info_plus.dart'; class AboutInfo { static Future> getInfo() async { diff --git a/lib/utils/environment.dart b/lib/utils/environment.dart index 31e48775..ba671b68 100644 --- a/lib/utils/environment.dart +++ b/lib/utils/environment.dart @@ -2,4 +2,4 @@ class Environment { static const sentryDSN = ''; static const crowdinKEY = ''; -} \ No newline at end of file +}