Various bugfixes

This commit is contained in:
Imran Remtulla
2024-05-17 15:56:41 -04:00
parent fbfeaf2a91
commit 389aebe54e

View File

@@ -820,22 +820,82 @@ class AppsProvider with ChangeNotifier {
appsToInstall = appsToInstall =
moveStrToEnd(appsToInstall, obtainiumId, strB: obtainiumTempId); moveStrToEnd(appsToInstall, obtainiumId, strB: obtainiumTempId);
Future<String> updateFn(String id, {bool skipInstalls = false}) async { Future<void> installFn(String id, bool willBeSilent,
DownloadedApk? downloadedFile, DownloadedXApkDir? downloadedDir) async {
apps[id]?.downloadProgress = -1;
notifyListeners();
try {
bool sayInstalled = true;
var contextIfNewInstall =
apps[id]?.installedInfo == null ? context : null;
bool needBGWorkaround =
willBeSilent && context == null && !settingsProvider.useShizuku;
if (downloadedFile != null) {
if (needBGWorkaround) {
// ignore: use_build_context_synchronously
installApk(downloadedFile, contextIfNewInstall,
needsBGWorkaround: true);
} else {
// ignore: use_build_context_synchronously
sayInstalled = await installApk(downloadedFile, contextIfNewInstall,
shizukuPretendToBeGooglePlay: apps[id]!
.app
.additionalSettings['shizukuPretendToBeGooglePlay'] ==
true);
}
} else {
if (needBGWorkaround) {
// ignore: use_build_context_synchronously
installXApkDir(downloadedDir!, contextIfNewInstall,
needsBGWorkaround: true);
} else {
// ignore: use_build_context_synchronously
sayInstalled = await installXApkDir(
downloadedDir!, contextIfNewInstall,
shizukuPretendToBeGooglePlay: apps[id]!
.app
.additionalSettings['shizukuPretendToBeGooglePlay'] ==
true);
}
}
if (willBeSilent && context == null) {
if (!settingsProvider.useShizuku) {
notificationsProvider?.notify(SilentUpdateAttemptNotification(
[apps[id]!.app],
id: id.hashCode));
} else {
notificationsProvider?.notify(SilentUpdateNotification(
[apps[id]!.app], sayInstalled,
id: id.hashCode));
}
}
if (sayInstalled) {
installedIds.add(id);
}
} finally {
apps[id]?.downloadProgress = null;
notifyListeners();
}
}
Future<Map<Object?, Object?>> downloadFn(String id,
{bool skipInstalls = false}) async {
bool willBeSilent = false;
DownloadedApk? downloadedFile;
DownloadedXApkDir? downloadedDir;
try { try {
var downloadedArtifact = var downloadedArtifact =
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
await downloadApp(apps[id]!.app, context, await downloadApp(apps[id]!.app, context,
notificationsProvider: notificationsProvider, notificationsProvider: notificationsProvider,
useExisting: useExisting); useExisting: useExisting);
DownloadedApk? downloadedFile;
DownloadedXApkDir? downloadedDir;
if (downloadedArtifact is DownloadedApk) { if (downloadedArtifact is DownloadedApk) {
downloadedFile = downloadedArtifact; downloadedFile = downloadedArtifact;
} else { } else {
downloadedDir = downloadedArtifact as DownloadedXApkDir; downloadedDir = downloadedArtifact as DownloadedXApkDir;
} }
id = downloadedFile?.appId ?? downloadedDir!.appId; id = downloadedFile?.appId ?? downloadedDir!.appId;
bool willBeSilent = await canInstallSilently(apps[id]!.app); willBeSilent = await canInstallSilently(apps[id]!.app);
if (!settingsProvider.useShizuku) { if (!settingsProvider.useShizuku) {
if (!(await settingsProvider.getInstallPermission(enforce: false))) { if (!(await settingsProvider.getInstallPermission(enforce: false))) {
throw ObtainiumError(tr('cancelled')); throw ObtainiumError(tr('cancelled'));
@@ -856,80 +916,33 @@ class AppsProvider with ChangeNotifier {
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
await waitForUserToReturnToForeground(context); await waitForUserToReturnToForeground(context);
} }
apps[id]?.downloadProgress = -1;
notifyListeners();
try {
if (!skipInstalls) {
bool sayInstalled = true;
var contextIfNewInstall =
apps[id]?.installedInfo == null ? context : null;
bool needBGWorkaround =
willBeSilent && context == null && !settingsProvider.useShizuku;
if (downloadedFile != null) {
if (needBGWorkaround) {
// ignore: use_build_context_synchronously
installApk(downloadedFile, contextIfNewInstall,
needsBGWorkaround: true);
} else {
// ignore: use_build_context_synchronously
sayInstalled = await installApk(
downloadedFile, contextIfNewInstall,
shizukuPretendToBeGooglePlay:
apps[id]!.app.additionalSettings[
'shizukuPretendToBeGooglePlay'] ==
true);
}
} else {
if (needBGWorkaround) {
// ignore: use_build_context_synchronously
installXApkDir(downloadedDir!, contextIfNewInstall,
needsBGWorkaround: true);
} else {
// ignore: use_build_context_synchronously
sayInstalled = await installXApkDir(
downloadedDir!, contextIfNewInstall,
shizukuPretendToBeGooglePlay:
apps[id]!.app.additionalSettings[
'shizukuPretendToBeGooglePlay'] ==
true);
}
}
if (willBeSilent && context == null) {
if (!settingsProvider.useShizuku) {
notificationsProvider?.notify(SilentUpdateAttemptNotification(
[apps[id]!.app],
id: id.hashCode));
} else {
notificationsProvider?.notify(SilentUpdateNotification(
[apps[id]!.app], sayInstalled,
id: id.hashCode));
}
}
if (sayInstalled) {
installedIds.add(id);
}
}
} finally {
apps[id]?.downloadProgress = null;
notifyListeners();
}
} catch (e) { } catch (e) {
errors.add(id, e, appName: apps[id]?.name); errors.add(id, e, appName: apps[id]?.name);
} }
return id; return {
'id': id,
'willBeSilent': willBeSilent,
'downloadedFile': downloadedFile,
'downloadedDir': downloadedDir
};
} }
List<Map<Object?, Object?>> downloadResults = [];
if (forceParallelDownloads || !settingsProvider.parallelDownloads) { if (forceParallelDownloads || !settingsProvider.parallelDownloads) {
for (var id in appsToInstall) { for (var id in appsToInstall) {
await updateFn(id); downloadResults.add(await downloadFn(id));
} }
} else { } else {
List<String> ids = await Future.wait( downloadResults = await Future.wait(
appsToInstall.map((id) => updateFn(id, skipInstalls: true))); appsToInstall.map((id) => downloadFn(id, skipInstalls: true)));
for (var id in ids) { }
if (!errors.appIdNames.containsKey(id)) { for (var res in downloadResults) {
await updateFn(id); if (!errors.appIdNames.containsKey(res['id'])) {
} await installFn(
res['id'] as String,
res['willBeSilent'] as bool,
res['downloadedFile'] as DownloadedApk?,
res['downloadedDir'] as DownloadedXApkDir?);
} }
} }
@@ -1166,40 +1179,38 @@ class AppsProvider with ChangeNotifier {
notifyListeners(); notifyListeners();
var sp = SourceProvider(); var sp = SourceProvider();
List<List<String>> errors = []; List<List<String>> errors = [];
List<App?> newApps = (await getAppsDir()) // Parse Apps from JSON await Future.wait((await getAppsDir()) // Parse Apps from JSON
.listSync() .listSync()
.where((item) => item.path.toLowerCase().endsWith('.json')) .map((item) async {
.where((item) => App? app;
singleId == null || if (item.path.toLowerCase().endsWith('.json') &&
item.path.split('/').last.toLowerCase() == (singleId == null ||
'${singleId.toLowerCase()}.json') item.path.split('/').last.toLowerCase() ==
.map((e) { '${singleId.toLowerCase()}.json')) {
try { try {
return App.fromJson(jsonDecode(File(e.path).readAsStringSync())); app = App.fromJson(jsonDecode(File(item.path).readAsStringSync()));
} catch (err) { } catch (err) {
if (err is FormatException) { if (err is FormatException) {
logs.add('Corrupt JSON when loading App (will be ignored): $e'); logs.add('Corrupt JSON when loading App (will be ignored): $e');
e.renameSync('${e.path}.corrupt'); item.renameSync('${item.path}.corrupt');
} else { } else {
rethrow; rethrow;
}
} }
} }
}).toList();
for (var app in newApps) {
// Put Apps into memory to list them (fast)
if (app != null) { if (app != null) {
try { try {
sp.getSource(app.url, overrideSource: app.overrideSource); sp.getSource(app.url, overrideSource: app.overrideSource);
apps.update( apps.update(
app.id, app.id,
(value) => AppInMemory( (value) => AppInMemory(app!, value.downloadProgress,
app, value.downloadProgress, value.installedInfo, value.icon), value.installedInfo, value.icon),
ifAbsent: () => AppInMemory(app, null, null, null)); ifAbsent: () => AppInMemory(app!, null, null, null));
} catch (e) { } catch (e) {
errors.add([app.id, app.finalName, e.toString()]); errors.add([app.id, app.finalName, e.toString()]);
} }
} }
} }));
notifyListeners(); notifyListeners();
if (errors.isNotEmpty) { if (errors.isNotEmpty) {
removeApps(errors.map((e) => e[0]).toList()); removeApps(errors.map((e) => e[0]).toList());
@@ -1207,19 +1218,17 @@ class AppsProvider with ChangeNotifier {
AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList())); AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList()));
} }
// Get install status and other OS info for each App (slow) // Get install status and other OS info for each App (slow)
await Future.wait(apps.values.map((app) {
return updateInstallStatusInMemory(app);
}));
notifyListeners();
// Reconcile version differences
List<App> modifiedApps = []; List<App> modifiedApps = [];
for (var app in apps.values) { await Future.wait(apps.values.map((app) async {
await updateInstallStatusInMemory(app);
var moddedApp = var moddedApp =
getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo); getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo);
if (moddedApp != null) { if (moddedApp != null) {
modifiedApps.add(moddedApp); modifiedApps.add(moddedApp);
} }
} }));
notifyListeners();
// Reconcile version differences
if (modifiedApps.isNotEmpty) { if (modifiedApps.isNotEmpty) {
await saveApps(modifiedApps, attemptToCorrectInstallStatus: false); await saveApps(modifiedApps, attemptToCorrectInstallStatus: false);
var removedAppIds = modifiedApps var removedAppIds = modifiedApps
@@ -1241,7 +1250,7 @@ class AppsProvider with ChangeNotifier {
{bool attemptToCorrectInstallStatus = true, {bool attemptToCorrectInstallStatus = true,
bool onlyIfExists = true}) async { bool onlyIfExists = true}) async {
attemptToCorrectInstallStatus = attemptToCorrectInstallStatus; attemptToCorrectInstallStatus = attemptToCorrectInstallStatus;
for (var a in apps) { await Future.wait(apps.map((a) async {
var app = a.deepCopy(); var app = a.deepCopy();
PackageInfo? info = await getInstalledInfo(app.id); PackageInfo? info = await getInstalledInfo(app.id);
var icon = await info?.applicationInfo?.getAppIcon(); var icon = await info?.applicationInfo?.getAppIcon();
@@ -1263,14 +1272,14 @@ class AppsProvider with ChangeNotifier {
rethrow; rethrow;
} }
} }
} }));
notifyListeners(); notifyListeners();
export(isAuto: true); export(isAuto: true);
} }
Future<void> removeApps(List<String> appIds) async { Future<void> removeApps(List<String> appIds) async {
var apkFiles = APKDir.listSync(); var apkFiles = APKDir.listSync();
for (var appId in appIds) { await Future.wait(appIds.map((appId) async {
File file = File('${(await getAppsDir()).path}/$appId.json'); File file = File('${(await getAppsDir()).path}/$appId.json');
if (file.existsSync()) { if (file.existsSync()) {
file.deleteSync(recursive: true); file.deleteSync(recursive: true);
@@ -1284,7 +1293,7 @@ class AppsProvider with ChangeNotifier {
if (apps.containsKey(appId)) { if (apps.containsKey(appId)) {
apps.remove(appId); apps.remove(appId);
} }
} }));
if (appIds.isNotEmpty) { if (appIds.isNotEmpty) {
notifyListeners(); notifyListeners();
export(isAuto: true); export(isAuto: true);
@@ -1543,6 +1552,8 @@ class AppsProvider with ChangeNotifier {
settingsMap.forEach((key, value) { settingsMap.forEach((key, value) {
if (value is int) { if (value is int) {
settingsProvider.prefs?.setInt(key, value); settingsProvider.prefs?.setInt(key, value);
} else if (value is double) {
settingsProvider.prefs?.setDouble(key, value);
} else if (value is bool) { } else if (value is bool) {
settingsProvider.prefs?.setBool(key, value); settingsProvider.prefs?.setBool(key, value);
} else if (value is List) { } else if (value is List) {