Enable experimental BG update support (not well tested) (#25)

This commit is contained in:
Imran Remtulla
2023-08-20 22:32:33 -04:00
parent 7c41692d5f
commit b59d3e77f9
15 changed files with 164 additions and 44 deletions

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "Želite li ukloniti aplikaciju?",
"other": "Želite li ukloniti aplikacije?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} i još 1 aplikacija je ažurirana.",
"other": "{} i još {} aplikacija je ažurirano."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "Sortiere nach Dateinamen, anstelle von ganzen Links",
"filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern",
"customLinkFilterRegex": "Benutzerdefinierter Link Filter nach Regulärem Ausdruck (Standard '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "App entfernen?",
"other": "Apps entfernen?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} und 1 weitere Anwendung wurden aktualisiert.",
"other": "{} und {} weitere Anwendungen wurden aktualisiert."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "Remove App?",
"other": "Remove Apps?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} and 1 more app were updated.",
"other": "{} and {} more apps were updated."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "¿Eliminar Aplicación?",
"other": "¿Eliminar Aplicaciones?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} y 1 aplicación más han sido actualizadas.",
"other": "{} y {} aplicaciones más han sido actualizadas."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "مرتب سازی بر اساس نام فایل به جای پیوندهای کامل",
"filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید",
"customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیش‌فرض '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "برنامه حذف شود؟",
"other": "برنامه ها حذف شوند؟"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} و 1 برنامه دیگر به روز شدند.",
"other": "{} و {} برنامه دیگر به روز شدند."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "Supprimer l'application ?",
"other": "Supprimer les applications ?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} et 1 autre application ont été mises à jour.",
"other": "{} et {} autres applications ont été mises à jour."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -246,6 +246,9 @@
"sortByFileNamesNotLinks": "Fájlnevek szerinti elrendezés teljes linkek helyett",
"filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel",
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "Eltávolítja az alkalmazást?",
"other": "Eltávolítja az alkalmazást?"
@@ -293,5 +296,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "A(z) {} és 1 további alkalmazás frissítve.",
"other": "{} és {} további alkalmazás frissítve."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "Rimuovere l'app?",
"other": "Rimuovere le app?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} e un'altra app sono state aggiornate.",
"other": "{} e altre {} app sono state aggiornate."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "フルのリンクではなくファイル名でソートする",
"filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする",
"customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "アプリを削除しますか?",
"other": "アプリを削除しますか?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} とさらに {} 個のアプリがアップデートされました",
"other": "{} とさらに {} 個のアプリがアップデートされました"
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -251,6 +251,9 @@
"sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków",
"filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego",
"customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "Usunąć aplikację?",
"other": "Usunąć aplikacje?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "Zaktualizowano {} i jeszcze 1 aplikację.",
"other": "Zaktualizowano {} i {} aplik."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "Удалить приложение?",
"other": "Удалить приложения?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} и еще 1 приложение были обновлены.",
"other": "{} и еще {} приложений были обновлены."
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -247,6 +247,9 @@
"sortByFileNamesNotLinks": "根据文件名而不是完整链接来排序",
"filterReleaseNotesByRegEx": "用正则表达式筛选发布说明",
"customLinkFilterRegex": "用正则表达式自定义链接筛选(默认 '.apk$'",
"appsPossiblyUpdated": "App Updates Attempted",
"appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background",
"xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.",
"removeAppQuestion": {
"one": "是否删除应用?",
"other": "是否删除应用?"
@@ -294,5 +297,9 @@
"xAndNMoreUpdatesInstalled": {
"one": "{} 和另外 1 个应用已更新。",
"other": "{} 和另外 {} 个应用已更新。"
},
"xAndNMoreUpdatesPossiblyInstalled": {
"one": "Attempts were made to update {} and 1 more app.",
"other": "Attempts were made to update {} and {} more apps."
}
}

View File

@@ -88,10 +88,8 @@ Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
: null;
logs.add(tr('bgUpdateIgnoreAfterIs', args: [ignoreAfter.toString()]));
var notificationsProvider = NotificationsProvider();
await notificationsProvider.notify(checkingUpdatesNotification);
try {
var appsProvider = AppsProvider();
await notificationsProvider.cancel(ErrorCheckingUpdatesNotification('').id);
await appsProvider.loadApps();
List<String> existingUpdateIds =
appsProvider.findExistingUpdates(installedOnly: true);
@@ -100,7 +98,9 @@ Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
try {
logs.add(tr('startedActualBGUpdateCheck'));
await appsProvider.checkUpdates(
ignoreAppsCheckedAfter: ignoreAfter, throwErrorsForRetry: true);
ignoreAppsCheckedAfter: ignoreAfter,
throwErrorsForRetry: true,
notificationsProvider: notificationsProvider);
} catch (e) {
if (e is RateLimitError || e is ClientException) {
var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15;
@@ -124,34 +124,29 @@ Future<void> bgUpdateCheck(int taskId, Map<String, dynamic>? params) async {
.where((id) => !existingUpdateIds.contains(id))
.map((e) => appsProvider.apps[e]!.app)
.toList();
// TODO: This silent update code doesn't work yet
// List<String> silentlyUpdated = await appsProvider
// .downloadAndInstallLatestApp(
// [...newUpdates.map((e) => e.id), ...existingUpdateIds], null);
// if (silentlyUpdated.isNotEmpty) {
// newUpdates = newUpdates
// .where((element) => !silentlyUpdated.contains(element.id))
// .toList();
// notificationsProvider.notify(
// SilentUpdateNotification(
// silentlyUpdated.map((e) => appsProvider.apps[e]!.app).toList()),
// cancelExisting: true);
// }
logs.add(
plural('bgCheckFoundUpdatesWillNotifyIfNeeded', newUpdates.length));
if (newUpdates.isNotEmpty) {
notificationsProvider.notify(UpdateNotification(newUpdates));
List<App> nonSilentUpdates = [];
List<App> silentUpdates = [];
for (var a in newUpdates) {
if (await appsProvider.canInstallSilently(a)) {
silentUpdates.add(a);
} else {
nonSilentUpdates.add(a);
}
}
if (silentUpdates.isNotEmpty) {
await appsProvider.downloadAndInstallLatestApps(
silentUpdates.map((e) => e.id).toList(), null,
notificationsProvider: notificationsProvider);
}
logs.add(plural(
'bgCheckFoundUpdatesWillNotifyIfNeeded', nonSilentUpdates.length));
if (err != null) {
throw err;
}
} catch (e) {
notificationsProvider
.notify(ErrorCheckingUpdatesNotification(e.toString()));
logs.add('${tr('errorCheckingUpdates')}: ${e.toString()}');
} finally {
logs.add(tr('bgUpdateTaskFinished'));
await notificationsProvider.cancel(checkingUpdatesNotification.id);
}
}

View File

@@ -239,9 +239,8 @@ class AppsProvider with ChangeNotifier {
return downloadedFile;
}
Future<Object> downloadApp(App app, BuildContext? context) async {
NotificationsProvider? notificationsProvider =
context?.read<NotificationsProvider>();
Future<Object> downloadApp(App app, BuildContext? context,
{NotificationsProvider? notificationsProvider}) async {
var notifId = DownloadNotification(app.finalName, 0).id;
if (apps[app.id] != null) {
apps[app.id]!.downloadProgress = 0;
@@ -507,7 +506,10 @@ class AppsProvider with ChangeNotifier {
// Returns an array of Ids for Apps that were successfully downloaded, regardless of installation result
Future<List<String>> downloadAndInstallLatestApps(
List<String> appIds, BuildContext? context,
{SettingsProvider? settingsProvider}) async {
{SettingsProvider? settingsProvider,
NotificationsProvider? notificationsProvider}) async {
notificationsProvider =
notificationsProvider ?? context?.read<NotificationsProvider>();
List<String> appsToInstall = [];
List<String> trackOnlyAppsToUpdate = [];
// For all specified Apps, filter out those for which:
@@ -567,8 +569,10 @@ class AppsProvider with ChangeNotifier {
for (var id in appsToInstall) {
try {
var downloadedArtifact =
// ignore: use_build_context_synchronously
var downloadedArtifact = await downloadApp(apps[id]!.app, context);
await downloadApp(apps[id]!.app, context,
notificationsProvider: notificationsProvider);
DownloadedApk? downloadedFile;
DownloadedXApkDir? downloadedDir;
if (downloadedArtifact is DownloadedApk) {
@@ -576,8 +580,8 @@ class AppsProvider with ChangeNotifier {
} else {
downloadedDir = downloadedArtifact as DownloadedXApkDir;
}
bool willBeSilent = await canInstallSilently(
apps[downloadedFile?.appId ?? downloadedDir!.appId]!.app);
var appId = downloadedFile?.appId ?? downloadedDir!.appId;
bool willBeSilent = await canInstallSilently(apps[appId]!.app);
if (!(await settingsProvider?.getInstallPermission(enforce: false) ??
true)) {
throw ObtainiumError(tr('cancelled'));
@@ -590,10 +594,25 @@ class AppsProvider with ChangeNotifier {
notifyListeners();
try {
if (downloadedFile != null) {
if (willBeSilent) {
// Would await forever - workaround - TODO
installApk(downloadedFile);
} else {
await installApk(downloadedFile);
}
} else {
if (willBeSilent) {
// Would await forever - workaround - TODO
installXApkDir(downloadedDir!);
} else {
await installXApkDir(downloadedDir!);
}
}
if (willBeSilent) {
notificationsProvider?.notify(SilentUpdateAttemptNotification(
[apps[appId]!.app],
id: appId.hashCode));
}
} finally {
apps[id]?.downloadProgress = null;
notifyListeners();
@@ -608,8 +627,6 @@ class AppsProvider with ChangeNotifier {
throw errors;
}
NotificationsProvider().cancel(UpdateNotification([]).id);
return installedIds;
}
@@ -971,7 +988,8 @@ class AppsProvider with ChangeNotifier {
Future<List<App>> checkUpdates(
{DateTime? ignoreAppsCheckedAfter,
bool throwErrorsForRetry = false}) async {
bool throwErrorsForRetry = false,
NotificationsProvider? notificationsProvider}) async {
List<App> updates = [];
MultiAppMultiError errors = MultiAppMultiError();
if (!gettingUpdates) {
@@ -998,9 +1016,14 @@ class AppsProvider with ChangeNotifier {
rethrow;
}
errors.add(appIds[i], e.toString());
notificationsProvider?.notify(ErrorCheckingUpdatesNotification(
'${appIds[i]}: ${e.toString()}',
id: appIds[i].hashCode));
}
if (newApp != null) {
updates.add(newApp);
notificationsProvider
?.notify(UpdateNotification([newApp], id: newApp.id.hashCode));
}
}
} finally {

View File

@@ -22,9 +22,9 @@ class ObtainiumNotification {
}
class UpdateNotification extends ObtainiumNotification {
UpdateNotification(List<App> updates)
UpdateNotification(List<App> updates, {int? id})
: super(
2,
id ?? 2,
tr('updatesAvailable'),
'',
'UPDATES_AVAILABLE',
@@ -41,8 +41,8 @@ class UpdateNotification extends ObtainiumNotification {
}
class SilentUpdateNotification extends ObtainiumNotification {
SilentUpdateNotification(List<App> updates)
: super(3, tr('appsUpdated'), '', 'APPS_UPDATED', tr('appsUpdated'),
SilentUpdateNotification(List<App> updates, {int? id})
: super(id ?? 3, tr('appsUpdated'), '', 'APPS_UPDATED', tr('appsUpdated'),
tr('appsUpdatedNotifDescription'), Importance.defaultImportance) {
message = updates.length == 1
? tr('xWasUpdatedToY',
@@ -52,10 +52,28 @@ class SilentUpdateNotification extends ObtainiumNotification {
}
}
class ErrorCheckingUpdatesNotification extends ObtainiumNotification {
ErrorCheckingUpdatesNotification(String error)
class SilentUpdateAttemptNotification extends ObtainiumNotification {
SilentUpdateAttemptNotification(List<App> updates, {int? id})
: super(
5,
id ?? 3,
tr('appsPossiblyUpdated'),
'',
'APPS_POSSIBLY_UPDATED',
tr('appsPossiblyUpdated'),
tr('appsPossiblyUpdatedNotifDescription'),
Importance.defaultImportance) {
message = updates.length == 1
? tr('xWasPossiblyUpdatedToY',
args: [updates[0].finalName, updates[0].latestVersion])
: plural('xAndNMoreUpdatesPossiblyInstalled', updates.length - 1,
args: [updates[0].finalName, (updates.length - 1).toString()]);
}
}
class ErrorCheckingUpdatesNotification extends ObtainiumNotification {
ErrorCheckingUpdatesNotification(String error, {int? id})
: super(
id ?? 5,
tr('errorCheckingUpdates'),
error,
'BG_UPDATE_CHECK_ERROR',