Compare commits

...

16 Commits

Author SHA1 Message Date
Imran
3af185b0f8 Merge pull request #2552 from aminosred25/aminosred25-patch-1
Try to handle response body as a JSON first before handling it as a p…
2025-09-21 16:56:50 -04:00
aminosred25
bfbb2710b6 Try to handle response body as a JSON first before handling it as a plain text 2025-09-21 22:33:57 +02:00
Imran
c81c3c5ea7 Merge pull request #2551 from ImranR98/dev
- Add 'sky22333/hubproxy' support for GitHub (#2513)
- Fix error in Vivo Store search when no result found (#2494)
- Correct a log string (#2519)
- Loose auto-filtering for farsroid.com (#2441)
- Re-enable auto-filtering for farsroid.com w/ toggle to disable it (#2441)
- Enable long-press and double-tap gestures on app icon in apps list (#2444, #2448)
2025-09-21 14:14:37 -04:00
Imran Remtulla
7391e9a94d Upgrade Flutter + packages, increment version 2025-09-21 14:11:40 -04:00
Imran Remtulla
04633131e7 Enable long-press and double-tap gestures on app icon in apps list (#2444, #2448) 2025-09-21 13:37:57 -04:00
Imran Remtulla
7bc818fbfa Re-enable auto-filtering for farsroid.com w/ toggle to disable it (#2441) 2025-09-21 13:01:59 -04:00
Imran Remtulla
4afcd92510 Loose auto-filtering for farsroid.com (#2441) 2025-09-21 12:51:06 -04:00
Imran Remtulla
0784f83792 Correct a log string (#2519) 2025-09-21 12:34:07 -04:00
Imran Remtulla
a6608f1461 Fix error in Vivo Store search when no result found (#2494) 2025-09-21 12:28:02 -04:00
Imran Remtulla
08d9c4daaa Add 'sky22333/hubproxy' support for GitHub (#2513) 2025-09-21 12:16:58 -04:00
Imran
225362d351 Merge pull request #2539 from neardaniel-pls/main
Refined translation terms
2025-09-19 23:13:36 -04:00
Imran
089bf97ff2 Merge pull request #2545 from kvak54/rustore-patch
Restore RuStore support through replace URL of API.
2025-09-19 23:13:24 -04:00
kvak54
123cd5b130 Restore RuStore support through replace URL of API.
If the application is published as an AAB,
then the old one produced an unusable file (one of split files).
The new one provide a monolithic file.
2025-09-14 21:07:32 +07:00
Near
bc24f008fa fixed spacing 2025-09-13 22:41:20 +01:00
Near
472ec4e400 refine translation terms 2025-09-13 22:37:19 +01:00
Imran
a56069e881 Merge pull request #2537 from ImranR98/dev
Fix versionCode issue (#2505) + Flutter upgrades
2025-09-12 15:16:01 -04:00
45 changed files with 350 additions and 129 deletions

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "استخدام خدمة مقدمة للتحقق من التحديثات (أكثر موثوقية وتستهلك طاقة أكبر)", "foregroundServiceExplanation": "استخدام خدمة مقدمة للتحقق من التحديثات (أكثر موثوقية وتستهلك طاقة أكبر)",
"fgServiceNotice": "هذا الإشعار مطلوب للتحقق من التحديث في الخلفية (يمكن إخفاؤه في إعدادات نظام التشغيل)", "fgServiceNotice": "هذا الإشعار مطلوب للتحقق من التحديث في الخلفية (يمكن إخفاؤه في إعدادات نظام التشغيل)",
"excludeSecrets": "استبعاد الأسرار", "excludeSecrets": "استبعاد الأسرار",
"GHReqPrefix": "مثيل \"sky22333/hubproxy\" لطلبات GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "إزالة التطبيق؟", "one": "إزالة التطبيق؟",
"other": "إزالة التطبيقات؟" "other": "إزالة التطبيقات؟"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)", "foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)",
"fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)", "fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)",
"excludeSecrets": "Exclude secrets", "excludeSecrets": "Exclude secrets",
"GHReqPrefix": "'sky22333/hubproxy' instance for GitHub requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Želite li ukloniti aplikaciju?", "one": "Želite li ukloniti aplikaciju?",
"other": "Želite li ukloniti aplikacije?" "other": "Želite li ukloniti aplikacije?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Usa el servei d'Obtainium en primer pla per comprovar les actualitzacions (és més fiable però consumeix més bateria)", "foregroundServiceExplanation": "Usa el servei d'Obtainium en primer pla per comprovar les actualitzacions (és més fiable però consumeix més bateria)",
"fgServiceNotice": "Aquesta notificació és necessària per comprovar les actualitzacions en segon pla (la pots ocultar als paràmetres del Sistema Operatiu)", "fgServiceNotice": "Aquesta notificació és necessària per comprovar les actualitzacions en segon pla (la pots ocultar als paràmetres del Sistema Operatiu)",
"excludeSecrets": "Exclude secrets", "excludeSecrets": "Exclude secrets",
"GHReqPrefix": "'sky22333/hubproxy' instance for GitHub requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "¿Suprimeixo l'aplicació?", "one": "¿Suprimeixo l'aplicació?",
"other": "¿Suprimeixo les aplicacions?" "other": "¿Suprimeixo les aplicacions?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Použít službu v popředí pro kontrolu aktualizací (spolehlivější, spotřebovává více energie)", "foregroundServiceExplanation": "Použít službu v popředí pro kontrolu aktualizací (spolehlivější, spotřebovává více energie)",
"fgServiceNotice": "Toto oznámení je nutné pro kontrolu aktualizací na pozadí (lze jej skrýt v nastavení systému)", "fgServiceNotice": "Toto oznámení je nutné pro kontrolu aktualizací na pozadí (lze jej skrýt v nastavení systému)",
"excludeSecrets": "Vyloučit tajemství", "excludeSecrets": "Vyloučit tajemství",
"GHReqPrefix": "instance 'sky22333/hubproxy' pro požadavky GitHubu",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Odstranit aplikaci?", "one": "Odstranit aplikaci?",
"other": "Odstranit aplikace?" "other": "Odstranit aplikace?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Brug en forgrundstjeneste til opdateringskontrol (mere pålidelig, bruger mere strøm)", "foregroundServiceExplanation": "Brug en forgrundstjeneste til opdateringskontrol (mere pålidelig, bruger mere strøm)",
"fgServiceNotice": "Denne meddelelse er nødvendig for baggrundsopdateringskontrol (den kan skjules i OS-indstillingerne).", "fgServiceNotice": "Denne meddelelse er nødvendig for baggrundsopdateringskontrol (den kan skjules i OS-indstillingerne).",
"excludeSecrets": "Udeluk hemmeligheder", "excludeSecrets": "Udeluk hemmeligheder",
"GHReqPrefix": "'sky22333/hubproxy'-instans til GitHub-anmodninger",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Fjern app?", "one": "Fjern app?",
"other": "Fjern apps?" "other": "Fjern apps?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Aktualisierungsprüfung im Vordergrund durchführen (zuverlässiger, verbraucht mehr Strom)", "foregroundServiceExplanation": "Aktualisierungsprüfung im Vordergrund durchführen (zuverlässiger, verbraucht mehr Strom)",
"fgServiceNotice": "Diese Benachrichtigung ist für die Prüfung von Updates im Hintergrund erforderlich (sie kann in den Betriebssystemeinstellungen ausgeblendet werden)", "fgServiceNotice": "Diese Benachrichtigung ist für die Prüfung von Updates im Hintergrund erforderlich (sie kann in den Betriebssystemeinstellungen ausgeblendet werden)",
"excludeSecrets": "Geheimnisse ausschließen", "excludeSecrets": "Geheimnisse ausschließen",
"GHReqPrefix": "sky22333/hubproxy'-Instanz für GitHub-Anfragen",
"removeAppQuestion": { "removeAppQuestion": {
"one": "App entfernen?", "one": "App entfernen?",
"other": "Apps entfernen?" "other": "Apps entfernen?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)", "foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)",
"fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)", "fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)",
"excludeSecrets": "Exclude secrets", "excludeSecrets": "Exclude secrets",
"GHReqPrefix": "'sky22333/hubproxy' instance for GitHub requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Forigi la aplikaĵon?", "one": "Forigi la aplikaĵon?",
"other": "Forigi la aplikaĵojn?" "other": "Forigi la aplikaĵojn?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)", "foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)",
"fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)", "fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)",
"excludeSecrets": "Exclude secrets", "excludeSecrets": "Exclude secrets",
"GHReqPrefix": "'sky22333/hubproxy' instance for GitHub requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remove app?", "one": "Remove app?",
"other": "Remove apps?" "other": "Remove apps?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Usar un servicio en primer plano para comprobar las actualizaciones (más fiable, consume más energía).", "foregroundServiceExplanation": "Usar un servicio en primer plano para comprobar las actualizaciones (más fiable, consume más energía).",
"fgServiceNotice": "Esta notificación es necesaria para la comprobación de actualizaciones en segundo plano (puede ocultarse en la configuración del sistema operativo).", "fgServiceNotice": "Esta notificación es necesaria para la comprobación de actualizaciones en segundo plano (puede ocultarse en la configuración del sistema operativo).",
"excludeSecrets": "Excluir secretos", "excludeSecrets": "Excluir secretos",
"GHReqPrefix": "Instancia \"sky22333/hubproxy\" para las solicitudes de GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "¿Eliminar aplicación?", "one": "¿Eliminar aplicación?",
"other": "¿Eliminar aplicaciones?" "other": "¿Eliminar aplicaciones?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)", "foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)",
"fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)", "fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)",
"excludeSecrets": "Exclude secrets", "excludeSecrets": "Exclude secrets",
"GHReqPrefix": "'sky22333/hubproxy' instance for GitHub requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "برنامه حذف شود؟", "one": "برنامه حذف شود؟",
"other": "برنامه ها حذف شوند؟" "other": "برنامه ها حذف شوند؟"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Utiliser un service de premier plan pour la vérification des mises à jour (plus fiable, consomme plus d'énergie)", "foregroundServiceExplanation": "Utiliser un service de premier plan pour la vérification des mises à jour (plus fiable, consomme plus d'énergie)",
"fgServiceNotice": "Cette notification est nécessaire pour la vérification des mises à jour en arrière-plan (elle peut être masquée dans les paramètres du système d'exploitation).", "fgServiceNotice": "Cette notification est nécessaire pour la vérification des mises à jour en arrière-plan (elle peut être masquée dans les paramètres du système d'exploitation).",
"excludeSecrets": "Exclure les secrets", "excludeSecrets": "Exclure les secrets",
"GHReqPrefix": "instance 'sky22333/hubproxy' pour les requêtes GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Supprimer l'application ?", "one": "Supprimer l'application ?",
"other": "Supprimer les applications ?" "other": "Supprimer les applications ?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Előtér-szolgáltatás használata a frissítések ellenőrzéséhez (megbízhatóbb, de több energiát fogyaszt)", "foregroundServiceExplanation": "Előtér-szolgáltatás használata a frissítések ellenőrzéséhez (megbízhatóbb, de több energiát fogyaszt)",
"fgServiceNotice": "Ez az értesítés a háttérben történő frissítésellenőrzéshez szükséges (a rendszer beállításaiban elrejthető).", "fgServiceNotice": "Ez az értesítés a háttérben történő frissítésellenőrzéshez szükséges (a rendszer beállításaiban elrejthető).",
"excludeSecrets": "Érzékeny adatok (például: személyes hozzáférési tokenek) kihagyása", "excludeSecrets": "Érzékeny adatok (például: személyes hozzáférési tokenek) kihagyása",
"GHReqPrefix": "'sky22333/hubproxy' példány a GitHub kérésekhez",
"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

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Gunakan layanan latar depan untuk pemeriksaan pembaruan (lebih dapat diandalkan, menghabiskan lebih banyak daya)", "foregroundServiceExplanation": "Gunakan layanan latar depan untuk pemeriksaan pembaruan (lebih dapat diandalkan, menghabiskan lebih banyak daya)",
"fgServiceNotice": "Pemberitahuan ini diperlukan untuk pemeriksaan pembaruan latar belakang (dapat disembunyikan dalam pengaturan OS)", "fgServiceNotice": "Pemberitahuan ini diperlukan untuk pemeriksaan pembaruan latar belakang (dapat disembunyikan dalam pengaturan OS)",
"excludeSecrets": "Mengecualikan rahasia", "excludeSecrets": "Mengecualikan rahasia",
"GHReqPrefix": "Instance 'sky22333/hubproxy' untuk permintaan GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Hapus aplikasi?", "one": "Hapus aplikasi?",
"other": "Hapus aplikasi?" "other": "Hapus aplikasi?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Utilizzare un servizio in primo piano per il controllo degli aggiornamenti (più affidabile, consuma più energia)", "foregroundServiceExplanation": "Utilizzare un servizio in primo piano per il controllo degli aggiornamenti (più affidabile, consuma più energia)",
"fgServiceNotice": "Questa notifica è necessaria per il controllo degli aggiornamenti in background (può essere nascosta nelle impostazioni del sistema operativo).", "fgServiceNotice": "Questa notifica è necessaria per il controllo degli aggiornamenti in background (può essere nascosta nelle impostazioni del sistema operativo).",
"excludeSecrets": "Escludere i segreti", "excludeSecrets": "Escludere i segreti",
"GHReqPrefix": "istanza 'sky22333/hubproxy' per le richieste a GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Rimuovere l'app?", "one": "Rimuovere l'app?",
"other": "Rimuovere le app?" "other": "Rimuovere le app?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "アップデート確認にフォアグラウンドサービスを使用する(より信頼性が高いが、より電力を消費する)", "foregroundServiceExplanation": "アップデート確認にフォアグラウンドサービスを使用する(より信頼性が高いが、より電力を消費する)",
"fgServiceNotice": "この通知は、バックグラウンドでアップデートを確認するために必要ですOSの設定で非表示にできます。", "fgServiceNotice": "この通知は、バックグラウンドでアップデートを確認するために必要ですOSの設定で非表示にできます。",
"excludeSecrets": "シークレットを除く", "excludeSecrets": "シークレットを除く",
"GHReqPrefix": "GitHub リクエスト用の 'sky22333/hubproxy' インスタンス",
"removeAppQuestion": { "removeAppQuestion": {
"one": "アプリを削除しますか?", "one": "アプリを削除しますか?",
"other": "アプリを削除しますか?" "other": "アプリを削除しますか?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "업데이트 확인을 위해 포그라운드 서비스 사용(안정성 향상, 전력 소비량 증가)", "foregroundServiceExplanation": "업데이트 확인을 위해 포그라운드 서비스 사용(안정성 향상, 전력 소비량 증가)",
"fgServiceNotice": "이 알림은 백그라운드 업데이트 확인에 필요합니다(OS 설정에서 숨길 수 있음).", "fgServiceNotice": "이 알림은 백그라운드 업데이트 확인에 필요합니다(OS 설정에서 숨길 수 있음).",
"excludeSecrets": "비밀 제외", "excludeSecrets": "비밀 제외",
"GHReqPrefix": "GitHub 요청을 위한 'sky22333/hubproxy' 인스턴스",
"removeAppQuestion": { "removeAppQuestion": {
"one": "앱을 제거하시겠습니까?", "one": "앱을 제거하시겠습니까?",
"other": "앱을 제거하시겠습니까?" "other": "앱을 제거하시겠습니까?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)", "foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)",
"fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)", "fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)",
"excludeSecrets": "Exclude secrets", "excludeSecrets": "Exclude secrets",
"GHReqPrefix": "'sky22333/hubproxy' instance for GitHub requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "ആപ്പ് നീക്കം ചെയ്യണോ?", "one": "ആപ്പ് നീക്കം ചെയ്യണോ?",
"other": "ആപ്പുകൾ നീക്കം ചെയ്യണോ?" "other": "ആപ്പുകൾ നീക്കം ചെയ്യണോ?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Gebruik een voorgronddienst voor het controleren van updates (betrouwbaarder, verbruikt meer stroom)", "foregroundServiceExplanation": "Gebruik een voorgronddienst voor het controleren van updates (betrouwbaarder, verbruikt meer stroom)",
"fgServiceNotice": "Deze melding is nodig voor het controleren van updates op de achtergrond (kan worden verborgen in de OS-instellingen)", "fgServiceNotice": "Deze melding is nodig voor het controleren van updates op de achtergrond (kan worden verborgen in de OS-instellingen)",
"excludeSecrets": "Geheimen uitsluiten", "excludeSecrets": "Geheimen uitsluiten",
"GHReqPrefix": "'sky22333/hubproxy' instantie voor GitHub verzoeken",
"removeAppQuestion": { "removeAppQuestion": {
"one": "App verwijderen?", "one": "App verwijderen?",
"other": "Apps verwijderen?" "other": "Apps verwijderen?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Używanie usługi pierwszoplanowej do sprawdzania aktualizacji (bardziej niezawodne, zużywa więcej energii)", "foregroundServiceExplanation": "Używanie usługi pierwszoplanowej do sprawdzania aktualizacji (bardziej niezawodne, zużywa więcej energii)",
"fgServiceNotice": "To powiadomienie jest wymagane do sprawdzania aktualizacji w tle (można je ukryć w ustawieniach systemu operacyjnego).", "fgServiceNotice": "To powiadomienie jest wymagane do sprawdzania aktualizacji w tle (można je ukryć w ustawieniach systemu operacyjnego).",
"excludeSecrets": "Wyklucz sekrety", "excludeSecrets": "Wyklucz sekrety",
"GHReqPrefix": "Instancja \"sky22333/hubproxy\" dla żądań GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Usunąć aplikację?", "one": "Usunąć aplikację?",
"few": "Usunąć aplikacje?", "few": "Usunąć aplikacje?",

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Usar um serviço em primeiro plano para verificação de atualizações (mais confiável, consome mais energia)", "foregroundServiceExplanation": "Usar um serviço em primeiro plano para verificação de atualizações (mais confiável, consome mais energia)",
"fgServiceNotice": "Essa notificação é necessária para a verificação de atualizações em segundo plano (ela pode ser ocultada nas configurações do sistema operacional)", "fgServiceNotice": "Essa notificação é necessária para a verificação de atualizações em segundo plano (ela pode ser ocultada nas configurações do sistema operacional)",
"excludeSecrets": "Excluir segredos", "excludeSecrets": "Excluir segredos",
"GHReqPrefix": "Instância \"sky22333/hubproxy\" para solicitações do GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remover app?", "one": "Remover app?",
"other": "Remover apps?" "other": "Remover apps?"

View File

@@ -336,25 +336,26 @@
"foregroundServiceExplanation": "Utilizar um serviço em primeiro plano para verificação de actualizações (mais fiável, consome mais energia)", "foregroundServiceExplanation": "Utilizar um serviço em primeiro plano para verificação de actualizações (mais fiável, consome mais energia)",
"fgServiceNotice": "Esta notificação é necessária para a verificação de actualizações em segundo plano (pode ser ocultada nas definições do SO)", "fgServiceNotice": "Esta notificação é necessária para a verificação de actualizações em segundo plano (pode ser ocultada nas definições do SO)",
"excludeSecrets": "Excluir segredos", "excludeSecrets": "Excluir segredos",
"GHReqPrefix": "Instância 'sky22333/hubproxy' para pedidos de GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remover aplicativo?", "one": "Remover aplicação?",
"other": "Remover aplicativos?" "other": "Remover aplicações?"
}, },
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "Muitas solicitações (taxa de solicitações limitada) - tente novamente em {} minuto", "one": "Muitos pedidos (taxa de pedidos limitada) - tente novamente em {} minuto",
"other": "Muitas solicitações (taxa limitada) - tente novamente em {} minutos" "other": "Muitos pedidos (taxa limitada) - tente novamente em {} minutos"
}, },
"bgUpdateGotErrorRetryInMinutes": { "bgUpdateGotErrorRetryInMinutes": {
"one": "A verificação de atualizações em segundo-plano encontrou um {}, agendada uma nova verificação em {} minuto", "one": "A verificação de atualizações em segundo plano encontrou um {}, agendada uma nova verificação em {} minuto",
"other": "A verificação de atualizações em segundo-plano encontrou um {}, agendada uma nova verificação em {} minutos" "other": "A verificação de atualizações em segundo plano encontrou um {}, agendada uma nova verificação em {} minutos"
}, },
"bgCheckFoundUpdatesWillNotifyIfNeeded": { "bgCheckFoundUpdatesWillNotifyIfNeeded": {
"one": "A verificação de atualizações em segundo-plano encontrou {} atualização, o usuário sera notificado caso necessário", "one": "A verificação de atualizações em segundo plano encontrou {} atualização, o utilizador será notificado caso necessário",
"other": "A verificação de atualizações em segundo-plano encontrou {} atualizações, o usuário sera notificado caso necessário" "other": "A verificação de atualizações em segundo plano encontrou {} atualizações, o utilizador será notificado caso necessário"
}, },
"apps": { "apps": {
"one": "{} Aplicativo", "one": "{} Aplicação",
"other": "{} Aplicativos" "other": "{} Aplicações"
}, },
"url": { "url": {
"one": "{} URL", "one": "{} URL",
@@ -377,20 +378,20 @@
"other": "Foram limpos {n} logs (antes = {antes}, depois = {depois})" "other": "Foram limpos {n} logs (antes = {antes}, depois = {depois})"
}, },
"xAndNMoreUpdatesAvailable": { "xAndNMoreUpdatesAvailable": {
"one": "{} e um outro aplicativo possui atualizações.", "one": "{} e uma outra aplicação possui atualizações.",
"other": "{} e {} outros aplicativo possuem atualizações." "other": "{} e {} outras aplicações possuem atualizações."
}, },
"xAndNMoreUpdatesInstalled": { "xAndNMoreUpdatesInstalled": {
"one": "{} e um outro aplicativo foram atualizado.", "one": "{} e uma outra aplicação foram atualizadas.",
"other": "{} e {} outros aplicativos foram atualizados." "other": "{} e {} outras aplicações foram atualizadas."
}, },
"xAndNMoreUpdatesFailed": { "xAndNMoreUpdatesFailed": {
"one": "Falha ao atualizar {} e mais 1 aplicação.", "one": "Falha ao atualizar {} e mais 1 aplicação.",
"other": "Falha ao atualizar {} e {} mais aplicações." "other": "Falha ao atualizar {} e {} outras aplicações."
}, },
"xAndNMoreUpdatesPossiblyInstalled": { "xAndNMoreUpdatesPossiblyInstalled": {
"one": "{} e um outro aplicativo podem ter sido atualizados.", "one": "{} e uma outra aplicação podem ter sido atualizadas.",
"other": "{} e {} outros aplicativos podem ter sido atualizados." "other": "{} e {} outras aplicações podem ter sido atualizadas."
}, },
"apk": { "apk": {
"one": "{} APK", "one": "{} APK",

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Использовать приоритетную службу для проверки обновлений (надёжнее, энергозатратнее)", "foregroundServiceExplanation": "Использовать приоритетную службу для проверки обновлений (надёжнее, энергозатратнее)",
"fgServiceNotice": "Это уведомление необходимо для фоновой проверки обновлений (оно может быть скрыто в настройках ОС)", "fgServiceNotice": "Это уведомление необходимо для фоновой проверки обновлений (оно может быть скрыто в настройках ОС)",
"excludeSecrets": "Исключить секреты", "excludeSecrets": "Исключить секреты",
"GHReqPrefix": "Экземпляр 'sky22333/hubproxy' для запросов на GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Удалить приложение?", "one": "Удалить приложение?",
"other": "Удалить приложения?" "other": "Удалить приложения?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Använd en förgrundstjänst för uppdateringskontroll (mer tillförlitlig, förbrukar mer ström)", "foregroundServiceExplanation": "Använd en förgrundstjänst för uppdateringskontroll (mer tillförlitlig, förbrukar mer ström)",
"fgServiceNotice": "Detta meddelande krävs för bakgrundsuppdateringskontroll (det kan döljas i OS-inställningarna)", "fgServiceNotice": "Detta meddelande krävs för bakgrundsuppdateringskontroll (det kan döljas i OS-inställningarna)",
"excludeSecrets": "Utesluta hemligheter", "excludeSecrets": "Utesluta hemligheter",
"GHReqPrefix": "Instansen \"sky22333/hubproxy\" för GitHub-förfrågningar",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Ta Bort App?", "one": "Ta Bort App?",
"other": "Ta Bort Appar?" "other": "Ta Bort Appar?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Güncelleme denetimi için bir ön plan hizmeti kullanın (daha güvenilir, daha fazla güç tüketir)", "foregroundServiceExplanation": "Güncelleme denetimi için bir ön plan hizmeti kullanın (daha güvenilir, daha fazla güç tüketir)",
"fgServiceNotice": "Bu bildirim arka planda güncelleme kontrolü için gereklidir (işletim sistemi ayarlarından gizlenebilir)", "fgServiceNotice": "Bu bildirim arka planda güncelleme kontrolü için gereklidir (işletim sistemi ayarlarından gizlenebilir)",
"excludeSecrets": "Sırları hariç tut", "excludeSecrets": "Sırları hariç tut",
"GHReqPrefix": "GitHub istekleri için 'sky22333/hubproxy' örneği",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Uygulamayı Kaldır?", "one": "Uygulamayı Kaldır?",
"other": "Uygulamaları Kaldır?" "other": "Uygulamaları Kaldır?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Використовуйте службу переднього плану для перевірки оновлень (надійніша, споживає більше енергії)", "foregroundServiceExplanation": "Використовуйте службу переднього плану для перевірки оновлень (надійніша, споживає більше енергії)",
"fgServiceNotice": "Це сповіщення необхідне для фонової перевірки оновлень (його можна приховати в налаштуваннях ОС)", "fgServiceNotice": "Це сповіщення необхідне для фонової перевірки оновлень (його можна приховати в налаштуваннях ОС)",
"excludeSecrets": "Виключити секрети", "excludeSecrets": "Виключити секрети",
"GHReqPrefix": "екземпляр 'sky22333/hubproxy' для запитів на GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Видалити застосунок?", "one": "Видалити застосунок?",
"other": "Видалити застосунки?" "other": "Видалити застосунки?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Sử dụng dịch vụ nền trước để kiểm tra cập nhật (đáng tin cậy hơn, tiêu tốn nhiều pin hơn)", "foregroundServiceExplanation": "Sử dụng dịch vụ nền trước để kiểm tra cập nhật (đáng tin cậy hơn, tiêu tốn nhiều pin hơn)",
"fgServiceNotice": "Thông báo này là bắt buộc để kiểm tra cập nhật nền (có thể ẩn trong cài đặt hệ điều hành).", "fgServiceNotice": "Thông báo này là bắt buộc để kiểm tra cập nhật nền (có thể ẩn trong cài đặt hệ điều hành).",
"excludeSecrets": "Loại trừ thông tin bí mật", "excludeSecrets": "Loại trừ thông tin bí mật",
"GHReqPrefix": "Thực thể 'sky22333/hubproxy' cho các yêu cầu GitHub",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Gỡ ứng dụng?", "one": "Gỡ ứng dụng?",
"other": "Gỡ ứng dụng?" "other": "Gỡ ứng dụng?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)", "foregroundServiceExplanation": "Use a foreground service for update checking (more reliable, consumes more power)",
"fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)", "fgServiceNotice": "This notification is required for background update checking (it can be hidden in the OS settings)",
"excludeSecrets": "Exclude secrets", "excludeSecrets": "Exclude secrets",
"GHReqPrefix": "'sky22333/hubproxy' instance for GitHub requests",
"removeAppQuestion": { "removeAppQuestion": {
"one": "移除應用程式?", "one": "移除應用程式?",
"other": "移除應用程式?" "other": "移除應用程式?"

View File

@@ -336,6 +336,7 @@
"foregroundServiceExplanation": "使用前台服务检查更新(更稳定,但也更耗电)", "foregroundServiceExplanation": "使用前台服务检查更新(更稳定,但也更耗电)",
"fgServiceNotice": "后台检查更新时需要此通知(可在操作系统设置中隐藏)", "fgServiceNotice": "后台检查更新时需要此通知(可在操作系统设置中隐藏)",
"excludeSecrets": "排除机密", "excludeSecrets": "排除机密",
"GHReqPrefix": "用于 GitHub 请求的 \"sky22333/hubproxy \"实例",
"removeAppQuestion": { "removeAppQuestion": {
"one": "是否删除应用?", "one": "是否删除应用?",
"other": "是否删除应用?" "other": "是否删除应用?"

View File

@@ -82,13 +82,13 @@ class APKCombo extends AppSource {
} }
@override @override
Future<String> apkUrlPrefetchModifier( Future<String> assetUrlPrefetchModifier(
String apkUrl, String assetUrl,
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
var freshURLs = await getApkUrls(standardUrl, additionalSettings); var freshURLs = await getApkUrls(standardUrl, additionalSettings);
var path2Match = Uri.parse(apkUrl).path; var path2Match = Uri.parse(assetUrl).path;
for (var url in freshURLs) { for (var url in freshURLs) {
if (Uri.parse(url.value).path == path2Match) { if (Uri.parse(url.value).path == path2Match) {
return url.value; return url.value;

View File

@@ -1,7 +1,9 @@
import 'dart:convert'; import 'dart:convert';
import 'package:easy_localization/easy_localization.dart';
import 'package:html/parser.dart'; import 'package:html/parser.dart';
import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/app_sources/html.dart';
import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
@@ -9,6 +11,17 @@ class Farsroid extends AppSource {
Farsroid() { Farsroid() {
hosts = ['farsroid.com']; hosts = ['farsroid.com'];
name = 'Farsroid'; name = 'Farsroid';
naiveStandardVersionDetection = true;
additionalSourceAppSpecificSettingFormItems = [
[
GeneratedFormSwitch(
'useFirstApkOfVersion',
label: tr('useFirstApkOfVersion'),
defaultValue: true,
),
],
];
} }
@override @override
@@ -57,15 +70,21 @@ class Farsroid extends AppSource {
if (html2.isEmpty) { if (html2.isEmpty) {
throw NoAPKError(); throw NoAPKError();
} }
var apkLinks = var apkLinks = (await grabLinksCommon(
(await grabLinksCommon(html2, res2.request!.url, additionalSettings)) html2,
.map((l) => MapEntry(Uri.parse(l.key).pathSegments.last, l.key)) res2.request!.url,
.where( additionalSettings,
(l) => l.key.toLowerCase().startsWith( )).map((l) => MapEntry(Uri.parse(l.key).pathSegments.last, l.key)).toList();
'$appName-$version'.toLowerCase(),
), if (additionalSettings['useFirstApkOfVersion'] == true) {
) apkLinks = apkLinks
.toList(); .where(
(l) => l.key.toLowerCase().startsWith(
'$appName-$version'.toLowerCase(),
),
)
.toList();
}
if (apkLinks.isEmpty) { if (apkLinks.isEmpty) {
throw NoAPKError(); throw NoAPKError();

View File

@@ -45,6 +45,45 @@ class GitHub extends AppSource {
const SizedBox(height: 4), const SizedBox(height: 4),
], ],
), ),
GeneratedFormTextField(
'GHReqPrefix',
label: tr('GHReqPrefix'),
hint: 'gh-proxy.com',
required: false,
additionalValidators: [
(value) {
try {
if (Uri.parse(
'https://${value}/api.github.com',
).scheme.isNotEmpty) {
throw true;
}
} catch (e) {
return tr('invalidInput');
}
return null;
},
],
belowWidgets: [
const SizedBox(height: 4),
GestureDetector(
onTap: () {
launchUrlString(
'https://github.com/sky22333/hubproxy',
mode: LaunchMode.externalApplication,
);
},
child: Text(
tr('about'),
style: const TextStyle(
decoration: TextDecoration.underline,
fontSize: 12,
),
),
),
const SizedBox(height: 4),
],
),
]; ];
additionalSourceAppSpecificSettingFormItems = [ additionalSourceAppSpecificSettingFormItems = [
@@ -270,6 +309,18 @@ class GitHub extends AppSource {
return null; return null;
} }
@override
Future<String> generalReqPrefetchModifier(
String reqUrl,
Map<String, dynamic> additionalSettings,
) async {
if ((additionalSettings['GHReqPrefix'] as String? ?? '').isNotEmpty) {
var uri = Uri.parse(reqUrl);
return 'https://${additionalSettings['GHReqPrefix']}/${uri.toString().substring('https://'.length)}';
}
return reqUrl;
}
Future<String> getAPIHost(Map<String, dynamic> additionalSettings) async => Future<String> getAPIHost(Map<String, dynamic> additionalSettings) async =>
'https://api.${hosts[0]}'; 'https://api.${hosts[0]}';
@@ -289,6 +340,12 @@ class GitHub extends AppSource {
Map<String, dynamic> additionalSettings, { Map<String, dynamic> additionalSettings, {
Function(Response)? onHttpErrorCode, Function(Response)? onHttpErrorCode,
}) async { }) async {
SettingsProvider settingsProvider = SettingsProvider();
await settingsProvider.initializeSettings();
var sourceConfigSettingValues = await getSourceConfigValues(
additionalSettings,
settingsProvider,
);
bool includePrereleases = additionalSettings['includePrereleases'] == true; bool includePrereleases = additionalSettings['includePrereleases'] == true;
bool fallbackToOlderReleases = bool fallbackToOlderReleases =
additionalSettings['fallbackToOlderReleases'] == true; additionalSettings['fallbackToOlderReleases'] == true;
@@ -344,6 +401,7 @@ class GitHub extends AppSource {
var url = !e['name'].toString().toLowerCase().endsWith('.apk') var url = !e['name'].toString().toLowerCase().endsWith('.apk')
? (e['browser_download_url'] ?? e['url']) ? (e['browser_download_url'] ?? e['url'])
: (e['url'] ?? e['browser_download_url']); : (e['url'] ?? e['browser_download_url']);
url = undoGHProxyMod(url, sourceConfigSettingValues);
e['final_url'] = (e['name'] != null) && (url != null) e['final_url'] = (e['name'] != null) && (url != null)
? MapEntry(e['name'] as String, url as String) ? MapEntry(e['name'] as String, url as String)
: const MapEntry('', ''); : const MapEntry('', '');
@@ -522,7 +580,10 @@ class GitHub extends AppSource {
allAssetUrls.add( allAssetUrls.add(
MapEntry( MapEntry(
(targetRelease['version'] ?? 'source') + '.tar.gz', (targetRelease['version'] ?? 'source') + '.tar.gz',
targetRelease['tarball_url'], undoGHProxyMod(
targetRelease['tarball_url'],
sourceConfigSettingValues,
),
), ),
); );
} }
@@ -530,7 +591,10 @@ class GitHub extends AppSource {
allAssetUrls.add( allAssetUrls.add(
MapEntry( MapEntry(
(targetRelease['version'] ?? 'source') + '.zip', (targetRelease['version'] ?? 'source') + '.zip',
targetRelease['zipball_url'], undoGHProxyMod(
targetRelease['zipball_url'],
sourceConfigSettingValues,
),
), ),
); );
} }
@@ -652,12 +716,23 @@ class GitHub extends AppSource {
} }
} }
undoGHProxyMod(
String reqUrl,
Map<String, String> sourceConfigSettingValues,
) => reqUrl.replaceFirst(
'https://${sourceConfigSettingValues['GHReqPrefix']}/',
'',
);
@override @override
Future<Map<String, List<String>>> search( Future<Map<String, List<String>>> search(
String query, { String query, {
Map<String, dynamic> querySettings = const {}, Map<String, dynamic> querySettings = const {},
}) async { }) async {
return searchCommon( var sp = SettingsProvider();
await sp.initializeSettings();
var sourceConfigSettingValues = await getSourceConfigValues({}, sp);
var results = await searchCommon(
query, query,
'${await getAPIHost({})}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', '${await getAPIHost({})}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100',
'items', 'items',
@@ -666,6 +741,15 @@ class GitHub extends AppSource {
}, },
querySettings: querySettings, querySettings: querySettings,
); );
if ((sourceConfigSettingValues['GHReqPrefix'] ?? '').isNotEmpty) {
Map<String, List<String>> results2 = {};
results.forEach((k, v) {
results2[undoGHProxyMod(k, sourceConfigSettingValues)] = v;
});
return results2;
} else {
return results;
}
} }
void rateLimitErrorCheck(Response res) { void rateLimitErrorCheck(Response res) {

View File

@@ -129,14 +129,14 @@ class GitLab extends AppSource {
} }
@override @override
Future<String> apkUrlPrefetchModifier( Future<String> assetUrlPrefetchModifier(
String apkUrl, String assetUrl,
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {}); String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
String optionalAuth = (PAT != null) ? 'private_token=$PAT' : ''; String optionalAuth = (PAT != null) ? 'private_token=$PAT' : '';
return '$apkUrl${(Uri.parse(apkUrl).query.isEmpty ? '?' : '&')}$optionalAuth'; return '$assetUrl${(Uri.parse(assetUrl).query.isEmpty ? '?' : '&')}$optionalAuth';
} }
@override @override

View File

@@ -146,10 +146,7 @@ Future<List<MapEntry<String, String>>> grabLinksCommon(
.map((e) => MapEntry(ensureAbsoluteUrl(e.key, reqUrl), e.value)) .map((e) => MapEntry(ensureAbsoluteUrl(e.key, reqUrl), e.value))
.toList(); .toList();
if (allLinks.isEmpty || matchLinksOutsideATags) { if (allLinks.isEmpty || matchLinksOutsideATags) {
allLinks = getLinksInLines(rawBody); // Decode the body if the response is a JSON
}
if (allLinks.isEmpty) {
// Getting desperate
try { try {
var jsonStrings = collectAllStringsFromJSONObject(jsonDecode(rawBody)); var jsonStrings = collectAllStringsFromJSONObject(jsonDecode(rawBody));
allLinks = getLinksInLines(jsonStrings.join('\n')); allLinks = getLinksInLines(jsonStrings.join('\n'));
@@ -163,7 +160,7 @@ Future<List<MapEntry<String, String>>> grabLinksCommon(
); );
} }
} catch (e) { } catch (e) {
// allLinks = getLinksInLines(rawBody);
} }
} }
List<MapEntry<String, String>> links = []; List<MapEntry<String, String>> links = [];

View File

@@ -80,20 +80,20 @@ class RuStore extends AppSource {
} }
Response res1 = await sourceRequest( Response res1 = await sourceRequest(
'https://backapi.rustore.ru/applicationData/download-link', 'https://backapi.rustore.ru/applicationData/v2/download-link',
additionalSettings, additionalSettings,
followRedirects: false, followRedirects: false,
postBody: {"appId": appDetails['appId'], "firstInstall": true}, postBody: {"appId": appDetails['appId'], "firstInstall": true},
); );
var downloadDetails = (await decodeJsonBody(res1.bodyBytes))['body']; var downloadDetails = (await decodeJsonBody(res1.bodyBytes))['body'];
if (res1.statusCode != 200 || downloadDetails['apkUrl'] == null) { if (res1.statusCode != 200 || downloadDetails['downloadUrls'][0]['url'] == null) {
throw NoAPKError(); throw NoAPKError();
} }
return APKDetails( return APKDetails(
version, version,
getApkUrlsFromUrls([ getApkUrlsFromUrls([
(downloadDetails['apkUrl'] as String).replaceAll( (downloadDetails['downloadUrls'][0]['url'] as String).replaceAll(
RegExp('\\.zip\$'), RegExp('\\.zip\$'),
'.apk', '.apk',
), ),

View File

@@ -124,12 +124,12 @@ class Uptodown extends AppSource {
} }
@override @override
Future<String> apkUrlPrefetchModifier( Future<String> assetUrlPrefetchModifier(
String apkUrl, String assetUrl,
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
var res = await sourceRequest(apkUrl, additionalSettings); var res = await sourceRequest(assetUrl, additionalSettings);
if (res.statusCode != 200) { if (res.statusCode != 200) {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }

View File

@@ -70,12 +70,14 @@ class VivoAppStore extends AppSource {
throw NoReleasesError(); throw NoReleasesError();
} }
Map<String, List<String>> results = {}; Map<String, List<String>> results = {};
var resultsJson = json['data']['appSearchResponse']['value']; var resultsJson = json['data']['appSearchResponse']?['value'];
for (var item in (resultsJson as List<dynamic>)) { if (resultsJson != null) {
results['$appDetailUrl${item['id']}'] = [ for (var item in (resultsJson as List<dynamic>)) {
item['title_zh'].toString(), results['$appDetailUrl${item['id']}'] = [
item['developer'].toString(), item['title_zh'].toString(),
]; item['developer'].toString(),
];
}
} }
return results; return results;
} }

View File

@@ -16,9 +16,14 @@ import 'package:provider/provider.dart';
import 'package:markdown/markdown.dart' as md; import 'package:markdown/markdown.dart' as md;
class AppPage extends StatefulWidget { class AppPage extends StatefulWidget {
const AppPage({super.key, required this.appId}); const AppPage({
super.key,
required this.appId,
this.showOppositeOfPreferredView = false,
});
final String appId; final String appId;
final bool showOppositeOfPreferredView;
@override @override
State<AppPage> createState() => _AppPageState(); State<AppPage> createState() => _AppPageState();
@@ -60,6 +65,11 @@ class _AppPageState extends State<AppPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var appsProvider = context.watch<AppsProvider>(); var appsProvider = context.watch<AppsProvider>();
var settingsProvider = context.watch<SettingsProvider>(); var settingsProvider = context.watch<SettingsProvider>();
var showAppWebpageFinal =
(settingsProvider.showAppWebpage &&
!widget.showOppositeOfPreferredView) ||
(!settingsProvider.showAppWebpage &&
widget.showOppositeOfPreferredView);
getUpdate(String id, {bool resetVersion = false}) async { getUpdate(String id, {bool resetVersion = false}) async {
try { try {
setState(() { setState(() {
@@ -565,7 +575,7 @@ class _AppPageState extends State<AppPage> {
icon: const Icon(Icons.settings), icon: const Icon(Icons.settings),
tooltip: tr('settings'), tooltip: tr('settings'),
), ),
if (app != null && settingsProvider.showAppWebpage) if (app != null && showAppWebpageFinal)
IconButton( IconButton(
onPressed: () { onPressed: () {
showDialog( showDialog(
@@ -661,10 +671,10 @@ class _AppPageState extends State<AppPage> {
); );
return Scaffold( return Scaffold(
appBar: settingsProvider.showAppWebpage ? AppBar() : appScreenAppBar(), appBar: showAppWebpageFinal ? AppBar() : appScreenAppBar(),
backgroundColor: Theme.of(context).colorScheme.surface, backgroundColor: Theme.of(context).colorScheme.surface,
body: RefreshIndicator( body: RefreshIndicator(
child: settingsProvider.showAppWebpage child: showAppWebpageFinal
? getAppWebView() ? getAppWebView()
: CustomScrollView( : CustomScrollView(
slivers: [ slivers: [

View File

@@ -451,40 +451,57 @@ class AppsPageState extends State<AppsPage> {
} }
getAppIcon(int appIndex) { getAppIcon(int appIndex) {
return FutureBuilder( return GestureDetector(
future: appsProvider.updateAppIcon(listedApps[appIndex].app.id), child: FutureBuilder(
builder: (ctx, val) { future: appsProvider.updateAppIcon(listedApps[appIndex].app.id),
return listedApps[appIndex].icon != null builder: (ctx, val) {
? Image.memory( return listedApps[appIndex].icon != null
listedApps[appIndex].icon!, ? Image.memory(
gaplessPlayback: true, listedApps[appIndex].icon!,
opacity: AlwaysStoppedAnimation( gaplessPlayback: true,
listedApps[appIndex].installedInfo == null ? 0.6 : 1, opacity: AlwaysStoppedAnimation(
), listedApps[appIndex].installedInfo == null ? 0.6 : 1,
) ),
: Row( )
mainAxisSize: MainAxisSize.min, : Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min,
children: [ mainAxisAlignment: MainAxisAlignment.center,
Transform( children: [
alignment: Alignment.center, Transform(
transform: Matrix4.rotationZ(0.31), alignment: Alignment.center,
child: Padding( transform: Matrix4.rotationZ(0.31),
padding: const EdgeInsets.all(15), child: Padding(
child: Image( padding: const EdgeInsets.all(15),
image: const AssetImage( child: Image(
'assets/graphics/icon_small.png', image: const AssetImage(
'assets/graphics/icon_small.png',
),
color:
Theme.of(context).brightness == Brightness.dark
? Colors.white.withOpacity(0.4)
: Colors.white.withOpacity(0.3),
colorBlendMode: BlendMode.modulate,
gaplessPlayback: true,
), ),
color: Theme.of(context).brightness == Brightness.dark
? Colors.white.withOpacity(0.4)
: Colors.white.withOpacity(0.3),
colorBlendMode: BlendMode.modulate,
gaplessPlayback: true,
), ),
), ),
), ],
], );
); },
),
onDoubleTap: () {
pm.openApp(listedApps[appIndex].app.id);
},
onLongPress: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AppPage(
appId: listedApps[appIndex].app.id,
showOppositeOfPreferredView: true,
),
),
);
}, },
); );
} }

View File

@@ -319,13 +319,24 @@ class _SettingsPageState extends State<SettingsPage> {
if (e.sourceConfigSettingFormItems.isNotEmpty) { if (e.sourceConfigSettingFormItems.isNotEmpty) {
return GeneratedForm( return GeneratedForm(
items: e.sourceConfigSettingFormItems.map((e) { items: e.sourceConfigSettingFormItems.map((e) {
e.defaultValue = settingsProvider.getSettingString(e.key); if (e is GeneratedFormSwitch) {
e.defaultValue = settingsProvider.getSettingBool(e.key);
} else {
e.defaultValue = settingsProvider.getSettingString(e.key);
}
return [e]; return [e];
}).toList(), }).toList(),
onValueChanges: (values, valid, isBuilding) { onValueChanges: (values, valid, isBuilding) {
if (valid && !isBuilding) { if (valid && !isBuilding) {
values.forEach((key, value) { values.forEach((key, value) {
settingsProvider.setSettingString(key, value); var formItem = e.sourceConfigSettingFormItems
.where((i) => i.key == key)
.firstOrNull;
if (formItem is GeneratedFormSwitch) {
settingsProvider.setSettingBool(key, value == true);
} else {
settingsProvider.setSettingString(key, value ?? '');
}
}); });
} }
}, },

View File

@@ -606,10 +606,20 @@ class AppsProvider with ChangeNotifier {
app.url, app.url,
overrideSource: app.overrideSource, overrideSource: app.overrideSource,
); );
String downloadUrl = await source.apkUrlPrefetchModifier( var additionalSettingsPlusSourceConfig = {
app.apkUrls[app.preferredApkIndex].value, ...app.additionalSettings,
...(await source.getSourceConfigValues(
app.additionalSettings,
settingsProvider,
)),
};
String downloadUrl = await source.assetUrlPrefetchModifier(
await source.generalReqPrefetchModifier(
app.apkUrls[app.preferredApkIndex].value,
additionalSettingsPlusSourceConfig,
),
app.url, app.url,
app.additionalSettings, additionalSettingsPlusSourceConfig,
); );
var notif = DownloadNotification(app.finalName, 100); var notif = DownloadNotification(app.finalName, 100);
notificationsProvider?.cancel(notif.id); notificationsProvider?.cancel(notif.id);
@@ -764,10 +774,13 @@ class AppsProvider with ChangeNotifier {
int? targetSDK = (await getInstalledInfo( int? targetSDK = (await getInstalledInfo(
app.id, app.id,
))?.applicationInfo?.targetSdkVersion; ))?.applicationInfo?.targetSdkVersion;
int requiredSDK = osInfo.version.sdkInt - 3;
// The APK should target a new enough API // The APK should target a new enough API
// https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setRequireUserAction(int) // https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setRequireUserAction(int)
if (!(targetSDK != null && targetSDK >= (osInfo.version.sdkInt - 3))) { if (!(targetSDK != null && targetSDK >= requiredSDK)) {
logs.add('Multiple APK URLs: ${app.id}'); logs.add(
'App currently targets API ${targetSDK} which is too low for background updates (requires API ${requiredSDK}): ${app.id}',
);
return false; return false;
} }
@@ -1324,15 +1337,26 @@ class AppsProvider with ChangeNotifier {
evenIfSingleChoice: true, evenIfSingleChoice: true,
); );
if (tempFileUrl != null) { if (tempFileUrl != null) {
var s = SourceProvider().getSource(
apps[id]!.app.url,
overrideSource: apps[id]!.app.overrideSource,
);
var additionalSettingsPlusSourceConfig = {
...apps[id]!.app.additionalSettings,
...(await s.getSourceConfigValues(
apps[id]!.app.additionalSettings,
settingsProvider,
)),
};
fileUrl = MapEntry( fileUrl = MapEntry(
tempFileUrl.key, tempFileUrl.key,
await (SourceProvider().getSource( await s.assetUrlPrefetchModifier(
await s.generalReqPrefetchModifier(
tempFileUrl.value,
additionalSettingsPlusSourceConfig,
),
apps[id]!.app.url, apps[id]!.app.url,
overrideSource: apps[id]!.app.overrideSource, additionalSettingsPlusSourceConfig,
)).apkUrlPrefetchModifier(
tempFileUrl.value,
apps[id]!.app.url,
apps[id]!.app.additionalSettings,
), ),
); );
} }

View File

@@ -249,6 +249,15 @@ class SettingsProvider with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
bool? getSettingBool(String settingId) {
return prefs?.getBool(settingId) ?? false;
}
void setSettingBool(String settingId, bool value) {
prefs?.setBool(settingId, value);
notifyListeners();
}
Map<String, int> get categories => Map<String, int> get categories =>
Map<String, int>.from(jsonDecode(prefs?.getString('categories') ?? '{}')); Map<String, int>.from(jsonDecode(prefs?.getString('categories') ?? '{}'));

View File

@@ -686,14 +686,27 @@ abstract class AppSource {
bool followRedirects = true, bool followRedirects = true,
Object? postBody, Object? postBody,
}) async { }) async {
var sp = SettingsProvider();
await sp.initializeSettings();
getSourceConfigValues(additionalSettings, sp);
var additionalSettingsPlusSourceConfig = {
...additionalSettings,
...(await getSourceConfigValues(additionalSettings, sp)),
};
url = await generalReqPrefetchModifier(
url,
additionalSettingsPlusSourceConfig,
);
var method = postBody == null ? 'GET' : 'POST'; var method = postBody == null ? 'GET' : 'POST';
var requestHeaders = await getRequestHeaders(additionalSettings); var requestHeaders = await getRequestHeaders(
additionalSettingsPlusSourceConfig,
);
var streamedResponseUrlWithResponseAndClient = var streamedResponseUrlWithResponseAndClient =
await sourceRequestStreamResponse( await sourceRequestStreamResponse(
method, method,
url, url,
requestHeaders, requestHeaders,
additionalSettings, additionalSettingsPlusSourceConfig,
followRedirects: followRedirects, followRedirects: followRedirects,
postBody: postBody, postBody: postBody,
); );
@@ -911,12 +924,19 @@ abstract class AppSource {
return null; return null;
} }
Future<String> apkUrlPrefetchModifier( Future<String> assetUrlPrefetchModifier(
String apkUrl, String assetUrl,
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
return apkUrl; return assetUrl;
}
Future<String> generalReqPrefetchModifier(
String reqUrl,
Map<String, dynamic> additionalSettings,
) async {
return reqUrl;
} }
bool canSearch = false; bool canSearch = false;

View File

@@ -5,10 +5,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: android_intent_plus name: android_intent_plus
sha256: "2329378af63f49b985cb2e110ac784d08374f1e2b1984be77ba9325b1c8cce11" sha256: "14a9f94c5825a528e8c38ee89a33dbeba947efbbf76f066c174f4f3ae4f48feb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.3.1" version: "6.0.0"
android_package_installer: android_package_installer:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -104,10 +104,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: battery_plus name: battery_plus
sha256: "03d5a6bb36db9d2b977c548f6b0262d5a84c4d5a4cfee2edac4a91d57011b365" sha256: ad16fcb55b7384be6b4bbc763d5e2031ac7ea62b2d9b6b661490c7b9741155bf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.3" version: "7.0.0"
battery_plus_platform_interface: battery_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -160,10 +160,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: connectivity_plus name: connectivity_plus
sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec sha256: "33bae12a398f841c6cda09d1064212957265869104c478e5ad51e2fb26c3973c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.5" version: "7.0.0"
connectivity_plus_platform_interface: connectivity_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -216,10 +216,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: device_info_plus name: device_info_plus
sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" sha256: "49413c8ca514dea7633e8def233b25efdf83ec8522955cc2c0e3ad802927e7c6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "11.5.0" version: "12.1.0"
device_info_plus_platform_interface: device_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -508,10 +508,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: fluttertoast name: fluttertoast
sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1" sha256: "144ddd74d49c865eba47abe31cbc746c7b311c82d6c32e571fd73c4264b740e2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.2.12" version: "9.0.0"
fraction: fraction:
dependency: transitive dependency: transitive
description: description:
@@ -828,10 +828,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: share_plus name: share_plus
sha256: d7dc0630a923883c6328ca31b89aa682bacbf2f8304162d29f7c6aaff03a27a1 sha256: "3424e9d5c22fd7f7590254ba09465febd6f8827c8b19a44350de4ac31d92d3a6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "11.1.0" version: "12.0.0"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -1059,10 +1059,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
sha256: "07cffecb7d68cbc6437cd803d5f11a86fe06736735c3dfe46ff73bcb0f958eed" sha256: "199bc33e746088546a39cc5f36bac5a278c5e53b40cb3196f99e7345fdcfae6b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.21" version: "6.3.22"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
@@ -1171,10 +1171,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: fb46db8216131a3e55bcf44040ca808423539bc6732e7ed34fb6d8044e3d512f sha256: fea63576b3b7e02b2df8b78ba92b48ed66caec2bb041e9a0b1cbd586d5d80bfd
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.23.0" version: "3.23.1"
win32: win32:
dependency: transitive dependency: transitive
description: description:

View File

@@ -16,7 +16,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.2.4+2320 version: 1.2.5+2321
environment: environment:
sdk: ^3.8.1 sdk: ^3.8.1
@@ -45,8 +45,8 @@ dependencies:
shared_preferences: ^2.5.3 shared_preferences: ^2.5.3
url_launcher: ^6.3.1 url_launcher: ^6.3.1
permission_handler: ^12.0.0+1 permission_handler: ^12.0.0+1
fluttertoast: ^8.2.12 fluttertoast: ^9.0.0
device_info_plus: ^11.4.0 device_info_plus: ^12.1.0
file_picker: ^10.1.9 file_picker: ^10.1.9
animations: ^2.0.11 animations: ^2.0.11
android_package_installer: # TODO: See if PR will be accepted (dev may not be active), else remove this comment android_package_installer: # TODO: See if PR will be accepted (dev may not be active), else remove this comment
@@ -57,14 +57,14 @@ dependencies:
git: git:
url: https://github.com/ImranR98/android_package_manager url: https://github.com/ImranR98/android_package_manager
ref: master ref: master
share_plus: ^11.0.0 share_plus: ^12.0.0
sqflite: ^2.4.2 sqflite: ^2.4.2
easy_localization: ^3.0.7+1 easy_localization: ^3.0.7+1
android_intent_plus: ^5.3.0 android_intent_plus: ^6.0.0
flutter_markdown: ^0.7.7+1 flutter_markdown: ^0.7.7+1
flutter_archive: ^6.0.3 flutter_archive: ^6.0.3
hsluv: ^1.1.3 hsluv: ^1.1.3
connectivity_plus: ^6.1.4 connectivity_plus: ^7.0.0
shared_storage: # TODO: Is this maintained? shared_storage: # TODO: Is this maintained?
git: git:
url: https://github.com/AlexBacich/shared-storage url: https://github.com/AlexBacich/shared-storage
@@ -85,7 +85,7 @@ dependencies:
ref: master ref: master
markdown: ^7.3.0 markdown: ^7.3.0
flutter_typeahead: ^5.2.0 flutter_typeahead: ^5.2.0
battery_plus: ^6.2.1 battery_plus: ^7.0.0
flutter_charset_detector: ^5.0.0 flutter_charset_detector: ^5.0.0
# The "flutter_lints" package below contains a set of recommended lints to # The "flutter_lints" package below contains a set of recommended lints to