diff --git a/android/app/build.gradle b/android/app/build.gradle index cfb50931..a9c10eb2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -30,6 +30,7 @@ android { ndkVersion flutter.ndkVersion compileOptions { + coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } @@ -48,6 +49,7 @@ android { targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName + multiDexEnabled true } buildTypes { @@ -81,4 +83,11 @@ dependencies { implementation("org.microg:cronet-common:$cronetVersion") implementation("org.microg:cronet-native:$cronetVersion") + // Core libraries + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' + + // Window + implementation 'androidx.window:window:1.0.0' + implementation 'androidx.window:window-java:1.0.0' + } diff --git a/lib/services/github_api.dart b/lib/services/github_api.dart index 74bbde69..73169538 100644 --- a/lib/services/github_api.dart +++ b/lib/services/github_api.dart @@ -13,7 +13,7 @@ import 'package:revanced_manager/models/patch.dart'; @lazySingleton class GithubAPI { late Dio _dio = Dio(); - + final _cacheOptions = CacheOptions( store: MemCacheStore(), maxStale: const Duration(days: 1), @@ -73,7 +73,9 @@ class GithubAPI { } } - Future?> getLatestRelease(String repoName) async { + Future?> getLatestRelease( + String repoName, + ) async { try { final response = await _dio.get( '/repos/$repoName/releases', @@ -119,9 +121,13 @@ class GithubAPI { return []; } - Future getLatestReleaseFile(String extension, String repoName) async { + Future getLatestReleaseFile( + String extension, + String repoName, + ) async { try { - final Map? release = await getLatestRelease(repoName); + final Map? release = + await getLatestRelease(repoName); if (release != null) { final Map? asset = (release['assets'] as List).firstWhereOrNull( @@ -160,7 +166,8 @@ class GithubAPI { Future getLastestReleaseVersion(String repoName) async { try { - final 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 d100b837..448fa7ec 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -39,7 +39,8 @@ class ManagerAPI { Future initialize() async { _prefs = await SharedPreferences.getInstance(); storedPatchesFile = - (await getApplicationDocumentsDirectory()).path + storedPatchesFile; + (await getApplicationDocumentsDirectory()).path + + storedPatchesFile; } String getApiUrl() { @@ -78,7 +79,8 @@ class ManagerAPI { } String getIntegrationsRepo() { - return _prefs.getString('integrationsRepo') ?? defaultIntegrationsRepo; + return _prefs.getString('integrationsRepo') ?? + defaultIntegrationsRepo; } Future setIntegrationsRepo(String value) async { @@ -146,10 +148,14 @@ class ManagerAPI { List getPatchedApps() { final List apps = _prefs.getStringList('patchedApps') ?? []; - return apps.map((a) => PatchedApplication.fromJson(jsonDecode(a))).toList(); + return apps + .map((a) => PatchedApplication.fromJson(jsonDecode(a))) + .toList(); } - Future setPatchedApps(List patchedApps) async { + Future setPatchedApps( + List patchedApps, + ) async { if (patchedApps.length > 1) { patchedApps.sort((a, b) => a.name.compareTo(b.name)); } @@ -251,15 +257,24 @@ class ManagerAPI { } Future downloadManager() async { - return await _revancedAPI.getLatestReleaseFile('.apk', defaultManagerRepo); + return await _revancedAPI.getLatestReleaseFile( + '.apk', + defaultManagerRepo, + ); } Future getLatestPatcherReleaseTime() async { - return await _revancedAPI.getLatestReleaseTime('.gz', defaultPatcherRepo); + return await _revancedAPI.getLatestReleaseTime( + '.gz', + defaultPatcherRepo, + ); } Future getLatestManagerReleaseTime() async { - return await _revancedAPI.getLatestReleaseTime('.apk', defaultManagerRepo); + return await _revancedAPI.getLatestReleaseTime( + '.apk', + defaultManagerRepo, + ); } Future getLatestManagerVersion() async { @@ -313,10 +328,12 @@ class ManagerAPI { final List unsavedApps = []; final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { - final List installedApps = await _rootAPI.getInstalledApps(); + final List installedApps = + await _rootAPI.getInstalledApps(); for (final String packageName in installedApps) { if (!patchedApps.any((app) => app.packageName == packageName)) { - final ApplicationWithIcon? application = await DeviceApps.getApp( + final ApplicationWithIcon? application = + await DeviceApps.getApp( packageName, true, ) as ApplicationWithIcon?; @@ -342,8 +359,10 @@ class ManagerAPI { 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)) { - final ApplicationWithIcon? application = await DeviceApps.getApp( + !patchedApps + .any((uapp) => uapp.packageName == app.packageName)) { + final ApplicationWithIcon? application = + await DeviceApps.getApp( app.packageName, true, ) as ApplicationWithIcon?; @@ -386,8 +405,9 @@ class ManagerAPI { final int currentInstalledVersionInt = int.parse( currentInstalledVersion.replaceAll(RegExp('[^0-9]'), ''), ); - final int currentSavedVersionInt = - int.parse(currentSavedVersion.replaceAll(RegExp('[^0-9]'), '')); + final int currentSavedVersionInt = int.parse( + currentSavedVersion.replaceAll(RegExp('[^0-9]'), ''), + ); if (currentInstalledVersionInt > currentSavedVersionInt) { app.hasUpdates = true; } @@ -399,9 +419,11 @@ class ManagerAPI { Future isAppUninstalled(PatchedApplication app) async { bool existsRoot = false; - final bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName); + final bool existsNonRoot = + await DeviceApps.isAppInstalled(app.packageName); if (app.isRooted) { - final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final bool hasRootPermissions = + await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { existsRoot = await _rootAPI.isAppInstalled(app.packageName); } @@ -410,7 +432,10 @@ class ManagerAPI { return !existsNonRoot; } - Future hasAppUpdates(String packageName, DateTime patchDate) async { + Future hasAppUpdates( + String packageName, + DateTime patchDate, + ) async { final List commits = await _githubAPI.getCommits( packageName, getPatchesRepo(), @@ -448,9 +473,13 @@ class ManagerAPI { return app != null && app.isSplit; } - Future setSelectedPatches(String app, List patches) async { + Future setSelectedPatches( + String app, + List patches, + ) async { final File selectedPatchesFile = File(storedPatchesFile); - final Map patchesMap = await readSelectedPatchesFile(); + final Map patchesMap = + await readSelectedPatchesFile(); if (patches.isEmpty) { patchesMap.remove(app); } else { @@ -460,7 +489,8 @@ class ManagerAPI { } Future> getSelectedPatches(String app) async { - final Map patchesMap = await readSelectedPatchesFile(); + final Map patchesMap = + await readSelectedPatchesFile(); return List.from(patchesMap.putIfAbsent(app, () => List.empty())); } diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index b600abac..b7c1f9ff 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -69,7 +69,8 @@ class PatcherAPI { onlyAppsWithLaunchIntent: true, ); for (final pkg in allPackages) { - if (!filteredApps.any((app) => app.packageName == pkg.packageName)) { + if (!filteredApps + .any((app) => app.packageName == pkg.packageName)) { final appInfo = await DeviceApps.getApp( pkg.packageName, true, @@ -83,7 +84,8 @@ class PatcherAPI { for (final Patch patch in _patches) { for (final Package package in patch.compatiblePackages) { try { - if (!filteredApps.any((app) => app.packageName == package.name)) { + if (!filteredApps + .any((app) => app.packageName == package.name)) { final ApplicationWithIcon? app = await DeviceApps.getApp( package.name, true, @@ -118,13 +120,17 @@ class PatcherAPI { return filteredPatches[packageName]; } - Future> getAppliedPatches(List appliedPatches) async { + Future> getAppliedPatches( + List appliedPatches, + ) async { return _patches .where((patch) => appliedPatches.contains(patch.name)) .toList(); } - Future needsResourcePatching(List selectedPatches) async { + Future needsResourcePatching( + List selectedPatches, + ) async { return selectedPatches.any( (patch) => patch.dependencies.any( (dep) => dep.contains('resource-'), @@ -145,7 +151,8 @@ class PatcherAPI { String originalFilePath, ) async { try { - final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final bool hasRootPermissions = + await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { originalFilePath = await _rootAPI.getOriginalFilePath( packageName, @@ -166,13 +173,15 @@ class PatcherAPI { String originalFilePath, List selectedPatches, ) async { - final bool includeSettings = await needsSettingsPatch(selectedPatches); + final bool includeSettings = + await needsSettingsPatch(selectedPatches); if (includeSettings) { try { final Patch? settingsPatch = _patches.firstWhereOrNull( (patch) => patch.name.contains('settings') && - patch.compatiblePackages.any((pack) => pack.name == packageName), + patch.compatiblePackages + .any((pack) => pack.name == packageName), ); if (settingsPatch != null) { selectedPatches.add(settingsPatch); @@ -184,7 +193,8 @@ class PatcherAPI { } } final File? patchBundleFile = await _managerAPI.downloadPatches(); - final File? integrationsFile = await _managerAPI.downloadIntegrations(); + final File? integrationsFile = + await _managerAPI.downloadIntegrations(); if (patchBundleFile != null) { _dataDir.createSync(); _tmpDir.createSync(); @@ -207,7 +217,8 @@ class PatcherAPI { 'patchedFilePath': patchedFile.path, 'outFilePath': _outFile!.path, 'integrationsPath': integrationsFile!.path, - 'selectedPatches': selectedPatches.map((p) => p.name).toList(), + 'selectedPatches': + selectedPatches.map((p) => p.name).toList(), 'cacheDirPath': cacheDir.path, 'keyStoreFilePath': _keyStoreFile.path, 'keystorePassword': _managerAPI.getKeystorePassword(), @@ -225,7 +236,8 @@ class PatcherAPI { if (_outFile != null) { try { if (patchedApp.isRooted) { - final bool hasRootPermissions = await _rootAPI.hasRootPermissions(); + final bool hasRootPermissions = + await _rootAPI.hasRootPermissions(); if (hasRootPermissions) { return _rootAPI.installApp( patchedApp.packageName, @@ -235,7 +247,9 @@ class PatcherAPI { } } else { await AppInstaller.installApk(_outFile!.path); - return await DeviceApps.isAppInstalled(patchedApp.packageName); + return await DeviceApps.isAppInstalled( + patchedApp.packageName, + ); } } on Exception catch (e) { if (kDebugMode) { @@ -307,7 +321,8 @@ class PatcherAPI { String getRecommendedVersion(String packageName) { final Map versions = {}; for (final Patch patch in _patches) { - final Package? package = patch.compatiblePackages.firstWhereOrNull( + final Package? package = + patch.compatiblePackages.firstWhereOrNull( (pack) => pack.name == packageName, ); if (package != null) { @@ -326,7 +341,8 @@ class PatcherAPI { versions ..clear() ..addEntries(entries); - versions.removeWhere((key, value) => value != versions.values.last); + versions + .removeWhere((key, value) => value != versions.values.last); return (versions.keys.toList()..sort()).last; } return ''; diff --git a/lib/services/revanced_api.dart b/lib/services/revanced_api.dart index eac575b1..bccca46f 100644 --- a/lib/services/revanced_api.dart +++ b/lib/services/revanced_api.dart @@ -15,7 +15,7 @@ import 'package:timeago/timeago.dart'; @lazySingleton class RevancedAPI { late Dio _dio = Dio(); - + final _cacheOptions = CacheOptions( store: MemCacheStore(), maxStale: const Duration(days: 1), @@ -142,7 +142,10 @@ class RevancedAPI { return null; } - Future getLatestReleaseFile(String extension, String repoName) async { + Future getLatestReleaseFile( + String extension, + String repoName, + ) async { try { final Map? release = await _getLatestRelease( extension, diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index c16d971f..c63e8b22 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:app_installer/app_installer.dart'; import 'package:cross_connectivity/cross_connectivity.dart'; -import 'package:device_apps/device_apps.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; @@ -25,12 +24,14 @@ import 'package:timezone/timezone.dart' as tz; @lazySingleton class HomeViewModel extends BaseViewModel { - final NavigationService _navigationService = locator(); + final NavigationService _navigationService = + locator(); final ManagerAPI _managerAPI = locator(); final PatcherAPI _patcherAPI = locator(); final GithubAPI _githubAPI = locator(); final Toast _toast = locator(); - final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + final flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); DateTime? _lastUpdate; bool showUpdatableApps = false; List patchedInstalledApps = []; @@ -41,8 +42,17 @@ class HomeViewModel extends BaseViewModel { const InitializationSettings( android: AndroidInitializationSettings('ic_notification'), ), - onSelectNotification: (p) => - DeviceApps.openApp('app.revanced.manager.flutter'), + onDidReceiveNotificationResponse: (response) async { + if (response.id == 0) { + _toast.showBottom('homeView.installingMessage'); + final File? managerApk = await _managerAPI.downloadManager(); + if (managerApk != null) { + await AppInstaller.installApk(managerApk.path); + } else { + _toast.showBottom('homeView.errorDownloadMessage'); + } + } + }, ); flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< @@ -52,6 +62,19 @@ class HomeViewModel extends BaseViewModel { if (!isConnected) { _toast.showBottom('homeView.noConnection'); } + final NotificationAppLaunchDetails? notificationAppLaunchDetails = + await flutterLocalNotificationsPlugin + .getNotificationAppLaunchDetails(); + if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? + false) { + _toast.showBottom('homeView.installingMessage'); + final File? managerApk = await _managerAPI.downloadManager(); + if (managerApk != null) { + await AppInstaller.installApk(managerApk.path); + } else { + _toast.showBottom('homeView.errorDownloadMessage'); + } + } _getPatchedApps(); _managerAPI.reAssessSavedApps().then((_) => _getPatchedApps()); } @@ -86,8 +109,10 @@ class HomeViewModel extends BaseViewModel { } Future hasManagerUpdates() async { - final String? latestVersion = await _managerAPI.getLatestManagerVersion(); - final String currentVersion = await _managerAPI.getCurrentManagerVersion(); + final String? latestVersion = + await _managerAPI.getLatestManagerVersion(); + final String currentVersion = + await _managerAPI.getCurrentManagerVersion(); if (latestVersion != null) { try { final int latestVersionInt = @@ -171,7 +196,9 @@ class HomeViewModel extends BaseViewModel { _toast.showBottom('homeView.updatesDisabled'); } - Future showUpdateConfirmationDialog(BuildContext parentContext) { + Future showUpdateConfirmationDialog( + BuildContext parentContext, + ) { return showModalBottomSheet( context: parentContext, isScrollControlled: true, diff --git a/lib/ui/views/navigation/navigation_viewmodel.dart b/lib/ui/views/navigation/navigation_viewmodel.dart index 0cdf582d..4ca900c3 100644 --- a/lib/ui/views/navigation/navigation_viewmodel.dart +++ b/lib/ui/views/navigation/navigation_viewmodel.dart @@ -17,12 +17,14 @@ import 'package:stacked/stacked.dart'; class NavigationViewModel extends IndexTrackingViewModel { Future initialize(BuildContext context) async { locator().initialize(context); - final SharedPreferences prefs = await SharedPreferences.getInstance(); + final SharedPreferences prefs = + await SharedPreferences.getInstance(); if (prefs.getBool('permissionsRequested') == null) { await prefs.setBool('permissionsRequested', true); RootAPI().hasRootPermissions().then( (value) => Permission.requestInstallPackages.request().then( - (value) => Permission.ignoreBatteryOptimizations.request(), + (value) => + Permission.ignoreBatteryOptimizations.request(), ), ); } @@ -37,7 +39,8 @@ class NavigationViewModel extends IndexTrackingViewModel { SystemUiOverlayStyle( systemNavigationBarColor: Colors.transparent, systemNavigationBarIconBrightness: - DynamicTheme.of(context)!.theme.brightness == Brightness.light + DynamicTheme.of(context)!.theme.brightness == + Brightness.light ? Brightness.dark : Brightness.light, ), diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index 5edd2b5e..82c09ec1 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -17,7 +17,8 @@ import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; class SettingsViewModel extends BaseViewModel { - final NavigationService _navigationService = locator(); + final NavigationService _navigationService = + locator(); final ManagerAPI _managerAPI = locator(); final Toast _toast = locator(); @@ -62,8 +63,11 @@ class SettingsViewModel extends BaseViewModel { try { final File outFile = File(_managerAPI.storedPatchesFile); if (outFile.existsSync()) { - final String dateTime = - DateTime.now().toString().replaceAll(' ', '_').split('.').first; + final String dateTime = DateTime.now() + .toString() + .replaceAll(' ', '_') + .split('.') + .first; await CRFileSaver.saveFileWithDialog( SaveFileDialogParams( sourceFilePath: outFile.path, @@ -83,7 +87,8 @@ class SettingsViewModel extends BaseViewModel { Future importPatches() async { try { - final FilePickerResult? result = await FilePicker.platform.pickFiles( + final FilePickerResult? result = + await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['json'], ); @@ -151,7 +156,7 @@ class SettingsViewModel extends BaseViewModel { Future getSdkVersion() async { final AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo; - return info.version.sdkInt ?? -1; + return info.version.sdkInt; } Future deleteLogs() async { diff --git a/lib/ui/widgets/homeView/update_confirmation_dialog.dart b/lib/ui/widgets/homeView/update_confirmation_dialog.dart index 2051aefc..108c5d78 100644 --- a/lib/ui/widgets/homeView/update_confirmation_dialog.dart +++ b/lib/ui/widgets/homeView/update_confirmation_dialog.dart @@ -16,12 +16,12 @@ class UpdateConfirmationDialog extends StatelessWidget { expand: false, snap: true, snapSizes: const [0.5], - builder: (context, scrollController) => SingleChildScrollView( + builder: (_, scrollController) => SingleChildScrollView( controller: scrollController, child: SafeArea( child: FutureBuilder?>( future: model.getLatestManagerRelease(), - builder: (context, snapshot) { + builder: (_, snapshot) { if (!snapshot.hasData) { return const SizedBox( height: 300, @@ -45,7 +45,8 @@ class UpdateConfirmationDialog extends StatelessWidget { children: [ Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ I18nText( 'homeView.updateDialogTitle', @@ -62,12 +63,14 @@ class UpdateConfirmationDialog extends StatelessWidget { children: [ Icon( Icons.new_releases_outlined, - color: - Theme.of(context).colorScheme.secondary, + color: Theme.of(context) + .colorScheme + .secondary, ), const SizedBox(width: 8.0), Text( - snapshot.data!['tag_name'] ?? 'Unknown', + snapshot.data!['tag_name'] ?? + 'Unknown', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w500, @@ -93,7 +96,8 @@ class UpdateConfirmationDialog extends StatelessWidget { ), ), Padding( - padding: const EdgeInsets.only(left: 24.0, bottom: 12.0), + padding: + const EdgeInsets.only(left: 24.0, bottom: 12.0), child: I18nText( 'homeView.updateChangelogTitle', child: Text( @@ -109,9 +113,12 @@ class UpdateConfirmationDialog extends StatelessWidget { ), ), Container( - margin: const EdgeInsets.symmetric(horizontal: 24.0), + margin: + const EdgeInsets.symmetric(horizontal: 24.0), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, + color: Theme.of(context) + .colorScheme + .secondaryContainer, borderRadius: BorderRadius.circular(12.0), ), child: Markdown( diff --git a/pubspec.yaml b/pubspec.yaml index 425cc487..b3fb47b3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,79 +10,79 @@ environment: sdk: ">=2.17.5 <3.0.0" dependencies: - animations: ^2.0.4 + animations: ^2.0.7 app_installer: ^1.1.0 - collection: ^1.16.0 + collection: ^1.17.0 cross_connectivity: ^3.0.5 - cr_file_saver: ^0.0.2 + cr_file_saver: ^0.0.2+1 device_apps: git: url: https://github.com/ponces/flutter_plugin_device_apps ref: revanced-manager - device_info_plus: ^4.1.2 + device_info_plus: ^8.1.0 + dynamic_color: ^1.6.3 dio: ^5.0.0 - dynamic_color: ^1.5.4 dynamic_themes: ^1.1.0 expandable: ^5.0.1 file_picker: git: url: https://github.com/alexmercerind/flutter_file_picker ref: master - flex_color_scheme: ^6.0.0 + flex_color_scheme: ^7.0.1 flutter: sdk: flutter - flutter_background: ^1.1.0 + flutter_background: ^1.2.0 flutter_cache_manager: ^3.3.0 flutter_i18n: ^0.32.4 - flutter_local_notifications: ^9.8.0+1 + flutter_local_notifications: ^13.0.0 flutter_localizations: sdk: flutter - flutter_svg: ^1.1.1+1 - fluttertoast: ^8.0.9 - font_awesome_flutter: ^10.1.0 + flutter_svg: ^2.0.4 + fluttertoast: ^8.2.1 + font_awesome_flutter: ^10.4.0 get_it: ^7.2.0 - google_fonts: ^3.0.1 - http: ^0.13.4 - injectable: ^1.5.3 + google_fonts: ^4.0.3 + http: ^0.13.5 + injectable: ^2.1.1 intl: ^0.17.0 - json_annotation: ^4.6.0 + json_annotation: ^4.8.0 logcat: git: url: https://github.com/SuaMusica/logcat ref: feature/nullSafe + package_info_plus: ^3.0.3 + path_provider: ^2.0.14 + permission_handler: ^10.2.0 native_dio_adapter: ^0.1.0 - package_info_plus: ^1.4.3+1 - path_provider: ^2.0.11 - permission_handler: ^10.0.0 pull_to_refresh: ^2.0.0 root: git: url: https://github.com/gokul1630/root ref: main share_extend: ^2.0.0 - shared_preferences: ^2.0.15 + shared_preferences: ^2.1.0 skeletons: ^0.0.3 stacked: ^3.2.0 - stacked_generator: ^1.0.0 + stacked_generator: ^1.1.0 stacked_services: ^1.0.0 - stacked_themes: ^0.3.9 - timeago: ^3.2.2 - timezone: ^0.8.0 - url_launcher: ^6.1.5 + stacked_themes: ^0.3.10 + timeago: ^3.3.0 + timezone: ^0.9.0 + url_launcher: ^6.1.10 wakelock: ^0.6.2 flutter_dotenv: ^5.0.2 + flutter_markdown: ^0.6.14 pub_release: ^8.0.3 - flutter_markdown: ^0.6.13 dio_cache_interceptor: ^3.4.0 dev_dependencies: - json_serializable: ^6.3.1 + json_serializable: ^6.6.1 build_runner: any - flutter_launcher_icons: ^0.10.0 + flutter_launcher_icons: ^0.13.0 flutter_lints: ^2.0.1 flutter_test: sdk: flutter - injectable_generator: ^1.5.4 + injectable_generator: ^2.1.5