From a3834ecec627a5279840107ea3b4b71302537bd9 Mon Sep 17 00:00:00 2001 From: "Omer I.S." Date: Tue, 6 Jan 2026 13:37:24 +0200 Subject: [PATCH 1/8] Convert translation files to PO --- .github/workflows/fastlane.yml | 16 -- .github/workflows/translations.yml | 38 ++++ lib/l10n/translation_service.dart | 31 ++++ lib/main.dart | 269 +---------------------------- pubspec.yaml | 7 + 5 files changed, 82 insertions(+), 279 deletions(-) delete mode 100644 .github/workflows/fastlane.yml create mode 100644 .github/workflows/translations.yml create mode 100644 lib/l10n/translation_service.dart diff --git a/.github/workflows/fastlane.yml b/.github/workflows/fastlane.yml deleted file mode 100644 index b88c5eb34..000000000 --- a/.github/workflows/fastlane.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Validate Fastlane metadata - -on: - workflow_dispatch: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - go: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Validate Fastlane Supply Metadata - uses: ashutoshgngwr/validate-fastlane-supply-metadata@v2 diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml new file mode 100644 index 000000000..b912c6771 --- /dev/null +++ b/.github/workflows/translations.yml @@ -0,0 +1,38 @@ +name: Auto-Update Translations + +on: + push: + branches: [ main ] + paths: + - 'lib/**.dart' + +jobs: + update-translations: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install gettext + run: sudo apt-get install -y gettext + + - name: Extract Strings and Update PO Files + run: | + mkdir -p assets/translations + # Search for tr('...') or tr("...") in the code + find lib -name "*.dart" | xgettext -f - \ + --from-code=UTF-8 \ + --language=Python \ + --keyword=tr \ + --output=assets/translations/app.pot || touch assets/translations/app.pot + + # Sync PO files with the new template + [ -f assets/translations/en.po ] && msgmerge -U assets/translations/en.po assets/translations/app.pot || cp assets/translations/app.pot assets/translations/en.po + [ -f assets/translations/he.po ] && msgmerge -U assets/translations/he.po assets/translations/app.pot || cp assets/translations/app.pot assets/translations/he.po + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "chore: update translation files" + title: "🌍 Translation Update" + body: "Found new strings via tr() function." + branch: translations-update \ No newline at end of file diff --git a/lib/l10n/translation_service.dart b/lib/l10n/translation_service.dart new file mode 100644 index 000000000..c4e65a2af --- /dev/null +++ b/lib/l10n/translation_service.dart @@ -0,0 +1,31 @@ +import 'package:flutter/services.dart'; +import 'package:gettext/gettext.dart'; +import 'dart:ui' as ui; + +class I18n { + static final Gettext _gt = Gettext(); + + static Future init() async { + // Determine the device language + String locale = ui.window.locale.languageCode; + + try { + // Load the .po file from assets + String poContent = await rootBundle.loadString('lib/l10n/$locale.po'); + _gt.addTranslations(locale, poContent); + _gt.locale = locale; + } catch (e) { + // Fallback to English if the language file is missing + try { + String enContent = await rootBundle.loadString('lib/l10n/en.po'); + _gt.addTranslations('en', enContent); + _gt.locale = 'en'; + } catch (err) { + print("Localization error: $err"); + } + } + } + + // Translation helper function + static String t(String key) => _gt.gettext(key); +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 1b94ebb6f..40cbc755e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,6 +19,8 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; import 'package:flutter_foreground_task/flutter_foreground_task.dart'; +// Added for PO file support +import 'package:easy_gettext/easy_gettext.dart'; List> supportedLocales = const [ MapEntry(Locale('en'), 'English'), @@ -28,7 +30,7 @@ List> supportedLocales = const [ MapEntry(Locale('ja'), '日本語'), MapEntry(Locale('hu'), 'Magyar'), MapEntry(Locale('de'), 'Deutsch'), - MapEntry(Locale('fa'), 'فارسی'), + MapEntry(Locale('fa'), 'فارסי'), MapEntry(Locale('fr'), 'Français'), MapEntry(Locale('es'), 'Español'), MapEntry(Locale('pl'), 'Polski'), @@ -70,7 +72,8 @@ Future loadTranslations() async { forceLocale: forceLocale, fallbackLocale: fallbackLocale, supportedLocales: supportedLocales.map((e) => e.key).toList(), - assetLoader: const RootBundleAssetLoader(), + // Updated to use GettextLoader for PO files + assetLoader: const GettextLoader(), useOnlyLangCode: false, useFallbackTranslations: true, path: localeDir, @@ -160,264 +163,4 @@ void main() async { child: EasyLocalization( supportedLocales: supportedLocales.map((e) => e.key).toList(), path: localeDir, - fallbackLocale: fallbackLocale, - useOnlyLangCode: false, - child: const Updatium(), - ), - ), - ); - BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask); -} - -class Updatium extends StatefulWidget { - const Updatium({super.key}); - - @override - State createState() => _UpdatiumState(); -} - -class _UpdatiumState extends State { - var existingUpdateInterval = -1; - - @override - void initState() { - super.initState(); - initPlatformState(); - WidgetsBinding.instance.addPostFrameCallback((_) { - requestNonOptionalPermissions(); - }); - } - - Future requestNonOptionalPermissions() async { - final NotificationPermission notificationPermission = - await FlutterForegroundTask.checkNotificationPermission(); - if (notificationPermission != NotificationPermission.granted) { - await FlutterForegroundTask.requestNotificationPermission(); - } - if (!await FlutterForegroundTask.isIgnoringBatteryOptimizations) { - await FlutterForegroundTask.requestIgnoreBatteryOptimization(); - } - } - - void initForegroundService() { - // 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 startForegroundService(bool restart) async { - initForegroundService(); - if (await FlutterForegroundTask.isRunningService) { - if (restart) { - return FlutterForegroundTask.restartService(); - } - } else { - return FlutterForegroundTask.startService( - serviceTypes: [ForegroundServiceTypes.specialUse], - serviceId: 666, - notificationTitle: tr('foregroundService'), - notificationText: tr('fgServiceNotice'), - notificationIcon: NotificationIcon( - metaDataName: 'com.omeritzics.updatium.service.NOTIFICATION_ICON', - ), - callback: startCallback, - ); - } - return null; - } - - stopForegroundService() async { - if (await FlutterForegroundTask.isRunningService) { - return FlutterForegroundTask.stopService(); - } - } - - // void onReceiveForegroundServiceData(Object data) { - // print('onReceiveTaskData: $data'); - // } - - @override - void dispose() { - // Remove a callback to receive data sent from the TaskHandler. - // FlutterForegroundTask.removeTaskDataCallback(onReceiveForegroundServiceData); - super.dispose(); - } - - Future initPlatformState() async { - await BackgroundFetch.configure( - BackgroundFetchConfig( - minimumFetchInterval: 15, - stopOnTerminate: false, - startOnBoot: true, - enableHeadless: true, - requiresBatteryNotLow: false, - requiresCharging: false, - requiresStorageNotLow: false, - requiresDeviceIdle: false, - requiredNetworkType: NetworkType.ANY, - ), - (String taskId) async { - await bgUpdateCheck(taskId, null); - BackgroundFetch.finish(taskId); - }, - (String taskId) async { - context.read().add('BG update task timed out.'); - BackgroundFetch.finish(taskId); - }, - ); - if (!mounted) return; - } - - @override - Widget build(BuildContext context) { - SettingsProvider settingsProvider = context.watch(); - AppsProvider appsProvider = context.read(); - LogsProvider logs = context.read(); - NotificationsProvider notifs = context.read(); - if (settingsProvider.updateInterval == 0) { - stopForegroundService(); - BackgroundFetch.stop(); - } else { - if (settingsProvider.useFGService) { - BackgroundFetch.stop(); - startForegroundService(false); - } else { - stopForegroundService(); - BackgroundFetch.start(); - } - } - if (settingsProvider.prefs == null) { - settingsProvider.initializeSettings(); - } else { - bool isFirstRun = settingsProvider.checkAndFlipFirstRun(); - if (isFirstRun) { - logs.add('This is the first ever run of Updatium.'); - // If this is the first run, add Updatium to the Apps list - if (!fdroid) { - getInstalledInfo(updatiumId) - .then((value) { - if (value?.versionName != null) { - appsProvider.saveApps([ - App( - updatiumId, - updatiumUrl, - 'omeritzics', - 'Updatium', - value!.versionName, - value.versionName!, - [], - 0, - { - 'versionDetection': true, - 'apkFilterRegEx': 'fdroid', - 'invertAPKFilter': true, - }, - null, - false, - ), - ], onlyIfExists: false); - } - }) - .catchError((err) { - print(err); - }); - } - } - if (!supportedLocales.map((e) => e.key).contains(context.locale) || - (settingsProvider.forcedLocale == null && - context.deviceLocale != context.locale)) { - settingsProvider.resetLocaleSafe(context); - } - } - - WidgetsBinding.instance.addPostFrameCallback((_) { - notifs.checkLaunchByNotif(); - }); - - return WithForegroundTask( - child: DynamicColorBuilder( - builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) { - // Decide on a colour/brightness scheme based on OS and user settings - ColorScheme lightColorScheme; - ColorScheme darkColorScheme; - if (lightDynamic != null && - darkDynamic != null && - settingsProvider.useMaterialYou) { - lightColorScheme = lightDynamic.harmonized(); - darkColorScheme = darkDynamic.harmonized(); - } else { - lightColorScheme = ColorScheme.fromSeed( - seedColor: settingsProvider.themeColor, - ); - darkColorScheme = ColorScheme.fromSeed( - seedColor: settingsProvider.themeColor, - brightness: Brightness.dark, - ); - } - - // set the background and surface colors to pure black in the amoled theme - if (settingsProvider.useBlackTheme) { - darkColorScheme = darkColorScheme - .copyWith(surface: Colors.black) - .harmonized(); - } - - if (settingsProvider.useSystemFont) NativeFeatures.loadSystemFont(); - - return MaterialApp( - title: 'Updatium', - localizationsDelegates: context.localizationDelegates, - supportedLocales: context.supportedLocales, - locale: context.locale, - navigatorKey: globalNavigatorKey, - debugShowCheckedModeBanner: false, - theme: ThemeData( - useMaterial3: true, - colorScheme: settingsProvider.theme == ThemeSettings.dark - ? darkColorScheme - : lightColorScheme, - fontFamily: settingsProvider.useSystemFont - ? 'SystemFont' - : 'Montserrat', - ), - darkTheme: ThemeData( - useMaterial3: true, - colorScheme: settingsProvider.theme == ThemeSettings.light - ? lightColorScheme - : darkColorScheme, - fontFamily: settingsProvider.useSystemFont - ? 'SystemFont' - : 'Montserrat', - ), - home: Shortcuts( - shortcuts: { - LogicalKeySet(LogicalKeyboardKey.select): - const ActivateIntent(), - }, - child: const HomePage(), - ), - ); - }, - ), - ); - } -} + fallbackLocale: \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 43db3e2b3..ae0ac1c0b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,13 @@ environment: dependencies: flutter: sdk: flutter + gettext: ^0.2.0 + easy_gettext: ^0.0.1 + +flutter: + assets: + - lib/l10n/en.po + - lib/l10n/he.po # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. From b0a3322efeb97221677881dae0588f84c41853fd Mon Sep 17 00:00:00 2001 From: "Omer I.S." Date: Tue, 6 Jan 2026 14:53:58 +0200 Subject: [PATCH 2/8] Re-enable online release auto signing --- .github/workflows/release.yml | 47 ++++++++++++++++++++++++----------- README.md | 2 +- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fcc36b2b8..bc88098bf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,4 @@ name: Build and Release -permissions: - contents: write - packages: write on: workflow_dispatch: @@ -9,6 +6,9 @@ on: beta: type: boolean description: Is beta? + draft: + type: boolean + description: Is draft? jobs: build: @@ -18,17 +18,22 @@ jobs: - uses: actions/checkout@v3 - uses: subosito/flutter-action@v2 - with: - channel: stable - uses: actions/setup-java@v4 with: distribution: 'temurin' # See 'Supported distributions' for available options - java-version: '21' + java-version: '17' - name: Flutter Doctor id: flutter_doctor run: | flutter doctor -v + + - name: Import GPG key + id: import_pgp_key + uses: crazy-max/ghaction-import-gpg@v6 + with: + gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }} + passphrase: ${{ secrets.PGP_PASSPHRASE }} - name: Check submodule id: check_submodule @@ -47,18 +52,29 @@ jobs: - name: Build APKs run: | - sed -i 's/signingConfig = signingConfigs.getByName("release")//g' android/app/build.gradle.kts + sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle flutter build apk --flavor normal && flutter build apk --split-per-abi --flavor normal for file in build/app/outputs/flutter-apk/app-*normal*.apk*; do mv "$file" "${file//-normal/}"; done flutter build apk --flavor fdroid -t lib/main_fdroid.dart && flutter build apk --split-per-abi --flavor fdroid -t lib/main_fdroid.dart rm ./build/app/outputs/flutter-apk/*.sha1 - cp ./sign.sh ./build/app/outputs/flutter-apk/ ls -l ./build/app/outputs/flutter-apk/ - - - name: Save Unsigned APKs as Action Artifacts - uses: actions/upload-artifact@v4 - with: - path: build/app/outputs/flutter-apk/* + + - name: Sign APKs + env: + KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} + KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + run: | + echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore + for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do + unsignedFn=${apk/-release/-unsigned} + mv "$apk" "$unsignedFn" + ${ANDROID_HOME}/build-tools/$(ls ${ANDROID_HOME}/build-tools/ | tail -1)/apksigner sign --ks apksign.keystore --ks-pass pass:"${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}" + sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 + gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 + done + rm apksign.keystore + PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" - name: Create Tag uses: mathieudutour/github-tag-action@v6.1 @@ -67,11 +83,12 @@ jobs: custom_tag: "${{ steps.extract_version.outputs.tag }}" tag_prefix: "" - - name: Create Draft Release + - name: Create Release And Upload APKs uses: ncipollo/release-action@v1 with: token: ${{ secrets.GH_ACCESS_TOKEN }} tag: "${{ steps.extract_version.outputs.tag }}" prerelease: "${{ steps.extract_version.outputs.beta }}" - draft: "true" + draft: "${{ inputs.draft }}" + artifacts: ./build/app/outputs/flutter-apk/*-release*.apk* generateReleaseNotes: true diff --git a/README.md b/README.md index 685d6421a..04cdfb9d2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Download Nightly](https://img.shields.io/badge/Download-Nightly-blue?style=for-the-badge&logo=android)](https://github.com/omeritzics/Updatium/releases/tag/nightly-build) (Note: Updatium is still not ready to function as an independant app, this is a work in progress) # ![Updatium Icon](./assets/graphics/icon_small.png) Updatium -Update your Android apps directly from the APK source. Forked from [Obtainium](https://github.com/ImranR98/Obtainium) due to the developer's problematic political views and his terrible behavior towards Jewish people who wanted to contribute to his app. +Update your Android apps directly from the APK source. Forked from [Obtainium](https://github.com/ImranR98/Obtainium) due to the developer's problematic political views and his terrible behaviour towards Jewish people who wanted to contribute to his app. Updatium allows you to install and update apps directly from their releases pages, and receive notifications when new releases are made available. From 5bd3437bc7d31d8ae479dc7cefa94d52b52640f7 Mon Sep 17 00:00:00 2001 From: "Omer I.S." <137101815+omeritzics@users.noreply.github.com> Date: Tue, 6 Jan 2026 14:58:09 +0200 Subject: [PATCH 3/8] Potential fix for code scanning alert no. 6: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/translations.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml index b912c6771..55de391c0 100644 --- a/.github/workflows/translations.yml +++ b/.github/workflows/translations.yml @@ -8,6 +8,9 @@ on: jobs: update-translations: + permissions: + contents: write + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 From 1d508890212353267d85e327a716cbabf96c5a58 Mon Sep 17 00:00:00 2001 From: "Omer I.S." <137101815+omeritzics@users.noreply.github.com> Date: Tue, 6 Jan 2026 15:03:59 +0200 Subject: [PATCH 4/8] Make android/settings.gradle.kts resilient to missing local.properties (CI friendly) --- android/settings.gradle.kts | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index ab39a10a2..32bae7193 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -1,13 +1,30 @@ pluginManagement { val flutterSdkPath = run { val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath + val localPropsFile = file("local.properties") + + val sdkFromProps = if (localPropsFile.exists()) { + localPropsFile.inputStream().use { properties.load(it) } + properties.getProperty("flutter.sdk") + } else null + + // Fallbacks if local.properties is missing or doesn't contain flutter.sdk: + // 1) Environment variable FLUTTER_ROOT + // 2) Environment variable FLUTTER_HOME + // 3) $HOME/flutter + sdkFromProps + ?: System.getenv("FLUTTER_ROOT") + ?: System.getenv("FLUTTER_HOME") + ?: "${System.getProperty("user.home")}/flutter" } - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + val flutterSdkDir = file(flutterSdkPath) + if (flutterSdkDir.exists()) { + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + } else { + // Avoid failing the build; warn and continue (CI builds can set the path separately). + println("Warning: Flutter SDK not found at '$flutterSdkPath'. Skipping includeBuild for flutter_tools.") + } repositories { google() From d22586d20ff8db4fcc6b686e969f6cb2325b37ba Mon Sep 17 00:00:00 2001 From: "Omer I.S." Date: Tue, 6 Jan 2026 15:16:09 +0200 Subject: [PATCH 5/8] Fix PO files --- .github/workflows/translations.yml | 34 +++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml index 55de391c0..9786b5a37 100644 --- a/.github/workflows/translations.yml +++ b/.github/workflows/translations.yml @@ -8,34 +8,48 @@ on: jobs: update-translations: + runs-on: ubuntu-latest + # Grant permission to create a Pull Request permissions: contents: write pull-requests: write - runs-on: ubuntu-latest + steps: - uses: actions/checkout@v3 - name: Install gettext run: sudo apt-get install -y gettext - - name: Extract Strings and Update PO Files + - name: Extract Strings and Update All PO Files run: | mkdir -p assets/translations - # Search for tr('...') or tr("...") in the code + + # 1. Extract strings from tr('...') calls. + # The extracted text becomes the 'msgid' (source text). find lib -name "*.dart" | xgettext -f - \ --from-code=UTF-8 \ --language=Python \ --keyword=tr \ + --no-wrap \ --output=assets/translations/app.pot || touch assets/translations/app.pot - # Sync PO files with the new template - [ -f assets/translations/en.po ] && msgmerge -U assets/translations/en.po assets/translations/app.pot || cp assets/translations/app.pot assets/translations/en.po - [ -f assets/translations/he.po ] && msgmerge -U assets/translations/he.po assets/translations/app.pot || cp assets/translations/app.pot assets/translations/he.po + # 2. Update every language file (.po) found in the assets folder. + # This loop handles all current and future languages automatically. + for po_file in assets/translations/*.po; do + if [ -f "$po_file" ]; then + echo "Merging updates into $po_file..." + msgmerge -U --no-fuzzy-matching "$po_file" assets/translations/app.pot + fi + done - name: Create Pull Request uses: peter-evans/create-pull-request@v5 with: - commit-message: "chore: update translation files" - title: "🌍 Translation Update" - body: "Found new strings via tr() function." - branch: translations-update \ No newline at end of file + commit-message: "chore: auto-update translation files from source" + title: "🌍 Global Translation Update" + body: | + This is an automated PR. + The translation bot scanned the Dart code and updated all `.po` files with new strings found in `tr()` calls. + branch: translations-update-all + base: main + delete-branch: true \ No newline at end of file From 17a02dd414878b2df92ede7bdbaf328988b4eb68 Mon Sep 17 00:00:00 2001 From: "Omer I.S." Date: Tue, 6 Jan 2026 18:01:31 +0200 Subject: [PATCH 6/8] Try fix builds --- .github/workflows/temp.yml | 71 ++++++++++++++++++++++++++++++++ lib/providers/apps_provider.dart | 3 ++ 2 files changed, 74 insertions(+) create mode 100644 .github/workflows/temp.yml diff --git a/.github/workflows/temp.yml b/.github/workflows/temp.yml new file mode 100644 index 000000000..1224e68df --- /dev/null +++ b/.github/workflows/temp.yml @@ -0,0 +1,71 @@ +name: Playing around (temp) + +on: + workflow_dispatch: + inputs: + beta: + type: boolean + description: Is beta? + +jobs: + build: + runs-on: ubuntu-latest + + steps: + + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v2 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '17' + + - name: Flutter Doctor + id: flutter_doctor + run: | + flutter doctor -v + + - name: Check submodule + id: check_submodule + run: | + git checkout ${{ inputs.checkout }} + + - name: Extract Version + id: extract_version + run: | + VERSION=$(grep -oP "^version: [^\+]+" pubspec.yaml | tail -c +10) + echo "version=$VERSION" >> $GITHUB_OUTPUT + if [ ${{ inputs.beta }} == true ]; then BETA=true; else BETA=false; fi + echo "beta=$BETA" >> $GITHUB_OUTPUT + TAG="v$VERSION" + echo "tag=$TAG" >> $GITHUB_OUTPUT + + - name: Build APKs + run: | + sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle + flutter build apk --flavor normal && flutter build apk --split-per-abi --flavor normal + for file in build/app/outputs/flutter-apk/app-*normal*.apk*; do mv "$file" "${file//-normal/}"; done + flutter build apk --flavor fdroid -t lib/main_fdroid.dart && flutter build apk --split-per-abi --flavor fdroid -t lib/main_fdroid.dart + rm ./build/app/outputs/flutter-apk/*.sha1 + ls -l ./build/app/outputs/flutter-apk/ + + - name: Save Unsigned APKs as Action Artifacts + uses: actions/upload-artifact@v4 + with: + path: build/app/outputs/flutter-apk/* + + #- name: Create Tag + # uses: mathieudutour/github-tag-action@v6.1 + # with: + # github_token: ${{ secrets.GH_ACCESS_TOKEN }} + # custom_tag: "${{ steps.extract_version.outputs.tag }}" + # tag_prefix: "" + + #- name: Create Draft Release + # uses: ncipollo/release-action@v1 + # with: + # token: ${{ secrets.GH_ACCESS_TOKEN }} + # tag: "${{ steps.extract_version.outputs.tag }}" + # prerelease: "${{ steps.extract_version.outputs.beta }}" + # draft: "true" + # generateReleaseNotes: true \ No newline at end of file diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 07193c75b..78c922b1d 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1725,6 +1725,8 @@ class AppsProvider with ChangeNotifier { if (settingsProvider.removeOnExternalUninstall) { await removeApps(removedAppIds); } + if (settingsProvider.removeOnExternalUninstall) { + await removeApps(removedAppIds); } } loadingApps = false; @@ -2485,6 +2487,7 @@ Future bgUpdateCheck(String taskId, Map? params) async { int minRetryIntervalForThisApp = err is RateLimitError ? (err.remainingMinutes * 60) : e is ClientException + : err is ClientException ? (15 * 60) : (toCheckApp.value + 1); if (minRetryIntervalForThisApp > maxRetryWaitSeconds) { From a2cebd38669562dfb3f18546dbf5ac2f7e9bc8c9 Mon Sep 17 00:00:00 2001 From: "Omer I.S." Date: Tue, 6 Jan 2026 18:02:41 +0200 Subject: [PATCH 7/8] Try fix building --- lib/app_sources/sourcehut.dart | 17 +++++++++-------- lib/providers/apps_provider.dart | 5 ----- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/app_sources/sourcehut.dart b/lib/app_sources/sourcehut.dart index 5f8437a1d..985eebcdd 100644 --- a/lib/app_sources/sourcehut.dart +++ b/lib/app_sources/sourcehut.dart @@ -86,14 +86,15 @@ class SourceHut extends AppSource { String? releaseDateString = entry.querySelector('pubDate')?.innerHtml; DateTime? releaseDate; try { - releaseDate = releaseDateString != null - ? DateFormat('E, dd MMM yyyy HH:mm:ss Z').parse(releaseDateString) - : null; - releaseDate = releaseDateString != null - ? DateFormat( - 'EEE, dd MMM yyyy HH:mm:ss Z', - ).parse(releaseDateString) - : null; + if (releaseDateString != null) { + try { + releaseDate = DateFormat('E, dd MMM yyyy HH:mm:ss Z') + .parse(releaseDateString); + } catch (_) { + releaseDate = DateFormat('EEE, dd MMM yyyy HH:mm:ss Z') + .parse(releaseDateString); + } + } } catch (e) { // ignore } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 78c922b1d..e43cdddfd 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1721,10 +1721,6 @@ class AppsProvider with ChangeNotifier { } // Delete externally uninstalled Apps if needed if (removedAppIds.isNotEmpty) { - if (removedAppIds.isNotEmpty) { - if (settingsProvider.removeOnExternalUninstall) { - await removeApps(removedAppIds); - } if (settingsProvider.removeOnExternalUninstall) { await removeApps(removedAppIds); } @@ -2487,7 +2483,6 @@ Future bgUpdateCheck(String taskId, Map? params) async { int minRetryIntervalForThisApp = err is RateLimitError ? (err.remainingMinutes * 60) : e is ClientException - : err is ClientException ? (15 * 60) : (toCheckApp.value + 1); if (minRetryIntervalForThisApp > maxRetryWaitSeconds) { From 1904c069998e6fcd354031d954fd0cb98d9afefc Mon Sep 17 00:00:00 2001 From: "Omer I.S." <137101815+omeritzics@users.noreply.github.com> Date: Tue, 6 Jan 2026 18:16:27 +0200 Subject: [PATCH 8/8] Update temp.yml --- .github/workflows/temp.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/temp.yml b/.github/workflows/temp.yml index 1224e68df..a51c898e3 100644 --- a/.github/workflows/temp.yml +++ b/.github/workflows/temp.yml @@ -1,5 +1,8 @@ name: Playing around (temp) +permissions: + contents: write + on: workflow_dispatch: inputs: @@ -68,4 +71,4 @@ jobs: # tag: "${{ steps.extract_version.outputs.tag }}" # prerelease: "${{ steps.extract_version.outputs.beta }}" # draft: "true" - # generateReleaseNotes: true \ No newline at end of file + # generateReleaseNotes: true