Apps bottom bar tweaks (#216)

This commit is contained in:
Imran Remtulla
2023-01-06 20:47:22 -05:00
parent b68cf5a1be
commit 95f3362a84

View File

@@ -348,8 +348,9 @@ class AppsPageState extends State<AppsPage> {
Row(
children: [
selectedApps.isEmpty
? IconButton(
visualDensity: VisualDensity.compact,
? TextButton.icon(
style:
const ButtonStyle(visualDensity: VisualDensity.compact),
onPressed: () {
selectThese(sortedApps.map((e) => e.app).toList());
},
@@ -357,7 +358,7 @@ class AppsPageState extends State<AppsPage> {
Icons.select_all_outlined,
color: Theme.of(context).colorScheme.primary,
),
tooltip: tr('selectAll'))
label: Text(sortedApps.length.toString()))
: TextButton.icon(
style:
const ButtonStyle(visualDensity: VisualDensity.compact),
@@ -375,31 +376,36 @@ class AppsPageState extends State<AppsPage> {
label: Text(selectedApps.length.toString())),
const VerticalDivider(),
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
selectedApps.isEmpty
? const SizedBox()
: IconButton(
IconButton(
visualDensity: VisualDensity.compact,
onPressed: () {
onPressed: selectedApps.isEmpty
? null
: () {
showDialog<Map<String, dynamic>?>(
context: context,
builder: (BuildContext ctx) {
return GeneratedFormModal(
title: tr('removeSelectedAppsQuestion'),
title:
tr('removeSelectedAppsQuestion'),
items: const [],
initValid: true,
message: tr(
'xWillBeRemovedButRemainInstalled',
args: [
plural('apps', selectedApps.length)
plural(
'apps', selectedApps.length)
]),
);
}).then((values) {
if (values != null) {
appsProvider.removeApps(
selectedApps.map((e) => e.id).toList());
appsProvider.removeApps(selectedApps
.map((e) => e.id)
.toList());
}
});
},
@@ -416,50 +422,71 @@ class AppsPageState extends State<AppsPage> {
: () {
HapticFeedback.heavyImpact();
List<GeneratedFormItem> formItems = [];
if (existingUpdateIdsAllOrSelected.isNotEmpty) {
formItems.add(GeneratedFormSwitch('updates',
if (existingUpdateIdsAllOrSelected
.isNotEmpty) {
formItems.add(GeneratedFormSwitch(
'updates',
label: tr('updateX', args: [
plural('apps',
existingUpdateIdsAllOrSelected.length)
plural(
'apps',
existingUpdateIdsAllOrSelected
.length)
]),
defaultValue: true));
}
if (newInstallIdsAllOrSelected.isNotEmpty) {
formItems.add(GeneratedFormSwitch('installs',
formItems.add(GeneratedFormSwitch(
'installs',
label: tr('installX', args: [
plural('apps',
newInstallIdsAllOrSelected.length)
plural(
'apps',
newInstallIdsAllOrSelected
.length)
]),
defaultValue: existingUpdateIdsAllOrSelected
defaultValue:
existingUpdateIdsAllOrSelected
.isNotEmpty));
}
if (trackOnlyUpdateIdsAllOrSelected.isNotEmpty) {
formItems.add(GeneratedFormSwitch('trackonlies',
label: tr('markXTrackOnlyAsUpdated', args: [
plural('apps',
trackOnlyUpdateIdsAllOrSelected.length)
if (trackOnlyUpdateIdsAllOrSelected
.isNotEmpty) {
formItems.add(GeneratedFormSwitch(
'trackonlies',
label: tr('markXTrackOnlyAsUpdated',
args: [
plural(
'apps',
trackOnlyUpdateIdsAllOrSelected
.length)
]),
defaultValue: existingUpdateIdsAllOrSelected
defaultValue:
existingUpdateIdsAllOrSelected
.isNotEmpty ||
newInstallIdsAllOrSelected.isNotEmpty));
newInstallIdsAllOrSelected
.isNotEmpty));
}
showDialog<Map<String, dynamic>?>(
context: context,
builder: (BuildContext ctx) {
var totalApps = existingUpdateIdsAllOrSelected
var totalApps =
existingUpdateIdsAllOrSelected.length +
newInstallIdsAllOrSelected
.length +
newInstallIdsAllOrSelected.length +
trackOnlyUpdateIdsAllOrSelected.length;
trackOnlyUpdateIdsAllOrSelected
.length;
return GeneratedFormModal(
title: tr('changeX',
args: [plural('apps', totalApps)]),
items: formItems.map((e) => [e]).toList(),
title: tr('changeX', args: [
plural('apps', totalApps)
]),
items: formItems
.map((e) => [e])
.toList(),
initValid: true,
);
}).then((values) {
if (values != null) {
if (values.isEmpty) {
values = getDefaultValuesFromFormItems(
values =
getDefaultValuesFromFormItems(
[formItems]);
}
bool shouldInstallUpdates =
@@ -478,20 +505,22 @@ class AppsPageState extends State<AppsPage> {
.then((_) {
List<String> toInstall = [];
if (shouldInstallUpdates) {
toInstall
.addAll(existingUpdateIdsAllOrSelected);
toInstall.addAll(
existingUpdateIdsAllOrSelected);
}
if (shouldInstallNew) {
toInstall
.addAll(newInstallIdsAllOrSelected);
toInstall.addAll(
newInstallIdsAllOrSelected);
}
if (shouldMarkTrackOnlies) {
toInstall.addAll(
trackOnlyUpdateIdsAllOrSelected);
}
appsProvider
.downloadAndInstallLatestApps(toInstall,
globalNavigatorKey.currentContext)
.downloadAndInstallLatestApps(
toInstall,
globalNavigatorKey
.currentContext)
.catchError((e) {
showError(e, context);
});
@@ -505,16 +534,17 @@ class AppsPageState extends State<AppsPage> {
icon: const Icon(
Icons.file_download_outlined,
)),
selectedApps.isEmpty
? const SizedBox()
: IconButton(
IconButton(
visualDensity: VisualDensity.compact,
onPressed: () async {
onPressed: selectedApps.isEmpty
? null
: () async {
try {
Set<String>? preselected;
var showPrompt = false;
for (var element in selectedApps) {
var currentCats = element.categories.toSet();
var currentCats =
element.categories.toSet();
if (preselected == null) {
preselected = currentCats;
} else {
@@ -527,15 +557,16 @@ class AppsPageState extends State<AppsPage> {
}
var cont = true;
if (showPrompt) {
cont = await showDialog<Map<String, dynamic>?>(
cont = await showDialog<
Map<String, dynamic>?>(
context: context,
builder: (BuildContext ctx) {
return GeneratedFormModal(
title: tr('categorize'),
items: const [],
initValid: true,
message:
tr('selectedCategorizeWarning'),
message: tr(
'selectedCategorizeWarning'),
);
}) !=
null;
@@ -548,7 +579,8 @@ class AppsPageState extends State<AppsPage> {
title: tr('categorize'),
items: const [],
initValid: true,
singleNullReturnButton: tr('continue'),
singleNullReturnButton:
tr('continue'),
additionalWidgets: [
CategoryEditorSelector(
preselected: !showPrompt
@@ -556,8 +588,8 @@ class AppsPageState extends State<AppsPage> {
: {},
showLabelWhenNotEmpty: false,
onSelected: (categories) {
appsProvider
.saveApps(selectedApps.map((e) {
appsProvider.saveApps(
selectedApps.map((e) {
e.categories = categories;
return e;
}).toList());
@@ -574,30 +606,32 @@ class AppsPageState extends State<AppsPage> {
tooltip: tr('categorize'),
icon: const Icon(Icons.category_outlined),
),
selectedApps.isEmpty
? const SizedBox()
: IconButton(
IconButton(
visualDensity: VisualDensity.compact,
onPressed: () {
onPressed: selectedApps.isEmpty
? null
: () {
showDialog(
context: context,
builder: (BuildContext ctx) {
return AlertDialog(
scrollable: true,
content: Padding(
padding: const EdgeInsets.only(top: 6),
padding:
const EdgeInsets.only(top: 6),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
MainAxisAlignment
.spaceAround,
children: [
IconButton(
onPressed:
appsProvider
onPressed: appsProvider
.areDownloadsRunning()
? null
: () {
showDialog(
context: context,
context:
context,
builder:
(BuildContext
ctx) {
@@ -605,47 +639,39 @@ class AppsPageState extends State<AppsPage> {
title: Text(tr(
'markXSelectedAppsAsUpdated',
args: [
selectedApps
.length
.toString()
selectedApps.length.toString()
])),
content: Text(
content:
Text(
tr('onlyWorksWithNonEVDApps'),
style: const TextStyle(
fontWeight:
FontWeight
.bold,
fontStyle:
FontStyle.italic),
FontWeight.bold,
fontStyle: FontStyle.italic),
),
actions: [
TextButton(
onPressed:
() {
Navigator.of(context)
.pop();
Navigator.of(context).pop();
},
child: Text(
tr('no'))),
child:
Text(tr('no'))),
TextButton(
onPressed:
() {
HapticFeedback
.selectionClick();
appsProvider
.saveApps(selectedApps.map((a) {
if (a.installedVersion !=
null) {
HapticFeedback.selectionClick();
appsProvider.saveApps(selectedApps.map((a) {
if (a.installedVersion != null) {
a.installedVersion = a.latestVersion;
}
return a;
}).toList());
Navigator.of(context)
.pop();
Navigator.of(context).pop();
},
child: Text(
tr('yes')))
child:
Text(tr('yes')))
],
);
}).whenComplete(() {
@@ -654,21 +680,25 @@ class AppsPageState extends State<AppsPage> {
.pop();
});
},
tooltip:
tr('markSelectedAppsUpdated'),
icon: const Icon(Icons.done)),
tooltip: tr(
'markSelectedAppsUpdated'),
icon: const Icon(
Icons.done)),
IconButton(
onPressed: () {
var pinStatus = selectedApps
var pinStatus =
selectedApps
.where((element) =>
element.pinned)
element
.pinned)
.isEmpty;
appsProvider.saveApps(
selectedApps.map((e) {
e.pinned = pinStatus;
return e;
}).toList());
Navigator.of(context).pop();
Navigator.of(context)
.pop();
},
tooltip: selectedApps
.where((element) =>
@@ -680,14 +710,16 @@ class AppsPageState extends State<AppsPage> {
.where((element) =>
element.pinned)
.isEmpty
? Icons.bookmark_outline_rounded
? Icons
.bookmark_outline_rounded
: Icons
.bookmark_remove_outlined),
),
IconButton(
onPressed: () {
String urls = '';
for (var a in selectedApps) {
for (var a
in selectedApps) {
urls += '${a.url}\n';
}
urls = urls.substring(
@@ -695,16 +727,20 @@ class AppsPageState extends State<AppsPage> {
Share.share(urls,
subject: tr(
'selectedAppURLsFromObtainium'));
Navigator.of(context).pop();
Navigator.of(context)
.pop();
},
tooltip: tr('shareSelectedAppURLs'),
icon: const Icon(Icons.share),
tooltip: tr(
'shareSelectedAppURLs'),
icon:
const Icon(Icons.share),
),
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext ctx) {
builder: (BuildContext
ctx) {
return GeneratedFormModal(
title: tr(
'resetInstallStatusForSelectedAppsQuestion'),
@@ -722,18 +758,22 @@ class AppsPageState extends State<AppsPage> {
}).then((values) {
if (values != null) {
appsProvider.saveApps(
selectedApps.map((e) {
e.installedVersion = null;
selectedApps
.map((e) {
e.installedVersion =
null;
return e;
}).toList());
}
}).whenComplete(() {
Navigator.of(context).pop();
Navigator.of(context)
.pop();
});
},
tooltip: tr('resetInstallStatus'),
icon: const Icon(
Icons.restore_page_outlined),
tooltip: tr(
'resetInstallStatus'),
icon: const Icon(Icons
.restore_page_outlined),
),
]),
),
@@ -744,7 +784,7 @@ class AppsPageState extends State<AppsPage> {
icon: const Icon(Icons.more_horiz),
),
],
)),
))),
const VerticalDivider(),
IconButton(
visualDensity: VisualDensity.compact,