mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-08-16 11:48:09 +02:00
UI improvements
This commit is contained in:
@@ -7,7 +7,6 @@ import 'package:obtainium/main.dart';
|
||||
import 'package:obtainium/pages/apps.dart';
|
||||
import 'package:obtainium/pages/settings.dart';
|
||||
import 'package:obtainium/providers/apps_provider.dart';
|
||||
import 'package:obtainium/providers/notifications_provider.dart';
|
||||
import 'package:obtainium/providers/settings_provider.dart';
|
||||
import 'package:obtainium/providers/source_provider.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
@@ -165,42 +164,11 @@ class _AppPageState extends State<AppPage> {
|
||||
onTap: app?.app == null || updating
|
||||
? null
|
||||
: () async {
|
||||
var fileUrl = await appsProvider.confirmAppFileUrl(
|
||||
app!.app, context, true);
|
||||
if (fileUrl != null) {
|
||||
NotificationsProvider notificationsProvider =
|
||||
(globalNavigatorKey.currentContext ?? context)
|
||||
.read<NotificationsProvider>();
|
||||
try {
|
||||
showMessage(
|
||||
'${tr('downloadingX', args: [fileUrl.key])}...',
|
||||
globalNavigatorKey.currentContext ?? context);
|
||||
await downloadFile(
|
||||
fileUrl.value,
|
||||
fileUrl.key
|
||||
.split('.')
|
||||
.reversed
|
||||
.toList()
|
||||
.sublist(1)
|
||||
.reversed
|
||||
.join('.'), (double? progress) {
|
||||
notificationsProvider.notify(DownloadNotification(
|
||||
fileUrl.key, progress?.ceil() ?? 0));
|
||||
}, '/storage/emulated/0/Download',
|
||||
headers: await source?.getRequestHeaders(
|
||||
app.app.additionalSettings,
|
||||
forAPKDownload: fileUrl.key.endsWith('.apk')
|
||||
? true
|
||||
: false));
|
||||
notificationsProvider.notify(DownloadedNotification(
|
||||
fileUrl.key, fileUrl.value));
|
||||
await appsProvider
|
||||
.downloadAppAssets([app!.app.id], context);
|
||||
} catch (e) {
|
||||
showError(
|
||||
e, globalNavigatorKey.currentContext ?? context);
|
||||
} finally {
|
||||
notificationsProvider
|
||||
.cancel(DownloadNotification(fileUrl.key, 0).id);
|
||||
}
|
||||
showError(e, context);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
|
@@ -854,29 +854,18 @@ class AppsPageState extends State<AppsPage> {
|
||||
scrollable: true,
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.only(top: 6),
|
||||
child: Row(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: appsProvider.areDownloadsRunning()
|
||||
? null
|
||||
: showMassMarkDialog,
|
||||
tooltip: tr('markSelectedAppsUpdated'),
|
||||
icon: const Icon(Icons.done)),
|
||||
IconButton(
|
||||
TextButton(
|
||||
onPressed: pinSelectedApps,
|
||||
tooltip: selectedApps
|
||||
child: Text(selectedApps
|
||||
.where((element) => element.pinned)
|
||||
.isEmpty
|
||||
? tr('pinToTop')
|
||||
: tr('unpinFromTop'),
|
||||
icon: Icon(selectedApps
|
||||
.where((element) => element.pinned)
|
||||
.isEmpty
|
||||
? Icons.bookmark_outline_rounded
|
||||
: Icons.bookmark_remove_outlined),
|
||||
),
|
||||
IconButton(
|
||||
: tr('unpinFromTop'))),
|
||||
const Divider(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
String urls = '';
|
||||
for (var a in selectedApps) {
|
||||
@@ -887,10 +876,9 @@ class AppsPageState extends State<AppsPage> {
|
||||
subject: 'Obtainium - ${tr('appsString')}');
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
tooltip: tr('shareSelectedAppURLs'),
|
||||
icon: const Icon(Icons.share_rounded),
|
||||
),
|
||||
IconButton(
|
||||
child: Text(tr('shareSelectedAppURLs'))),
|
||||
const Divider(),
|
||||
TextButton(
|
||||
onPressed: selectedAppIds.isEmpty
|
||||
? null
|
||||
: () {
|
||||
@@ -912,11 +900,32 @@ class AppsPageState extends State<AppsPage> {
|
||||
urls +=
|
||||
'</ul>\n\n<p><a href="$obtainiumUrl">${tr('about')}</a></p>';
|
||||
Share.share(urls,
|
||||
subject: 'Obtainium - ${tr('appsString')}');
|
||||
subject:
|
||||
'Obtainium - ${tr('appsString')}');
|
||||
},
|
||||
tooltip: tr('shareAppConfigLinks'),
|
||||
icon: const Icon(Icons.ios_share),
|
||||
),
|
||||
child: Text(tr('shareAppConfigLinks'))),
|
||||
const Divider(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
appsProvider
|
||||
.downloadAppAssets(
|
||||
selectedApps.map((e) => e.id).toList(),
|
||||
globalNavigatorKey.currentContext ??
|
||||
context)
|
||||
.catchError((e) => showError(
|
||||
e,
|
||||
globalNavigatorKey.currentContext ??
|
||||
context));
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(tr('downloadX',
|
||||
args: [tr('releaseAsset').toLowerCase()]))),
|
||||
const Divider(),
|
||||
TextButton(
|
||||
onPressed: appsProvider.areDownloadsRunning()
|
||||
? null
|
||||
: showMassMarkDialog,
|
||||
child: Text(tr('markSelectedAppsUpdated'))),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
@@ -916,6 +916,73 @@ class AppsProvider with ChangeNotifier {
|
||||
return installedIds;
|
||||
}
|
||||
|
||||
Future<List<String>> downloadAppAssets(
|
||||
List<String> appIds, BuildContext context,
|
||||
{bool forceParallelDownloads = false}) async {
|
||||
NotificationsProvider notificationsProvider =
|
||||
context.read<NotificationsProvider>();
|
||||
List<MapEntry<MapEntry<String, String>, App>> filesToDownload = [];
|
||||
for (var id in appIds) {
|
||||
if (apps[id] == null) {
|
||||
throw ObtainiumError(tr('appNotFound'));
|
||||
}
|
||||
MapEntry<String, String>? fileUrl;
|
||||
if (apps[id]!.app.apkUrls.isNotEmpty ||
|
||||
apps[id]!.app.otherAssetUrls.isNotEmpty) {
|
||||
// ignore: use_build_context_synchronously
|
||||
fileUrl = await confirmAppFileUrl(apps[id]!.app, context, true);
|
||||
}
|
||||
if (fileUrl != null) {
|
||||
filesToDownload.add(MapEntry(fileUrl, apps[id]!.app));
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare to download+install Apps
|
||||
MultiAppMultiError errors = MultiAppMultiError();
|
||||
List<String> downloadedIds = [];
|
||||
|
||||
Future<void> downloadFn(MapEntry<String, String> fileUrl, App app) async {
|
||||
try {
|
||||
await downloadFile(
|
||||
fileUrl.value,
|
||||
fileUrl.key
|
||||
.split('.')
|
||||
.reversed
|
||||
.toList()
|
||||
.sublist(1)
|
||||
.reversed
|
||||
.join('.'), (double? progress) {
|
||||
notificationsProvider
|
||||
.notify(DownloadNotification(fileUrl.key, progress?.ceil() ?? 0));
|
||||
}, '/storage/emulated/0/Download',
|
||||
headers: await SourceProvider()
|
||||
.getSource(app.url, overrideSource: app.overrideSource)
|
||||
.getRequestHeaders(app.additionalSettings,
|
||||
forAPKDownload:
|
||||
fileUrl.key.endsWith('.apk') ? true : false));
|
||||
notificationsProvider
|
||||
.notify(DownloadedNotification(fileUrl.key, fileUrl.value));
|
||||
} catch (e) {
|
||||
errors.add(fileUrl.key, e);
|
||||
} finally {
|
||||
notificationsProvider.cancel(DownloadNotification(fileUrl.key, 0).id);
|
||||
}
|
||||
}
|
||||
|
||||
if (forceParallelDownloads || !settingsProvider.parallelDownloads) {
|
||||
for (var urlWithApp in filesToDownload) {
|
||||
await downloadFn(urlWithApp.key, urlWithApp.value);
|
||||
}
|
||||
} else {
|
||||
await Future.wait(filesToDownload
|
||||
.map((urlWithApp) => downloadFn(urlWithApp.key, urlWithApp.value)));
|
||||
}
|
||||
if (errors.idsByErrorString.isNotEmpty) {
|
||||
throw errors;
|
||||
}
|
||||
return downloadedIds;
|
||||
}
|
||||
|
||||
Future<Directory> getAppsDir() async {
|
||||
Directory appsDir =
|
||||
Directory('${(await getExternalStorageDirectory())!.path}/app_data');
|
||||
|
Reference in New Issue
Block a user