diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4bd632..a3f6101 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,6 +2,10 @@ name: Build and Release on: workflow_dispatch: + inputs: + beta: + type: boolean + description: Is beta? jobs: build: @@ -19,6 +23,17 @@ jobs: gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }} passphrase: ${{ secrets.PGP_PASSPHRASE }} + - 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" + if [ $BETA == true ]; then TAG="$TAG"-beta; fi + echo "tag=$TAG" >> $GITHUB_OUTPUT + - name: Build APKs run: | sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle @@ -43,16 +58,6 @@ jobs: done rm apksign.keystore PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" - - - name: Extract Version - id: extract_version - run: | - VERSION=$(grep -oP "currentVersion = '\K[^']+" lib/main.dart) - echo "version=$VERSION" >> $GITHUB_OUTPUT - TAG=$(grep -oP "'.*\\\$currentVersion.*'" lib/main.dart | head -c -2 | tail -c +2 | sed "s/\$currentVersion/$VERSION/g") - echo "tag=$TAG" >> $GITHUB_OUTPUT - if [ -n "$(echo $TAG | grep -oP '\-beta$')" ]; then BETA=true; else BETA=false; fi - echo "beta=$BETA" >> $GITHUB_OUTPUT - name: Create Tag uses: mathieudutour/github-tag-action@v6.1 diff --git a/assets/graphics/badge_obtainium.png b/assets/graphics/badge_obtainium.png new file mode 100644 index 0000000..1fc20ba Binary files /dev/null and b/assets/graphics/badge_obtainium.png differ diff --git a/assets/translations/bs.json b/assets/translations/bs.json index fa1fcba..9dc697d 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -73,6 +73,8 @@ "unpinFromTop": "Otkvači sa vrha", "resetInstallStatusForSelectedAppsQuestion": "Resetujte status instalacije za odabrane aplikacije?", "installStatusOfXWillBeResetExplanation": "Status instalacije bilo koje odabrane aplikacije će se resetovati.\n\nTo može pomoći kada je verzija aplikacije prikazana u Obtainiumu netačna zbog neuspjelih ažuriranja ili drugih problema.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Podijeli odabrane URL-ove aplikacija", "resetInstallStatus": "Resetujte status instalacije", "more": "Više", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku is not running", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index 18b0a67..cd4378c 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -73,6 +73,8 @@ "unpinFromTop": "Odepnout shora", "resetInstallStatusForSelectedAppsQuestion": "Obnovit stav instalace vybraných aplikací?", "installStatusOfXWillBeResetExplanation": "Stav instalace vybraných aplikací bude resetován. To může být užitečné, pokud je verze aplikace zobrazená v Obtainium nesprávná z důvodu neúspěšných aktualizací nebo jiných problémů.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Sdílet adresy URL vybraných aplikací", "resetInstallStatus": "Obnovit stav instalace", "more": "Více", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku neběží", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 3c924b4..a7028c4 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -73,6 +73,8 @@ "unpinFromTop": "„Oben anheften“ aufheben", "resetInstallStatusForSelectedAppsQuestion": "Installationsstatus für ausgewählte Apps zurücksetzen?", "installStatusOfXWillBeResetExplanation": "Der Installationsstatus der ausgewählten Apps wird zurückgesetzt. Dies kann hilfreich sein, wenn die in Obtainium angezeigte App-Version aufgrund fehlgeschlagener Aktualisierungen oder anderer Probleme falsch ist.", + "customLinkMessage": "Diese Links funktionieren auf Geräten, wo Obtainium installiert ist", + "shareAppConfigLinks": "Teile die Appkonfiguration als HTML-Link", "shareSelectedAppURLs": "Ausgewählte App-URLs teilen", "resetInstallStatus": "Installationsstatus zurücksetzen", "more": "Mehr", @@ -286,9 +288,12 @@ "normal": "Normal", "shizuku": "Shizuku", "root": "Root", - "shizukuBinderNotFound": "Shizuku läuft nicht", - "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", - "requestHeader": "Request header", + "shizukuBinderNotFound": "Kompatibler Shizukudienst wurde nicht gefunden", + "useSystemFont": "Verwende die Systemschriftart", + "systemFontError": "Fehler beim Laden der Systemschriftart: {}", + "useVersionCodeAsOSVersion": "Verwende die Appversion als erkannte Version vom Betriebssystem", + "requestHeader": "Request Header", + "useLatestAssetDateAsReleaseDate": "Den letzten Asset-Upload als Veröffentlichungsdatum verwenden", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 7f2daf1..74a25d7 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -73,6 +73,8 @@ "unpinFromTop": "Unpin from top", "resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?", "installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Share Selected App URLs", "resetInstallStatus": "Reset Install Status", "more": "More", @@ -291,6 +293,7 @@ "systemFontError": "Error loading the system font: {}", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index abe6417..b02120a 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -73,6 +73,8 @@ "unpinFromTop": "Desfijar de arriba", "resetInstallStatusForSelectedAppsQuestion": "¿Restuarar estado de instalación para las aplicaciones seleccionadas?", "installStatusOfXWillBeResetExplanation": "El estado de instalación de las aplicaciones seleccionadas será restaurado.\n\nEsto puede ser de útil cuando la versión de la aplicación mostrada en Obtainium es incorrecta por actualizaciones fallidas u otros motivos.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Compartir URLs de las aplicaciones seleccionadas", "resetInstallStatus": "Restaurar Estado de Instalación", "more": "Más", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku no está operativo", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index feea14f..30c9881 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -73,6 +73,8 @@ "unpinFromTop": "برداشتن پین از بالا", "resetInstallStatusForSelectedAppsQuestion": "وضعیت نصب برنامه‌های انتخابی بازنشانی شود؟", "installStatusOfXWillBeResetExplanation": "وضعیت نصب برنامه‌های انتخاب‌شده بازنشانی می‌شود.\n\nاگر نسخه برنامه نشان‌داده‌شده در Obtainium به دلیل به‌روزرسانی‌های ناموفق یا مشکلات دیگر نادرست باشد، می‌تواند کمک کند.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "اشتراک گذاری آدرس اینترنتی برنامه های انتخاب شده", "resetInstallStatus": "بازنشانی وضعیت نصب", "more": "بیشتر", @@ -85,22 +87,22 @@ "author": "سازنده", "upToDateApps": "برنامه های به روز", "nonInstalledApps": "برنامه های نصب نشده", - "importExport": "وادر کردن/صادر کردن", + "importExport": "درون ریزی/برون ریزی", "settings": "تنظیمات", - "exportedTo": "صادر کردن به{}", + "exportedTo": "برون ریزی به{}", "obtainiumExport": "صادرکردن Obtainium", "invalidInput": "ورودی نامعتبر", "importedX": "وارد شده {}", "obtainiumImport": "واردکردن Obtainium", - "importFromURLList": "وارد کردن از فهرست آدرس اینترنتی", + "importFromURLList": "درون ریزی از فهرست آدرس اینترنتی", "searchQuery": "جستجوی سوال", "appURLList": "فهرست آدرس اینترنتی برنامه", "line": "خط", "searchX": "جستجو {}", "noResults": "نتیجه ای پیدا نشد", - "importX": "وارد کردن {}", - "importedAppsIdDisclaimer": "ممکن است برنامه‌های وارد شده به اشتباه به‌عنوان \"نصب نشده\" نشان داده شوند.\nبرای رفع این مشکل، آنها را دوباره از طریق Obtainium نصب کنید.\nاین نباید روی داده‌های برنامه تأثیر بگذارد.\n\nفقط بر روی آدرس اینترنتی و روش‌های وارد کردن شخص ثالث تأثیر می‌گذارد.", - "importErrors": "خطاهای وارد کردن", + "importX": "درون ریزی {}", + "importedAppsIdDisclaimer": "ممکن است برنامه‌های وارد شده به اشتباه به‌عنوان \"نصب نشده\" نشان داده شوند.\nبرای رفع این مشکل، آنها را دوباره از طریق Obtainium نصب کنید.\nاین نباید روی داده‌های برنامه تأثیر بگذارد.\n\nفقط بر روی آدرس اینترنتی و روش‌های درون ریزی شخص ثالث تأثیر می‌گذارد.", + "importErrors": "خطاهای درون ریزی", "importedXOfYApps": "{} از {} برنامه وارد شد.", "followingURLsHadErrors": "آدرس های اینترنتی زیر دارای خطا بودند:", "selectURL": "آدرس اینترنتی انتخاب شده", @@ -133,7 +135,7 @@ "close": "بستن", "share": "اشتراک گذاری", "appNotFound": "برنامه پیدا نشد", - "obtainiumExportHyphenatedLowercase": "صادر کردن-obtainium", + "obtainiumExportHyphenatedLowercase": "برون ریزی-obtainium", "pickAnAPK": "یک APK انتخاب کنید", "appHasMoreThanOnePackage": "{} بیش از یک بسته دارد:", "deviceSupportsXArch": "دستگاه شما از معماری پردازنده {} پشتیبانی میکند", @@ -210,7 +212,7 @@ "releaseDateAsVersionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند، اما تاریخ انتشار در دسترس است.", "changes": "تغییرات", "releaseDate": "تاریخ انتشار", - "importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)", + "importFromURLsInFile": "درون ریزی از آدرس های اینترنتی موجود در فایل (مانند OPML)", "versionDetection": "تشخیص نسخه", "standardVersionDetection": "تشخیص نسخه استاندارد", "groupByCategory": "گروه بر اساس دسته", @@ -235,7 +237,7 @@ "addInfoInSettings": "این اطلاعات را در تنظیمات اضافه کنید.", "githubSourceNote": "با استفاده از کلید API می توان از محدودیت نرخ GitHub جلوگیری کرد.", "gitlabSourceNote": "استخراج APK GitLab ممکن است بدون کلید API کار نکند.", - "sortByLastLinkSegment": "Sort by only the last segment of the link", + "sortByLastLinkSegment": "فقط بر اساس آخرین بخش پیوند مرتب کنید", "filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید", "customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیش‌فرض '.apk$')", "appsPossiblyUpdated": "به‌روزرسانی برنامه انجام شد", @@ -245,25 +247,25 @@ "backgroundUpdateReqsExplanation": "به روز رسانی پس زمینه ممکن است برای همه برنامه ها امکان پذیر نباشد.", "backgroundUpdateLimitsExplanation": "موفقیت نصب پس‌زمینه تنها زمانی مشخص می‌شود که Obtainium باز شود.", "verifyLatestTag": "برچسب \"آخرین\" را تأیید کنید", - "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit", - "filterByLinkText": "Filter links by link text", + "intermediateLinkRegex": "برای بازدید از پیوند «میانگین» فیلتر کنید", + "filterByLinkText": "لینک ها را بر اساس متن پیوند فیلتر کنید", "intermediateLinkNotFound": "لینک میانی پیدا نشد", - "intermediateLink": "Intermediate link", + "intermediateLink": "پیوند میانی", "exemptFromBackgroundUpdates": "معاف از به‌روزرسانی‌های پس‌زمینه (در صورت فعال بودن)", "bgUpdatesOnWiFiOnly": "به‌روزرسانی‌های پس‌زمینه را در صورت عدم اتصال به WiFi غیرفعال کنید", "autoSelectHighestVersionCode": "انتخاب خودکار بالاترین نسخه کد APK", "versionExtractionRegEx": "نسخه استخراج RegEx", "matchGroupToUse": "گروه مورد استفاده را مطابقت دهید", "highlightTouchTargets": "اهداف لمسی کمتر واضح را برجسته کنید", - "pickExportDir": "فهرست صادرات را انتخاب کنید", - "autoExportOnChanges": "صادرات خودکار تغییرات", - "includeSettings": "Include settings", + "pickExportDir": "فهرست برون ریزی را انتخاب کنید", + "autoExportOnChanges": "برون ریزی خودکار تغییرات", + "includeSettings": "شامل تنظیمات", "filterVersionsByRegEx": "فیلتر کردن نسخه ها با RegEx", "trySelectingSuggestedVersionCode": "نسخه پیشنهادی APK نسخه کد را انتخاب کنید", "dontSortReleasesList": "حفظ سفارش انتشار از API", "reverseSort": "مرتب سازی معکوس", - "takeFirstLink": "Take first link", - "skipSort": "Skip sorting", + "takeFirstLink": "لینک اول را بگیرید", + "skipSort": "از مرتب سازی صرف نظر کنید", "debugMenu": "منوی اشکال زدایی", "bgTaskStarted": "کار پس زمینه شروع شد - لاگ های مربوط را بررسی کنید.", "runBgCheckNow": "اکنون به‌روزرسانی پس‌زمینه را بررسی کنید", @@ -281,14 +283,15 @@ "onlyCheckInstalledOrTrackOnlyApps": "فقط برنامه های نصب شده و فقط ردیابی را برای به روز رسانی بررسی کنید", "supportFixedAPKURL": "پشتیبانی از URL های APK ثابت", "selectX": "انتخاب کنید {}", - "parallelDownloads": "Allow parallel downloads", - "installMethod": "Installation method", + "parallelDownloads": "اجازه دانلود موازی", + "installMethod": "روش نصب", "normal": "Normal", "shizuku": "Shizuku", "root": "Root", - "shizukuBinderNotFound": "Shizuku is not running", - "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", - "requestHeader": "Request header", + "shizukuBinderNotFound": "Shizuku در حال اجرا نیست", + "useVersionCodeAsOSVersion": "استفاده کد نسخه برنامه به جای نسخه شناسایی شده توسط سیستم عامل استفاده کنید", + "requestHeader": "درخواست سطر بالایی", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 0a64673..3a3fa7e 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -73,6 +73,8 @@ "unpinFromTop": "Détacher du haut", "resetInstallStatusForSelectedAppsQuestion": "Réinitialiser l'état d'installation des applications sélectionnées ?", "installStatusOfXWillBeResetExplanation": "L'état d'installation de toutes les applications sélectionnées sera réinitialisé.\n\nCela peut aider lorsque la version de l'application affichée dans Obtainium est incorrecte en raison d'échecs de mises à jour ou d'autres problèmes.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Partager les URL d'application sélectionnées", "resetInstallStatus": "Réinitialiser le statut d'installation", "more": "Plus", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku is not running", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index df48201..ecf9bf2 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -73,6 +73,8 @@ "unpinFromTop": "Eltávolít felülről", "resetInstallStatusForSelectedAppsQuestion": "Visszaállítja a kiválasztott appok telepítési állapotát?", "installStatusOfXWillBeResetExplanation": "A kiválasztott appok telepítési állapota visszaáll.\n\nEz akkor segíthet, ha az Obtainiumban megjelenített app verzió hibás, frissítések vagy egyéb problémák miatt.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Ossza meg a kiválasztott app URL címeit", "resetInstallStatus": "Telepítési állapot visszaállítása", "more": "További", @@ -244,10 +246,10 @@ "backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.", "backgroundUpdateLimitsExplanation": "A háttérben történő telepítés sikeressége csak az Obtainium megnyitásakor állapítható meg.", "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", - "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit", - "filterByLinkText": "Filter links by link text", - "intermediateLinkNotFound": "Közvetítő link nem található", - "intermediateLink": "Intermediate link", + "intermediateLinkRegex": "Szűrés egy 'köztes' látogatási linkre", + "filterByLinkText": "A hivatkozások szűrése linkszöveg alapján", + "intermediateLinkNotFound": "Köztes link nem található", + "intermediateLink": "Köztes link", "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", "autoSelectHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", @@ -261,8 +263,8 @@ "trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t", "dontSortReleasesList": "Az API-ból származó kiadási sorrend megőrzése", "reverseSort": "Fordított rendezés", - "takeFirstLink": "Take first link", - "skipSort": "Skip sorting", + "takeFirstLink": "Vegye az első linket", + "skipSort": "A válogatás kihagyása", "debugMenu": "Hibakereső menü", "bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.", "enableBackgroundUpdates": "Frissítések a háttérben", @@ -282,13 +284,14 @@ "supportFixedAPKURL": "Támogatja a rögzített APK URL-eket", "selectX": "Kiválaszt {}", "parallelDownloads": "Párhuzamos letöltéseket enged", - "installMethod": "Installation method", - "normal": "Normal", + "installMethod": "Telepítési mód", + "normal": "Normál", "shizuku": "Shizuku", "root": "Root", - "shizukuBinderNotFound": "Shizuku is not running", - "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", - "requestHeader": "Request header", + "shizukuBinderNotFound": "A Shizuku nem fut", + "useVersionCodeAsOSVersion": "Az app versionCode használata a rendszer által észlelt verzióként", + "requestHeader": "Kérelem fejléc", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" diff --git a/assets/translations/it.json b/assets/translations/it.json index 91dff86..48dfc9b 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -73,6 +73,8 @@ "unpinFromTop": "Rimuovi dall'alto", "resetInstallStatusForSelectedAppsQuestion": "Ripristinare lo stato d'installazione delle app selezionate?", "installStatusOfXWillBeResetExplanation": "Lo stato d'installazione di ogni app selezionata sarà ripristinato.\n\nCiò può essere d'aiuto nel caso in cui la versione mostrata dell'app in Obtainium non sia corretta a causa di un aggiornamento fallito o di altri problemi.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Condividi gli URL delle app selezionate", "resetInstallStatus": "Ripristina lo stato d'installazione", "more": "Altro", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku non è in esecuzione", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 43101c1..0cfbf76 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -73,6 +73,8 @@ "unpinFromTop": "トップから固定解除", "resetInstallStatusForSelectedAppsQuestion": "選択したアプリのインストール状態をリセットしますか?", "installStatusOfXWillBeResetExplanation": "選択したアプリのインストール状態がリセットされます。\n\nアップデートに失敗した場合など、Obtainiumに表示されるアプリのバージョンが正しくない場合に有効です。", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "選択したアプリのURLを共有する", "resetInstallStatus": "インストール状態をリセットする", "more": "もっと見る", @@ -291,6 +293,7 @@ "systemFontError": "システムフォントの読み込みエラー: {}", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/nl.json b/assets/translations/nl.json index 88ae1b4..af5610e 100644 --- a/assets/translations/nl.json +++ b/assets/translations/nl.json @@ -73,6 +73,8 @@ "unpinFromTop": "Losmaken van de bovenkant", "resetInstallStatusForSelectedAppsQuestion": "Installatiestatus resetten voor geselecteerde apps?", "installStatusOfXWillBeResetExplanation": "De installatiestatus van alle geselecteerde apps zal worden gereset.\n\nDit kan helpen wanneer de versie van de app die in Obtainium wordt weergegeven onjuist is vanwege mislukte updates of andere problemen.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Deel geselecteerde app URL's", "resetInstallStatus": "Reset installatiestatus", "more": "Meer", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku is not running", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "App verwijderen?", "other": "Apps verwijderen?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index c602475..574cc79 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -73,6 +73,8 @@ "unpinFromTop": "Odepnij", "resetInstallStatusForSelectedAppsQuestion": "Zresetować status instalacji dla wybranych aplikacji?", "installStatusOfXWillBeResetExplanation": "Stan instalacji wybranych aplikacji zostanie zresetowany.\n\nMoże być to pomocne, gdy wersja aplikacji wyświetlana w Obtainium jest nieprawidłowa z powodu nieudanych aktualizacji lub innych problemów.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Udostępnij wybrane adresy URL aplikacji", "resetInstallStatus": "Zresetuj stan instalacji", "more": "Więcej", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku is not running", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 2fe1cb2..cdb38fe 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -73,6 +73,8 @@ "unpinFromTop": "Desafixar do topo", "resetInstallStatusForSelectedAppsQuestion": "Reiniciar status de instalação para aplicativos selecionados?", "installStatusOfXWillBeResetExplanation": "O status de instalação de qualquer aplicativo selecionado será reiniciado.\n\nIsso pode ajudar quando uma versão de um aplicativo mostrada no Obtainium é incorreta devido a falhas ao atualizar ou outros problemas.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Compartilhar URLs de aplicativos selecionados", "resetInstallStatus": "Reiniciar status de Iistalação", "more": "Mais", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku não está rodando", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Remover aplicativo?", "other": "Remover aplicativos?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index ab25718..dbb281f 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -73,6 +73,8 @@ "unpinFromTop": "Открепить", "resetInstallStatusForSelectedAppsQuestion": "Сбросить статус установки для выбранных приложений?", "installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, некорректная — из-за неудачных обновлений или других проблем", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Поделиться выбранными URL-адресами приложений", "resetInstallStatus": "Сбросить статус установки", "more": "Ещё", @@ -291,6 +293,7 @@ "systemFontError": "Ошибка загрузки системного шрифта: {}", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 6886fdc..9c068c7 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -73,6 +73,8 @@ "unpinFromTop": "Avnåla", "resetInstallStatusForSelectedAppsQuestion": "Återställ Installationsstatus för valda Appar?", "installStatusOfXWillBeResetExplanation": "Installationsstatusen för de markerade apparna kommer återställas.\n\n Detta kan hjälpa när appversionen visad i Obtanium är fel på grund av misslyckade uppdateringar eller andra orsaker.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Dela Valda Appars URL:er", "resetInstallStatus": "Återställ Installationstatus", "more": "Mer", @@ -275,6 +277,7 @@ "shizukuBinderNotFound": "Shizuku is not running", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Ta Bort App?", "other": "Ta Bort Appar?" diff --git a/assets/translations/tr.json b/assets/translations/tr.json index 35f8c16..1b6ba32 100644 --- a/assets/translations/tr.json +++ b/assets/translations/tr.json @@ -73,6 +73,8 @@ "unpinFromTop": "Üstten Kaldır", "resetInstallStatusForSelectedAppsQuestion": "Seçilen Uygulamaların Yükleme Durumunu Sıfırlamak İstiyor musunuz?", "installStatusOfXWillBeResetExplanation": "Seçilen Uygulamaların yükleme durumu sıfırlanacak.\n\nBu, Obtainium'da gösterilen uygulama sürümünün başarısız güncellemeler veya diğer sorunlar nedeniyle yanlış olması durumunda yardımcı olabilir.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Seçilen Uygulama URL'larını Paylaş", "resetInstallStatus": "Yükleme Durumunu Sıfırla", "more": "Daha Fazla", @@ -289,6 +291,7 @@ "shizukuBinderNotFound": "Shizuku is not running", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "Uygulamayı Kaldır?", "other": "Uygulamaları Kaldır?" diff --git a/assets/translations/vi.json b/assets/translations/vi.json index 9d65204..6bbbf1c 100644 --- a/assets/translations/vi.json +++ b/assets/translations/vi.json @@ -73,6 +73,8 @@ "unpinFromTop": "Bỏ ghim khỏi đầu trang", "resetInstallStatusForSelectedAppsQuestion": "Đặt lại trạng thái cài đặt cho ứng dụng đã chọn?", "installStatusOfXWillBeResetExplanation": "Trạng thái cài đặt của mọi Ứng dụng đã chọn sẽ được đặt lại.\n\nĐiều này có thể hữu ích khi phiên bản Ứng dụng hiển thị trong Obtainium không chính xác do cập nhật không thành công hoặc các sự cố khác.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "Chia sẻ URL ứng dụng đã chọn", "resetInstallStatus": "Đặt lại trạng thái cài đặt", "more": "Nhiều hơn", @@ -287,6 +289,7 @@ "shizuku": "Shizuku", "root": "Root", "shizukuBinderNotFound": "Shizuku chưa khởi động", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion":{ "one": "Gỡ ứng dụng?", "other": "Gỡ ứng dụng?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 094c032..07be631 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -73,6 +73,8 @@ "unpinFromTop": "取消置顶", "resetInstallStatusForSelectedAppsQuestion": "是否重置选中应用的安装状态?", "installStatusOfXWillBeResetExplanation": "选中应用的安装状态将会被重置。\n\n当更新安装失败或其他问题导致 Obtainium 中的应用版本显示错误时,可以尝试通过此方法解决。", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", "shareSelectedAppURLs": "分享选中应用的 URL", "resetInstallStatus": "重置安装状态", "more": "更多", @@ -291,6 +293,7 @@ "systemFontError": "加载系统字体出错:{}", "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", + "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 7c0e19d..c08ae5a 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -76,6 +76,10 @@ class GitHub extends AppSource { [ GeneratedFormSwitch('dontSortReleasesList', label: tr('dontSortReleasesList')) + ], + [ + GeneratedFormSwitch('useLatestAssetDateAsReleaseDate', + label: tr('useLatestAssetDateAsReleaseDate'), defaultValue: false) ] ]; @@ -237,6 +241,8 @@ class GitHub extends AppSource { bool verifyLatestTag = additionalSettings['verifyLatestTag'] == true; bool dontSortReleasesList = additionalSettings['dontSortReleasesList'] == true; + bool useLatestAssetDateAsReleaseDate = + additionalSettings['useLatestAssetDateAsReleaseDate'] == true; dynamic latestRelease; if (verifyLatestTag) { var temp = requestUrl.split('?'); @@ -277,10 +283,31 @@ class GitHub extends AppSource { .toList() ?? []; - DateTime? getReleaseDateFromRelease(dynamic rel) => + DateTime? getPublishDateFromRelease(dynamic rel) => rel?['published_at'] != null ? DateTime.parse(rel['published_at']) : null; + DateTime? getNewestAssetDateFromRelease(dynamic rel) { + var t = (rel['assets'] as List?) + ?.map((e) { + return e?['updated_at'] != null + ? DateTime.parse(e['updated_at']) + : null; + }) + .where((e) => e != null) + .toList(); + t?.sort((a, b) => b!.compareTo(a!)); + if (t?.isNotEmpty == true) { + return t!.first; + } + return null; + } + + DateTime? getReleaseDateFromRelease(dynamic rel, bool useAssetDate) => + !useAssetDate + ? getPublishDateFromRelease(rel) + : getNewestAssetDateFromRelease(rel); + if (dontSortReleasesList) { releases = releases.reversed.toList(); } else { @@ -305,8 +332,12 @@ class GitHub extends AppSource { (nameA as String).substring(matchA!.start, matchA.end), (nameB as String).substring(matchB!.start, matchB.end)); } else { - return (getReleaseDateFromRelease(a) ?? DateTime(1)) - .compareTo(getReleaseDateFromRelease(b) ?? DateTime(0)); + return (getReleaseDateFromRelease( + a, useLatestAssetDateAsReleaseDate) ?? + DateTime(1)) + .compareTo(getReleaseDateFromRelease( + b, useLatestAssetDateAsReleaseDate) ?? + DateTime(0)); } } }); @@ -366,7 +397,8 @@ class GitHub extends AppSource { throw NoReleasesError(); } String? version = targetRelease['tag_name'] ?? targetRelease['name']; - DateTime? releaseDate = getReleaseDateFromRelease(targetRelease); + DateTime? releaseDate = getReleaseDateFromRelease( + targetRelease, useLatestAssetDateAsReleaseDate); if (version == null) { throw NoVersionError(); } diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 1e8b1e9..106be54 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -149,6 +149,7 @@ class HTML extends AppSource { [ GeneratedFormTextField('requestHeader', label: tr('requestHeader'), + required: false, additionalValidators: [ (value) { if ((value ?? 'empty:valid') @@ -301,16 +302,15 @@ class HTML extends AppSource { } var rel = links.last.key; String? version; - if (additionalSettings['supportFixedAPKURL'] != true) { - version = rel.hashCode.toString(); - } version = extractVersion( additionalSettings['versionExtractionRegEx'] as String?, additionalSettings['matchGroupToUse'] as String?, additionalSettings['versionExtractWholePage'] == true ? res.body.split('\r\n').join('\n').split('\n').join('\\n') : rel); - version ??= (await checkDownloadHash(rel)).toString(); + version ??= additionalSettings['supportFixedAPKURL'] != true + ? rel.hashCode.toString() + : (await checkDownloadHash(rel)).toString(); return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(), AppNames(uri.host, tr('app'))); } diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index 5ac21f8..8c36b3f 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -13,6 +13,7 @@ abstract class GeneratedFormItem { late dynamic defaultValue; List additionalValidators; dynamic ensureType(dynamic val); + GeneratedFormItem clone(); GeneratedFormItem(this.key, {this.label = 'Input', @@ -44,6 +45,20 @@ class GeneratedFormTextField extends GeneratedFormItem { String ensureType(val) { return val.toString(); } + + @override + GeneratedFormTextField clone() { + return GeneratedFormTextField(key, + label: label, + belowWidgets: belowWidgets, + defaultValue: defaultValue, + additionalValidators: List.from(additionalValidators), + required: required, + max: max, + hint: hint, + password: password, + textInputType: textInputType); + } } class GeneratedFormDropdown extends GeneratedFormItem { @@ -64,6 +79,20 @@ class GeneratedFormDropdown extends GeneratedFormItem { String ensureType(val) { return val.toString(); } + + @override + GeneratedFormDropdown clone() { + return GeneratedFormDropdown( + key, + opts?.map((e) => MapEntry(e.key, e.value)).toList(), + label: label, + belowWidgets: belowWidgets, + defaultValue: defaultValue, + disabledOptKeys: + disabledOptKeys != null ? List.from(disabledOptKeys!) : null, + additionalValidators: List.from(additionalValidators), + ); + } } class GeneratedFormSwitch extends GeneratedFormItem { @@ -79,6 +108,15 @@ class GeneratedFormSwitch extends GeneratedFormItem { bool ensureType(val) { return val == true || val == 'true'; } + + @override + GeneratedFormSwitch clone() { + return GeneratedFormSwitch(key, + label: label, + belowWidgets: belowWidgets, + defaultValue: defaultValue, + additionalValidators: List.from(additionalValidators)); + } } class GeneratedFormTagInput extends GeneratedFormItem { @@ -103,6 +141,20 @@ class GeneratedFormTagInput extends GeneratedFormItem { Map> ensureType(val) { return val is Map> ? val : {}; } + + @override + GeneratedFormTagInput clone() { + return GeneratedFormTagInput(key, + label: label, + belowWidgets: belowWidgets, + defaultValue: defaultValue, + additionalValidators: List.from(additionalValidators), + deleteConfirmationMessage: deleteConfirmationMessage, + singleSelect: singleSelect, + alignment: alignment, + emptyMessage: emptyMessage, + showLabelWhenNotEmpty: showLabelWhenNotEmpty); + } } typedef OnValueChanges = void Function( @@ -119,6 +171,19 @@ class GeneratedForm extends StatefulWidget { State createState() => _GeneratedFormState(); } +List> cloneFormItems( + List> items) { + List> clonedItems = []; + for (var row in items) { + List clonedRow = []; + for (var it in row) { + clonedRow.add(it.clone()); + } + clonedItems.add(clonedRow); + } + return clonedItems; +} + class GeneratedFormSubForm extends GeneratedFormItem { final List> items; @@ -129,6 +194,12 @@ class GeneratedFormSubForm extends GeneratedFormItem { ensureType(val) { return val; // Not easy to validate List> } + + @override + GeneratedFormSubForm clone() { + return GeneratedFormSubForm(key, cloneFormItems(items), + label: label, belowWidgets: belowWidgets, defaultValue: defaultValue); + } } // Generates a color in the HSLuv (Pastel) color space @@ -510,15 +581,12 @@ class _GeneratedFormState extends State { ]); } else if (widget.items[r][e] is GeneratedFormSubForm) { List subformColumn = []; - var formItems = (widget.items[r][e] as GeneratedFormSubForm).items; - var compact = formItems.length == 1 && formItems[0].length == 1; + var compact = (widget.items[r][e] as GeneratedFormSubForm) + .items + .length == + 1 && + (widget.items[r][e] as GeneratedFormSubForm).items[0].length == 1; for (int i = 0; i < values[fieldKey].length; i++) { - var items = formItems - .map((x) => x.map((y) { - y.defaultValue = values[fieldKey]?[i]?[y.key]; - return y; - }).toList()) - .toList(); var internalFormKey = ValueKey(generateRandomNumber( values[fieldKey].length, seed2: i, @@ -537,8 +605,17 @@ class _GeneratedFormState extends State { ), GeneratedForm( key: internalFormKey, - items: items, + items: cloneFormItems( + (widget.items[r][e] as GeneratedFormSubForm).items) + .map((x) => x.map((y) { + y.defaultValue = values[fieldKey]?[i]?[y.key]; + y.key = '${y.key.toString()},$internalFormKey'; + return y; + }).toList()) + .toList(), onValueChanges: (values, valid, isBuilding) { + values = values.map( + (key, value) => MapEntry(key.split(',')[0], value)); if (valid) { this.values[fieldKey]?[i] = values; } diff --git a/lib/main.dart b/lib/main.dart index df577ff..c965ce2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,10 +19,6 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.15.9'; -const String currentReleaseTag = - 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES - List> supportedLocales = const [ MapEntry(Locale('en'), 'English'), MapEntry(Locale('zh'), '简体中文'), @@ -144,6 +140,7 @@ class _ObtainiumState extends State { BackgroundFetchConfig( minimumFetchInterval: 15, stopOnTerminate: false, + startOnBoot: true, enableHeadless: true, requiresBatteryNotLow: false, requiresCharging: false, @@ -174,20 +171,29 @@ class _ObtainiumState extends State { // If this is the first run, ask for notification permissions and add Obtainium to the Apps list Permission.notification.request(); if (!fdroid) { - appsProvider.saveApps([ - App( - obtainiumId, - 'https://github.com/ImranR98/Obtainium', - 'ImranR98', - 'Obtainium', - currentReleaseTag, - currentReleaseTag, - [], - 0, - {'includePrereleases': true}, - null, - false) - ], onlyIfExists: false); + getInstalledInfo(obtainiumId).then((value) { + if (value?.versionName != null) { + appsProvider.saveApps([ + App( + obtainiumId, + obtainiumUrl, + 'ImranR98', + 'Obtainium', + value!.versionName, + value.versionName!, + [], + 0, + { + 'includePrereleases': true, + 'versionDetection': 'standardVersionDetection' + }, + null, + false) + ], onlyIfExists: false); + } + }).catchError((err) { + print(err); + }); } } if (!supportedLocales diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 25f8b72..c5570c0 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -871,20 +873,44 @@ class AppsPageState extends State { onPressed: () { String urls = ''; for (var a in selectedApps) { - urls += 'obtainium://add/${a.url}\n'; + urls += '${a.url}\n'; } urls = urls.substring(0, urls.length - 1); Share.share(urls, - subject: tr('selectedAppURLsFromObtainium')); + subject: + '${tr('obtainium')} - ${tr('appsString')}'); Navigator.of(context).pop(); }, tooltip: tr('shareSelectedAppURLs'), - icon: const Icon(Icons.share), + icon: const Icon(Icons.share_rounded), ), IconButton( - onPressed: resetSelectedAppsInstallStatuses, - tooltip: tr('resetInstallStatus'), - icon: const Icon(Icons.restore_page_outlined), + onPressed: selectedAppIds.isEmpty + ? null + : () { + String urls = + '

${tr('customLinkMessage')}:

\n\n
    \n'; + for (var a in selectedApps) { + urls += + '
  • ${a.name}
  • \n'; + } + urls += + '
\n\n

${tr('about')}

'; + Share.share(urls, + subject: + '${tr('obtainium')} - ${tr('appsString')}'); + }, + tooltip: tr('shareAppConfigLinks'), + icon: const Icon(Icons.ios_share), ), ]), ), diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 071947d..38f6417 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -234,6 +234,20 @@ Future downloadFile( return downloadedFile; } +Future getInstalledInfo(String? packageName, + {bool printErr = true}) async { + if (packageName != null) { + try { + return await pm.getPackageInfo(packageName: packageName); + } catch (e) { + if (printErr) { + print(e); // OK + } + } + } + return null; +} + class AppsProvider with ChangeNotifier { // In memory App state (should always be kept in sync with local storage versions) Map apps = {}; @@ -639,6 +653,7 @@ class AppsProvider with ChangeNotifier { MapEntry? apkUrl; var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == true; if (!trackOnly) { + // ignore: use_build_context_synchronously apkUrl = await confirmApkUrl(apps[id]!.app, context); } if (apkUrl != null) { @@ -775,20 +790,6 @@ class AppsProvider with ChangeNotifier { return appsDir; } - Future getInstalledInfo(String? packageName, - {bool printErr = true}) async { - if (packageName != null) { - try { - return await pm.getPackageInfo(packageName: packageName); - } catch (e) { - if (printErr) { - print(e); // OK - } - } - } - return null; - } - bool isVersionDetectionPossible(AppInMemory? app) { if (app?.app == null) { return false; @@ -917,6 +918,17 @@ class AppsProvider with ChangeNotifier { : false; } + Future updateInstallStatusInMemory(AppInMemory app) async { + apps[app.app.id]?.installedInfo = await getInstalledInfo(app.app.id); + apps[app.app.id]?.icon = + await apps[app.app.id]?.installedInfo?.applicationInfo?.getAppIcon(); + apps[app.app.id]?.app.name = await (apps[app.app.id] + ?.installedInfo + ?.applicationInfo + ?.getAppLabel()) ?? + app.name; + } + Future loadApps({String? singleId}) async { while (loadingApps) { await Future.delayed(const Duration(microseconds: 1)); @@ -965,19 +977,11 @@ class AppsProvider with ChangeNotifier { NotificationsProvider().notify( AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList())); } - - for (var app in apps.values) { - // Get install status and other OS info for each App (slow) - apps[app.app.id]?.installedInfo = await getInstalledInfo(app.app.id); - apps[app.app.id]?.icon = - await apps[app.app.id]?.installedInfo?.applicationInfo?.getAppIcon(); - apps[app.app.id]?.app.name = await (apps[app.app.id] - ?.installedInfo - ?.applicationInfo - ?.getAppLabel()) ?? - app.name; - notifyListeners(); - } + // Get install status and other OS info for each App (slow) + await Future.wait(apps.values.map((app) { + return updateInstallStatusInMemory(app); + })); + notifyListeners(); // Reconcile version differences List modifiedApps = []; for (var app in apps.values) { @@ -1000,7 +1004,6 @@ class AppsProvider with ChangeNotifier { } } } - loadingApps = false; notifyListeners(); } diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index c649fb7..147dfc9 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -16,6 +16,7 @@ import 'package:shared_storage/shared_storage.dart' as saf; String obtainiumTempId = 'imranr98_obtainium_${GitHub().hosts[0]}'; String obtainiumId = 'dev.imranr.obtainium'; +String obtainiumUrl = 'https://github.com/ImranR98/Obtainium'; enum InstallMethodSettings { normal, shizuku, root } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 57ea4dd..c66b1d3 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -276,9 +276,10 @@ class App { json['installedVersion'] == null ? null : json['installedVersion'] as String, - json['latestVersion'] as String, - assumed2DlistToStringMapList(jsonDecode(json['apkUrls'])), - json['preferredApkIndex'] as int, + (json['latestVersion'] ?? tr('unknown')) as String, + assumed2DlistToStringMapList(jsonDecode( + (json['apkUrls'] ?? '[["placeholder", "placeholder"]]'))), + (json['preferredApkIndex'] ?? -1) as int, jsonDecode(json['additionalSettings']) as Map, json['lastUpdateCheck'] == null ? null diff --git a/pubspec.lock b/pubspec.lock index 8743138..aeed1b5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -410,10 +410,10 @@ packages: dependency: transitive description: name: image - sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271" + sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" url: "https://pub.dev" source: hosted - version: "4.1.3" + version: "4.1.4" intl: dependency: transitive description: @@ -530,10 +530,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" path_provider_linux: dependency: transitive description: @@ -682,10 +682,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" + sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.3.5" shared_preferences_linux: dependency: transitive description: @@ -847,10 +847,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: cdb7b6da34483f9b2c9f8b2b29bc468fa7271d92e2021607ca0c4d3bcb04cdd4 + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" url: "https://pub.dev" source: hosted - version: "6.2.3" + version: "6.2.4" url_launcher_linux: dependency: transitive description: @@ -943,10 +943,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "02d8f3ebbc842704b2b662377b3ee11c0f8f1bbaa8eab6398262f40049819160" + sha256: "4d062ad505390ecef1c4bfb6001cd857a51e00912cc9dfb66edb1886a9ebd80c" url: "https://pub.dev" source: hosted - version: "3.10.1" + version: "3.10.2" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 287afec..a4a262b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.15.9+245 # When changing this, update the tag in main() accordingly +version: 0.15.11+247 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0'