Compare commits

...

9 Commits

Author SHA1 Message Date
Imran Remtulla
75430573f3 Add "de/select all" button to multi-select menus (#2401) 2025-08-01 14:52:54 -04:00
Imran Remtulla
f71e97f6e2 Minor wording changes (#2402, #2406) 2025-08-01 14:06:00 -04:00
Imran Remtulla
93380f4229 Minor bug in F-Droid variant (#2373) 2025-08-01 12:09:03 -04:00
Imran Remtulla
6495987248 Restore Oxford comma but only for English (#2245) 2025-08-01 11:57:50 -04:00
Imran Remtulla
69904265c9 Don't init the foreground service unless it is needed (#2437) 2025-08-01 11:56:53 -04:00
Imran
71bf23a110 Merge pull request #2427 from ImranR98/dev
Stop accidentally sharing GitHub/GitLab PATs with Codeberg, Mullvad (#2423)
2025-07-25 09:51:56 -04:00
Imran
544a1d6711 Merge pull request #2397 from Nassau123/patch-1
Patch 1
2025-07-25 09:51:17 -04:00
Imran
d43370e7f5 Delete .devcontainer/devcontainer.json 2025-07-25 09:51:02 -04:00
Nassau123
58c24ec6de Create devcontainer.json 2025-07-09 04:59:29 +03:00
9 changed files with 71 additions and 32 deletions

View File

@@ -327,7 +327,7 @@
"smartname": "Name (Smart)",
"sortMethod": "Sort Method",
"welcome": "Welcome",
"documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions and other resources that will help you understand how to use the app.",
"documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions, and other resources that will help you understand how to use the app.",
"batteryOptimizationNote": "Note that background downloads may work more reliably if you disable OS battery optimizations for Obtainium.",
"fileDeletionError": "Failed to delete file (try deleting it manually then try again): \"{}\"",
"foregroundService": "Obtainium foreground service",

View File

@@ -327,7 +327,7 @@
"smartname": "Name (Smart)",
"sortMethod": "Sort Method",
"welcome": "Welcome",
"documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions and other resources that will help you understand how to use the app.",
"documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions, and other resources that will help you understand how to use the app.",
"batteryOptimizationNote": "Note that background downloads may work more reliably if you disable OS battery optimizations for Obtainium.",
"fileDeletionError": "Failed to delete file (try deleting it manually then try again): \"{}\"",
"foregroundService": "Obtainium foreground service",

View File

@@ -25,7 +25,7 @@
"standard": "Standard",
"custom": "Custom",
"useMaterialYou": "Use Material You",
"githubStarredRepos": "GitHub starred repos",
"githubStarredRepos": "GitHub starred repositories",
"uname": "Username",
"wrongArgNum": "Wrong number of arguments provided",
"xIsTrackOnly": "{} is track-only",
@@ -313,7 +313,7 @@
"badDownload": "The APK could not be parsed (incompatible or partial download)",
"beforeNewInstallsShareToAppVerifier": "Share new apps with AppVerifier (if available)",
"appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
"wiki": "Help/Wiki",
"wiki": "Help/wiki",
"crowdsourcedConfigsLabel": "Crowdsourced app configurations (use at your own risk)",
"crowdsourcedConfigsShort": "Crowdsourced app configurations",
"allowInsecure": "Allow insecure HTTP requests",
@@ -327,7 +327,7 @@
"smartname": "Name (smart)",
"sortMethod": "Sort method",
"welcome": "Welcome",
"documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions and other resources that will help you understand how to use the app.",
"documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions, and other resources that will help you understand how to use the app.",
"batteryOptimizationNote": "Note that background downloads may work more reliably if you switch to the \"foreground service\" in the Obtainium settings and/or disable battery optimization for Obtainium in your OS settings.",
"fileDeletionError": "Failed to delete file (try deleting it manually then try again): \"{}\"",
"foregroundService": "Obtainium foreground service",

View File

@@ -327,7 +327,7 @@
"smartname": "Name (Smart)",
"sortMethod": "Sort Method",
"welcome": "Welcome",
"documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions and other resources that will help you understand how to use the app.",
"documentationLinksNote": "The Obtainium GitHub page linked below contains links to videos, articles, discussions, and other resources that will help you understand how to use the app.",
"batteryOptimizationNote": "Note that background downloads may work more reliably if you disable OS battery optimizations for Obtainium.",
"fileDeletionError": "Failed to delete file (try deleting it manually then try again): \"{}\"",
"foregroundService": "Obtainium foreground service",

View File

@@ -313,7 +313,7 @@
"badDownload": "De APK kon niet worden verwerkt (incompatibele of gedeeltelijke download)",
"beforeNewInstallsShareToAppVerifier": "Nieuwe Apps delen met AppVerifier (indien beschikbaar)",
"appVerifierInstructionToast": "Deel het met AppVerifier en keer daarna hier terug.",
"wiki": "Help/Wiki",
"wiki": "Help/wiki",
"crowdsourcedConfigsLabel": "Crowdsourced App-configuraties (gebruik op eigen risico)",
"crowdsourcedConfigsShort": "App-configuraties door menigte",
"allowInsecure": "Onveilige HTTP-verzoeken toestaan",

View File

@@ -158,6 +158,7 @@ void showError(dynamic e, BuildContext context) {
}
String list2FriendlyString(List<String> list) {
var isEnglish = tr('and') == 'and'; // Quick hack, find better way;
return list.length == 2
? '${list[0]} ${tr('and')} ${list[1]}'
: list
@@ -169,7 +170,7 @@ String list2FriendlyString(List<String> list) {
(e.key == list.length - 1
? ''
: e.key == list.length - 2
? ' and '
? '${isEnglish ? ',' : ''} and '
: ', '),
)
.join('');

View File

@@ -185,7 +185,6 @@ class _ObtainiumState extends State<Obtainium> {
initPlatformState();
WidgetsBinding.instance.addPostFrameCallback((_) {
requestNonOptionalPermissions();
initForegroundService();
});
}
@@ -201,28 +200,32 @@ class _ObtainiumState extends State<Obtainium> {
}
void initForegroundService() {
FlutterForegroundTask.init(
androidNotificationOptions: AndroidNotificationOptions(
channelId: 'bg_update',
channelName: tr('foregroundService'),
channelDescription: tr('foregroundService'),
onlyAlertOnce: true,
),
iosNotificationOptions: const IOSNotificationOptions(
showNotification: false,
playSound: false,
),
foregroundTaskOptions: ForegroundTaskOptions(
eventAction: ForegroundTaskEventAction.repeat(900000),
autoRunOnBoot: true,
autoRunOnMyPackageReplaced: true,
allowWakeLock: true,
allowWifiLock: true,
),
);
// ignore: invalid_use_of_visible_for_testing_member
if (!FlutterForegroundTask.isInitialized) {
FlutterForegroundTask.init(
androidNotificationOptions: AndroidNotificationOptions(
channelId: 'bg_update',
channelName: tr('foregroundService'),
channelDescription: tr('foregroundService'),
onlyAlertOnce: true,
),
iosNotificationOptions: const IOSNotificationOptions(
showNotification: false,
playSound: false,
),
foregroundTaskOptions: ForegroundTaskOptions(
eventAction: ForegroundTaskEventAction.repeat(900000),
autoRunOnBoot: true,
autoRunOnMyPackageReplaced: true,
allowWakeLock: true,
allowWifiLock: true,
),
);
}
}
Future<ServiceRequestResult?> startForegroundService(bool restart) async {
initForegroundService();
if (await FlutterForegroundTask.isRunningService) {
if (restart) {
return FlutterForegroundTask.restartService();

View File

@@ -396,9 +396,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
Expanded(
child: TextButton(
style: outlineButtonStyle,
onPressed:
appsProvider.apps.isEmpty ||
importInProgress
onPressed: importInProgress
? null
: () {
runObtainiumExport(pickOnly: true);
@@ -710,6 +708,12 @@ class _SelectionModalState extends State<SelectionModal> {
}
}
void selectAll({bool deselect = false}) {
for (var e in entrySelections.keys) {
entrySelections[e] = !deselect;
}
}
@override
Widget build(BuildContext context) {
Map<MapEntry<String, List<String>>, bool> filteredEntrySelections = {};
@@ -731,6 +735,32 @@ class _SelectionModalState extends State<SelectionModal> {
}
});
}
getSelectAllButton() {
if (widget.onlyOneSelectionAllowed) {
return SizedBox.shrink();
}
var noneSelected = entrySelections.values.where((v) => v == true).isEmpty;
return noneSelected
? TextButton(
style: const ButtonStyle(visualDensity: VisualDensity.compact),
onPressed: () {
setState(() {
selectAll();
});
},
child: Text(tr('selectAll')),
)
: TextButton(
style: const ButtonStyle(visualDensity: VisualDensity.compact),
onPressed: () {
setState(() {
selectAll(deselect: true);
});
},
child: Text(tr('deselectX', args: [''])),
);
}
return AlertDialog(
scrollable: true,
title: Text(widget.title ?? tr('pick')),
@@ -900,6 +930,7 @@ class _SelectionModalState extends State<SelectionModal> {
],
),
actions: [
getSelectAllButton(),
TextButton(
onPressed: () {
Navigator.of(context).pop();

View File

@@ -1121,6 +1121,7 @@ class AppsProvider with ChangeNotifier {
obtainiumId,
strB: obtainiumTempId,
);
appsToInstall = moveStrToEnd(appsToInstall, '$obtainiumId.fdroid');
Future<void> installFn(
String id,
@@ -2511,7 +2512,10 @@ Future<void> bgUpdateCheck(String taskId, Map<String, dynamic>? params) async {
}
}
if (toInstall.isNotEmpty) {
var tempObtArr = toInstall.where((element) => element.key == obtainiumId);
var tempObtArr = toInstall.where(
(element) =>
element.key == obtainiumId || element.key == '$obtainiumId.fdroid',
);
if (tempObtArr.isNotEmpty) {
// Move obtainium to the end of the list as it must always install last
var obt = tempObtArr.first;