perf: Reduce amount of network requests

This commit is contained in:
oSumAtrIX 2023-09-29 18:39:07 +02:00
parent 8661d72e45
commit 8ce266bc94
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
12 changed files with 78 additions and 272 deletions

View File

@ -56,9 +56,7 @@
"updatesDisabled": "Updating a patched app is currently disabled. Repatch the app again." "updatesDisabled": "Updating a patched app is currently disabled. Repatch the app again."
}, },
"applicationItem": { "applicationItem": {
"patchButton": "Patch", "infoButton": "Info"
"infoButton": "Info",
"changelogLabel": "Changelog"
}, },
"latestCommitCard": { "latestCommitCard": {
"loadingLabel": "Loading...", "loadingLabel": "Loading...",

View File

@ -1,5 +1,4 @@
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:revanced_manager/utils/string.dart';
part 'patch.g.dart'; part 'patch.g.dart';

View File

@ -16,9 +16,7 @@ class PatchedApplication {
required this.patchDate, required this.patchDate,
this.isRooted = false, this.isRooted = false,
this.isFromStorage = false, this.isFromStorage = false,
this.hasUpdates = false,
this.appliedPatches = const [], this.appliedPatches = const [],
this.changelog = const [],
}); });
factory PatchedApplication.fromJson(Map<String, dynamic> json) => factory PatchedApplication.fromJson(Map<String, dynamic> json) =>
@ -36,9 +34,7 @@ class PatchedApplication {
DateTime patchDate; DateTime patchDate;
bool isRooted; bool isRooted;
bool isFromStorage; bool isFromStorage;
bool hasUpdates;
List<String> appliedPatches; List<String> appliedPatches;
List<String> changelog;
Map<String, dynamic> toJson() => _$PatchedApplicationToJson(this); Map<String, dynamic> toJson() => _$PatchedApplicationToJson(this);

View File

@ -51,6 +51,7 @@ class GithubAPI {
Future<void> clearAllCache() async { Future<void> clearAllCache() async {
try { try {
await _cacheOptions.store!.clean(); await _cacheOptions.store!.clean();
await DefaultCacheManager().emptyCache();
} on Exception catch (e) { } on Exception catch (e) {
if (kDebugMode) { if (kDebugMode) {
print(e); print(e);
@ -142,38 +143,6 @@ class GithubAPI {
} }
} }
Future<List<String>> getCommits(
String packageName,
String repoName,
DateTime since,
) async {
final String path =
'src/main/kotlin/app/revanced/patches/${repoAppPath[packageName]}';
try {
final response = await _dio.get(
'/repos/$repoName/commits',
queryParameters: {
'path': path,
'since': since.toIso8601String(),
},
);
final List<dynamic> commits = response.data;
return commits
.map(
(commit) => commit['commit']['message'].split('\n')[0] +
' - ' +
commit['commit']['author']['name'] +
'\n' as String,
)
.toList();
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
}
return [];
}
Future<File?> getLatestReleaseFile( Future<File?> getLatestReleaseFile(
String extension, String extension,
String repoName, String repoName,
@ -237,30 +206,4 @@ class GithubAPI {
} }
return null; return null;
} }
Future<List<Patch>> getPatches(
String repoName,
String version,
String url,
) async {
List<Patch> patches = [];
try {
final File? f = await getPatchesReleaseFile(
'.json',
repoName,
version,
url,
);
if (f != null) {
final List<dynamic> list = jsonDecode(f.readAsStringSync());
patches = list.map((patch) => Patch.fromJson(patch)).toList();
}
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
}
return patches;
}
} }

View File

@ -616,39 +616,6 @@ class ManagerAPI {
); );
} }
Future<void> reAssessSavedApps() async {
final List<PatchedApplication> patchedApps = getPatchedApps();
final List<PatchedApplication> unsavedApps =
await getUnsavedApps(patchedApps);
patchedApps.addAll(unsavedApps);
final List<PatchedApplication> toRemove =
await getAppsToRemove(patchedApps);
patchedApps.removeWhere((a) => toRemove.contains(a));
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) {
final String? currentInstalledVersion =
(await DeviceApps.getApp(app.packageName))?.versionName;
if (currentInstalledVersion != null) {
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;
}
}
}
}
await setPatchedApps(patchedApps);
}
Future<bool> isAppUninstalled(PatchedApplication app) async { Future<bool> isAppUninstalled(PatchedApplication app) async {
bool existsRoot = false; bool existsRoot = false;
final bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName); final bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName);
@ -662,37 +629,6 @@ class ManagerAPI {
return !existsNonRoot; return !existsNonRoot;
} }
Future<bool> hasAppUpdates(
String packageName,
DateTime patchDate,
) async {
final List<String> commits = await _githubAPI.getCommits(
packageName,
getPatchesRepo(),
patchDate,
);
return commits.isNotEmpty;
}
Future<List<String>> getAppChangelog(
String packageName,
DateTime patchDate,
) async {
List<String> newCommits = await _githubAPI.getCommits(
packageName,
getPatchesRepo(),
patchDate,
);
if (newCommits.isEmpty) {
newCommits = await _githubAPI.getCommits(
packageName,
getPatchesRepo(),
patchDate,
);
}
return newCommits;
}
Future<bool> isSplitApk(PatchedApplication patchedApp) async { Future<bool> isSplitApk(PatchedApplication patchedApp) async {
Application? app; Application? app;
if (patchedApp.isFromStorage) { if (patchedApp.isFromStorage) {
@ -760,6 +696,8 @@ class ManagerAPI {
Future<void> resetLastSelectedPatches() async { Future<void> resetLastSelectedPatches() async {
final File selectedPatchesFile = File(storedPatchesFile); final File selectedPatchesFile = File(storedPatchesFile);
selectedPatchesFile.deleteSync(); if (selectedPatchesFile.existsSync()) {
selectedPatchesFile.deleteSync();
}
} }
} }

View File

@ -7,12 +7,15 @@ import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:injectable/injectable.dart'; import 'package:injectable/injectable.dart';
import 'package:synchronized/synchronized.dart';
import 'package:timeago/timeago.dart'; import 'package:timeago/timeago.dart';
@lazySingleton @lazySingleton
class RevancedAPI { class RevancedAPI {
late Dio _dio = Dio(); late Dio _dio = Dio();
final Lock getToolsLock = Lock();
final _cacheOptions = CacheOptions( final _cacheOptions = CacheOptions(
store: MemCacheStore(), store: MemCacheStore(),
maxStale: const Duration(days: 1), maxStale: const Duration(days: 1),
@ -38,6 +41,7 @@ class RevancedAPI {
Future<void> clearAllCache() async { Future<void> clearAllCache() async {
try { try {
await _cacheOptions.store!.clean(); await _cacheOptions.store!.clean();
await DefaultCacheManager().emptyCache();
} on Exception catch (e) { } on Exception catch (e) {
if (kDebugMode) { if (kDebugMode) {
print(e); print(e);
@ -66,21 +70,23 @@ class RevancedAPI {
Future<Map<String, dynamic>?> _getLatestRelease( Future<Map<String, dynamic>?> _getLatestRelease(
String extension, String extension,
String repoName, String repoName,
) async { ) {
try { return getToolsLock.synchronized(() async {
final response = await _dio.get('/tools'); try {
final List<dynamic> tools = response.data['tools']; final response = await _dio.get('/tools');
return tools.firstWhereOrNull( final List<dynamic> tools = response.data['tools'];
(t) => return tools.firstWhereOrNull(
t['repository'] == repoName && (t) =>
(t['name'] as String).endsWith(extension), t['repository'] == repoName &&
); (t['name'] as String).endsWith(extension),
} on Exception catch (e) { );
if (kDebugMode) { } on Exception catch (e) {
print(e); if (kDebugMode) {
print(e);
}
return null;
} }
return null; });
}
} }
Future<String?> getLatestReleaseVersion( Future<String?> getLatestReleaseVersion(

View File

@ -37,15 +37,15 @@ class HomeViewModel extends BaseViewModel {
DateTime? _lastUpdate; DateTime? _lastUpdate;
bool showUpdatableApps = false; bool showUpdatableApps = false;
List<PatchedApplication> patchedInstalledApps = []; List<PatchedApplication> patchedInstalledApps = [];
List<PatchedApplication> patchedUpdatableApps = [];
String? _latestManagerVersion = ''; String? _latestManagerVersion = '';
File? downloadedApk; File? downloadedApk;
Future<void> initialize(BuildContext context) async { Future<void> initialize(BuildContext context) async {
_latestManagerVersion = await _managerAPI.getLatestManagerVersion();
if (!_managerAPI.getPatchesConsent()) { if (!_managerAPI.getPatchesConsent()) {
await showPatchesConsent(context); await showPatchesConsent(context);
} }
_latestManagerVersion = await _managerAPI.getLatestManagerVersion();
await _patcherAPI.initialize(); await _patcherAPI.initialize();
await flutterLocalNotificationsPlugin.initialize( await flutterLocalNotificationsPlugin.initialize(
const InitializationSettings( const InitializationSettings(
@ -83,7 +83,6 @@ class HomeViewModel extends BaseViewModel {
} }
} }
_getPatchedApps(); _getPatchedApps();
_managerAPI.reAssessSavedApps().then((_) => _getPatchedApps());
} }
void navigateToAppInfo(PatchedApplication app) { void navigateToAppInfo(PatchedApplication app) {
@ -108,10 +107,6 @@ class HomeViewModel extends BaseViewModel {
void _getPatchedApps() { void _getPatchedApps() {
patchedInstalledApps = _managerAPI.getPatchedApps().toList(); patchedInstalledApps = _managerAPI.getPatchedApps().toList();
patchedUpdatableApps = _managerAPI
.getPatchedApps()
.where((app) => app.hasUpdates == true)
.toList();
notifyListeners(); notifyListeners();
} }

View File

@ -39,9 +39,9 @@ class NavigationViewModel extends IndexTrackingViewModel {
// Force disable Material You on Android 11 and below // Force disable Material You on Android 11 and below
if (dynamicTheme.themeId.isOdd) { if (dynamicTheme.themeId.isOdd) {
const int ANDROID_12_SDK_VERSION = 31; const int android12SdkVersion = 31;
final AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo; final AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo;
if (info.version.sdkInt < ANDROID_12_SDK_VERSION) { if (info.version.sdkInt < android12SdkVersion) {
await prefs.setInt('themeMode', 0); await prefs.setInt('themeMode', 0);
await prefs.setBool('useDynamicTheme', false); await prefs.setBool('useDynamicTheme', false);
await dynamicTheme.setTheme(0); await dynamicTheme.setTheme(0);

View File

@ -79,8 +79,6 @@ class InstalledAppsCard extends StatelessWidget {
icon: app.icon, icon: app.icon,
name: app.name, name: app.name,
patchDate: app.patchDate, patchDate: app.patchDate,
changelog: app.changelog,
isUpdatableApp: false,
onPressed: () => onPressed: () =>
locator<HomeViewModel>().navigateToAppInfo(app), locator<HomeViewModel>().navigateToAppInfo(app),
), ),

View File

@ -5,8 +5,8 @@ import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_api_url.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_api_url.dart';
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_enable_patches_selection.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_auto_update_patches.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_auto_update_patches.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_enable_patches_selection.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_patches.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_patches.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_universal_patches.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_experimental_universal_patches.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';

View File

@ -1,6 +1,5 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
@ -13,151 +12,84 @@ class ApplicationItem extends StatefulWidget {
required this.icon, required this.icon,
required this.name, required this.name,
required this.patchDate, required this.patchDate,
required this.changelog,
required this.isUpdatableApp,
required this.onPressed, required this.onPressed,
}) : super(key: key); }) : super(key: key);
final Uint8List icon; final Uint8List icon;
final String name; final String name;
final DateTime patchDate; final DateTime patchDate;
final List<String> changelog;
final bool isUpdatableApp;
final Function() onPressed; final Function() onPressed;
@override @override
State<ApplicationItem> createState() => _ApplicationItemState(); State<ApplicationItem> createState() => _ApplicationItemState();
} }
class _ApplicationItemState extends State<ApplicationItem> class _ApplicationItemState extends State<ApplicationItem> {
with TickerProviderStateMixin {
late AnimationController _animationController;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ExpandableController expController = ExpandableController();
return Container( return Container(
margin: const EdgeInsets.only(bottom: 16.0), margin: const EdgeInsets.only(bottom: 16.0),
child: CustomCard( child: CustomCard(
onTap: () { child: Row(
expController.toggle(); mainAxisAlignment: MainAxisAlignment.spaceBetween,
_animationController.isCompleted children: [
? _animationController.reverse() Flexible(
: _animationController.forward(); child: Row(
},
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(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Row(
children: [
SizedBox(
width: 40,
child: Image.memory(widget.icon, height: 40, width: 40),
),
const SizedBox(width: 19),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
widget.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
Text(
format(widget.patchDate),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
],
),
),
],
),
),
Row(
children: [ children: [
RotationTransition( SizedBox(
turns: Tween(begin: 0.0, end: 0.50) width: 40,
.animate(_animationController), child: Image.memory(widget.icon, height: 40, width: 40),
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.arrow_drop_down),
),
), ),
const SizedBox(width: 8), const SizedBox(width: 19),
Column( Expanded(
mainAxisAlignment: MainAxisAlignment.center, child: Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
CustomMaterialButton( Text(
label: widget.isUpdatableApp widget.name,
? I18nText('applicationItem.patchButton') maxLines: 1,
: I18nText('applicationItem.infoButton'), overflow: TextOverflow.ellipsis,
onPressed: widget.onPressed, style: const TextStyle(
), fontSize: 16,
], fontWeight: FontWeight.w500,
),
),
Text(
format(widget.patchDate),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
],
),
), ),
], ],
), ),
],
),
collapsed: const SizedBox(),
expanded: Padding(
padding: const EdgeInsets.only(
top: 16.0,
left: 4.0,
right: 4.0,
bottom: 4.0,
), ),
child: Column( Row(
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: <Widget>[ const SizedBox(width: 8),
I18nText( Column(
'applicationItem.changelogLabel', mainAxisAlignment: MainAxisAlignment.center,
child: const Text( crossAxisAlignment: CrossAxisAlignment.end,
'', children: <Widget>[
style: TextStyle(fontWeight: FontWeight.w700), CustomMaterialButton(
), label: I18nText('applicationItem.infoButton'),
onPressed: widget.onPressed,
),
],
), ),
const SizedBox(height: 4),
Text('\u2022 ${widget.changelog.join('\n\u2022 ')}'),
], ],
), ),
), ],
), ),
), ),
); );

View File

@ -75,6 +75,7 @@ dependencies:
flutter_markdown: ^0.6.14 flutter_markdown: ^0.6.14
dio_cache_interceptor: ^3.4.0 dio_cache_interceptor: ^3.4.0
install_plugin: ^2.1.0 install_plugin: ^2.1.0
synchronized: ^3.1.0
dev_dependencies: dev_dependencies:
json_serializable: ^6.6.1 json_serializable: ^6.6.1