mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-14 21:56:44 +02:00
Compare commits
58 Commits
v0.13.22-b
...
v0.13.26-b
Author | SHA1 | Date | |
---|---|---|---|
ce89d456e1 | |||
a0c48fcca6 | |||
d0cba6d6bc | |||
6baf6ccf4b | |||
a2571e61a8 | |||
f61824ff0d | |||
734a1aeb01 | |||
5269aad90d | |||
eaeee188eb | |||
8c850e06ca | |||
0f754a8da8 | |||
81c4d4f393 | |||
5317aee18d | |||
b66eeba3b5 | |||
522ff1ddf7 | |||
7ef9c43ee3 | |||
05ac76e3e9 | |||
4838402797 | |||
0de12c7c07 | |||
0dadd8bffe | |||
75a0cb1189 | |||
a52d936b4d | |||
cfd04dc602 | |||
7622e63975 | |||
3e7172b9d1 | |||
7aa0294447 | |||
5b89c4d293 | |||
3bb991f57f | |||
1dd3aa0e8a | |||
189cecbc37 | |||
9680ba08e9 | |||
dcf5bd37ca | |||
d6a4b0a96d | |||
5f8638d349 | |||
1de274df39 | |||
3df801c54e | |||
d473cb49c5 | |||
2a5118a2cf | |||
347c56da55 | |||
8073723e1f | |||
c8e90a755d | |||
aeb0a5d8ea | |||
09fe7f3ecd | |||
a549411589 | |||
f426b5e118 | |||
12a8ef5e31 | |||
8210279a4c | |||
999d13b80d | |||
0573c0b270 | |||
5a36a7980c | |||
6bf9b5297f | |||
fdc6b0ff00 | |||
73c20a53d2 | |||
16ae8d8e4d | |||
3f8cfae64e | |||
6861a71efb | |||
2a603f410f | |||
6d22788f92 |
@ -18,6 +18,7 @@ Currently supported App sources:
|
|||||||
- [SourceHut](https://git.sr.ht/)
|
- [SourceHut](https://git.sr.ht/)
|
||||||
- [APKMirror](https://apkmirror.com/) (Track-Only)
|
- [APKMirror](https://apkmirror.com/) (Track-Only)
|
||||||
- [APKPure](https://apkpure.com/)
|
- [APKPure](https://apkpure.com/)
|
||||||
|
- [Huawei AppGallery](https://appgallery.huawei.com/)
|
||||||
- Third Party F-Droid Repos
|
- Third Party F-Droid Repos
|
||||||
- Jenkins Jobs
|
- Jenkins Jobs
|
||||||
- [Steam](https://store.steampowered.com/mobile)
|
- [Steam](https://store.steampowered.com/mobile)
|
||||||
|
@ -49,7 +49,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
|
||||||
applicationId "dev.imranr.obtainium"
|
applicationId "dev.imranr.obtainium"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
</application>
|
</application>
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
|
<uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
|
@ -244,6 +244,9 @@
|
|||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Add this info in the Settings.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||||
|
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||||
|
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||||
|
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Želite li ukloniti aplikaciju?",
|
"one": "Želite li ukloniti aplikaciju?",
|
||||||
"other": "Želite li ukloniti aplikacije?"
|
"other": "Želite li ukloniti aplikacije?"
|
||||||
|
@ -229,7 +229,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen",
|
"dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen",
|
||||||
"dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen",
|
"dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen",
|
||||||
"moveNonInstalledAppsToBottom": "Nicht installierte Apps ans Ende der Apps Ansicht verschieben",
|
"moveNonInstalledAppsToBottom": "Nicht installierte Apps ans Ende der Apps Ansicht verschieben",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Aktiviert Suche and Better APK Discovery)",
|
"gitlabPATLabel": "GitLab Personal Access Token\n(Aktiviert Suche und bessere APK Entdeckung)",
|
||||||
"about": "Über",
|
"about": "Über",
|
||||||
"requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)",
|
"requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)",
|
||||||
"checkOnStart": "Überprüfe einmalig beim Start",
|
"checkOnStart": "Überprüfe einmalig beim Start",
|
||||||
@ -240,10 +240,13 @@
|
|||||||
"disablePageTransitions": "Animationen für Seitenübergänge deaktivieren",
|
"disablePageTransitions": "Animationen für Seitenübergänge deaktivieren",
|
||||||
"reversePageTransitions": "Umgekehrte Animationen für Seitenübergänge",
|
"reversePageTransitions": "Umgekehrte Animationen für Seitenübergänge",
|
||||||
"minStarCount": "Minimale Anzahl von Sternen",
|
"minStarCount": "Minimale Anzahl von Sternen",
|
||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "Fügen Sie diese Informationen unten hinzu.",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Fügen Sie diese Info in den Einstellungen hinzu.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "Die GitHub-Ratenbegrenzung kann mit einem API-Schlüssel umgangen werden.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel",
|
||||||
|
"sortByFileNamesNotLinks": "Sortiere nach Dateinamen, anstelle von ganzen Links",
|
||||||
|
"filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern",
|
||||||
|
"customLinkFilterRegex": "Benutzerdefinierter Link Filter nach Regulärem Ausdruck (Standard '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "App entfernen?",
|
"one": "App entfernen?",
|
||||||
"other": "Apps entfernen?"
|
"other": "Apps entfernen?"
|
||||||
|
@ -244,6 +244,9 @@
|
|||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Add this info in the Settings.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||||
|
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||||
|
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||||
|
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Remove App?",
|
"one": "Remove App?",
|
||||||
"other": "Remove Apps?"
|
"other": "Remove Apps?"
|
||||||
|
@ -244,6 +244,9 @@
|
|||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Add this info in the Settings.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||||
|
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||||
|
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||||
|
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "¿Eliminar Aplicación?",
|
"one": "¿Eliminar Aplicación?",
|
||||||
"other": "¿Eliminar Aplicaciones?"
|
"other": "¿Eliminar Aplicaciones?"
|
||||||
|
@ -229,21 +229,24 @@
|
|||||||
"dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید",
|
"dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید",
|
||||||
"dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید",
|
"dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید",
|
||||||
"moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید",
|
"moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید",
|
||||||
"gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو را فعال می کند and Better APK Discovery)",
|
"gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو و کشف بهتر APK را فعال میکند)",
|
||||||
"about": "درباره",
|
"about": "درباره",
|
||||||
"requiresCredentialsInSettings": "این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)",
|
"requiresCredentialsInSettings": "این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)",
|
||||||
"checkOnStart": "بررسی در شروع",
|
"checkOnStart": "بررسی در شروع",
|
||||||
"tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید",
|
"tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید",
|
||||||
"removeOnExternalUninstall": "Automatically remove externally uninstalled Apps",
|
"removeOnExternalUninstall": "حذف خودکار برنامه های حذف نصب شده خارجی",
|
||||||
"pickHighestVersionCode": "Auto-select highest version code APK",
|
"pickHighestVersionCode": "انتخاب خودکار بالاترین کد نسخه APK",
|
||||||
"checkUpdateOnDetailPage": "Check for updates on opening an App detail page",
|
"checkUpdateOnDetailPage": "برای باز کردن صفحه جزئیات برنامه، بهروزرسانیها را بررسی کنید",
|
||||||
"disablePageTransitions": "Disable page transition animations",
|
"disablePageTransitions": "غیرفعال کردن انیمیشن های انتقال صفحه",
|
||||||
"reversePageTransitions": "Reverse page transition animations",
|
"reversePageTransitions": "انیمیشن های انتقال معکوس صفحه",
|
||||||
"minStarCount": "Minimum Star Count",
|
"minStarCount": "حداقل تعداد ستاره",
|
||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "این اطلاعات را در زیر اضافه کنید",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "این اطلاعات را در تنظیمات اضافه کنید.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "با استفاده از کلید API می توان از محدودیت نرخ GitHub جلوگیری کرد.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "استخراج APK GitLab ممکن است بدون کلید API کار نکند.",
|
||||||
|
"sortByFileNamesNotLinks": "مرتب سازی بر اساس نام فایل به جای پیوندهای کامل",
|
||||||
|
"filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید",
|
||||||
|
"customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیشفرض '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "برنامه حذف شود؟",
|
"one": "برنامه حذف شود؟",
|
||||||
"other": "برنامه ها حذف شوند؟"
|
"other": "برنامه ها حذف شوند؟"
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
"addApp": "Ajouter une application",
|
"addApp": "Ajouter une application",
|
||||||
"appSourceURL": "URL de la source de l'application",
|
"appSourceURL": "URL de la source de l'application",
|
||||||
"error": "Erreur",
|
"error": "Erreur",
|
||||||
"add": "Ajoutée",
|
"add": "Ajouter",
|
||||||
"searchSomeSourcesLabel": "Rechercher (certaines sources uniquement)",
|
"searchSomeSourcesLabel": "Rechercher (certaines sources uniquement)",
|
||||||
"search": "Rechercher",
|
"search": "Rechercher",
|
||||||
"additionalOptsFor": "Options supplémentaires pour {}",
|
"additionalOptsFor": "Options supplémentaires pour {}",
|
||||||
@ -244,6 +244,9 @@
|
|||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Add this info in the Settings.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||||
|
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||||
|
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||||
|
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Supprimer l'application ?",
|
"one": "Supprimer l'application ?",
|
||||||
"other": "Supprimer les applications ?"
|
"other": "Supprimer les applications ?"
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
"bgUpdateTaskFinished": "A háttérfrissítés ellenőrzési feladat befejeződött",
|
"bgUpdateTaskFinished": "A háttérfrissítés ellenőrzési feladat befejeződött",
|
||||||
"firstRun": "Ez az Obtainium első futása",
|
"firstRun": "Ez az Obtainium első futása",
|
||||||
"settingUpdateCheckIntervalTo": "A frissítési intervallum beállítása erre: {}",
|
"settingUpdateCheckIntervalTo": "A frissítési intervallum beállítása erre: {}",
|
||||||
"githubPATLabel": "GitHub személyes hozzáférési token (megnöveli a díjkorlátot)",
|
"githubPATLabel": "GitHub Personal Access Token (megnöveli a díjkorlátot)",
|
||||||
"githubPATHint": "A PAT-nak a következő formátumban kell lennie: felhasználónév:token",
|
"githubPATHint": "A PAT-nak a következő formátumban kell lennie: felhasználónév:token",
|
||||||
"githubPATFormat": "felhasználónév:token",
|
"githubPATFormat": "felhasználónév:token",
|
||||||
"includePrereleases": "Tartalmazza az előzetes kiadásokat",
|
"includePrereleases": "Tartalmazza az előzetes kiadásokat",
|
||||||
@ -93,13 +93,13 @@
|
|||||||
"author": "Szerző",
|
"author": "Szerző",
|
||||||
"upToDateApps": "Naprakész appok",
|
"upToDateApps": "Naprakész appok",
|
||||||
"nonInstalledApps": "Nem telepített appok",
|
"nonInstalledApps": "Nem telepített appok",
|
||||||
"importExport": "Import/Export",
|
"importExport": "Importálás/Exportálás",
|
||||||
"settings": "Beállítások",
|
"settings": "Beállítások",
|
||||||
"exportedTo": "Exportálva ide {}",
|
"exportedTo": "Exportálva ide {}",
|
||||||
"obtainiumExport": "Obtainium Export",
|
"obtainiumExport": "Obtainium Adat Exportálás",
|
||||||
"invalidInput": "Hibás bemenet",
|
"invalidInput": "Hibás bemenet",
|
||||||
"importedX": "Importálva innen {}",
|
"importedX": "Importálva innen {}",
|
||||||
"obtainiumImport": "Obtainium Import",
|
"obtainiumImport": "Obtainium Adat Importálás",
|
||||||
"importFromURLList": "Importálás URL listából",
|
"importFromURLList": "Importálás URL listából",
|
||||||
"searchQuery": "Keresési lekérdezés",
|
"searchQuery": "Keresési lekérdezés",
|
||||||
"appURLList": "App URL lista",
|
"appURLList": "App URL lista",
|
||||||
@ -139,11 +139,11 @@
|
|||||||
"appSource": "App forrás",
|
"appSource": "App forrás",
|
||||||
"noLogs": "Nincsenek naplók",
|
"noLogs": "Nincsenek naplók",
|
||||||
"appLogs": "App naplók",
|
"appLogs": "App naplók",
|
||||||
"close": "Bezár",
|
"close": "Bezárás",
|
||||||
"share": "Megoszt",
|
"share": "Megosztás",
|
||||||
"appNotFound": "App nem található",
|
"appNotFound": "App nem található",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
||||||
"pickAnAPK": "Válasszon egy APK-t",
|
"pickAnAPK": "Válasszon egy APK-ot",
|
||||||
"appHasMoreThanOnePackage": "A(z) {} egynél több csomaggal rendelkezik:",
|
"appHasMoreThanOnePackage": "A(z) {} egynél több csomaggal rendelkezik:",
|
||||||
"deviceSupportsXArch": "Eszköze támogatja a {} CPU architektúrát.",
|
"deviceSupportsXArch": "Eszköze támogatja a {} CPU architektúrát.",
|
||||||
"deviceSupportsFollowingArchs": "Az eszköze a következő CPU architektúrákat támogatja:",
|
"deviceSupportsFollowingArchs": "Az eszköze a következő CPU architektúrákat támogatja:",
|
||||||
@ -210,7 +210,7 @@
|
|||||||
"copiedToClipboard": "Másolva a vágólapra",
|
"copiedToClipboard": "Másolva a vágólapra",
|
||||||
"storagePermissionDenied": "Tárhely engedély megtagadva",
|
"storagePermissionDenied": "Tárhely engedély megtagadva",
|
||||||
"selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.",
|
"selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.",
|
||||||
"filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel",
|
"filterAPKsByRegEx": "Az APK-ok szűrése reguláris kifejezéssel",
|
||||||
"removeFromObtainium": "Eltávolítás az Obtainiumból",
|
"removeFromObtainium": "Eltávolítás az Obtainiumból",
|
||||||
"uninstallFromDevice": "Eltávolítás a készülékről",
|
"uninstallFromDevice": "Eltávolítás a készülékről",
|
||||||
"onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.",
|
"onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.",
|
||||||
@ -222,27 +222,30 @@
|
|||||||
"versionDetection": "Verzió érzékelés",
|
"versionDetection": "Verzió érzékelés",
|
||||||
"standardVersionDetection": "Alapért. verzió érzékelés",
|
"standardVersionDetection": "Alapért. verzió érzékelés",
|
||||||
"groupByCategory": "Csoportosítás Kategória alapján",
|
"groupByCategory": "Csoportosítás Kategória alapján",
|
||||||
"autoApkFilterByArch": "Ha lehetséges, próbálja CPU architektúra szerint szűrni az APK-kat",
|
"autoApkFilterByArch": "Ha lehetséges, próbálja CPU architektúra szerint szűrni az APK-okat",
|
||||||
"overrideSource": "Forrás felülbírálása",
|
"overrideSource": "Forrás felülbírálása",
|
||||||
"dontShowAgain": "Ne mutassa ezt újra",
|
"dontShowAgain": "Ne mutassa ezt újra",
|
||||||
"dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést",
|
"dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést",
|
||||||
"dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket",
|
"dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket",
|
||||||
"moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára",
|
"moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést and Better APK Discovery)",
|
"gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést és jobb APK felfedezés)",
|
||||||
"about": "Rólunk",
|
"about": "Rólunk",
|
||||||
"requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)",
|
"requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)",
|
||||||
"checkOnStart": "Egyszer az indításkor",
|
"checkOnStart": "Egyszer az alkalmazás indításakor is",
|
||||||
"tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból",
|
"tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból",
|
||||||
"removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása",
|
"removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása",
|
||||||
"pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása",
|
"pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása",
|
||||||
"checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor",
|
"checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor",
|
||||||
"disablePageTransitions": "Lap áttűnési animációk tiltása",
|
"disablePageTransitions": "Lap áttűnési animációk letiltása",
|
||||||
"reversePageTransitions": "Fordított lap áttűnési animációk",
|
"reversePageTransitions": "Fordított lap áttűnési animációk",
|
||||||
"minStarCount": "Minimális csillag szám",
|
"minStarCount": "Minimális csillag szám",
|
||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "Adja hozzá ezt az infót alább.",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Adja hozzá ezt az infót a Beállításokban.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "A GitHub sebességkorlátozás elkerülhető API-kulcs használatával.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.",
|
||||||
|
"sortByFileNamesNotLinks": "Fájlnevek szerinti elrendezés teljes linkek helyett",
|
||||||
|
"filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel",
|
||||||
|
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Eltávolítja az alkalmazást?",
|
"one": "Eltávolítja az alkalmazást?",
|
||||||
"other": "Eltávolítja az alkalmazást?"
|
"other": "Eltávolítja az alkalmazást?"
|
||||||
@ -285,10 +288,10 @@
|
|||||||
},
|
},
|
||||||
"xAndNMoreUpdatesAvailable": {
|
"xAndNMoreUpdatesAvailable": {
|
||||||
"one": "A(z) {} és 1 további alkalmazás frissítéseket kapott.",
|
"one": "A(z) {} és 1 további alkalmazás frissítéseket kapott.",
|
||||||
"other": "{} és további {} alkalmazás frissítéseket kapott."
|
"other": "{} és {} további alkalmazás frissítéseket kapott."
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesInstalled": {
|
"xAndNMoreUpdatesInstalled": {
|
||||||
"one": "A(z) {} és 1 további alkalmazás frissítve.",
|
"one": "A(z) {} és 1 további alkalmazás frissítve.",
|
||||||
"other": "{} és további {} alkalmazás frissítve."
|
"other": "{} és {} további alkalmazás frissítve."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,6 +244,9 @@
|
|||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Add this info in the Settings.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
||||||
|
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||||
|
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||||
|
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Rimuovere l'app?",
|
"one": "Rimuovere l'app?",
|
||||||
"other": "Rimuovere le app?"
|
"other": "Rimuovere le app?"
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
"githubPATFormat": "ユーザー名:トークン",
|
"githubPATFormat": "ユーザー名:トークン",
|
||||||
"includePrereleases": "プレリリースを含む",
|
"includePrereleases": "プレリリースを含む",
|
||||||
"fallbackToOlderReleases": "旧リリースへのフォールバック",
|
"fallbackToOlderReleases": "旧リリースへのフォールバック",
|
||||||
"filterReleaseTitlesByRegEx": "正規表現でリリースタイトルを絞り込む",
|
"filterReleaseTitlesByRegEx": "正規表現でリリースタイトルをフィルタリングする",
|
||||||
"invalidRegEx": "無効な正規表現",
|
"invalidRegEx": "無効な正規表現",
|
||||||
"noDescription": "説明はありません",
|
"noDescription": "説明はありません",
|
||||||
"cancel": "キャンセル",
|
"cancel": "キャンセル",
|
||||||
@ -88,7 +88,7 @@
|
|||||||
"showOutdatedOnly": "アップデートが存在するアプリのみ表示する",
|
"showOutdatedOnly": "アップデートが存在するアプリのみ表示する",
|
||||||
"filter": "フィルター",
|
"filter": "フィルター",
|
||||||
"filterActive": "フィルター *",
|
"filterActive": "フィルター *",
|
||||||
"filterApps": "アプリを絞り込む",
|
"filterApps": "アプリをフィルタリングする",
|
||||||
"appName": "アプリ名",
|
"appName": "アプリ名",
|
||||||
"author": "作者",
|
"author": "作者",
|
||||||
"upToDateApps": "最新のアプリ",
|
"upToDateApps": "最新のアプリ",
|
||||||
@ -211,7 +211,7 @@
|
|||||||
"copiedToClipboard": "クリップボードにコピーしました",
|
"copiedToClipboard": "クリップボードにコピーしました",
|
||||||
"storagePermissionDenied": "ストレージ権限が拒否されました",
|
"storagePermissionDenied": "ストレージ権限が拒否されました",
|
||||||
"selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。",
|
"selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。",
|
||||||
"filterAPKsByRegEx": "正規表現でAPKを絞り込む",
|
"filterAPKsByRegEx": "正規表現でAPKをフィルタリングする",
|
||||||
"removeFromObtainium": "Obtainiumから削除する",
|
"removeFromObtainium": "Obtainiumから削除する",
|
||||||
"uninstallFromDevice": "デバイスからアンインストールする",
|
"uninstallFromDevice": "デバイスからアンインストールする",
|
||||||
"onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。",
|
"onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。",
|
||||||
@ -239,11 +239,14 @@
|
|||||||
"checkUpdateOnDetailPage": "アプリの詳細ページを開く際にアップデートを確認する",
|
"checkUpdateOnDetailPage": "アプリの詳細ページを開く際にアップデートを確認する",
|
||||||
"disablePageTransitions": "ページ遷移アニメーションを無効化する",
|
"disablePageTransitions": "ページ遷移アニメーションを無効化する",
|
||||||
"reversePageTransitions": "ページ遷移アニメーションを反転する",
|
"reversePageTransitions": "ページ遷移アニメーションを反転する",
|
||||||
"minStarCount": "Minimum Star Count",
|
"minStarCount": "最小スター数",
|
||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "下部でこの情報を追加してください。",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "設定でこの情報を追加してください。",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。",
|
||||||
|
"sortByFileNamesNotLinks": "フルのリンクではなくファイル名でソートする",
|
||||||
|
"filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする",
|
||||||
|
"customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "アプリを削除しますか?",
|
"one": "アプリを削除しますか?",
|
||||||
"other": "アプリを削除しますか?"
|
"other": "アプリを削除しますか?"
|
||||||
|
@ -244,10 +244,13 @@
|
|||||||
"disablePageTransitions": "Wyłącz animacje przejścia między stronami",
|
"disablePageTransitions": "Wyłącz animacje przejścia między stronami",
|
||||||
"reversePageTransitions": "Odwróć animacje przejścia pomiędzy stronami",
|
"reversePageTransitions": "Odwróć animacje przejścia pomiędzy stronami",
|
||||||
"minStarCount": "Minimalna ilość gwiazdek",
|
"minStarCount": "Minimalna ilość gwiazdek",
|
||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "Dodaj tę informację poniżej.",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Dodaj tę informację w Ustawieniach.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.",
|
||||||
|
"sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków",
|
||||||
|
"filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego",
|
||||||
|
"customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Usunąć aplikację?",
|
"one": "Usunąć aplikację?",
|
||||||
"other": "Usunąć aplikacje?"
|
"other": "Usunąć aplikacje?"
|
||||||
|
@ -240,10 +240,13 @@
|
|||||||
"disablePageTransitions": "Отключить анимацию перехода между страницами",
|
"disablePageTransitions": "Отключить анимацию перехода между страницами",
|
||||||
"reversePageTransitions": "Реверс анимации перехода между страницами",
|
"reversePageTransitions": "Реверс анимации перехода между страницами",
|
||||||
"minStarCount": "Минимальное количество звёзд",
|
"minStarCount": "Минимальное количество звёзд",
|
||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "Добавьте эту информацию ниже.",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Добавьте эту информацию в Настройки.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "Лимит запросов GitHub можно обойти, используя ключ API.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.",
|
||||||
|
"sortByFileNamesNotLinks": "Sort by file names instead of full links",
|
||||||
|
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||||
|
"customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Удалить приложение?",
|
"one": "Удалить приложение?",
|
||||||
"other": "Удалить приложения?"
|
"other": "Удалить приложения?"
|
||||||
|
@ -107,7 +107,7 @@
|
|||||||
"searchX": "搜索 {}",
|
"searchX": "搜索 {}",
|
||||||
"noResults": "无结果",
|
"noResults": "无结果",
|
||||||
"importX": "导入 {}",
|
"importX": "导入 {}",
|
||||||
"importedAppsIdDisclaimer": "导入的应用可能错误地显示为“未安装”。\n请通过 Obtainium 重新安装这些应用来解决此问题。",
|
"importedAppsIdDisclaimer": "导入的应用可能会错误地显示为“未安装”状态。\n请通过 Obtainium 重新安装这些应用来解决此问题。",
|
||||||
"importErrors": "导入错误",
|
"importErrors": "导入错误",
|
||||||
"importedXOfYApps": "已导入 {} 中的 {} 个应用。",
|
"importedXOfYApps": "已导入 {} 中的 {} 个应用。",
|
||||||
"followingURLsHadErrors": "下列 URL 存在错误:",
|
"followingURLsHadErrors": "下列 URL 存在错误:",
|
||||||
@ -229,7 +229,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "不显示“仅追踪”模式警告",
|
"dontShowTrackOnlyWarnings": "不显示“仅追踪”模式警告",
|
||||||
"dontShowAPKOriginWarnings": "不显示 APK 文件来源警告",
|
"dontShowAPKOriginWarnings": "不显示 APK 文件来源警告",
|
||||||
"moveNonInstalledAppsToBottom": "将未安装应用置底",
|
"moveNonInstalledAppsToBottom": "将未安装应用置底",
|
||||||
"gitlabPATLabel": "GitLab 个人访问令牌\n(用于搜索应用 and Better APK Discovery)",
|
"gitlabPATLabel": "GitLab 个人访问令牌\n(启用搜索功能并增强 APK 发现)",
|
||||||
"about": "相关文档",
|
"about": "相关文档",
|
||||||
"requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)",
|
"requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)",
|
||||||
"checkOnStart": "启动时进行一次检查",
|
"checkOnStart": "启动时进行一次检查",
|
||||||
@ -240,10 +240,13 @@
|
|||||||
"disablePageTransitions": "禁用页面过渡动画效果",
|
"disablePageTransitions": "禁用页面过渡动画效果",
|
||||||
"reversePageTransitions": "反转页面过渡动画效果",
|
"reversePageTransitions": "反转页面过渡动画效果",
|
||||||
"minStarCount": "最小星标数",
|
"minStarCount": "最小星标数",
|
||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "在下方添加此凭据。",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "在“设置”中添加此凭据。",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
"gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。",
|
||||||
|
"sortByFileNamesNotLinks": "根据文件名而不是完整链接来排序",
|
||||||
|
"filterReleaseNotesByRegEx": "用正则表达式筛选发布说明",
|
||||||
|
"customLinkFilterRegex": "用正则表达式自定义链接筛选(默认 '.apk$')",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "是否删除应用?",
|
"one": "是否删除应用?",
|
||||||
"other": "是否删除应用?"
|
"other": "是否删除应用?"
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:obtainium/app_sources/github.dart';
|
import 'package:obtainium/app_sources/github.dart';
|
||||||
import 'package:obtainium/components/generated_form.dart';
|
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
@ -9,26 +7,8 @@ class Codeberg extends AppSource {
|
|||||||
Codeberg() {
|
Codeberg() {
|
||||||
host = 'codeberg.org';
|
host = 'codeberg.org';
|
||||||
|
|
||||||
additionalSourceAppSpecificSettingFormItems = [
|
additionalSourceAppSpecificSettingFormItems =
|
||||||
[
|
gh.additionalSourceAppSpecificSettingFormItems;
|
||||||
GeneratedFormSwitch('includePrereleases',
|
|
||||||
label: tr('includePrereleases'), defaultValue: false)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
GeneratedFormSwitch('fallbackToOlderReleases',
|
|
||||||
label: tr('fallbackToOlderReleases'), defaultValue: true)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
GeneratedFormTextField('filterReleaseTitlesByRegEx',
|
|
||||||
label: tr('filterReleaseTitlesByRegEx'),
|
|
||||||
required: false,
|
|
||||||
additionalValidators: [
|
|
||||||
(value) {
|
|
||||||
return regExValidator(value);
|
|
||||||
}
|
|
||||||
])
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
canSearch = true;
|
canSearch = true;
|
||||||
searchQuerySettingFormItems = gh.searchQuerySettingFormItems;
|
searchQuerySettingFormItems = gh.searchQuerySettingFormItems;
|
||||||
|
@ -75,6 +75,16 @@ class GitHub extends AppSource {
|
|||||||
return regExValidator(value);
|
return regExValidator(value);
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
],
|
||||||
|
[
|
||||||
|
GeneratedFormTextField('filterReleaseNotesByRegEx',
|
||||||
|
label: tr('filterReleaseNotesByRegEx'),
|
||||||
|
required: false,
|
||||||
|
additionalValidators: [
|
||||||
|
(value) {
|
||||||
|
return regExValidator(value);
|
||||||
|
}
|
||||||
|
])
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -196,6 +206,12 @@ class GitHub extends AppSource {
|
|||||||
true
|
true
|
||||||
? additionalSettings['filterReleaseTitlesByRegEx']
|
? additionalSettings['filterReleaseTitlesByRegEx']
|
||||||
: null;
|
: null;
|
||||||
|
String? regexNotesFilter =
|
||||||
|
(additionalSettings['filterReleaseNotesByRegEx'] as String?)
|
||||||
|
?.isNotEmpty ==
|
||||||
|
true
|
||||||
|
? additionalSettings['filterReleaseNotesByRegEx']
|
||||||
|
: null;
|
||||||
Response res = await sourceRequest(requestUrl);
|
Response res = await sourceRequest(requestUrl);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var releases = jsonDecode(res.body) as List<dynamic>;
|
var releases = jsonDecode(res.body) as List<dynamic>;
|
||||||
@ -264,6 +280,11 @@ class GitHub extends AppSource {
|
|||||||
!RegExp(regexFilter).hasMatch(nameToFilter.trim())) {
|
!RegExp(regexFilter).hasMatch(nameToFilter.trim())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (regexNotesFilter != null &&
|
||||||
|
!RegExp(regexNotesFilter)
|
||||||
|
.hasMatch(((releases[i]['body'] as String?) ?? '').trim())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var apkUrls = getReleaseAPKUrls(releases[i]);
|
var apkUrls = getReleaseAPKUrls(releases[i]);
|
||||||
if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
|
if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
import 'package:obtainium/components/generated_form.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
@ -85,11 +86,31 @@ bool _isNumeric(String s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class HTML extends AppSource {
|
class HTML extends AppSource {
|
||||||
|
HTML() {
|
||||||
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
|
[
|
||||||
|
GeneratedFormSwitch('sortByFileNamesNotLinks',
|
||||||
|
label: tr('sortByFileNamesNotLinks'))
|
||||||
|
],
|
||||||
|
[
|
||||||
|
GeneratedFormTextField('customLinkFilterRegex',
|
||||||
|
label: tr('customLinkFilterRegex'),
|
||||||
|
hint: 'download/(.*/)?(android|apk|mobile)',
|
||||||
|
required: false,
|
||||||
|
additionalValidators: [
|
||||||
|
(value) {
|
||||||
|
return regExValidator(value);
|
||||||
|
}
|
||||||
|
])
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
// TODO: implement requestHeaders choice, hardcoded for now
|
// TODO: implement requestHeaders choice, hardcoded for now
|
||||||
Map<String, String>? get requestHeaders => {
|
Map<String, String>? get requestHeaders => {
|
||||||
"User-Agent":
|
"User-Agent":
|
||||||
"Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0"
|
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"
|
||||||
};
|
};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -105,14 +126,29 @@ class HTML extends AppSource {
|
|||||||
var uri = Uri.parse(standardUrl);
|
var uri = Uri.parse(standardUrl);
|
||||||
Response res = await sourceRequest(standardUrl);
|
Response res = await sourceRequest(standardUrl);
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
List<String> links = parse(res.body)
|
var html = parse(res.body);
|
||||||
|
List<String> allLinks = html
|
||||||
.querySelectorAll('a')
|
.querySelectorAll('a')
|
||||||
.map((element) => element.attributes['href'] ?? '')
|
.map((element) => element.attributes['href'] ?? '')
|
||||||
.where((element) =>
|
|
||||||
Uri.parse(element).path.toLowerCase().endsWith('.apk'))
|
|
||||||
.toList();
|
.toList();
|
||||||
links.sort((a, b) => compareAlphaNumeric(a, b));
|
List<String> links = [];
|
||||||
if (additionalSettings['apkFilterRegEx'] != null) {
|
if ((additionalSettings['customLinkFilterRegex'] as String?)
|
||||||
|
?.isNotEmpty ==
|
||||||
|
true) {
|
||||||
|
var reg = RegExp(additionalSettings['customLinkFilterRegex']);
|
||||||
|
links = allLinks.where((element) => reg.hasMatch(element)).toList();
|
||||||
|
} else {
|
||||||
|
links = allLinks
|
||||||
|
.where((element) =>
|
||||||
|
Uri.parse(element).path.toLowerCase().endsWith('.apk'))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
links.sort((a, b) => additionalSettings['sortByFileNamesNotLinks'] == true
|
||||||
|
? compareAlphaNumeric(a.split('/').where((e) => e.isNotEmpty).last,
|
||||||
|
b.split('/').where((e) => e.isNotEmpty).last)
|
||||||
|
: compareAlphaNumeric(a, b));
|
||||||
|
if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty ==
|
||||||
|
true) {
|
||||||
var reg = RegExp(additionalSettings['apkFilterRegEx']);
|
var reg = RegExp(additionalSettings['apkFilterRegEx']);
|
||||||
links = links.where((element) => reg.hasMatch(element)).toList();
|
links = links.where((element) => reg.hasMatch(element)).toList();
|
||||||
}
|
}
|
||||||
|
90
lib/app_sources/huaweiappgallery.dart
Normal file
90
lib/app_sources/huaweiappgallery.dart
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:http/http.dart';
|
||||||
|
import 'package:obtainium/custom_errors.dart';
|
||||||
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
|
class HuaweiAppGallery extends AppSource {
|
||||||
|
HuaweiAppGallery() {
|
||||||
|
name = 'Huawei AppGallery';
|
||||||
|
host = 'appgallery.huawei.com';
|
||||||
|
overrideVersionDetectionFormDefault('releaseDateAsVersion', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
|
RegExp standardUrlRegEx = RegExp('^https?://$host/app/[^/]+');
|
||||||
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase());
|
||||||
|
if (match == null) {
|
||||||
|
throw InvalidURLError(name);
|
||||||
|
}
|
||||||
|
return url.substring(0, match.end);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDlUrl(String standardUrl) =>
|
||||||
|
'https://${host!.replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}';
|
||||||
|
|
||||||
|
requestAppdlRedirect(String dlUrl) async {
|
||||||
|
Response res = await sourceRequest(dlUrl, followRedirects: false);
|
||||||
|
if (res.statusCode == 200 ||
|
||||||
|
res.statusCode == 302 ||
|
||||||
|
res.statusCode == 304) {
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
throw getObtainiumHttpError(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appIdFromRedirectDlUrl(String redirectDlUrl) {
|
||||||
|
var parts = redirectDlUrl
|
||||||
|
.split('?')[0]
|
||||||
|
.split('/')
|
||||||
|
.last
|
||||||
|
.split('.')
|
||||||
|
.reversed
|
||||||
|
.toList();
|
||||||
|
parts.removeAt(0);
|
||||||
|
parts.removeAt(0);
|
||||||
|
return parts.reversed.join('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> tryInferringAppId(String standardUrl,
|
||||||
|
{Map<String, dynamic> additionalSettings = const {}}) async {
|
||||||
|
String dlUrl = getDlUrl(standardUrl);
|
||||||
|
Response res = await requestAppdlRedirect(dlUrl);
|
||||||
|
return res.headers['location'] != null
|
||||||
|
? appIdFromRedirectDlUrl(res.headers['location']!)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
|
String standardUrl,
|
||||||
|
Map<String, dynamic> additionalSettings,
|
||||||
|
) async {
|
||||||
|
String dlUrl = getDlUrl(standardUrl);
|
||||||
|
Response res = await requestAppdlRedirect(dlUrl);
|
||||||
|
if (res.headers['location'] == null) {
|
||||||
|
throw NoReleasesError();
|
||||||
|
}
|
||||||
|
String appId = appIdFromRedirectDlUrl(res.headers['location']!);
|
||||||
|
var relDateStr =
|
||||||
|
res.headers['location']?.split('?')[0].split('.').reversed.toList()[1];
|
||||||
|
var relDateStrAdj = relDateStr?.split('');
|
||||||
|
var tempLen = relDateStrAdj?.length ?? 0;
|
||||||
|
var i = 2;
|
||||||
|
while (i < tempLen) {
|
||||||
|
relDateStrAdj?.insert((i + i ~/ 2 - 1), '-');
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
var relDate = relDateStrAdj == null
|
||||||
|
? null
|
||||||
|
: DateFormat('yy-MM-dd-HH-mm').parse(relDateStrAdj.join(''));
|
||||||
|
if (relDateStr == null) {
|
||||||
|
throw NoVersionError();
|
||||||
|
}
|
||||||
|
return APKDetails(
|
||||||
|
relDateStr, [MapEntry('$appId.apk', dlUrl)], AppNames(name, appId),
|
||||||
|
releaseDate: relDate);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:html/parser.dart';
|
import 'package:html/parser.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
import 'package:obtainium/app_sources/html.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/providers/source_provider.dart';
|
import 'package:obtainium/providers/source_provider.dart';
|
||||||
|
|
||||||
@ -7,54 +8,73 @@ class VLC extends AppSource {
|
|||||||
VLC() {
|
VLC() {
|
||||||
host = 'videolan.org';
|
host = 'videolan.org';
|
||||||
}
|
}
|
||||||
|
get dwUrlBase => 'https://get.$host/vlc-android/';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, String>? get requestHeaders => HTML().requestHeaders;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url) {
|
String sourceSpecificStandardizeURL(String url) {
|
||||||
return 'https://$host';
|
return 'https://$host';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<String?> getLatestVersion(String standardUrl) async {
|
||||||
|
Response res = await sourceRequest(dwUrlBase);
|
||||||
|
if (res.statusCode == 200) {
|
||||||
|
var dwLinks = parse(res.body)
|
||||||
|
.querySelectorAll('a')
|
||||||
|
.where((element) => element.attributes['href'] != 'last/')
|
||||||
|
.map((e) => e.attributes['href']?.split('/')[0])
|
||||||
|
.toList();
|
||||||
|
String? version = dwLinks.isNotEmpty ? dwLinks.last : null;
|
||||||
|
if (version == null) {
|
||||||
|
throw NoVersionError();
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
} else {
|
||||||
|
throw getObtainiumHttpError(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
Response res = await sourceRequest(
|
String? version = await getLatestVersion(standardUrl);
|
||||||
'https://www.videolan.org/vlc/download-android.html');
|
if (version == null) {
|
||||||
|
throw NoVersionError();
|
||||||
|
}
|
||||||
|
String? targetUrl = '$dwUrlBase$version/';
|
||||||
|
Response res = await sourceRequest(targetUrl);
|
||||||
|
List<String> apkUrls = [];
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var dwUrlBase = 'get.videolan.org/vlc-android';
|
apkUrls = parse(res.body)
|
||||||
var dwLinks = parse(res.body)
|
|
||||||
.querySelectorAll('a')
|
.querySelectorAll('a')
|
||||||
.where((element) =>
|
.map((e) => e.attributes['href']?.split('/').last)
|
||||||
element.attributes['href']?.contains(dwUrlBase) ?? false)
|
.where((h) =>
|
||||||
|
h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk'))
|
||||||
|
.map((e) => targetUrl + e!)
|
||||||
.toList();
|
.toList();
|
||||||
String? version = dwLinks.isNotEmpty
|
} else {
|
||||||
? dwLinks.first.attributes['href']
|
throw getObtainiumHttpError(res);
|
||||||
?.split('/')
|
}
|
||||||
.where((s) => s.isNotEmpty)
|
|
||||||
.last
|
|
||||||
: null;
|
|
||||||
if (version == null) {
|
|
||||||
throw NoVersionError();
|
|
||||||
}
|
|
||||||
String? targetUrl = 'https://$dwUrlBase/$version/';
|
|
||||||
Response res2 = await sourceRequest(targetUrl);
|
|
||||||
String mirrorDwBase =
|
|
||||||
'https://plug-mirror.rcac.purdue.edu/vlc/vlc-android/$version/';
|
|
||||||
List<String> apkUrls = [];
|
|
||||||
if (res2.statusCode == 200) {
|
|
||||||
apkUrls = parse(res2.body)
|
|
||||||
.querySelectorAll('a')
|
|
||||||
.map((e) => e.attributes['href'])
|
|
||||||
.where((h) =>
|
|
||||||
h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk'))
|
|
||||||
.map((e) => mirrorDwBase + e!)
|
|
||||||
.toList();
|
|
||||||
} else {
|
|
||||||
throw getObtainiumHttpError(res2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return APKDetails(
|
return APKDetails(
|
||||||
version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC'));
|
version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC'));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> apkUrlPrefetchModifier(
|
||||||
|
String apkUrl, String standardUrl) async {
|
||||||
|
Response res = await sourceRequest(apkUrl);
|
||||||
|
if (res.statusCode == 200) {
|
||||||
|
String? apkUrl =
|
||||||
|
parse(res.body).querySelector('#alt_link')?.attributes['href'];
|
||||||
|
if (apkUrl == null) {
|
||||||
|
throw NoAPKError();
|
||||||
|
}
|
||||||
|
return apkUrl;
|
||||||
} else {
|
} else {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,8 @@ class GeneratedFormModal extends StatefulWidget {
|
|||||||
this.initValid = false,
|
this.initValid = false,
|
||||||
this.message = '',
|
this.message = '',
|
||||||
this.additionalWidgets = const [],
|
this.additionalWidgets = const [],
|
||||||
this.singleNullReturnButton});
|
this.singleNullReturnButton,
|
||||||
|
this.primaryActionColour});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final String message;
|
final String message;
|
||||||
@ -19,6 +20,7 @@ class GeneratedFormModal extends StatefulWidget {
|
|||||||
final bool initValid;
|
final bool initValid;
|
||||||
final List<Widget> additionalWidgets;
|
final List<Widget> additionalWidgets;
|
||||||
final String? singleNullReturnButton;
|
final String? singleNullReturnButton;
|
||||||
|
final Color? primaryActionColour;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GeneratedFormModal> createState() => _GeneratedFormModalState();
|
State<GeneratedFormModal> createState() => _GeneratedFormModalState();
|
||||||
@ -71,6 +73,10 @@ class _GeneratedFormModalState extends State<GeneratedFormModal> {
|
|||||||
: widget.singleNullReturnButton!)),
|
: widget.singleNullReturnButton!)),
|
||||||
widget.singleNullReturnButton == null
|
widget.singleNullReturnButton == null
|
||||||
? TextButton(
|
? TextButton(
|
||||||
|
style: widget.primaryActionColour == null
|
||||||
|
? null
|
||||||
|
: TextButton.styleFrom(
|
||||||
|
foregroundColor: widget.primaryActionColour),
|
||||||
onPressed: !valid
|
onPressed: !valid
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
|
@ -22,7 +22,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart';
|
|||||||
// ignore: implementation_imports
|
// ignore: implementation_imports
|
||||||
import 'package:easy_localization/src/localization.dart';
|
import 'package:easy_localization/src/localization.dart';
|
||||||
|
|
||||||
const String currentVersion = '0.13.22';
|
const String currentVersion = '0.13.26';
|
||||||
const String currentReleaseTag =
|
const String currentReleaseTag =
|
||||||
'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
|
'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
|
||||||
|
|
||||||
@ -299,7 +299,9 @@ class _ObtainiumState extends State<Obtainium> {
|
|||||||
? lightColorScheme
|
? lightColorScheme
|
||||||
: darkColorScheme,
|
: darkColorScheme,
|
||||||
fontFamily: 'Metropolis'),
|
fontFamily: 'Metropolis'),
|
||||||
home: const HomePage());
|
home: Shortcuts(shortcuts: <LogicalKeySet, Intent>{
|
||||||
|
LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
|
||||||
|
}, child: const HomePage()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -643,15 +643,15 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
label: tr('installX', args: [
|
label: tr('installX', args: [
|
||||||
plural('apps', newInstallIdsAllOrSelected.length)
|
plural('apps', newInstallIdsAllOrSelected.length)
|
||||||
]),
|
]),
|
||||||
defaultValue: existingUpdateIdsAllOrSelected.isNotEmpty));
|
defaultValue: existingUpdateIdsAllOrSelected.isEmpty));
|
||||||
}
|
}
|
||||||
if (trackOnlyUpdateIdsAllOrSelected.isNotEmpty) {
|
if (trackOnlyUpdateIdsAllOrSelected.isNotEmpty) {
|
||||||
formItems.add(GeneratedFormSwitch('trackonlies',
|
formItems.add(GeneratedFormSwitch('trackonlies',
|
||||||
label: tr('markXTrackOnlyAsUpdated', args: [
|
label: tr('markXTrackOnlyAsUpdated', args: [
|
||||||
plural('apps', trackOnlyUpdateIdsAllOrSelected.length)
|
plural('apps', trackOnlyUpdateIdsAllOrSelected.length)
|
||||||
]),
|
]),
|
||||||
defaultValue: existingUpdateIdsAllOrSelected.isNotEmpty ||
|
defaultValue: existingUpdateIdsAllOrSelected.isEmpty &&
|
||||||
newInstallIdsAllOrSelected.isNotEmpty));
|
newInstallIdsAllOrSelected.isEmpty));
|
||||||
}
|
}
|
||||||
showDialog<Map<String, dynamic>?>(
|
showDialog<Map<String, dynamic>?>(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -403,10 +403,13 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
Switch(
|
Switch(
|
||||||
value:
|
value:
|
||||||
settingsProvider.reversePageTransitions,
|
settingsProvider.reversePageTransitions,
|
||||||
onChanged: (value) {
|
onChanged: settingsProvider
|
||||||
settingsProvider.reversePageTransitions =
|
.disablePageTransitions
|
||||||
value;
|
? null
|
||||||
})
|
: (value) {
|
||||||
|
settingsProvider
|
||||||
|
.reversePageTransitions = value;
|
||||||
|
})
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
height32,
|
height32,
|
||||||
|
@ -7,6 +7,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:android_intent_plus/flag.dart';
|
import 'package:android_intent_plus/flag.dart';
|
||||||
import 'package:android_package_installer/android_package_installer.dart';
|
import 'package:android_package_installer/android_package_installer.dart';
|
||||||
|
import 'package:android_package_manager/android_package_manager.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -29,6 +30,8 @@ import 'package:http/http.dart';
|
|||||||
import 'package:android_intent_plus/android_intent.dart';
|
import 'package:android_intent_plus/android_intent.dart';
|
||||||
import 'package:flutter_archive/flutter_archive.dart';
|
import 'package:flutter_archive/flutter_archive.dart';
|
||||||
|
|
||||||
|
final pm = AndroidPackageManager();
|
||||||
|
|
||||||
class AppInMemory {
|
class AppInMemory {
|
||||||
late App app;
|
late App app;
|
||||||
double? downloadProgress;
|
double? downloadProgress;
|
||||||
@ -322,16 +325,39 @@ class AppsProvider with ChangeNotifier {
|
|||||||
.isNotEmpty;
|
.isNotEmpty;
|
||||||
|
|
||||||
Future<bool> canInstallSilently(App app) async {
|
Future<bool> canInstallSilently(App app) async {
|
||||||
return false;
|
if (app.apkUrls.length > 1) {
|
||||||
// TODO: Uncomment the below if silent updates are ever figured out
|
// Manual API selection means silent install is not possible
|
||||||
// // NOTE: This is unreliable - try to get from OS in the future
|
return false;
|
||||||
// if (app.apkUrls.length > 1) {
|
}
|
||||||
// return false;
|
|
||||||
// }
|
var osInfo = await DeviceInfoPlugin().androidInfo;
|
||||||
// var osInfo = await DeviceInfoPlugin().androidInfo;
|
String? installerPackageName;
|
||||||
// return app.installedVersion != null &&
|
try {
|
||||||
// osInfo.version.sdkInt >= 30 &&
|
installerPackageName = osInfo.version.sdkInt >= 30
|
||||||
// osInfo.version.release.compareTo('12') >= 0;
|
? (await pm.getInstallSourceInfo(packageName: app.id))
|
||||||
|
?.installingPackageName
|
||||||
|
: (await pm.getInstallerPackageName(packageName: app.id));
|
||||||
|
} catch (e) {
|
||||||
|
// Probably not installed - ignore
|
||||||
|
}
|
||||||
|
if (installerPackageName != obtainiumId) {
|
||||||
|
// If we did not install the app (or it isn't installed), silent install is not possible
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int? targetSDK;
|
||||||
|
try {
|
||||||
|
targetSDK = (await pm.getPackageInfo(packageName: app.id))
|
||||||
|
?.applicationInfo
|
||||||
|
?.targetSdkVersion;
|
||||||
|
} catch (e) {
|
||||||
|
// Weird if you get here - ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// The OS must also be new enough and the APK should target a new enough API
|
||||||
|
return osInfo.version.sdkInt >= 30 &&
|
||||||
|
targetSDK != null &&
|
||||||
|
targetSDK >= // https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setRequireUserAction(int)
|
||||||
|
(osInfo.version.sdkInt - 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> waitForUserToReturnToForeground(BuildContext context) async {
|
Future<void> waitForUserToReturnToForeground(BuildContext context) async {
|
||||||
@ -359,26 +385,24 @@ class AppsProvider with ChangeNotifier {
|
|||||||
zipFile: File(filePath), destinationDir: Directory(destinationPath));
|
zipFile: File(filePath), destinationDir: Directory(destinationPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> installXApkDir(DownloadedXApkDir dir,
|
Future<void> installXApkDir(DownloadedXApkDir dir) async {
|
||||||
{bool silent = false}) async {
|
|
||||||
// We don't know which APKs in an XAPK are supported by the user's device
|
// We don't know which APKs in an XAPK are supported by the user's device
|
||||||
// So we try installing all of them and assume success if at least one installed
|
// So we try installing all of them and assume success if at least one installed
|
||||||
// If 0 APKs installed, throw the first install error encountered
|
// If 0 APKs installed, throw the first install error encountered
|
||||||
try {
|
try {
|
||||||
var somethingInstalled = false;
|
var somethingInstalled = false;
|
||||||
Object? firstError;
|
MultiAppMultiError errors = MultiAppMultiError();
|
||||||
for (var file in dir.extracted
|
for (var file in dir.extracted
|
||||||
.listSync(recursive: true, followLinks: false)
|
.listSync(recursive: true, followLinks: false)
|
||||||
.whereType<File>()) {
|
.whereType<File>()) {
|
||||||
if (file.path.toLowerCase().endsWith('.apk')) {
|
if (file.path.toLowerCase().endsWith('.apk')) {
|
||||||
try {
|
try {
|
||||||
somethingInstalled = somethingInstalled ||
|
somethingInstalled = somethingInstalled ||
|
||||||
await installApk(DownloadedApk(dir.appId, file),
|
await installApk(DownloadedApk(dir.appId, file));
|
||||||
silent: silent);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logs.add(
|
logs.add(
|
||||||
'Could not install APK from XAPK \'${file.path}\': ${e.toString()}');
|
'Could not install APK from XAPK \'${file.path}\': ${e.toString()}');
|
||||||
firstError ??= e;
|
errors.add(dir.appId, e.toString());
|
||||||
}
|
}
|
||||||
} else if (file.path.toLowerCase().endsWith('.obb')) {
|
} else if (file.path.toLowerCase().endsWith('.obb')) {
|
||||||
await moveObbFile(file, dir.appId);
|
await moveObbFile(file, dir.appId);
|
||||||
@ -386,16 +410,15 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
if (somethingInstalled) {
|
if (somethingInstalled) {
|
||||||
dir.file.delete(recursive: true);
|
dir.file.delete(recursive: true);
|
||||||
} else if (firstError != null) {
|
} else if (errors.content.isNotEmpty) {
|
||||||
throw firstError;
|
throw errors;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
dir.extracted.delete(recursive: true);
|
dir.extracted.delete(recursive: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> installApk(DownloadedApk file, {bool silent = false}) async {
|
Future<bool> installApk(DownloadedApk file) async {
|
||||||
// TODO: Use 'silent' when/if ever possible
|
|
||||||
var newInfo = await PackageArchiveInfo.fromPath(file.file.path);
|
var newInfo = await PackageArchiveInfo.fromPath(file.file.path);
|
||||||
AppInfo? appInfo;
|
AppInfo? appInfo;
|
||||||
try {
|
try {
|
||||||
@ -571,7 +594,6 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
bool willBeSilent = await canInstallSilently(
|
bool willBeSilent = await canInstallSilently(
|
||||||
apps[downloadedFile?.appId ?? downloadedDir!.appId]!.app);
|
apps[downloadedFile?.appId ?? downloadedDir!.appId]!.app);
|
||||||
willBeSilent = false; // TODO: Remove this when silent updates work
|
|
||||||
if (!(await settingsProvider?.getInstallPermission(enforce: false) ??
|
if (!(await settingsProvider?.getInstallPermission(enforce: false) ??
|
||||||
true)) {
|
true)) {
|
||||||
throw ObtainiumError(tr('cancelled'));
|
throw ObtainiumError(tr('cancelled'));
|
||||||
@ -584,9 +606,9 @@ class AppsProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
try {
|
try {
|
||||||
if (downloadedFile != null) {
|
if (downloadedFile != null) {
|
||||||
await installApk(downloadedFile, silent: willBeSilent);
|
await installApk(downloadedFile);
|
||||||
} else {
|
} else {
|
||||||
await installXApkDir(downloadedDir!, silent: willBeSilent);
|
await installXApkDir(downloadedDir!);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
apps[id]?.downloadProgress = null;
|
apps[id]?.downloadProgress = null;
|
||||||
@ -892,6 +914,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext ctx) {
|
builder: (BuildContext ctx) {
|
||||||
return GeneratedFormModal(
|
return GeneratedFormModal(
|
||||||
|
primaryActionColour: Theme.of(context).colorScheme.error,
|
||||||
title: plural('removeAppQuestion', apps.length),
|
title: plural('removeAppQuestion', apps.length),
|
||||||
items: !showUninstallOption
|
items: !showUninstallOption
|
||||||
? []
|
? []
|
||||||
|
@ -14,6 +14,7 @@ import 'package:obtainium/app_sources/fdroid.dart';
|
|||||||
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
import 'package:obtainium/app_sources/fdroidrepo.dart';
|
||||||
import 'package:obtainium/app_sources/github.dart';
|
import 'package:obtainium/app_sources/github.dart';
|
||||||
import 'package:obtainium/app_sources/gitlab.dart';
|
import 'package:obtainium/app_sources/gitlab.dart';
|
||||||
|
import 'package:obtainium/app_sources/huaweiappgallery.dart';
|
||||||
import 'package:obtainium/app_sources/izzyondroid.dart';
|
import 'package:obtainium/app_sources/izzyondroid.dart';
|
||||||
import 'package:obtainium/app_sources/html.dart';
|
import 'package:obtainium/app_sources/html.dart';
|
||||||
import 'package:obtainium/app_sources/jenkins.dart';
|
import 'package:obtainium/app_sources/jenkins.dart';
|
||||||
@ -355,10 +356,14 @@ abstract class AppSource {
|
|||||||
|
|
||||||
Map<String, String>? get requestHeaders => null;
|
Map<String, String>? get requestHeaders => null;
|
||||||
|
|
||||||
Future<Response> sourceRequest(String url) async {
|
Future<Response> sourceRequest(String url,
|
||||||
if (requestHeaders != null) {
|
{bool followRedirects = true}) async {
|
||||||
|
if (requestHeaders != null || followRedirects == false) {
|
||||||
var req = Request('GET', Uri.parse(url));
|
var req = Request('GET', Uri.parse(url));
|
||||||
req.headers.addAll(requestHeaders!);
|
req.followRedirects = followRedirects;
|
||||||
|
if (requestHeaders != null) {
|
||||||
|
req.headers.addAll(requestHeaders!);
|
||||||
|
}
|
||||||
return Response.fromStream(await Client().send(req));
|
return Response.fromStream(await Client().send(req));
|
||||||
} else {
|
} else {
|
||||||
return get(Uri.parse(url));
|
return get(Uri.parse(url));
|
||||||
@ -431,14 +436,14 @@ abstract class AppSource {
|
|||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
SettingsProvider settingsProvider) async {
|
SettingsProvider settingsProvider) async {
|
||||||
Map<String, String> results = {};
|
Map<String, String> results = {};
|
||||||
sourceConfigSettingFormItems.forEach((e) {
|
for (var e in sourceConfigSettingFormItems) {
|
||||||
var val = hostChanged
|
var val = hostChanged
|
||||||
? additionalSettings[e.key]
|
? additionalSettings[e.key]
|
||||||
: settingsProvider.getSettingString(e.key);
|
: settingsProvider.getSettingString(e.key);
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
results[e.key] = val;
|
results[e.key] = val;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,6 +513,7 @@ class SourceProvider {
|
|||||||
SourceHut(),
|
SourceHut(),
|
||||||
APKMirror(),
|
APKMirror(),
|
||||||
APKPure(),
|
APKPure(),
|
||||||
|
HuaweiAppGallery(),
|
||||||
// APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden)
|
// APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden)
|
||||||
Mullvad(),
|
Mullvad(),
|
||||||
Signal(),
|
Signal(),
|
||||||
|
91
pubspec.lock
91
pubspec.lock
@ -5,27 +5,36 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: android_alarm_manager_plus
|
name: android_alarm_manager_plus
|
||||||
sha256: "80f963d47cb7ab0818144c7b0668aea4c038f9cb8626626e89a4ea77375defb7"
|
sha256: c20d91a9096596f66274bf8172321c278f9cba8091638f80205fe66d31587fa5
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
android_intent_plus:
|
android_intent_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: android_intent_plus
|
name: android_intent_plus
|
||||||
sha256: "2c87d8330ba5deef5fe20e77f4d178190b3b24531dce08368030ab4be40a9d4e"
|
sha256: f72ae20bb37108694f442e7ae6acbd28b453ca62ce86842f6787b784355abfe6
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "4.0.2"
|
||||||
android_package_installer:
|
android_package_installer:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: main
|
ref: main
|
||||||
resolved-ref: f09c79eee5be3c60b04760143eb954a13fdd07f1
|
resolved-ref: ba2aa7a11edc2649d1d80c25ed9291521262f714
|
||||||
url: "https://github.com/ImranR98/android_package_installer"
|
url: "https://github.com/ImranR98/android_package_installer"
|
||||||
source: git
|
source: git
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
|
android_package_manager:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: master
|
||||||
|
resolved-ref: "6e68991ef9c6232695abce2eef345d3cca2f52ac"
|
||||||
|
url: "https://github.com/ImranR98/android_package_manager"
|
||||||
|
source: git
|
||||||
|
version: "0.5.4"
|
||||||
animations:
|
animations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -158,10 +167,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: device_info_plus
|
name: device_info_plus
|
||||||
sha256: "2c35b6d1682b028e42d07b3aee4b98fa62996c10bc12cb651ec856a80d6a761b"
|
sha256: "86add5ef97215562d2e090535b0a16f197902b10c369c558a100e74ea06e8659"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.0.2"
|
version: "9.0.3"
|
||||||
device_info_plus_platform_interface:
|
device_info_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -206,10 +215,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: ffi
|
name: ffi
|
||||||
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
|
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.1.0"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -296,10 +305,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_markdown
|
name: flutter_markdown
|
||||||
sha256: "4b1bfbb802d76320a1a46d9ce984106135093efd9d969765d07c2125af107bdf"
|
sha256: "2b206d397dd7836ea60035b2d43825c8a303a76a5098e66f42d55a753e18d431"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.17"
|
version: "0.6.17+1"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -482,50 +491,50 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2"
|
sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.15"
|
version: "2.1.0"
|
||||||
path_provider_android:
|
path_provider_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_android
|
name: path_provider_android
|
||||||
sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86"
|
sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.27"
|
version: "2.1.0"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_foundation
|
name: path_provider_foundation
|
||||||
sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297"
|
sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.4"
|
version: "2.3.0"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_linux
|
name: path_provider_linux
|
||||||
sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57
|
sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.11"
|
version: "2.2.0"
|
||||||
path_provider_platform_interface:
|
path_provider_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_platform_interface
|
name: path_provider_platform_interface
|
||||||
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
|
sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.6"
|
version: "2.1.0"
|
||||||
path_provider_windows:
|
path_provider_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96"
|
sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.7"
|
version: "2.2.0"
|
||||||
permission_handler:
|
permission_handler:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -578,10 +587,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: platform
|
name: platform
|
||||||
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
|
sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.1"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -610,18 +619,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: share_plus
|
name: share_plus
|
||||||
sha256: ed3fcea4f789ed95913328e629c0c53e69e80e08b6c24542f1b3576046c614e8
|
sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.2"
|
version: "7.1.0"
|
||||||
share_plus_platform_interface:
|
share_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: share_plus_platform_interface
|
name: share_plus_platform_interface
|
||||||
sha256: "0c6e61471bd71b04a138b8b588fa388e66d8b005e6f2deda63371c5c505a0981"
|
sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.1"
|
version: "3.3.0"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -642,10 +651,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_foundation
|
name: shared_preferences_foundation
|
||||||
sha256: f39696b83e844923b642ce9dd4bd31736c17e697f6731a5adf445b1274cf3cd4
|
sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.3"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -783,10 +792,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
sha256: "78cb6dea3e93148615109e58e42c35d1ffbf5ef66c44add673d0ab75f12ff3af"
|
sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.37"
|
version: "6.0.38"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -863,26 +872,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_android
|
name: webview_flutter_android
|
||||||
sha256: d936a09fbfd08cb78f7329e0bbacf6158fbdfe24ffc908b22444c07d295eb193
|
sha256: bca797abba472868655b5f1a6029c1132385685ee9db4713cb0e7f33076210c6
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.9.2"
|
version: "3.9.3"
|
||||||
webview_flutter_platform_interface:
|
webview_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_platform_interface
|
name: webview_flutter_platform_interface
|
||||||
sha256: "564ef378cafc1a0e29f1d76ce175ef517a0a6115875dff7b43fccbef2b0aeb30"
|
sha256: "0ca3cfcc6781a7de701d580917af4a9efc4e3e129f8ead95a80587f0a749480a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.0"
|
version: "2.5.0"
|
||||||
webview_flutter_wkwebview:
|
webview_flutter_wkwebview:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_wkwebview
|
name: webview_flutter_wkwebview
|
||||||
sha256: "5fa098f28b606f699e8ca52d9e4e11edbbfef65189f5f77ae92703ba5408fd25"
|
sha256: ed749f94ac9e814d04a258a9255cf69cfa4cc6006ff59542aea7fb4590144972
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.7.2"
|
version: "3.7.3"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -903,10 +912,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: xdg_directories
|
name: xdg_directories
|
||||||
sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff
|
sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.2"
|
||||||
xml:
|
xml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
12
pubspec.yaml
12
pubspec.yaml
@ -1,5 +1,5 @@
|
|||||||
name: obtainium
|
name: obtainium
|
||||||
description: A new Flutter project.
|
description: Get Android App Updates Directly From the Source.
|
||||||
|
|
||||||
# The following line prevents the package from being accidentally published to
|
# The following line prevents the package from being accidentally published to
|
||||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||||
@ -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
|
# 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
|
# 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.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 0.13.22+186 # When changing this, update the tag in main() accordingly
|
version: 0.13.26+190 # When changing this, update the tag in main() accordingly
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.18.2 <3.0.0'
|
sdk: '>=2.18.2 <3.0.0'
|
||||||
@ -55,9 +55,13 @@ dependencies:
|
|||||||
git:
|
git:
|
||||||
url: https://github.com/ImranR98/android_package_installer
|
url: https://github.com/ImranR98/android_package_installer
|
||||||
ref: main
|
ref: main
|
||||||
|
android_package_manager:
|
||||||
|
git:
|
||||||
|
url: https://github.com/ImranR98/android_package_manager
|
||||||
|
ref: master
|
||||||
share_plus: ^7.0.0
|
share_plus: ^7.0.0
|
||||||
installed_apps: ^1.3.1
|
installed_apps: ^1.3.1 # TODO: Remove when android_package_manager supports getting icon as UInt8List and versionCode
|
||||||
package_archive_info: ^0.1.0
|
package_archive_info: ^0.1.0 # TODO: Remove when android_package_manager supports getting versionCode
|
||||||
android_alarm_manager_plus: ^3.0.0
|
android_alarm_manager_plus: ^3.0.0
|
||||||
sqflite: ^2.2.0+3
|
sqflite: ^2.2.0+3
|
||||||
easy_localization: ^3.0.1
|
easy_localization: ^3.0.1
|
||||||
|
Reference in New Issue
Block a user