Compare commits

...

34 Commits

Author SHA1 Message Date
Imran Remtulla
d9729f08c0 Merge pull request #278 from ImranR98/dev
Fixed breaking typo in fa.json
2023-02-12 19:32:25 -05:00
Imran Remtulla
eda5c1bac6 Fixed breaking typo in fa.json 2023-02-12 19:32:05 -05:00
Imran Remtulla
5574ea870b Merge pull request #277 from ImranR98/dev
Added FA to language menu
2023-02-12 19:26:09 -05:00
Imran Remtulla
9f03234ac1 Added FA to language menu
(and renamed file for consistency)
2023-02-12 19:25:44 -05:00
Imran Remtulla
b2503dd43d Merge pull request #276 from ImranR98/dev
Increment version
2023-02-12 19:20:18 -05:00
Imran Remtulla
e01ca704bc Increment version 2023-02-12 19:19:59 -05:00
Imran Remtulla
6aa4ace8e2 Merge pull request #275 from mehdijahann/main
Add FA(Persian) language
2023-02-12 19:19:14 -05:00
Mehdee
d762467a31 Update FA.json 2023-02-13 08:16:06 +09:00
Mehdee
b07cce8ecd Create FA.json 2023-02-13 07:07:30 +09:00
Imran Remtulla
8002a946b2 Merge pull request #273 from ImranR98/dev
Reverse changes related to App ID changes (#270)
2023-02-12 14:37:21 -05:00
Imran Remtulla
fd9aebc5b2 Reverse changes related to App ID changes (#270) 2023-02-12 14:36:54 -05:00
Imran Remtulla
1be38d361f Merge pull request #272 from ImranR98/dev
No longer blocking App ID changes in updates
2023-02-12 14:20:04 -05:00
Imran Remtulla
32c40ae7b3 No longer blocking App ID changes in updates 2023-02-12 14:16:19 -05:00
Imran Remtulla
07223d81c7 Merge pull request #268 from gidano/main
Updated hu.json
2023-02-11 12:02:41 -05:00
gidano
78baee7265 Updated hu.json 2023-02-11 11:41:52 +01:00
Imran Remtulla
348c33dfe9 Merge pull request #266 from rollingmoai/patch-1
Add installation badges
2023-02-10 20:36:38 -05:00
Imran Remtulla
c408d70ae6 Merge pull request #260 from atilluF/ita
Update Italian translation
2023-02-10 20:23:13 -05:00
Imran Remtulla
3ae4e7cc8a Merge pull request #259 from bluefly000/japanese-translation
Update Japanese translation
2023-02-10 20:23:06 -05:00
rollingmoai
dab0f2bb72 Add installation badges 2023-02-09 22:13:16 +08:00
atilluF
4baf6bcd3b Update it.json 2023-02-05 12:10:59 +01:00
bluefly000
db4517aa13 Update Japanese translation 2023-02-05 12:23:30 +09:00
Imran Remtulla
55d4d1f978 Merge pull request #258 from ImranR98/dev
Removed unused commented code
2023-02-04 20:06:57 -05:00
Imran Remtulla
f89ac5965f Removed unused commented code 2023-02-04 20:06:22 -05:00
Imran Remtulla
d5ebaa161f Merge pull request #257 from ImranR98/dev
Remove unused class
2023-02-04 20:05:39 -05:00
Imran Remtulla
a4c014a8bf Remove unused class 2023-02-04 20:05:20 -05:00
Imran Remtulla
bbaa42fb01 Merge pull request #256 from ImranR98/dev
Bugfixes (#254, #252), App Uninstall and Settings Feature (#257)
2023-02-04 19:46:24 -05:00
Imran Remtulla
4fe311bc03 Update packages, increment version 2023-02-04 19:44:18 -05:00
Imran Remtulla
ea68b97ff7 Mark updated feature more clear 2023-02-04 19:30:41 -05:00
Imran Remtulla
6e0f6b528e Added App settings button 2023-02-04 19:11:28 -05:00
Imran Remtulla
a2c227931e Added uninstall option 2023-02-04 18:58:14 -05:00
Imran Remtulla
15ad3bb439 Removed unnecessary repetitive log 2023-02-04 17:21:39 -05:00
Imran Remtulla
b03d7fba1a Fix permission error on Android 10 #252 2023-02-04 17:07:59 -05:00
Imran Remtulla
31c491d7c5 Fix prev. commit. 2023-02-04 16:50:33 -05:00
Imran Remtulla
71c80f11f5 'Fix' for GlobalKey error #254 2023-02-04 12:30:34 -05:00
16 changed files with 456 additions and 113 deletions

View File

@@ -22,6 +22,15 @@ Currently supported App sources:
- "HTML" (Fallback) - "HTML" (Fallback)
- Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked) - Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked)
## Installation
[<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png"
alt="Get it on GitHub"
height="80">](https://github.com/ImranR98/Obtainium/releases)
[<img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png"
alt="Get it on IzzyOnDroid"
height="80">](https://apt.izzysoft.de/fdroid/index/apk/dev.imranr.obtainium)
## Limitations ## Limitations
- App installs happen asynchronously and the success/failure of an install cannot be determined directly. This results in install statuses and versions sometimes being out of sync with the OS until the next launch or until the problem is manually corrected. - App installs happen asynchronously and the success/failure of an install cannot be determined directly. This results in install statuses and versions sometimes being out of sync with the OS until the next launch or until the problem is manually corrected.
- Auto (unattended) updates are unsupported due to a lack of any capable Flutter plugin. - Auto (unattended) updates are unsupported due to a lack of any capable Flutter plugin.

View File

@@ -3,7 +3,8 @@
<application <application
android:label="Obtainium" android:label="Obtainium"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
@@ -51,7 +52,8 @@
<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"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission <uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/> android:maxSdkVersion="29"/>
</manifest> </manifest>

View File

@@ -74,7 +74,6 @@
"changeX": "Ändern {}", "changeX": "Ändern {}",
"installUpdateApps": "Apps installieren/aktualisieren", "installUpdateApps": "Apps installieren/aktualisieren",
"installUpdateSelectedApps": "Ausgewählte Apps installieren/aktualisieren", "installUpdateSelectedApps": "Ausgewählte Apps installieren/aktualisieren",
"onlyWorksWithNonEVDApps": "Funktioniert nur bei Apps, deren Installationsstatus nicht automatisch erkannt werden kann (ungewöhnlich).",
"markXSelectedAppsAsUpdated": "Markiere {} ausgewählte Apps als aktuell?", "markXSelectedAppsAsUpdated": "Markiere {} ausgewählte Apps als aktuell?",
"no": "Nein", "no": "Nein",
"yes": "Ja", "yes": "Ja",
@@ -178,7 +177,6 @@
"installedVersionX": "Installierte Version: {}", "installedVersionX": "Installierte Version: {}",
"lastUpdateCheckX": "Letzte Aktualisierungsprüfung: {}", "lastUpdateCheckX": "Letzte Aktualisierungsprüfung: {}",
"remove": "Entfernen", "remove": "Entfernen",
"removeAppQuestion": "App entfernen?",
"yesMarkUpdated": "Ja, als aktualisiert markieren", "yesMarkUpdated": "Ja, als aktualisiert markieren",
"fdroid": "F-Droid", "fdroid": "F-Droid",
"appIdOrName": "App ID oder Name", "appIdOrName": "App ID oder Name",
@@ -212,6 +210,13 @@
"storagePermissionDenied": "Storage permission denied", "storagePermissionDenied": "Storage permission denied",
"selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.",
"filterAPKsByRegEx": "Filter APKs by Regular Expression", "filterAPKsByRegEx": "Filter APKs by Regular Expression",
"removeFromObtainium": "Remove from Obtainium",
"uninstallFromDevice": "Uninstall from Device",
"onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.",
"removeAppQuestion": {
"one": "App entfernen?",
"other": "App entfernen?"
},
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minute erneut", "one": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minute erneut",
"other": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minuten erneut" "other": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minuten erneut"

View File

@@ -74,7 +74,6 @@
"changeX": "Change {}", "changeX": "Change {}",
"installUpdateApps": "Install/Update Apps", "installUpdateApps": "Install/Update Apps",
"installUpdateSelectedApps": "Install/Update Selected Apps", "installUpdateSelectedApps": "Install/Update Selected Apps",
"onlyWorksWithNonEVDApps": "Only works for Apps whose install status cannot be automatically detected (uncommon).",
"markXSelectedAppsAsUpdated": "Mark {} Selected Apps as Updated?", "markXSelectedAppsAsUpdated": "Mark {} Selected Apps as Updated?",
"no": "No", "no": "No",
"yes": "Yes", "yes": "Yes",
@@ -178,7 +177,6 @@
"installedVersionX": "Installed Version: {}", "installedVersionX": "Installed Version: {}",
"lastUpdateCheckX": "Last Update Check: {}", "lastUpdateCheckX": "Last Update Check: {}",
"remove": "Remove", "remove": "Remove",
"removeAppQuestion": "Remove App?",
"yesMarkUpdated": "Yes, Mark as Updated", "yesMarkUpdated": "Yes, Mark as Updated",
"fdroid": "F-Droid", "fdroid": "F-Droid",
"appIdOrName": "App ID or Name", "appIdOrName": "App ID or Name",
@@ -212,6 +210,13 @@
"storagePermissionDenied": "Storage permission denied", "storagePermissionDenied": "Storage permission denied",
"selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.",
"filterAPKsByRegEx": "Filter APKs by Regular Expression", "filterAPKsByRegEx": "Filter APKs by Regular Expression",
"removeFromObtainium": "Remove from Obtainium",
"uninstallFromDevice": "Uninstall from Device",
"onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.",
"removeAppQuestion": {
"one": "Remove App?",
"other": "Remove Apps?"
},
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "Too many requests (rate limited) - try again in {} minute", "one": "Too many requests (rate limited) - try again in {} minute",
"other": "Too many requests (rate limited) - try again in {} minutes" "other": "Too many requests (rate limited) - try again in {} minutes"

264
assets/translations/fa.json Normal file
View File

@@ -0,0 +1,264 @@
{
"invalidURLForSource": "آدرس اینترنتی برنامه {} معتبر نیست",
"noReleaseFound": "نسخه مناسبی پیدا نشد",
"noVersionFound": "نمی توان نسخه منتشر شده را تعیین کرد",
"urlMatchesNoSource": "آدرس اینترنتی با منبع شناخته شده مطابقت ندارد",
"cantInstallOlderVersion": "نمی توان نسخه قدیمی یک برنامه را نصب کرد",
"appIdMismatch": "شناسه بسته دانلود شده با شناسه برنامه موجود مطابقت ندارد",
"functionNotImplemented": "این کلاس این تابع را پیاده سازی نکرده است",
"placeholder": "نگهدارنده مکان",
"someErrors": "برخی از خطاها رخ داده است",
"unexpectedError": "خطای غیرمنتظره",
"ok": "باشه",
"and": "و",
"startedBgUpdateTask": "شروع بررسی بروزرسانی BG",
"bgUpdateIgnoreAfterIs": "نادیده گرفتن بروزرسانی BG بعد از {} است",
"startedActualBGUpdateCheck": "بررسی به‌روزرسانی واقعی BG آغاز شد",
"bgUpdateTaskFinished": "کار بررسی به‌روزرسانی BG تمام شد",
"firstRun": "این اولین اجرای Obtainium است",
"settingUpdateCheckIntervalTo": "تنظیم فاصله به‌روزرسانی روی {}",
"githubPATLabel": "توکن دسترسی شخصی گیت هاب(محدودیت نرخ را افزایش میدهد)",
"githubPATHint": "PAT باید در این قالب باشد: username:token",
"githubPATFormat": "username:token",
"githubPATLinkText": "درباره گیتهاب PATs",
"includePrereleases": "شامل نسخه های اولیه",
"fallbackToOlderReleases": "بازگشت به نسخه های قدیمی تر",
"filterReleaseTitlesByRegEx": "عناوین انتشار را با بیان منظم فیلتر کنید",
"invalidRegEx": "عبارت منظم نامعتبر است",
"noDescription": "بدون توضیحات",
"cancel": "لغو",
"continue": "ادامه دهید",
"requiredInBrackets": "(ضروری)",
"dropdownNoOptsError": "خطا: کشویی باید حداقل یک گزینه داشته باشد",
"colour": "رنگ",
"githubStarredRepos": "مخازن ستاره دار گیتهاب",
"uname": "نام کاربری",
"wrongArgNum": "تعداد آرگومان های ارائه شده اشتباه است",
"xIsTrackOnly": "{} فقط ردیابی",
"source": "منبع",
"app": "برنامه",
"appsFromSourceAreTrackOnly": "برنامه‌های این منبع «فقط ردیابی» هستند",
"youPickedTrackOnly": "شما گزینه ی «فقط ردیابی» را انتخاب کرده اید",
"trackOnlyAppDescription": "برنامه برای به روز رسانی ها ردیابی می شود، اما Obtainium قادر به دانلود یا نصب آن نخواهد بود.",
"cancelled": "لغو شد",
"appAlreadyAdded": "برنامه قبلاً اضافه شده است",
"alreadyUpToDateQuestion": "برنامه از قبل به روز شده است؟",
"addApp": "افزودن برنامه",
"appSourceURL": "آدرس اینترنتی منبع برنامه",
"error": "خطا",
"add": "اضافه کردن",
"searchSomeSourcesLabel": "جستجو (فقط برخی منابع)",
"search": "جستجو کردن",
"additionalOptsFor": "گزینه های اضافی برای {}",
"supportedSourcesBelow": "منابع پشتیبانی شده:",
"trackOnlyInBrackets": "«فقط ردیابی»",
"searchableInBrackets": "(قابل جستجو)",
"appsString": "برنامه ها",
"noApps": "برنامه ای وجود ندارد",
"noAppsForFilter": "برنامه ای برای فیلتر کردن وجود ندارد",
"byX": "توسط {}",
"percentProgress": "پیش رفتن: {}%",
"pleaseWait": "لطفا صبر کنید",
"updateAvailable": "بروزرسانی در دسترس",
"estimateInBracketsShort": "(تخمین)",
"notInstalled": "نصب نشده",
"estimateInBrackets": "(تخمین زدن)",
"selectAll": "انتخاب همه",
"deselectN": "لغو انتخاب {}",
"xWillBeRemovedButRemainInstalled": "{} از Obtainium حذف می‌شود اما روی دستگاه نصب می‌ماند.",
"removeSelectedAppsQuestion": "برنامه های انتخابی حذف شود؟",
"removeSelectedApps": "حذف برنامه های انتخاب شده",
"updateX": "به روز رسانی {}",
"installX": "نصب {}",
"markXTrackOnlyAsUpdated": "علامت {}\n(فقط ردیابی)\nبروز شده",
"changeX": "تغییر دادن {}",
"installUpdateApps": "نصب/به‌روزرسانی برنامه‌ها",
"installUpdateSelectedApps": "برنامه‌های انتخابی را نصب/به‌روزرسانی کنید",
"markXSelectedAppsAsUpdated": "{} برنامه های انتخابی را به عنوان به روز علامت گذاری کنید؟",
"no": "خیر",
"yes": "بله",
"markSelectedAppsUpdated": "برنامه های انتخاب شده را به عنوان به روز علامت گذاری کنید",
"pinToTop": "پین به بالا",
"unpinFromTop": "برداشتن پین از بالا",
"resetInstallStatusForSelectedAppsQuestion": "وضعیت نصب برنامه‌های انتخابی بازنشانی شود؟",
"installStatusOfXWillBeResetExplanation": "وضعیت نصب برنامه‌های انتخاب‌شده بازنشانی می‌شود.\n\nاگر نسخه برنامه نشان‌داده‌شده در Obtainium به دلیل به‌روزرسانی‌های ناموفق یا مشکلات دیگر نادرست باشد، می‌تواند کمک کند.",
"shareSelectedAppURLs": "اشتراک گذاری آدرس اینترنتی برنامه های انتخاب شده",
"resetInstallStatus": "بازنشانی وضعیت نصب",
"more": "بیشتر",
"removeOutdatedFilter": "فیلتر برنامه قدیمی را حذف کنید",
"showOutdatedOnly": "فقط برنامه های قدیمی را نشان دهید",
"filter": "فیلتر",
"filterActive": "فیلتر *",
"filterApps": "فیلتر کردن برنامه ها",
"appName": "نام برنامه",
"author": "سازنده",
"upToDateApps": "برنامه های به روز",
"nonInstalledApps": "برنامه های نصب نشده",
"importExport": "وادر کردن/صادر کردن",
"settings": "تنظیمات",
"exportedTo": "صادر کردن به{}",
"obtainiumExport": "صادرکردن Obtainium",
"invalidInput": "ورودی نامعتبر",
"importedX": "وارد شده {}",
"obtainiumImport": "واردکردن Obtainium",
"importFromURLList": "وارد کردن از فهرست آدرس اینترنتی",
"searchQuery": "جستجوی سوال",
"appURLList": "فهرست آدرس اینترنتی برنامه",
"line": "خط",
"searchX": "جستجو {}",
"noResults": "نتیجه ای پیدا نشد",
"importX": "وارد کردن {}",
"importedAppsIdDisclaimer": "ممکن است برنامه‌های وارد شده به اشتباه به‌عنوان \"نصب نشده\" نشان داده شوند.\nبرای رفع این مشکل، آنها را دوباره از طریق Obtainium نصب کنید.\nاین نباید روی داده‌های برنامه تأثیر بگذارد.\n\nفقط بر روی آدرس اینترنتی و روش‌های وارد کردن شخص ثالث تأثیر می‌گذارد.",
"importErrors": "خطاهای وارد کردن",
"importedXOfYApps": "{} از {} برنامه وارد شد.",
"followingURLsHadErrors": "آدرس های اینترنتی زیر دارای خطا بودند:",
"okay": "باشه",
"selectURL": "آدرس اینترنتی انتخاب شده",
"selectURLs": "آدرس های اینترنتی انتخاب شده",
"pick": "انتخاب",
"theme": "تم",
"dark": "تاریک",
"light": "روشن",
"followSystem": "هماهنگ با سیستم",
"obtainium": "Obtainium",
"materialYou": "Material You",
"appSortBy": "مرتب سازی برنامه بر اساس",
"authorName": "سازنده/اسم",
"nameAuthor": "اسم/سازنده",
"asAdded": "همانطور که اضافه شد",
"appSortOrder": "ترتیب مرتب سازی برنامه",
"ascending": "صعودی",
"descending": "نزولی",
"bgUpdateCheckInterval": "فاصله بررسی به‌روزرسانی در پس‌زمینه",
"neverManualOnly": "هرگز - فقط دستی",
"appearance": "ظاهر",
"showWebInAppView": "نمایش صفحه وب منبع در نمای برنامه",
"pinUpdates": "به‌روزرسانی‌ها را به نمای بالای برنامه‌ها پین کنید",
"updates": "به روز رسانی ها",
"sourceSpecific": "منبع خاص",
"appSource": "منبع برنامه",
"noLogs": "بدون گزارش",
"appLogs": "گزارش های برنامه",
"close": "بستن",
"share": "اشتراک گذاری",
"appNotFound": "برنامه پیدا نشد",
"obtainiumExportHyphenatedLowercase": "صادر کردن-obtainium",
"pickAnAPK": "یک APK انتخاب کنید",
"appHasMoreThanOnePackage": "{} بیش از یک بسته دارد:",
"deviceSupportsXArch": "دستگاه شما از معماری پردازنده {} پشتیبانی میکند",
"deviceSupportsFollowingArchs": "دستگاه شما از معماری های پردازنده زیر پشتیبانی می کند:",
"warning": "اخطار",
"sourceIsXButPackageFromYPrompt": "منبع برنامه \"{}\" است اما بسته انتشار از \"{}\" آمده است. ادامه هید؟",
"updatesAvailable": "بروزرسانی در دسترس ",
"updatesAvailableNotifDescription": "به کاربر اطلاع می دهد که به روز رسانی برای یک یا چند برنامه ردیابی شده توسط Obtainium در دسترس است",
"noNewUpdates": "به روز رسانی جدیدی وجود ندارد.",
"xHasAnUpdate": "{} یک به روز رسانی دارد.",
"appsUpdated": "برنامه ها به روز شدند",
"appsUpdatedNotifDescription": "به کاربر اطلاع می دهد که به روز رسانی یک یا چند برنامه در پس زمینه اعمال شده است",
"xWasUpdatedToY": "{} به {} به روز شد.",
"errorCheckingUpdates": "خطا در بررسی به‌روزرسانی‌ها",
"errorCheckingUpdatesNotifDescription": "اعلانی که وقتی بررسی به‌روزرسانی پس‌زمینه ناموفق است نشان می‌دهد",
"appsRemoved": "برنامه ها حذف شدند",
"appsRemovedNotifDescription": "به کاربر اطلاع می دهد که یک یا چند برنامه به دلیل خطا در هنگام بارگیری حذف شده است",
"xWasRemovedDueToErrorY": "{} به دلیل این خطا حذف شد: {}",
"completeAppInstallation": "نصب کامل برنامه",
"obtainiumMustBeOpenToInstallApps": "Obtainium باید برای نصب برنامه ها باز باشد",
"completeAppInstallationNotifDescription": "از کاربر می‌خواهد برای پایان نصب برنامه به Obtainium برگردد",
"checkingForUpdates": "بررسی به‌روزرسانی‌ها",
"checkingForUpdatesNotifDescription": "اعلان گذرا که هنگام بررسی به روز رسانی ظاهر می شود",
"pleaseAllowInstallPerm": "لطفاً به Obtainium اجازه دهید برنامه‌ها را نصب کند",
"trackOnly": "فقط ردیابی",
"errorWithHttpStatusCode": "خطا {}",
"versionCorrectionDisabled": "تصحیح نسخه غیرفعال شد (به نظر می رسد افزونه کار نمی کند)",
"unknown": "ناشناخته",
"none": "هیچ",
"never": "هرگز",
"latestVersionX": "آخرین نسخه: {}",
"installedVersionX": "نسخه نصب شده: {}",
"lastUpdateCheckX": "بررسی آخرین به‌روزرسانی: {}",
"remove": "حذف",
"yesMarkUpdated": "بله، علامت گذاری به عنوان به روز شده",
"fdroid": "F-Droid",
"appIdOrName": "شناسه یا نام برنامه",
"appWithIdOrNameNotFound": "هیچ برنامه ای با آن شناسه یا نام یافت نشد",
"reposHaveMultipleApps": "مخازن ممکن است شامل چندین برنامه باشد",
"fdroidThirdPartyRepo": "مخازن شخص ثالث F-Droid",
"steam": "Steam",
"steamMobile": "Steam Mobile",
"steamChat": "Steam Chat",
"install": "نصب",
"markInstalled": "علامت گذاری به عنوان نصب شده",
"update": "به روز رسانی",
"markUpdated": "علامت گذاری به روز شد",
"additionalOptions": "گزینه های اضافی",
"disableVersionDetection": "غیرفعال کردن تشخیص نسخه",
"noVersionDetectionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند.",
"downloadingX": "در حال دانلود {}",
"downloadNotifDescription": "کاربر را از پیشرفت دانلود یک برنامه مطلع می کند",
"noAPKFound": "APK پیدا نشد فایل",
"noVersionDetection": "بدون تشخیص نسخه",
"categorize": "دسته بندی کردن",
"categories": "دسته بندی ها",
"category": "دسته بندی",
"noCategory": "بدون دسته بندی",
"noCategories": "بدون دسته بندی ها",
"deleteCategoriesQuestion": "دسته بندی ها حذف شوند؟",
"categoryDeleteWarning": "همه برنامه‌ها در دسته‌های حذف شده روی دسته‌بندی نشده تنظیم می‌شوند.",
"addCategory": "اضافه کردن دسته",
"label": "برچسب",
"language": "زبان",
"storagePermissionDenied": "مجوز ذخیره سازی رد شد",
"selectedCategorizeWarning": "این جایگزین تنظیمات دسته بندی موجود برای برنامه های انتخابی می شود.",
"filterAPKsByRegEx": "فایل‌های APK را با نظم فیلتر کنید",
"removeFromObtainium": "از Obtainium حذف کنید",
"uninstallFromDevice": "حذف نصب از دستگاه",
"onlyWorksWithNonVersionDetectApps": "فقط برای برنامه‌هایی کار می‌کند که تشخیص نسخه غیرفعال است.",
"removeAppQuestion": {
"one": "برنامه حذف شود؟",
"other": "برنامه ها حذف شوند؟"
},
"tooManyRequestsTryAgainInMinutes": {
"one": "درخواست‌های بسیار زیاد (نرخ محدود) - {} دقیقه دیگر دوباره امتحان کنید",
"other": "درخواست های بسیار زیاد (نرخ محدود) - بعد از {} دقیقه دوباره امتحان کنید"
},
"bgUpdateGotErrorRetryInMinutes": {
"one": "بررسی به‌روزرسانی BG با یک {} مواجه شد، یک بررسی مجدد را در {} دقیقه برنامه‌ریزی می‌کند",
"other": "بررسی به‌روزرسانی BG با {} مواجه شد، یک بررسی مجدد را در {} دقیقه برنامه‌ریزی می‌کند"
},
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
"one": "بررسی به‌روزرسانی BG پیدا شد {} به‌روزرسانی - در صورت نیاز به کاربر اطلاع می‌دهد",
"other": "بررسی به‌روزرسانی BG {} به‌روزرسانی‌های یافت شده - در صورت نیاز به کاربر اطلاع می‌دهد"
},
"apps": {
"one": "برنامه {}",
"other": "{} برنامه ها"
},
"url": {
"one": "{} آدرس اینترنتی",
"other": "{} آدرس های اینترنتی"
},
"minute": {
"one": "{} دقیقه",
"other": "{} دقیقه"
},
"hour": {
"one": "{} ساعت",
"other": "{} ساعت"
},
"day": {
"one": "{} روز",
"other": "{} روز"
},
"clearedNLogsBeforeXAfterY": {
"one": "گزارش {n} پاک شد (قبل از = {پیش از}، بعد = {بعد})",
"other": "{n} گزارش پاک شد (قبل از = {پیش از}، بعد = {بعد})"
},
"xAndNMoreUpdatesAvailable": {
"one": "{} و 1 برنامه دیگر به‌روزرسانی دارند.",
"other": "{} و {} برنامه دیگر به روز رسانی دارند."
},
"xAndNMoreUpdatesInstalled": {
"one": "{} و 1 برنامه دیگر به روز شدند.",
"other": "{} و {} برنامه دیگر به روز شدند."
}
}

View File

@@ -74,7 +74,6 @@
"changeX": "Változás {}", "changeX": "Változás {}",
"installUpdateApps": "Appok telepítése/frissítése", "installUpdateApps": "Appok telepítése/frissítése",
"installUpdateSelectedApps": "Telepítse/frissítse a kiválasztott appokat", "installUpdateSelectedApps": "Telepítse/frissítse a kiválasztott appokat",
"onlyWorksWithNonEVDApps": "Csak azoknál az alkalmazásoknál működik, amelyek telepítési állapota nem észlelhető autom. (nem gyakori).",
"markXSelectedAppsAsUpdated": "Megjelöl {} kiválasztott alkalmazást frissítettként?", "markXSelectedAppsAsUpdated": "Megjelöl {} kiválasztott alkalmazást frissítettként?",
"no": "Nem", "no": "Nem",
"yes": "Igen", "yes": "Igen",
@@ -178,7 +177,6 @@
"installedVersionX": "Telepített verzió: {}", "installedVersionX": "Telepített verzió: {}",
"lastUpdateCheckX": "Frissítés ellenőrizve: {}", "lastUpdateCheckX": "Frissítés ellenőrizve: {}",
"remove": "Eltávolítás", "remove": "Eltávolítás",
"removeAppQuestion": "Eltávolítja az alkalmazást?",
"yesMarkUpdated": "Igen, megjelölés frissítettként", "yesMarkUpdated": "Igen, megjelölés frissítettként",
"fdroid": "F-Droid", "fdroid": "F-Droid",
"appIdOrName": "App ID vagy név", "appIdOrName": "App ID vagy név",
@@ -210,7 +208,14 @@
"language": "Nyelv", "language": "Nyelv",
"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": "Filter APKs by Regular Expression", "filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel",
"removeFromObtainium": "Eltávolítás az Obtainiumbó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.",
"removeAppQuestion": {
"one": "Eltávolítja az alkalmazást?",
"other": "Eltávolítja az alkalmazást?"
},
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "Túl sok kérés (korlátozott arány) próbálja újra {} perc múlva", "one": "Túl sok kérés (korlátozott arány) próbálja újra {} perc múlva",
"other": "Túl sok kérés (korlátozott arány) próbálja újra {} perc múlva" "other": "Túl sok kérés (korlátozott arány) próbálja újra {} perc múlva"

View File

@@ -74,7 +74,6 @@
"changeX": "Modifica {}", "changeX": "Modifica {}",
"installUpdateApps": "Installa/Aggiorna App", "installUpdateApps": "Installa/Aggiorna App",
"installUpdateSelectedApps": "Installa/Aggiorna le App selezionate", "installUpdateSelectedApps": "Installa/Aggiorna le App selezionate",
"onlyWorksWithNonEVDApps": "Funziona solo per le App il cui stato d'installazione non può essere rilevato automaticamente (inconsueto).",
"markXSelectedAppsAsUpdated": "Contrassegnare le {} App selezionate come aggiornate?", "markXSelectedAppsAsUpdated": "Contrassegnare le {} App selezionate come aggiornate?",
"no": "No", "no": "No",
"yes": "Sì", "yes": "Sì",
@@ -178,7 +177,6 @@
"installedVersionX": "Versione installata: {}", "installedVersionX": "Versione installata: {}",
"lastUpdateCheckX": "Ultimo controllo degli aggiornamenti: {}", "lastUpdateCheckX": "Ultimo controllo degli aggiornamenti: {}",
"remove": "Rimuovi", "remove": "Rimuovi",
"removeAppQuestion": "Rimuovere l'App?",
"yesMarkUpdated": "Sì, contrassegna come aggiornato", "yesMarkUpdated": "Sì, contrassegna come aggiornato",
"fdroid": "F-Droid", "fdroid": "F-Droid",
"appIdOrName": "ID o nome dell'App", "appIdOrName": "ID o nome dell'App",
@@ -209,9 +207,16 @@
"addCategory": "Aggiungi categoria", "addCategory": "Aggiungi categoria",
"label": "Etichetta", "label": "Etichetta",
"language": "Lingua", "language": "Lingua",
"storagePermissionDenied": "Storage permission denied", "storagePermissionDenied": "Accesso ai file non autorizzato",
"selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "selectedCategorizeWarning": "Ciò sostituirà le impostazioni di categoria esistenti per le App selezionate.",
"filterAPKsByRegEx": "Filter APKs by Regular Expression", "filterAPKsByRegEx": "Filtra file APK con espressioni regolari",
"removeFromObtainium": "Rimuovi da Obtainium",
"uninstallFromDevice": "Disinstalla dal dispositivo",
"onlyWorksWithNonVersionDetectApps": "Funziona solo per le App con il rilevamento della versione disattivato.",
"removeAppQuestion": {
"one": "Rimuovere l'App?",
"other": "Rimuovere le App?"
},
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "Troppe richieste (traffico limitato) - riprova tra {} minuto", "one": "Troppe richieste (traffico limitato) - riprova tra {} minuto",
"other": "Troppe richieste (traffico limitato) - riprova tra {} minuti" "other": "Troppe richieste (traffico limitato) - riprova tra {} minuti"

View File

@@ -74,7 +74,6 @@
"changeX": "{} を変更する", "changeX": "{} を変更する",
"installUpdateApps": "アプリのインストール/アップデート", "installUpdateApps": "アプリのインストール/アップデート",
"installUpdateSelectedApps": "選択したアプリのインストール/アップデート", "installUpdateSelectedApps": "選択したアプリのインストール/アップデート",
"onlyWorksWithNonEVDApps": "インストール状況を自動検出できないアプリ(一般的でないもの)のみ動作します。",
"markXSelectedAppsAsUpdated": "{}個の選択したアプリをアップデート済みとしてマークしますか?", "markXSelectedAppsAsUpdated": "{}個の選択したアプリをアップデート済みとしてマークしますか?",
"no": "いいえ", "no": "いいえ",
"yes": "はい", "yes": "はい",
@@ -178,7 +177,6 @@
"installedVersionX": "インストールされたバージョン: {}", "installedVersionX": "インストールされたバージョン: {}",
"lastUpdateCheckX": "最終アップデート確認: {}", "lastUpdateCheckX": "最終アップデート確認: {}",
"remove": "削除", "remove": "削除",
"removeAppQuestion": "アプリを削除しますか?",
"yesMarkUpdated": "はい、アップデート済みとしてマークします", "yesMarkUpdated": "はい、アップデート済みとしてマークします",
"fdroid": "F-Droid", "fdroid": "F-Droid",
"appIdOrName": "アプリのIDまたは名前", "appIdOrName": "アプリのIDまたは名前",
@@ -212,6 +210,13 @@
"storagePermissionDenied": "ストレージ権限が拒否されました", "storagePermissionDenied": "ストレージ権限が拒否されました",
"selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。", "selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。",
"filterAPKsByRegEx": "正規表現でAPKを絞り込む", "filterAPKsByRegEx": "正規表現でAPKを絞り込む",
"removeFromObtainium": "Obtainiumから削除する",
"uninstallFromDevice": "デバイスからアンインストールする",
"onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。",
"removeAppQuestion": {
"one": "アプリを削除しますか?",
"other": "アプリを削除しますか?"
},
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "リクエストが多すぎます(レート制限)- {}分後に再試行してください", "one": "リクエストが多すぎます(レート制限)- {}分後に再試行してください",
"other": "リクエストが多すぎます(レート制限)- {}分後に再試行してください" "other": "リクエストが多すぎます(レート制限)- {}分後に再試行してください"

View File

@@ -178,7 +178,6 @@
"installedVersionX": "已安装: {}", "installedVersionX": "已安装: {}",
"lastUpdateCheckX": "最后检查: {}", "lastUpdateCheckX": "最后检查: {}",
"remove": "删除", "remove": "删除",
"removeAppQuestion": "删除应用?",
"yesMarkUpdated": "'是的,标为已更新", "yesMarkUpdated": "'是的,标为已更新",
"fdroid": "F-Droid", "fdroid": "F-Droid",
"appIdOrName": "应用 ID 或名称", "appIdOrName": "应用 ID 或名称",
@@ -212,6 +211,12 @@
"storagePermissionDenied": "存储权限已被拒绝", "storagePermissionDenied": "存储权限已被拒绝",
"selectedCategorizeWarning": "这将取代所选应用程序的任何现有类别", "selectedCategorizeWarning": "这将取代所选应用程序的任何现有类别",
"filterAPKsByRegEx": "Filter APKs by Regular Expression", "filterAPKsByRegEx": "Filter APKs by Regular Expression",
"removeFromObtainium": "Remove from Obtainium",
"uninstallFromDevice": "Uninstall from Device",
"removeAppQuestion": {
"one": "删除应用?",
"other": "删除应用?"
},
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "请求过多 (API 限制) - 在 {} 分钟后重试", "one": "请求过多 (API 限制) - 在 {} 分钟后重试",
"other": "请求过多 (API 限制) - 在 {} 分钟后重试" "other": "请求过多 (API 限制) - 在 {} 分钟后重试"

View File

@@ -21,7 +21,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.10.6'; const String currentVersion = '0.10.10';
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
@@ -33,7 +33,8 @@ const supportedLocales = [
Locale('it'), Locale('it'),
Locale('ja'), Locale('ja'),
Locale('hu'), Locale('hu'),
Locale('de') Locale('de'),
Locale('fa')
]; ];
const fallbackLocale = Locale('en'); const fallbackLocale = Locale('en');
const localeDir = 'assets/translations'; const localeDir = 'assets/translations';

View File

@@ -42,6 +42,8 @@ class _AppPageState extends State<AppPage> {
getUpdate(app.app.id); getUpdate(app.app.id);
} }
var trackOnly = app?.app.additionalSettings['trackOnly'] == true; var trackOnly = app?.app.additionalSettings['trackOnly'] == true;
var noVersionDetection =
app?.app.additionalSettings['noVersionDetection'] == true;
var infoColumn = Column( var infoColumn = Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@@ -190,8 +192,9 @@ class _AppPageState extends State<AppPage> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
if (app?.app.installedVersion != null && if (noVersionDetection &&
!trackOnly && !trackOnly &&
app?.app.installedVersion != null &&
app?.app.installedVersion != app?.app.latestVersion) app?.app.installedVersion != app?.app.latestVersion)
IconButton( IconButton(
onPressed: app?.downloadProgress != null onPressed: app?.downloadProgress != null
@@ -203,13 +206,6 @@ class _AppPageState extends State<AppPage> {
return AlertDialog( return AlertDialog(
title: Text(tr( title: Text(tr(
'alreadyUpToDateQuestion')), 'alreadyUpToDateQuestion')),
content: Text(
tr('onlyWorksWithNonEVDApps'),
style: const TextStyle(
fontWeight:
FontWeight.bold,
fontStyle:
FontStyle.italic)),
actions: [ actions: [
TextButton( TextButton(
onPressed: () { onPressed: () {
@@ -268,7 +264,8 @@ class _AppPageState extends State<AppPage> {
}).toList(); }).toList();
return GeneratedFormModal( return GeneratedFormModal(
title: tr('additionalOptions'), title: tr('additionalOptions'),
items: items); items: items,
);
}).then((values) { }).then((values) {
if (app != null && values != null) { if (app != null && values != null) {
var changedApp = app.app; var changedApp = app.app;
@@ -289,7 +286,15 @@ class _AppPageState extends State<AppPage> {
}); });
}, },
tooltip: tr('additionalOptions'), tooltip: tr('additionalOptions'),
icon: const Icon(Icons.settings)), icon: const Icon(Icons.edit)),
if (app != null && app.installedInfo != null)
IconButton(
onPressed: () {
appsProvider.openAppSettings(app.app.id);
},
icon: const Icon(Icons.settings),
tooltip: tr('settings'),
),
if (app != null && settingsProvider.showAppWebpage) if (app != null && settingsProvider.showAppWebpage)
IconButton( IconButton(
onPressed: () { onPressed: () {
@@ -342,6 +347,8 @@ class _AppPageState extends State<AppPage> {
if (res.isNotEmpty && mounted) { if (res.isNotEmpty && mounted) {
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
}).catchError((e) {
showError(e, context);
}); });
}).catchError((e) { }).catchError((e) {
showError(e, context); showError(e, context);
@@ -361,39 +368,11 @@ class _AppPageState extends State<AppPage> {
onPressed: app?.downloadProgress != null onPressed: app?.downloadProgress != null
? null ? null
: () { : () {
showDialog( appsProvider.removeAppsWithModal(
context: context, context, [app!.app]).then((value) {
builder: (BuildContext ctx) { if (value == true) {
return AlertDialog(
title: Text(tr('removeAppQuestion')),
content: Text(tr(
'xWillBeRemovedButRemainInstalled',
args: [
app?.installedInfo?.name ??
app?.app.name ??
tr('app')
])),
actions: [
TextButton(
onPressed: () {
HapticFeedback
.selectionClick();
appsProvider.removeApps(
[app!.app.id]).then((_) {
int count = 0;
Navigator.of(context)
.popUntil((_) =>
count++ >= 2);
});
},
child: Text(tr('remove'))),
TextButton(
onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, }
child: Text(tr('cancel')))
],
);
}); });
}, },
style: TextButton.styleFrom( style: TextButton.styleFrom(

View File

@@ -389,28 +389,8 @@ class AppsPageState extends State<AppsPage> {
onPressed: selectedApps.isEmpty onPressed: selectedApps.isEmpty
? null ? null
: () { : () {
showDialog<Map<String, dynamic>?>( appsProvider.removeAppsWithModal(
context: context, context, selectedApps.toList());
builder: (BuildContext ctx) {
return GeneratedFormModal(
title: tr(
'removeSelectedAppsQuestion'),
items: const [],
initValid: true,
message: tr(
'xWillBeRemovedButRemainInstalled',
args: [
plural('apps',
selectedApps.length)
]),
);
}).then((values) {
if (values != null) {
appsProvider.removeApps(selectedApps
.map((e) => e.id)
.toList());
}
});
}, },
tooltip: tr('removeSelectedApps'), tooltip: tr('removeSelectedApps'),
icon: const Icon(Icons.delete_outline_outlined), icon: const Icon(Icons.delete_outline_outlined),
@@ -660,7 +640,7 @@ class AppsPageState extends State<AppsPage> {
])), ])),
content: content:
Text( Text(
tr('onlyWorksWithNonEVDApps'), tr('onlyWorksWithNonVersionDetectApps'),
style: const TextStyle(fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), style: const TextStyle(fontWeight: FontWeight.bold, fontStyle: FontStyle.italic),
), ),
actions: [ actions: [
@@ -673,7 +653,7 @@ class AppsPageState extends State<AppsPage> {
onPressed: () { onPressed: () {
HapticFeedback.selectionClick(); HapticFeedback.selectionClick();
appsProvider.saveApps(selectedApps.map((a) { appsProvider.saveApps(selectedApps.map((a) {
if (a.installedVersion != null) { if (a.installedVersion != null && a.additionalSettings['noVersionDetection'] == true) {
a.installedVersion = a.latestVersion; a.installedVersion = a.latestVersion;
} }
return a; return a;

View File

@@ -63,21 +63,29 @@ class _HomePageState extends State<HomePage> {
.map((e) => .map((e) =>
NavigationDestination(icon: Icon(e.icon), label: e.title)) NavigationDestination(icon: Icon(e.icon), label: e.title))
.toList(), .toList(),
onDestinationSelected: (int index) { onDestinationSelected: (int index) async {
HapticFeedback.selectionClick(); HapticFeedback.selectionClick();
setState(() {
if (index == 0) { if (index == 0) {
while ((pages[0].widget.key as GlobalKey<AppsPageState>)
.currentState !=
null) {
// Avoid duplicate GlobalKey error
await Future.delayed(const Duration(microseconds: 1));
}
setState(() {
selectedIndexHistory.clear(); selectedIndexHistory.clear();
});
} else if (selectedIndexHistory.isEmpty || } else if (selectedIndexHistory.isEmpty ||
(selectedIndexHistory.isNotEmpty && (selectedIndexHistory.isNotEmpty &&
selectedIndexHistory.last != index)) { selectedIndexHistory.last != index)) {
setState(() {
int existingInd = selectedIndexHistory.indexOf(index); int existingInd = selectedIndexHistory.indexOf(index);
if (existingInd >= 0) { if (existingInd >= 0) {
selectedIndexHistory.removeAt(existingInd); selectedIndexHistory.removeAt(existingInd);
} }
selectedIndexHistory.add(index); selectedIndexHistory.add(index);
}
}); });
}
}, },
selectedIndex: selectedIndex:
selectedIndexHistory.isEmpty ? 0 : selectedIndexHistory.last, selectedIndexHistory.isEmpty ? 0 : selectedIndexHistory.last,

View File

@@ -5,6 +5,7 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:android_intent_plus/flag.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';
@@ -12,6 +13,8 @@ import 'package:flutter/services.dart';
import 'package:install_plugin_v2/install_plugin_v2.dart'; import 'package:install_plugin_v2/install_plugin_v2.dart';
import 'package:installed_apps/app_info.dart'; import 'package:installed_apps/app_info.dart';
import 'package:installed_apps/installed_apps.dart'; import 'package:installed_apps/installed_apps.dart';
import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/components/generated_form_modal.dart';
import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/logs_provider.dart'; import 'package:obtainium/providers/logs_provider.dart';
import 'package:obtainium/providers/notifications_provider.dart'; import 'package:obtainium/providers/notifications_provider.dart';
@@ -23,6 +26,7 @@ import 'package:path_provider/path_provider.dart';
import 'package:flutter_fgbg/flutter_fgbg.dart'; import 'package:flutter_fgbg/flutter_fgbg.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:android_intent_plus/android_intent.dart';
class AppInMemory { class AppInMemory {
late App app; late App app;
@@ -259,6 +263,15 @@ class AppsProvider with ChangeNotifier {
attemptToCorrectInstallStatus: false); attemptToCorrectInstallStatus: false);
} }
void uninstallApp(String appId) async {
var intent = AndroidIntent(
action: 'android.intent.action.DELETE',
data: 'package:$appId',
flags: <int>[Flag.FLAG_ACTIVITY_NEW_TASK],
package: 'vnd.android.package-archive');
await intent.launch();
}
Future<String?> confirmApkUrl(App app, BuildContext? context) async { Future<String?> confirmApkUrl(App app, BuildContext? context) async {
// If the App has more than one APK, the user should pick one (if context provided) // If the App has more than one APK, the user should pick one (if context provided)
String? apkUrl = app.apkUrls[app.preferredApkIndex]; String? apkUrl = app.apkUrls[app.preferredApkIndex];
@@ -444,9 +457,6 @@ class AppsProvider with ChangeNotifier {
} catch (e) { } catch (e) {
// //
} }
if (!res) {
logs.add(tr('versionCorrectionDisabled'));
}
return res; return res;
} }
@@ -625,6 +635,57 @@ class AppsProvider with ChangeNotifier {
} }
} }
Future<bool> removeAppsWithModal(BuildContext context, List<App> apps) async {
var showUninstallOption =
apps.where((a) => a.installedVersion != null).isNotEmpty;
var values = await showDialog(
context: context,
builder: (BuildContext ctx) {
return GeneratedFormModal(
title: plural('removeAppQuestion', apps.length),
items: !showUninstallOption
? []
: [
[
GeneratedFormSwitch('rmAppEntry',
label: tr('removeFromObtainium'), defaultValue: true)
],
[
GeneratedFormSwitch('uninstallApp',
label: tr('uninstallFromDevice'))
]
],
initValid: true,
);
});
if (values != null) {
bool uninstall = values['uninstallApp'] == true && showUninstallOption;
bool remove = values['rmAppEntry'] == true || !showUninstallOption;
if (uninstall) {
for (var i = 0; i < apps.length; i++) {
if (apps[i].installedVersion != null) {
uninstallApp(apps[i].id);
apps[i].installedVersion = null;
}
}
await saveApps(apps, attemptToCorrectInstallStatus: false);
}
if (remove) {
await removeApps(apps.map((e) => e.id).toList());
}
return uninstall || remove;
}
return false;
}
Future<void> openAppSettings(String appId) async {
final AndroidIntent intent = AndroidIntent(
action: 'action_application_details_settings',
data: 'package:$appId',
);
await intent.launch();
}
Future<App?> checkUpdate(String appId) async { Future<App?> checkUpdate(String appId) async {
App? currentApp = apps[appId]!.app; App? currentApp = apps[appId]!.app;
SourceProvider sourceProvider = SourceProvider(); SourceProvider sourceProvider = SourceProvider();
@@ -710,7 +771,7 @@ class AppsProvider with ChangeNotifier {
exportDir = await getExternalStorageDirectory(); exportDir = await getExternalStorageDirectory();
path = exportDir!.path; path = exportDir!.path;
} }
if ((await DeviceInfoPlugin().androidInfo).version.sdkInt <= 28) { if ((await DeviceInfoPlugin().androidInfo).version.sdkInt <= 29) {
if (await Permission.storage.isDenied) { if (await Permission.storage.isDenied) {
await Permission.storage.request(); await Permission.storage.request();
} }

View File

@@ -9,6 +9,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
android_intent_plus:
dependency: "direct main"
description:
name: android_intent_plus
sha256: ebd110b60723334bdc6eeb373116d6c52e9bed8feb9dcbd9f034531f56636e31
url: "https://pub.dev"
source: hosted
version: "3.1.5"
animations: animations:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -101,10 +109,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: cross_file name: cross_file
sha256: f71079978789bc2fe78d79227f1f8cfe195b31bbd8db2399b0d15a4b96fb843b sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.3+2" version: "0.3.3+4"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@@ -157,10 +165,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: dynamic_color name: dynamic_color
sha256: "37a15576f5a0bfd5555b613cf20ea3bd379607cf88d457374a16032f4e942174" sha256: c4a508284b14ec4dda5adba2c28b2cdd34fbae1afead7e8c52cad87d51c5405b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.4" version: "1.6.2"
easy_localization: easy_localization:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -609,10 +617,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "1ffa239043ab8baf881ec3094a3c767af9d10399b2839020b9e4d44c0bb23951" sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.3"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
@@ -830,10 +838,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_android name: webview_flutter_android
sha256: "9d97fa2bae0f1900553c48a2ef0aaa3864367fd7bb625d683c460754b691312c" sha256: "5f49a6e5fc59e21fcec5e1bbcd401afbee9792a24a4f3d9cef9b5bb0cd1e3767"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.1" version: "3.2.4"
webview_flutter_platform_interface: webview_flutter_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -846,10 +854,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: "523aff9168af9bb2170e4809e0499d7dee065c3919799fd3341d3e616c137960" sha256: "92e7e7fa468f1df597fb9d37bcf1f303175cbe147c4dbdf06ecc323d950116eb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2" version: "3.0.5"
win32: win32:
dependency: transitive dependency: transitive
description: description:
@@ -883,5 +891,5 @@ packages:
source: hosted source: hosted
version: "3.1.1" version: "3.1.1"
sdks: sdks:
dart: ">=2.18.2 <4.0.0" dart: ">=2.18.2 <3.0.0"
flutter: ">=3.3.0" flutter: ">=3.4.0-17.0.pre"

View File

@@ -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.10.6+112 # When changing this, update the tag in main() accordingly version: 0.10.10+116 # 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'
@@ -58,6 +58,7 @@ dependencies:
android_alarm_manager_plus: ^2.1.0 android_alarm_manager_plus: ^2.1.0
sqflite: ^2.2.0+3 sqflite: ^2.2.0+3
easy_localization: ^3.0.1 easy_localization: ^3.0.1
android_intent_plus: ^3.1.5
dev_dependencies: dev_dependencies: