Compare commits

..

21 Commits

Author SHA1 Message Date
Imran
c0968e8991 Merge pull request #2008 from ImranR98/dev
- Fix broken "Download Asset" function for HTML source (#1998)
- Add "refresh before download" (#1943)
- Remove WhatsApp, VLC, and Telegram App sources - no longer needed as HTML source sufficient (#1943)
2024-12-08 16:41:24 -05:00
Imran Remtulla
243b1eb2ac Update packages, increment version 2024-12-08 16:39:26 -05:00
Imran Remtulla
c6c61d1c83 Merge remote-tracking branch 'origin/main' into dev 2024-12-08 16:37:08 -05:00
Imran
f207967411 Merge pull request #1995 from ygxbnet/patch-2
Update zh.json
2024-12-08 16:36:56 -05:00
Imran Remtulla
29bb5cc8cd Removed Telegram App 2024-12-08 16:36:46 -05:00
Imran Remtulla
dbbc2ff19c Removed VLC (#1943) 2024-12-08 16:21:36 -05:00
Imran Remtulla
c012b016f9 Add "refresh before download" + remove WhatsApp (#1943) 2024-12-08 15:58:44 -05:00
Imran Remtulla
22815b8209 Minor bug 2024-12-08 14:53:31 -05:00
Imran Remtulla
619d4f1a51 Fix broken "Download Asset" function for HTML source (#1998) 2024-12-08 13:47:32 -05:00
YGXB_net
50e8929763 Update zh.json 2024-11-30 21:49:58 +08:00
Imran
0e2a0b65ec Merge pull request #1990 from ImranR98/dev
- Improved XAPK Support (#682)
- Custom user-agent for APKMirror (as per feedback in #1973)
- Minor change to German translation (#1986)
2024-11-23 16:31:46 -05:00
Imran Remtulla
5b79f399d1 Minor change to German translation (#1986) 2024-11-23 16:29:10 -05:00
Imran Remtulla
2961d5ac17 Merge remote-tracking branch 'origin/main' into dev 2024-11-23 16:27:21 -05:00
Imran Remtulla
4af4160aaa Increment version 2024-11-23 16:27:11 -05:00
Imran Remtulla
327f73cc9e More changes for XAPK support (#682) 2024-11-23 16:26:11 -05:00
Imran Remtulla
e82170fec6 Improved XAPK Support (#682) 2024-11-23 16:05:02 -05:00
Imran Remtulla
8922b1c048 Custom user-agent for APKMirror (as per feedback in #1973) 2024-11-23 15:26:58 -05:00
Imran
e9550c6ff0 Merge pull request #1980 from Hamster45105/wiki-links
Update wiki links
2024-11-23 01:53:07 -05:00
Hamish
890c3682c4 Update wiki links 2024-11-23 17:17:04 +11:00
Imran
a2c38968e1 Merge pull request #1977 from summoner001/main
Update hu.json
2024-11-15 13:14:29 -05:00
summoner001
a9c3ee4c54 Update hu.json
Correcting translation.
2024-11-15 14:34:01 +01:00
37 changed files with 230 additions and 248 deletions

View File

@@ -7,7 +7,7 @@ Get Android app updates straight from the source.
Obtainium allows you to install and update apps directly from their releases pages, and receive notifications when new releases are made available. Obtainium allows you to install and update apps directly from their releases pages, and receive notifications when new releases are made available.
More info: More info:
- [Obtainium Wiki](https://github.com/ImranR98/Obtainium/wiki) - [Obtainium Wiki](https://wiki.obtainium.imranr.dev/) ([repository](https://github.com/ImranR98/Obtainium-Wiki))
- [AppVerifier](https://github.com/soupslurpr/AppVerifier) - App verification tool (recommended, integrates with Obtainium) - [AppVerifier](https://github.com/soupslurpr/AppVerifier) - App verification tool (recommended, integrates with Obtainium)
- [apps.obtainium.imranr.dev](https://apps.obtainium.imranr.dev/) - Crowdsourced app configurations ([repository](https://github.com/ImranR98/apps.obtainium.imranr.dev)) - [apps.obtainium.imranr.dev](https://apps.obtainium.imranr.dev/) - Crowdsourced app configurations ([repository](https://github.com/ImranR98/apps.obtainium.imranr.dev))
- [Side Of Burritos - You should use this instead of F-Droid | How to use app RSS feed](https://youtu.be/FFz57zNR_M0) - Original motivation for this app - [Side Of Burritos - You should use this instead of F-Droid | How to use app RSS feed](https://youtu.be/FFz57zNR_M0) - Original motivation for this app
@@ -31,11 +31,7 @@ Currently supported App sources:
- [Tencent App Store](https://sj.qq.com/) - [Tencent App Store](https://sj.qq.com/)
- Jenkins Jobs - Jenkins Jobs
- [APKMirror](https://apkmirror.com/) (Track-Only) - [APKMirror](https://apkmirror.com/) (Track-Only)
- Open Source - App-Specific:
- [VLC](https://videolan.org/)
- Other - App-Specific: - Other - App-Specific:
- [WhatsApp](https://whatsapp.com)
- [Telegram App](https://telegram.org)
- [Neutron Code](https://neutroncode.com) - [Neutron Code](https://neutroncode.com)
- Direct APK Link - Direct APK Link
- "HTML" (Fallback): Any other URL that returns an HTML page with links to APK files - "HTML" (Fallback): Any other URL that returns an HTML page with links to APK files

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourced App Configs", "crowdsourcedConfigsShort": "Crowdsourced App Configs",
"allowInsecure": "Allow insecure HTTP requests", "allowInsecure": "Allow insecure HTTP requests",
"stayOneVersionBehind": "Stay one version behind latest", "stayOneVersionBehind": "Stay one version behind latest",
"refreshBeforeDownload": "Refresh app details before download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Želite li ukloniti aplikaciju?", "one": "Želite li ukloniti aplikaciju?",
"other": "Želite li ukloniti aplikacije?" "other": "Želite li ukloniti aplikacije?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Konfigurace aplikací s využitím crowdsourcingu", "crowdsourcedConfigsShort": "Konfigurace aplikací s využitím crowdsourcingu",
"allowInsecure": "Povolení nezabezpečených požadavků HTTP", "allowInsecure": "Povolení nezabezpečených požadavků HTTP",
"stayOneVersionBehind": "Zůstaňte o jednu verzi pozadu za nejnovější", "stayOneVersionBehind": "Zůstaňte o jednu verzi pozadu za nejnovější",
"refreshBeforeDownload": "Obnovení údajů o aplikaci před stažením",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Odstranit Apku?", "one": "Odstranit Apku?",
"other": "Odstranit Apky?" "other": "Odstranit Apky?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourcede app-konfigurationer", "crowdsourcedConfigsShort": "Crowdsourcede app-konfigurationer",
"allowInsecure": "Tillad usikre HTTP-anmodninger", "allowInsecure": "Tillad usikre HTTP-anmodninger",
"stayOneVersionBehind": "Forbliv én version bagud den seneste", "stayOneVersionBehind": "Forbliv én version bagud den seneste",
"refreshBeforeDownload": "Opdater app-detaljer før download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Fjern app?", "one": "Fjern app?",
"other": "Fjern apps?" "other": "Fjern apps?"

View File

@@ -114,7 +114,7 @@
"light": "Hell", "light": "Hell",
"followSystem": "System folgen", "followSystem": "System folgen",
"followSystemThemeExplanation": "Das Folgen des Systemthemes ist unter Android < 10 nur mit Hilfe von Drittanbieterapps möglich", "followSystemThemeExplanation": "Das Folgen des Systemthemes ist unter Android < 10 nur mit Hilfe von Drittanbieterapps möglich",
"useBlackTheme": "Pure Black Dark Theme verwenden", "useBlackTheme": "Rein schwarzen Hintergrund verwenden",
"appSortBy": "App sortieren nach", "appSortBy": "App sortieren nach",
"authorName": "Autor/Name", "authorName": "Autor/Name",
"nameAuthor": "Name/Autor", "nameAuthor": "Name/Autor",
@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourced App-Konfigurationen", "crowdsourcedConfigsShort": "Crowdsourced App-Konfigurationen",
"allowInsecure": "Unsichere HTTP-Anfragen zulassen", "allowInsecure": "Unsichere HTTP-Anfragen zulassen",
"stayOneVersionBehind": "Eine Version hinter der neuesten Version bleiben", "stayOneVersionBehind": "Eine Version hinter der neuesten Version bleiben",
"refreshBeforeDownload": "App-Details vor dem Download aktualisieren",
"removeAppQuestion": { "removeAppQuestion": {
"one": "App entfernen?", "one": "App entfernen?",
"other": "Apps entfernen?" "other": "Apps entfernen?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourced App Configs", "crowdsourcedConfigsShort": "Crowdsourced App Configs",
"allowInsecure": "Allow insecure HTTP requests", "allowInsecure": "Allow insecure HTTP requests",
"stayOneVersionBehind": "Stay one version behind latest", "stayOneVersionBehind": "Stay one version behind latest",
"refreshBeforeDownload": "Refresh app details before download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Forigi la aplikaĵon?", "one": "Forigi la aplikaĵon?",
"other": "Forigi la aplikaĵojn?" "other": "Forigi la aplikaĵojn?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourced App Configs", "crowdsourcedConfigsShort": "Crowdsourced App Configs",
"allowInsecure": "Allow insecure HTTP requests", "allowInsecure": "Allow insecure HTTP requests",
"stayOneVersionBehind": "Stay one version behind latest", "stayOneVersionBehind": "Stay one version behind latest",
"refreshBeforeDownload": "Refresh app details before download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remove App?", "one": "Remove App?",
"other": "Remove Apps?" "other": "Remove Apps?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Configuración de aplicaciones por crowdsourcing", "crowdsourcedConfigsShort": "Configuración de aplicaciones por crowdsourcing",
"allowInsecure": "Permitir peticiones HTTP inseguras", "allowInsecure": "Permitir peticiones HTTP inseguras",
"stayOneVersionBehind": "Mantenerse una versión por detrás de la última", "stayOneVersionBehind": "Mantenerse una versión por detrás de la última",
"refreshBeforeDownload": "Actualiza los datos de la aplicación antes de descargarla",
"removeAppQuestion": { "removeAppQuestion": {
"one": "¿Eliminar aplicación?", "one": "¿Eliminar aplicación?",
"other": "¿Eliminar aplicaciones?" "other": "¿Eliminar aplicaciones?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourced App Configs", "crowdsourcedConfigsShort": "Crowdsourced App Configs",
"allowInsecure": "درخواست های HTTP ناامن را مجاز کنید", "allowInsecure": "درخواست های HTTP ناامن را مجاز کنید",
"stayOneVersionBehind": "Stay one version behind latest", "stayOneVersionBehind": "Stay one version behind latest",
"refreshBeforeDownload": "Refresh app details before download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "برنامه حذف شود؟", "one": "برنامه حذف شود؟",
"other": "برنامه ها حذف شوند؟" "other": "برنامه ها حذف شوند؟"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Applis communautaires", "crowdsourcedConfigsShort": "Applis communautaires",
"allowInsecure": "Autoriser les requêtes HTTP non sécurisées", "allowInsecure": "Autoriser les requêtes HTTP non sécurisées",
"stayOneVersionBehind": "Rester à une version de la dernière", "stayOneVersionBehind": "Rester à une version de la dernière",
"refreshBeforeDownload": "Actualiser les détails de l'application avant de la télécharger",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Supprimer l'application?", "one": "Supprimer l'application?",
"other": "Supprimer les applications?" "other": "Supprimer les applications?"

View File

@@ -213,7 +213,7 @@
"releaseDateAsVersion": "Használja a kiadás dátumát verzió-karakterláncként", "releaseDateAsVersion": "Használja a kiadás dátumát verzió-karakterláncként",
"releaseTitleAsVersion": "Használja a kiadás címét verzió-karakterláncként", "releaseTitleAsVersion": "Használja a kiadás címét verzió-karakterláncként",
"releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió-érzékelés nem működik megfelelően, de elérhető a kiadás dátuma.", "releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió-érzékelés nem működik megfelelően, de elérhető a kiadás dátuma.",
"changes": "Változásnapló", "changes": "Változáslista",
"releaseDate": "Kiadás dátuma", "releaseDate": "Kiadás dátuma",
"importFromURLsInFile": "Importálás fájlban található webcímből (pl. OPML)", "importFromURLsInFile": "Importálás fájlban található webcímből (pl. OPML)",
"versionDetectionExplanation": "A verzió-karakterlánc egyeztetése az rendszer által érzékelt verzióval", "versionDetectionExplanation": "A verzió-karakterlánc egyeztetése az rendszer által érzékelt verzióval",
@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourced App Configs", "crowdsourcedConfigsShort": "Crowdsourced App Configs",
"allowInsecure": "Nem biztonságos HTTP-kérések engedélyezése", "allowInsecure": "Nem biztonságos HTTP-kérések engedélyezése",
"stayOneVersionBehind": "Maradjon egy verzióval a legújabb mögött", "stayOneVersionBehind": "Maradjon egy verzióval a legújabb mögött",
"refreshBeforeDownload": "Az alkalmazás adatainak frissítése letöltés előtt",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Eltávolítja az alkalmazást?", "one": "Eltávolítja az alkalmazást?",
"other": "Eltávolítja az alkalmazásokat?" "other": "Eltávolítja az alkalmazásokat?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Konfigurasi Aplikasi Crowdsourced", "crowdsourcedConfigsShort": "Konfigurasi Aplikasi Crowdsourced",
"allowInsecure": "Izinkan permintaan HTTP yang tidak aman", "allowInsecure": "Izinkan permintaan HTTP yang tidak aman",
"stayOneVersionBehind": "Tetap satu versi di belakang versi terbaru", "stayOneVersionBehind": "Tetap satu versi di belakang versi terbaru",
"refreshBeforeDownload": "Segarkan detail aplikasi sebelum mengunduh",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Hapus aplikasi?", "one": "Hapus aplikasi?",
"other": "Hapus aplikasi?" "other": "Hapus aplikasi?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Configurazioni di app in crowdsourcing", "crowdsourcedConfigsShort": "Configurazioni di app in crowdsourcing",
"allowInsecure": "Consentire le richieste HTTP non sicure", "allowInsecure": "Consentire le richieste HTTP non sicure",
"stayOneVersionBehind": "Rimanere una versione indietro rispetto alla più recente", "stayOneVersionBehind": "Rimanere una versione indietro rispetto alla più recente",
"refreshBeforeDownload": "Aggiornare i dettagli dell'app prima del download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Rimuovere l'app?", "one": "Rimuovere l'app?",
"other": "Rimuovere le app?" "other": "Rimuovere le app?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "クラウドソーシングによるアプリの設定", "crowdsourcedConfigsShort": "クラウドソーシングによるアプリの設定",
"allowInsecure": "安全でないHTTPリクエストを許可する", "allowInsecure": "安全でないHTTPリクエストを許可する",
"stayOneVersionBehind": "最新のバージョンから1つ前のものを使用する", "stayOneVersionBehind": "最新のバージョンから1つ前のものを使用する",
"refreshBeforeDownload": "ダウンロード前にアプリの詳細を更新する",
"removeAppQuestion": { "removeAppQuestion": {
"one": "アプリを削除しますか?", "one": "アプリを削除しますか?",
"other": "アプリを削除しますか?" "other": "アプリを削除しますか?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "App-configuraties door menigte", "crowdsourcedConfigsShort": "App-configuraties door menigte",
"allowInsecure": "Onveilige HTTP-verzoeken toestaan", "allowInsecure": "Onveilige HTTP-verzoeken toestaan",
"stayOneVersionBehind": "Blijf een versie achter op de nieuwste", "stayOneVersionBehind": "Blijf een versie achter op de nieuwste",
"refreshBeforeDownload": "Vernieuw app details voor download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "App verwijderen?", "one": "App verwijderen?",
"other": "Apps verwijderen?" "other": "Apps verwijderen?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Baza konfiguracji", "crowdsourcedConfigsShort": "Baza konfiguracji",
"allowInsecure": "Zezwalaj na niezabezpieczone żądania HTTP", "allowInsecure": "Zezwalaj na niezabezpieczone żądania HTTP",
"stayOneVersionBehind": "Pozostań jedną wersję w tyle za najnowszą", "stayOneVersionBehind": "Pozostań jedną wersję w tyle za najnowszą",
"refreshBeforeDownload": "Odśwież szczegóły aplikacji przed pobraniem",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Usunąć aplikację?", "one": "Usunąć aplikację?",
"few": "Usunąć aplikacje?", "few": "Usunąć aplikacje?",

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Configurações de aplicações com base em crowdsourcing", "crowdsourcedConfigsShort": "Configurações de aplicações com base em crowdsourcing",
"allowInsecure": "Permitir pedidos HTTP inseguros", "allowInsecure": "Permitir pedidos HTTP inseguros",
"stayOneVersionBehind": "Manter-se uma versão atrás da mais recente", "stayOneVersionBehind": "Manter-se uma versão atrás da mais recente",
"refreshBeforeDownload": "Atualizar os detalhes da aplicação antes da transferência",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remover aplicativo?", "one": "Remover aplicativo?",
"other": "Remover aplicativos?" "other": "Remover aplicativos?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Конфиги приложений с помощью краудсорсинга", "crowdsourcedConfigsShort": "Конфиги приложений с помощью краудсорсинга",
"allowInsecure": "Разрешить небезопасные HTTP-запросы", "allowInsecure": "Разрешить небезопасные HTTP-запросы",
"stayOneVersionBehind": "Не отставайте от последней версии", "stayOneVersionBehind": "Не отставайте от последней версии",
"refreshBeforeDownload": "Обновляйте информацию о приложении перед загрузкой",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Удалить приложение?", "one": "Удалить приложение?",
"other": "Удалить приложения?" "other": "Удалить приложения?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Appkonfigurationer med hjälp av crowdsourcing", "crowdsourcedConfigsShort": "Appkonfigurationer med hjälp av crowdsourcing",
"allowInsecure": "Tillåt osäkra HTTP-förfrågningar", "allowInsecure": "Tillåt osäkra HTTP-förfrågningar",
"stayOneVersionBehind": "Håll dig en version bakom den senaste", "stayOneVersionBehind": "Håll dig en version bakom den senaste",
"refreshBeforeDownload": "Uppdatera appdetaljerna före nedladdning",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Ta Bort App?", "one": "Ta Bort App?",
"other": "Ta Bort Appar?" "other": "Ta Bort Appar?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Kitle Kaynaklı Uygulama Yapılandırmaları", "crowdsourcedConfigsShort": "Kitle Kaynaklı Uygulama Yapılandırmaları",
"allowInsecure": "Güvensiz HTTP isteklerine izin ver", "allowInsecure": "Güvensiz HTTP isteklerine izin ver",
"stayOneVersionBehind": "En son sürümün bir sürüm gerisinde kalın", "stayOneVersionBehind": "En son sürümün bir sürüm gerisinde kalın",
"refreshBeforeDownload": "İndirmeden önce uygulama ayrıntılarını yenileyin",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Uygulamayı Kaldır?", "one": "Uygulamayı Kaldır?",
"other": "Uygulamaları Kaldır?" "other": "Uygulamaları Kaldır?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Налаштування краудсорсингових додатків", "crowdsourcedConfigsShort": "Налаштування краудсорсингових додатків",
"allowInsecure": "Дозволити незахищені HTTP-запити", "allowInsecure": "Дозволити незахищені HTTP-запити",
"stayOneVersionBehind": "Залишайтеся на одну версію актуальнішою", "stayOneVersionBehind": "Залишайтеся на одну версію актуальнішою",
"refreshBeforeDownload": "Оновіть інформацію про програму перед завантаженням",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Видалити застосунок?", "one": "Видалити застосунок?",
"other": "Видалити застосунки?" "other": "Видалити застосунки?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourced App Configs", "crowdsourcedConfigsShort": "Crowdsourced App Configs",
"allowInsecure": "Allow insecure HTTP requests", "allowInsecure": "Allow insecure HTTP requests",
"stayOneVersionBehind": "Stay one version behind latest", "stayOneVersionBehind": "Stay one version behind latest",
"refreshBeforeDownload": "Refresh app details before download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Gỡ ứng dụng?", "one": "Gỡ ứng dụng?",
"other": "Gỡ ứng dụng?" "other": "Gỡ ứng dụng?"

View File

@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "Crowdsourced App Configs", "crowdsourcedConfigsShort": "Crowdsourced App Configs",
"allowInsecure": "Allow insecure HTTP requests", "allowInsecure": "Allow insecure HTTP requests",
"stayOneVersionBehind": "Stay one version behind latest", "stayOneVersionBehind": "Stay one version behind latest",
"refreshBeforeDownload": "Refresh app details before download",
"removeAppQuestion": { "removeAppQuestion": {
"one": "移除應用程式?", "one": "移除應用程式?",
"other": "移除應用程式?" "other": "移除應用程式?"

View File

@@ -186,10 +186,10 @@
"additionalOptions": "附加选项", "additionalOptions": "附加选项",
"disableVersionDetection": "禁用版本检测", "disableVersionDetection": "禁用版本检测",
"noVersionDetectionExplanation": "此选项应该仅用于无法进行版本检测的应用。", "noVersionDetectionExplanation": "此选项应该仅用于无法进行版本检测的应用。",
"downloadingX": "正在下载{}", "downloadingX": "正在下载 {}",
"downloadX": "下载 {}", "downloadX": "下载 {}",
"downloadedX": "下载 {}", "downloadedX": "下载 {}",
"releaseAsset": "发行版附件", "releaseAsset": "发行件",
"downloadNotifDescription": "提示应用的下载进度", "downloadNotifDescription": "提示应用的下载进度",
"noAPKFound": "未找到 APK 文件", "noAPKFound": "未找到 APK 文件",
"noVersionDetection": "禁用版本检测", "noVersionDetection": "禁用版本检测",
@@ -317,6 +317,7 @@
"crowdsourcedConfigsShort": "众包应用程序配置", "crowdsourcedConfigsShort": "众包应用程序配置",
"allowInsecure": "允许不安全的 HTTP 请求", "allowInsecure": "允许不安全的 HTTP 请求",
"stayOneVersionBehind": "比最新版本晚一个版本", "stayOneVersionBehind": "比最新版本晚一个版本",
"refreshBeforeDownload": "下载前刷新应用程序详细信息",
"removeAppQuestion": { "removeAppQuestion": {
"one": "是否删除应用?", "one": "是否删除应用?",
"other": "是否删除应用?" "other": "是否删除应用?"

View File

@@ -1,5 +1,5 @@
<p>Obtainium allows you to install and update Apps directly from their releases pages, and receive notifications when new releases are made available.</p> <p>Obtainium allows you to install and update Apps directly from their releases pages, and receive notifications when new releases are made available.</p>
<p>Read the <a href="https://github.com/ImranR98/Obtainium/wiki">Wiki</a></p> <p>Read the <a href="https://wiki.obtainium.imranr.dev/">Wiki</a></p>
<p> <p>
<b>Currently supported App sources:</b> <b>Currently supported App sources:</b>
</p> </p>

View File

@@ -1,5 +1,5 @@
<p>Obtainium позволяет вам устанавливать и обновлять приложения прямо с их объявлений о выпусках и получать уведомления о новых выпусках.</p> <p>Obtainium позволяет вам устанавливать и обновлять приложения прямо с их объявлений о выпусках и получать уведомления о новых выпусках.</p>
<p>Для деталей читайте <a href="https://github.com/ImranR98/Obtainium/wiki">Вики</a></p> <p>Для деталей читайте <a href="https://wiki.obtainium.imranr.dev/">Вики</a></p>
<p> <p>
<b>Поддерживаемые источники приложений:</b> <b>Поддерживаемые источники приложений:</b>
</p> </p>

View File

@@ -5,6 +5,8 @@ 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/components/generated_form.dart';
import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/apps_provider.dart';
import 'package:obtainium/providers/settings_provider.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
class APKMirror extends AppSource { class APKMirror extends AppSource {
@@ -31,6 +33,16 @@ class APKMirror extends AppSource {
]; ];
} }
@override
Future<Map<String, String>?> getRequestHeaders(
Map<String, dynamic> additionalSettings,
{bool forAPKDownload = false}) async {
return {
"User-Agent":
"Obtainium/${(await getInstalledInfo(obtainiumId))?.versionName ?? '1.0.0'}"
};
}
@override @override
String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) { String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) {
RegExp standardUrlRegEx = RegExp( RegExp standardUrlRegEx = RegExp(

View File

@@ -105,11 +105,7 @@ class APKPure extends AppSource {
.map((e) => e.text.trim()) .map((e) => e.text.trim())
.map((t) => t == 'APKs' ? 'APK' : t) ?? .map((t) => t == 'APKs' ? 'APK' : t) ??
[]; [];
String type = types.isEmpty String type = types.isEmpty ? 'APK' : types.first;
? 'APK'
: types.length == 1
? types.first
: types.last;
String? dateString = apkInfo String? dateString = apkInfo
?.querySelector('div.info-bottom span.time') ?.querySelector('div.info-bottom span.time')
?.text ?.text

View File

@@ -7,6 +7,9 @@ import 'package:obtainium/providers/apps_provider.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
String ensureAbsoluteUrl(String ambiguousUrl, Uri referenceAbsoluteUrl) { String ensureAbsoluteUrl(String ambiguousUrl, Uri referenceAbsoluteUrl) {
if (ambiguousUrl.startsWith('//')) {
ambiguousUrl = '${referenceAbsoluteUrl.scheme}:$ambiguousUrl';
}
try { try {
Uri.parse(ambiguousUrl).origin; Uri.parse(ambiguousUrl).origin;
return ambiguousUrl; return ambiguousUrl;
@@ -353,7 +356,12 @@ class HTML extends AppSource {
forAPKDownload: true), forAPKDownload: true),
allowInsecure: additionalSettings['allowInsecure'] == true)) allowInsecure: additionalSettings['allowInsecure'] == true))
.toString(); .toString();
return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(), return APKDetails(
version,
[rel]
.map((e) =>
MapEntry('${e.hashCode}-${Uri.parse(e).pathSegments.last}', e))
.toList(),
AppNames(uri.host, tr('app'))); AppNames(uri.host, tr('app')));
} }
} }

View File

@@ -1,110 +0,0 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:html/parser.dart';
import 'package:http/http.dart';
import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/source_provider.dart';
class VLC extends AppSource {
VLC() {
hosts = ['videolan.org'];
}
get dwUrlBase => 'https://get.${hosts[0]}/vlc-android/';
@override
Future<Map<String, String>?> getRequestHeaders(
Map<String, dynamic> additionalSettings,
{bool forAPKDownload = false}) async {
return {
"User-Agent":
"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"
};
}
@override
String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) {
return 'https://${hosts[0]}';
}
Future<String?> getLatestVersion(
String standardUrl, Map<String, dynamic> additionalSettings) async {
Response res = await sourceRequest(dwUrlBase, additionalSettings);
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
Future<APKDetails> getLatestAPKDetails(
String standardUrl,
Map<String, dynamic> additionalSettings,
) async {
Response res = await get(
Uri.parse('https://www.videolan.org/vlc/download-android.html'));
if (res.statusCode == 200) {
var dwUrlBase = 'get.videolan.org/vlc-android';
var dwLinks = parse(res.body)
.querySelectorAll('a')
.where((element) =>
element.attributes['href']?.contains(dwUrlBase) ?? false)
.toList();
String? version = dwLinks.isNotEmpty
? dwLinks.first.attributes['href']
?.split('/')
.where((s) => s.isNotEmpty)
.last
: null;
if (version == null) {
throw NoVersionError();
}
String? targetUrl = 'https://$dwUrlBase/$version/';
var apkUrls = ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']
.map((e) => '${targetUrl}VLC-Android-$version-$e.apk')
.toList();
return APKDetails(
version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC'));
} else {
throw getObtainiumHttpError(res);
}
}
@override
Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
Map<String, dynamic> additionalSettings) async {
Response res = await sourceRequest(apkUrl, additionalSettings);
if (res.statusCode == 200) {
String? apkUrl =
parse(res.body).querySelector('#alt_link')?.attributes['href'];
if (apkUrl == null) {
throw NoAPKError();
}
return apkUrl;
} else if (res.statusCode == 500 &&
res.body.toLowerCase().indexOf('mirror') > 0) {
var html = parse(res.body);
var err = '';
html.body?.nodes.forEach((element) {
if (element.text != null) {
err += '${element.text}\n';
}
});
err = err.trim();
if (err.isEmpty) {
err = tr('err');
}
throw ObtainiumError(err);
} else {
throw getObtainiumHttpError(res);
}
}
}

View File

@@ -1,55 +0,0 @@
import 'package:html/parser.dart';
import 'package:http/http.dart';
import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/source_provider.dart';
class WhatsApp extends AppSource {
WhatsApp() {
hosts = ['whatsapp.com'];
versionDetectionDisallowed = true;
}
@override
String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) {
return 'https://${hosts[0]}';
}
@override
Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
Map<String, dynamic> additionalSettings) async {
Response res =
await sourceRequest('$standardUrl/android', additionalSettings);
if (res.statusCode == 200) {
var targetLinks = parse(res.body)
.querySelectorAll('a')
.map((e) => e.attributes['href'] ?? '')
.where((e) => e.isNotEmpty)
.where((e) => e.contains('WhatsApp.apk'))
.toList();
if (targetLinks.isEmpty) {
throw NoAPKError();
}
return targetLinks[0];
} else {
throw getObtainiumHttpError(res);
}
}
@override
Future<APKDetails> getLatestAPKDetails(
String standardUrl,
Map<String, dynamic> additionalSettings,
) async {
// This is a CDN link that is consistent per version
// But it has query params that change constantly
Uri apkUri = Uri.parse(await apkUrlPrefetchModifier(
standardUrl, standardUrl, additionalSettings));
var unusableApkUrl = '${apkUri.origin}/${apkUri.path}';
// So we use the param-less URL is a pseudo-version to add the app and check for updates
// See #357 for why we can't scrape the version number directly
// But we re-fetch the URL again with its latest query params at the actual download time
String version = unusableApkUrl.hashCode.toString();
return APKDetails(version, getApkUrlsFromUrls([unusableApkUrl]),
AppNames('Meta', 'WhatsApp'));
}
}

View File

@@ -886,7 +886,7 @@ class _SettingsPageState extends State<SettingsPage> {
), ),
IconButton( IconButton(
onPressed: () { onPressed: () {
launchUrlString('${settingsProvider.sourceUrl}/wiki', launchUrlString('https://wiki.obtainium.imranr.dev/',
mode: LaunchMode.externalApplication); mode: LaunchMode.externalApplication);
}, },
icon: const Icon(Icons.help_outline_rounded), icon: const Icon(Icons.help_outline_rounded),

View File

@@ -516,11 +516,29 @@ class AppsProvider with ChangeNotifier {
.listSync() .listSync()
.where((e) => e.path.toLowerCase().endsWith('.apk')) .where((e) => e.path.toLowerCase().endsWith('.apk'))
.toList(); .toList();
FileSystemEntity? temp;
apks.removeWhere((element) {
bool res = element.uri.pathSegments.last.startsWith(app.id);
if (res) {
temp = element;
}
return res;
});
if (temp != null) {
apks = [
temp!,
...apks,
];
}
for (var i = 0; i < apks.length; i++) { for (var i = 0; i < apks.length; i++) {
try { try {
newInfo = await pm.getPackageArchiveInfo( newInfo =
archiveFilePath: apks.first.path); await pm.getPackageArchiveInfo(archiveFilePath: apks[i].path);
break; if (newInfo != null) {
break;
}
} catch (e) { } catch (e) {
if (i == apks.length - 1) { if (i == apks.length - 1) {
rethrow; rethrow;
@@ -644,28 +662,47 @@ class AppsProvider with ChangeNotifier {
var somethingInstalled = false; var somethingInstalled = false;
try { try {
MultiAppMultiError errors = MultiAppMultiError(); MultiAppMultiError errors = MultiAppMultiError();
List<File> APKFiles = [];
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 { APKFiles.add(file);
somethingInstalled = somethingInstalled ||
await installApk(
DownloadedApk(dir.appId, file), firstTimeWithContext,
needsBGWorkaround: needsBGWorkaround,
shizukuPretendToBeGooglePlay: shizukuPretendToBeGooglePlay);
} catch (e) {
logs.add(
'Could not install APK from XAPK \'${file.path}\': ${e.toString()}');
errors.add(dir.appId, e, appName: apps[dir.appId]?.name);
}
} else if (file.path.toLowerCase().endsWith('.obb')) { } else if (file.path.toLowerCase().endsWith('.obb')) {
await moveObbFile(file, dir.appId); await moveObbFile(file, dir.appId);
} }
} }
if (somethingInstalled) {
File? temp;
APKFiles.removeWhere((element) {
bool res = element.uri.pathSegments.last.startsWith(dir.appId);
if (res) {
temp = element;
}
return res;
});
if (temp != null) {
APKFiles = [
temp!,
...APKFiles,
];
}
try {
await installApk(
DownloadedApk(dir.appId, APKFiles[0]), firstTimeWithContext,
needsBGWorkaround: needsBGWorkaround,
shizukuPretendToBeGooglePlay: shizukuPretendToBeGooglePlay,
additionalAPKs: APKFiles.sublist(1)
.map((a) => DownloadedApk(dir.appId, a))
.toList());
somethingInstalled = true;
dir.file.delete(recursive: true); dir.file.delete(recursive: true);
} else if (errors.idsByErrorString.isNotEmpty) { } catch (e) {
logs.add('Could not install APKs from XAPK: ${e.toString()}');
errors.add(dir.appId, e, appName: apps[dir.appId]?.name);
}
if (errors.idsByErrorString.isNotEmpty) {
throw errors; throw errors;
} }
} finally { } finally {
@@ -677,7 +714,8 @@ class AppsProvider with ChangeNotifier {
Future<bool> installApk( Future<bool> installApk(
DownloadedApk file, BuildContext? firstTimeWithContext, DownloadedApk file, BuildContext? firstTimeWithContext,
{bool needsBGWorkaround = false, {bool needsBGWorkaround = false,
bool shizukuPretendToBeGooglePlay = false}) async { bool shizukuPretendToBeGooglePlay = false,
List<DownloadedApk> additionalAPKs = const []}) async {
if (firstTimeWithContext != null && if (firstTimeWithContext != null &&
settingsProvider.beforeNewInstallsShareToAppVerifier && settingsProvider.beforeNewInstallsShareToAppVerifier &&
(await getInstalledInfo('dev.soupslurpr.appverifier')) != null) { (await getInstalledInfo('dev.soupslurpr.appverifier')) != null) {
@@ -693,6 +731,7 @@ class AppsProvider with ChangeNotifier {
if (newInfo == null) { if (newInfo == null) {
try { try {
file.file.deleteSync(recursive: true); file.file.deleteSync(recursive: true);
additionalAPKs.forEach((a) => a.file.deleteSync(recursive: true));
} catch (e) { } catch (e) {
// //
} finally { } finally {
@@ -720,8 +759,10 @@ class AppsProvider with ChangeNotifier {
} }
int? code; int? code;
if (!settingsProvider.useShizuku) { if (!settingsProvider.useShizuku) {
code = var allAPKs = [file.file.path];
await AndroidPackageInstaller.installApk(apkFilePath: file.file.path); allAPKs.addAll(additionalAPKs.map((a) => a.file.path));
code = await AndroidPackageInstaller.installApk(
apkFilePath: allAPKs.join(','));
} else { } else {
code = await ShizukuApkInstaller.installAPK(file.file.uri.toString(), code = await ShizukuApkInstaller.installAPK(file.file.uri.toString(),
shizukuPretendToBeGooglePlay ? "com.android.vending" : ""); shizukuPretendToBeGooglePlay ? "com.android.vending" : "");
@@ -847,6 +888,11 @@ class AppsProvider with ChangeNotifier {
} }
MapEntry<String, String>? apkUrl; MapEntry<String, String>? apkUrl;
var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == true; var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == true;
var refreshBeforeDownload =
apps[id]!.app.additionalSettings['refreshBeforeDownload'] == true;
if (refreshBeforeDownload) {
await checkUpdate(apps[id]!.app.id);
}
if (!trackOnly) { if (!trackOnly) {
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
apkUrl = await confirmAppFileUrl(apps[id]!.app, context, false); apkUrl = await confirmAppFileUrl(apps[id]!.app, context, false);
@@ -1033,6 +1079,11 @@ class AppsProvider with ChangeNotifier {
throw ObtainiumError(tr('appNotFound')); throw ObtainiumError(tr('appNotFound'));
} }
MapEntry<String, String>? fileUrl; MapEntry<String, String>? fileUrl;
var refreshBeforeDownload =
apps[id]!.app.additionalSettings['refreshBeforeDownload'] == true;
if (refreshBeforeDownload) {
await checkUpdate(apps[id]!.app.id);
}
if (apps[id]!.app.apkUrls.isNotEmpty || if (apps[id]!.app.apkUrls.isNotEmpty ||
apps[id]!.app.otherAssetUrls.isNotEmpty) { apps[id]!.app.otherAssetUrls.isNotEmpty) {
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously

View File

@@ -3,6 +3,7 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:obtainium/providers/settings_provider.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
class ObtainiumNotification { class ObtainiumNotification {
@@ -44,23 +45,19 @@ class SilentUpdateNotification extends ObtainiumNotification {
SilentUpdateNotification(List<App> updates, bool succeeded, {int? id}) SilentUpdateNotification(List<App> updates, bool succeeded, {int? id})
: super( : super(
id ?? 3, id ?? 3,
succeeded succeeded ? tr('appsUpdated') : tr('appsNotUpdated'),
? tr('appsUpdated')
: tr('appsNotUpdated'),
'', '',
'APPS_UPDATED', 'APPS_UPDATED',
tr('appsUpdatedNotifChannel'), tr('appsUpdatedNotifChannel'),
tr('appsUpdatedNotifDescription'), tr('appsUpdatedNotifDescription'),
Importance.defaultImportance) { Importance.defaultImportance) {
message = updates.length == 1 message = updates.length == 1
? tr(succeeded ? tr(succeeded ? 'xWasUpdatedToY' : 'xWasNotUpdatedToY',
? 'xWasUpdatedToY' args: [updates[0].finalName, updates[0].latestVersion])
: 'xWasNotUpdatedToY', : plural(
args: [updates[0].finalName, updates[0].latestVersion]) succeeded ? 'xAndNMoreUpdatesInstalled' : "xAndNMoreUpdatesFailed",
: plural(succeeded updates.length - 1,
? 'xAndNMoreUpdatesInstalled' args: [updates[0].finalName, (updates.length - 1).toString()]);
: "xAndNMoreUpdatesFailed",
updates.length - 1, args: [updates[0].finalName, (updates.length - 1).toString()]);
} }
} }
@@ -214,7 +211,7 @@ class NotificationsProvider {
channelDescription: channelDescription, channelDescription: channelDescription,
importance: importance, importance: importance,
priority: importanceToPriority[importance]!, priority: importanceToPriority[importance]!,
groupKey: 'dev.imranr.obtainium.$channelCode', groupKey: '$obtainiumId.$channelCode',
progress: progPercent ?? 0, progress: progPercent ?? 0,
maxProgress: 100, maxProgress: 100,
showProgress: progPercent != null, showProgress: progPercent != null,

View File

@@ -25,11 +25,8 @@ import 'package:obtainium/app_sources/jenkins.dart';
import 'package:obtainium/app_sources/neutroncode.dart'; import 'package:obtainium/app_sources/neutroncode.dart';
import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/sourceforge.dart';
import 'package:obtainium/app_sources/sourcehut.dart'; import 'package:obtainium/app_sources/sourcehut.dart';
import 'package:obtainium/app_sources/telegramapp.dart';
import 'package:obtainium/app_sources/tencent.dart'; import 'package:obtainium/app_sources/tencent.dart';
import 'package:obtainium/app_sources/uptodown.dart'; import 'package:obtainium/app_sources/uptodown.dart';
import 'package:obtainium/app_sources/vlc.dart';
import 'package:obtainium/app_sources/whatsapp.dart';
import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/mass_app_sources/githubstars.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart';
@@ -214,6 +211,72 @@ appJSONCompatibilityModifiers(Map<String, dynamic> json) {
'\\d+.\\d+.\\d+'; '\\d+.\\d+.\\d+';
additionalSettings = replacementAdditionalSettings; additionalSettings = replacementAdditionalSettings;
} }
// WhatsApp from before it was removed should be converted to HTML (#1943)
if (json['url'] == 'https://whatsapp.com' &&
json['id'] == 'com.whatsapp' &&
json['author'] == 'Meta' &&
json['name'] == 'WhatsApp' &&
json['overrideSource'] == null &&
additionalSettings['trackOnly'] == false &&
additionalSettings['versionExtractionRegEx'] == '' &&
json['lastUpdateCheck'] != null) {
json['url'] = 'https://whatsapp.com/android';
var replacementAdditionalSettings = getDefaultValuesFromFormItems(
HTML().combinedAppSpecificSettingFormItems);
replacementAdditionalSettings['refreshBeforeDownload'] = true;
additionalSettings = replacementAdditionalSettings;
}
// VLC from before it was removed should be converted to HTML (#1943)
if (json['url'] == 'https://videolan.org' &&
json['id'] == 'org.videolan.vlc' &&
json['author'] == 'VideoLAN' &&
json['name'] == 'VLC' &&
json['overrideSource'] == null &&
additionalSettings['trackOnly'] == false &&
additionalSettings['versionExtractionRegEx'] == '' &&
json['lastUpdateCheck'] != null) {
json['url'] = 'https://www.videolan.org/vlc/download-android.html';
var replacementAdditionalSettings = getDefaultValuesFromFormItems(
HTML().combinedAppSpecificSettingFormItems);
replacementAdditionalSettings['refreshBeforeDownload'] = true;
replacementAdditionalSettings['intermediateLink'] =
<Map<String, dynamic>>[
{
'customLinkFilterRegex': 'APK',
'filterByLinkText': true,
'skipSort': false,
'reverseSort': false,
'sortByLastLinkSegment': false
},
{
'customLinkFilterRegex': 'arm64-v8a\\.apk\$',
'filterByLinkText': false,
'skipSort': false,
'reverseSort': false,
'sortByLastLinkSegment': false
}
];
replacementAdditionalSettings['versionExtractionRegEx'] =
'/vlc-android/([^/]+)/';
replacementAdditionalSettings['matchGroupToUse'] = "1";
additionalSettings = replacementAdditionalSettings;
}
// Telegram App from before it was removed should be converted to Direct APK Link (#1943)
if (json['url'] == 'https://telegram.org' &&
json['id'] == 'org.telegram.messenger.web' &&
json['author'] == 'Telegram' &&
json['name'] == 'Telegram' &&
json['overrideSource'] == null &&
additionalSettings['trackOnly'] == false &&
additionalSettings['versionExtractionRegEx'] == '' &&
json['lastUpdateCheck'] != null) {
json['url'] = 'https://telegram.org/dl/android/apk';
var newSource = DirectAPKLink();
json['overrideSource'] = newSource.runtimeType.toString();
var replacementAdditionalSettings = getDefaultValuesFromFormItems(
newSource.combinedAppSpecificSettingFormItems);
additionalSettings = replacementAdditionalSettings;
}
} }
json['additionalSettings'] = jsonEncode(additionalSettings); json['additionalSettings'] = jsonEncode(additionalSettings);
// F-Droid no longer needs cloudflare exception since override can be used - migrate apps appropriately // F-Droid no longer needs cloudflare exception since override can be used - migrate apps appropriately
@@ -240,7 +303,7 @@ class App {
late String name; late String name;
String? installedVersion; String? installedVersion;
late String latestVersion; late String latestVersion;
List<MapEntry<String, String>> apkUrls = []; List<MapEntry<String, String>> apkUrls = []; // Key is name, value is URL
List<MapEntry<String, String>> otherAssetUrls = []; List<MapEntry<String, String>> otherAssetUrls = [];
late int preferredApkIndex; late int preferredApkIndex;
late Map<String, dynamic> additionalSettings; late Map<String, dynamic> additionalSettings;
@@ -586,6 +649,10 @@ abstract class AppSource {
label: tr('skipUpdateNotifications')) label: tr('skipUpdateNotifications'))
], ],
[GeneratedFormTextField('about', label: tr('about'), required: false)], [GeneratedFormTextField('about', label: tr('about'), required: false)],
[
GeneratedFormSwitch('refreshBeforeDownload',
label: tr('refreshBeforeDownload'))
]
]; ];
// Previous 2 variables combined into one at runtime for convenient usage // Previous 2 variables combined into one at runtime for convenient usage
@@ -808,9 +875,6 @@ class SourceProvider {
Tencent(), Tencent(),
Jenkins(), Jenkins(),
APKMirror(), APKMirror(),
VLC(),
WhatsApp(),
TelegramApp(),
NeutronCode(), NeutronCode(),
DirectAPKLink(), DirectAPKLink(),
HTML() // This should ALWAYS be the last option as they are tried in order HTML() // This should ALWAYS be the last option as they are tried in order

View File

@@ -14,7 +14,7 @@ packages:
description: description:
path: "." path: "."
ref: main ref: main
resolved-ref: ba2aa7a11edc2649d1d80c25ed9291521262f714 resolved-ref: bcad19e964d377da8816718032e5dbf6dd16ba3a
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"
@@ -404,10 +404,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_launcher_icons name: flutter_launcher_icons
sha256: "619817c4b65b322b5104b6bb6dfe6cda62d9729bd7ad4303ecc8b4e690a67a77" sha256: "31cd0885738e87c72d6f055564d37fabcdacee743b396b78c7636c169cac64f5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.14.1" version: "0.14.2"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
@@ -449,10 +449,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_markdown name: flutter_markdown
sha256: f0e599ba89c9946c8e051780f0ec99aba4ba15895e0380a7ab68f420046fc44e sha256: "255b00afa1a7bad19727da6a7780cf3db6c3c12e68d302d85e0ff1fdf173db9e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.4+1" version: "0.7.4+3"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:
@@ -667,18 +667,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a sha256: "8c4967f8b7cb46dc914e178daa29813d83ae502e0529d7b0478330616a691ef7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.12" version: "2.2.14"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.1"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@@ -731,10 +731,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_html name: permission_handler_html
sha256: af26edbbb1f2674af65a8f4b56e1a6f526156bc273d0e65dd8075fab51c78851 sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.3+2" version: "0.1.3+5"
permission_handler_platform_interface: permission_handler_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -843,10 +843,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" sha256: "7f172d1b06de5da47b6264c2692ee2ead20bbbc246690427cdb4fc301cd0c549"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.3.4"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
@@ -945,10 +945,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: sqflite_common name: sqflite_common
sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490" sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.4+5" version: "2.5.4+6"
sqflite_darwin: sqflite_darwin:
dependency: transitive dependency: transitive
description: description:
@@ -1057,10 +1057,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.1" version: "6.3.2"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
@@ -1073,10 +1073,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.1" version: "3.2.2"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -1145,10 +1145,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_android name: webview_flutter_android
sha256: "86c2d01c37c4578ee46560109cf2e18fb271f0d080a796f09188d0952352e057" sha256: "285cedfd9441267f6cca8843458620b5fda1af75b04f5818d0441acda5d7df19"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.2" version: "4.1.0"
webview_flutter_platform_interface: webview_flutter_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -1161,18 +1161,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: "3be297aa4ca78205abdd284cf55f168c35246c75b3079990ad8ba9d257681a30" sha256: b7e92f129482460951d96ef9a46b49db34bd2e1621685de26e9eaafd9674e7eb
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.16.2" version: "3.16.3"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: "84ba388638ed7a8cb3445a320c8273136ab2631cd5f2c57888335504ddab1bc2" sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.8.0" version: "5.9.0"
win32_registry: win32_registry:
dependency: transitive dependency: transitive
description: description:

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: 1.1.31+2288 version: 1.1.33+2290
environment: environment:
sdk: '>=3.0.0 <4.0.0' sdk: '>=3.0.0 <4.0.0'