103 Commits

Author SHA1 Message Date
Imran Remtulla
fc3f6dc937 Return all install-capable activities per app for external installer selection and show grouped expandable picker with deduplication, consistent single/multi-intent visuals, and activity name shown in subtitle only when multiple intents exist (#3067) 2026-07-14 20:46:58 +01:00
Imran Remtulla
bf67115464 Add notification permission request on first non-TV launch and declare POST_NOTIFICATIONS in manifest (#3070) 2026-07-14 09:37:03 +01:00
Imran Remtulla
652788d276 fix: guard onNewIntent against uninitialized plugin callResult (#3018) 2026-07-08 21:29:17 +01:00
Imran Remtulla
9e2e0bddd1 Fix #3018 crash on resume with pending share intent, #3015 add-app nav bar overlap, #3019 banner-only-for-updates setting 2026-07-08 15:04:25 +01:00
Imran Remtulla
84b0bf1a65 URL-encode shared URLs to preserve query params in SEND intent deeplinks 2026-07-08 11:10:09 +01:00
Anton Petrov
4c3e9ece75 Implement SEND intent (#2994) 2026-07-08 11:00:37 +01:00
Imran Remtulla
ab60373574 experiment: replace background_fetch + flutter_foreground_task with workmanager
THIS IS EXPERIMENTAL AND MAY NEED TO BE REVERTED.

- Replace background_fetch (^1.7.0) and flutter_foreground_task (^9.2.2)
  with workmanager (^0.9.0+3)
- Single callbackDispatcher replaces both the old headless task and the
  foreground service TaskHandler — simplifies to one code path
- WorkManager constraints enforce WiFi-only and charging-only at the OS
  level instead of checking in Dart after waking the app
- Fix: enableBackgroundUpdates toggle now properly cancels/resumes
  WorkManager tasks (previously the toggle was UI-only and didn't
  actually stop background checks)
- Add "Run background check now" button to the bottom of the Updates
  settings card for manual testing
- Detailed logging at every stage: WorkManager init, task registration,
  callback invocation, completion, and crashes
- Removed: foreground service declaration, FOREGROUND_SERVICE_SPECIAL_USE
  permission, useFGService setting, showBatteryOptimizationPrompt setting,
  and 4 orphaned translation keys

Known risk: workmanager was previously tried and abandoned in Nov 2022
(PR #97) due to fluttercommunity/flutter_workmanager#415 and #363 (tasks
stopping after app closed / after 3-5 days). These issues remain open
but the package has had 4 years of updates since then.
2026-07-06 17:29:44 +01:00
Imran Remtulla
c2aac8885a feat: per-download cancel button and download size display
Add a cancel button for in-progress downloads (in the app list tile, the
detail page, and the download notification) and surface download sizes:
the expected size before starting (best-effort probe) and live
received/total progress in the UI and notification.

- Route notification Cancel taps via the FLN background isolate to the main
  isolate (IsolateNameServer/SendPort); gated off for background-isolate
  downloads whose cancel token isn't reachable.
- Share per-app download state (progress + bytes) across AppInMemory copies
  so UI listeners keep updating after saveApps replaces the map entry.
- Treat cancellations silently and keep the .part file for later resume.
2026-07-02 21:03:58 +01:00
Imran Remtulla
df76426c68 feat: add installer abstraction with Shizuku and external-app install modes
Introduce a lib/installers/ strategy layer (Installer + InstallResult with
stock, Shizuku, and external implementations) and route install decisions
through it instead of the inline useShizuku branching.

Add an external-installer mode that hands a downloaded APK/bundle to a
user-chosen installer app: discovery and a FileProvider content URI come from
two tiny native helpers, while intent dispatch, foreground tracking, and
install confirmation (via lastUpdateTime, robust to pseudo-versions) live in
Dart. Replace the useShizuku toggle with an install-method selector and
migrate the old setting.
2026-07-02 17:25:42 +01:00
Imran Remtulla
6e2c2c592c fix: resolve bugs, dead code, unsafe patterns, and infrastructure issues
HIGH severity:
- Fix Completer double-completion masking CheckUpdatesException as StateError
- Delete orphaned APK files on install-already-pending status code
- Stop transient source-load errors from permanently deleting user app entries
- Await saveApps in setCategories to avoid data inconsistency
- Guard packageManager.openApp double-tap behind installed check
- Fix hashCode.abs() overflow on min int value in DownloadNotification

MEDIUM severity:
- Wrap checkETagHeader client.send in try/finally to prevent resource leak
- Remove unused loadingCompleter dead code in loadApps
- Pass additionalSettings (not {}) in apkcombo sourceRequest call
- Remove dead getRequestHeaders call in coolapk
- Add missing == true on boolean setting checks in fdroidrepo
- Zero-pad month/day in itchio date version string
- Deep-copy form items by value in izzyondroid and codeberg constructors
- Remove redundant double-reverse for sort=none in github release sorting
- Clamp negative gradient stop to valid range in app_list_tile
- Show WebView error state when main frame resource fails to load
- Defer WebView appId changes until page load completes
- Defer category pruning side effect out of build into post-frame callback
- Expand URL regex in import_export to match whitespace-delimited URLs
- Remove future-update-in-build side effect for source notes in add_app
- Add items hash to form reinit check alongside widget key

LOW severity:
- Add 'name' field to all 11 AppSource subclasses that lacked it
- Remove unused source_provider imports from app_detail_widgets, category_editor
- Rename copy-pasted bool show param to bool value on non-show setter pairs
- Delete dead proguard-rules.pro (Gson is not a dependency)
- Remove npm package files from git tracking in assets/translations
- Fix DEVELOPER_GUIDE test directory reference
2026-07-02 14:38:17 +01:00
Imran Remtulla
226eab22a0 Fix bugs, improve readability, and clean up across the codebase
Bugs fixed:
- generated_form.dart: initForm() crashed on GeneratedFormSwitch (missing case)
- apps_provider.dart: HttpClient leak in downloadFile(), now protected by try/finally
- apps_provider_install.dart: magic numbers 0/3 replaced with named constants
- app.dart: unstable hash from Map.toString() replaced with jsonEncode
- home.dart: context.read in build() → context.select (no rebuild on app add/remove)
- apps.dart: O(n²) string concat → StringBuffer; setState without mounted guard
- farsroid.dart: Uri.encodeFull encoded ?/& → removed; missing status code check added
- rustore.dart: null appId creating .../null URL; error-swallowing try/catch fixed
- jenkins.dart: unsafe json['timestamp'] as int cast → int.tryParse
- aptoide.dart: fragile substring+12 ID extraction → capturing regex group
- apkpure.dart: unguarded DeviceInfoPlugin; empty arch filename trailing dash
- apkmirror.dart: regex filter producing misleading NoVersionError
- apk4free.dart: empty-string version bypassing title-parsing fallback
- tencent.dart: substring(18) magic number → jsVar.length constant
- rockmods.dart: unsafe as Map? cast → is Map guard
- fdroid.dart: null appId in URL interpolation; RegExp instantiated in for loop

Refactored:
- source_provider.dart: ~290 lines of legacy JSON migrations → app_migrations.dart
- import_export.dart: IIFE pattern → normal async/try/catch/finally
- import_export.dart: deduplicated PlatformException handling
- add_app.dart: cleaned up state mutation outside setState pattern
- app_list_builder.dart: sort(added) returns List.from() instead of mutable ref
- codeberg.dart: gh → _gh for consistency with gitlab.dart
- uptodown.dart: parseDateTimeMMMddCommayyyy → parseUptodownDate
- app_list_tile.dart: redundant SizedBox.shrink() → if-spread; IIFE → helper method

Docs & comments:
- README: removed redundant source-code link
- DEVELOPER_GUIDE: added app_migrations.dart; improved settings reference
- Comments: prevApp flag, home SizedBox.shrink, huawei date logic, gradient stop,
  telegramapp URL discard, gitlab _gh usage, coolapk device fingerprint note
- Fixed outdated 'Previous 2 variables' comment in source_provider.dart

CI & infra:
- release.yml: fixed undefined inputs.checkout; added fetch-depth: 0; v3→v4
- translation-validate.yaml: fixed @v6.0.2 typo → @v4
- build.sh: added set -euo pipefail
- proguard-rules.pro: removed dead Gson example rule
- standardize.mjs: warns on untracked keys; fixed broken error logging

Translations:
- en.json: added 4 missing keys (downloadFailed, downloadedXNotifChannel,
  import, noMatchingReleaseFound)
2026-07-01 10:11:08 +01:00
Imran Remtulla
83f22e975e fix: revert non-lib files to f85309b9 (last known good release APK)
The release crash was a native SIGSEGV in libflutter.so caused by an
ABI mismatch. Commit f85309b9 was the last one that produced a working
release APK. All files outside lib/ that changed since then are reverted
to that commit: android/ build config, pubspec, build.sh, sign.sh,
docker, .gitignore, analysis_options.yaml, and the .flutter submodule.
The Dart source code in lib/ is deliberately kept at its current state.

Also adds a minimal proguard-rules.pro (2 lines) with -dontwarn for
androidx.window.extensions/sidecar, which R8 needs to complete the build.
2026-06-29 22:07:18 +01:00
Imran Remtulla
06993a5595 fix: set shrink=false in gradle.properties to disable Android R8
The Flutter Gradle plugin's shouldShrinkResources() checks the "shrink"
project property before forcing isMinifyEnabled=true on release builds.
Setting it to false in gradle.properties prevents R8 from running entirely,
eliminating the need for any proguard-rules.pro (no -dontwarn, no -keep,
no maintenance burden). Dart-side tree-shaking is unaffected.
2026-06-29 19:46:04 +01:00
Imran Remtulla
c851da8381 fix: proguard-rules.pro with -dontwarn and per-plugin -keep rules
The Flutter docs state R8 is always enabled on release (--no-shrink has no
effect). The SDK's own flutter_proguard_rules.pro ships a best-effort
-if..-keep rule, but it only covers classes directly implementing
FlutterPlugin - not the internal/model/companion classes that plugins also
access via reflection at startup. Stripping those causes immediate launch
crashes (NoClassDefFoundError).

This file adds the -dontwarn for androidx.window (compile-time-only OEM
stubs pulled transitively by the newer Flutter embedder) and blanket -keep
rules for every native plugin package R8 was observed to remove (sourced
from usage.txt of a prior release build).
2026-06-29 19:08:13 +01:00
Imran Remtulla
a5015d5dc1 fix: don't replace Flutter's proguard defaults; proguard-rules.pro only needs -dontwarn for androidx.window
The Flutter Gradle plugin (FlutterPlugin.kt:218-225) already programmatically
applies the SDK's own flutter_proguard_rules.pro (which ships -dontwarn
android.** and an -if..-keep for FlutterPlugin implementations) plus
proguard-android-optimize.txt. An explicit proguardFiles(...) block in
build.gradle.kts REPLACES that list, silently losing the SDK's rules.

Now build.gradle.kts leaves the proguardFiles list alone (the plugin manages
it) and the only thing proguard-rules.pro adds is -dontwarn for
androidx.window.extensions/sidecar — the one package the SDK's built-in
-dontwarn android.** doesn't match (it's "androidx", not "android").
2026-06-29 17:25:48 +01:00
Imran Remtulla
fdadcec2a4 fix: wire proguard-rules.pro into release buildType, with keep rules and dontwarn
The Flutter embedder (io.flutter:flutter_embedding_release) transitively
pulls androidx.window:window-java:1.2.0, whose ExtensionsUtil references
the compile-time-only androidx.window.extensions / sidecar modules. R8
(rightly) rejects the missing classes. The -dontwarn suppresses those
errors *and* 5ad3cb1 already needed, while the -keep rules prevent R8
from stripping plugin classes accessed reflectively at launch (the
Flutter Gradle plugin forces isMinifyEnabled=true on release regardless
of build.gradle.kts).

The Gson boilerplate present in the old proguard-rules.pro was removed;
none of those rules are relevant to this app (the Gson classes are
transitive noise from a plugin dependency, and the example.com.gson
package literally doesn't exist).
2026-06-29 17:12:28 +01:00
Imran Remtulla
cb55e00acc chore: remove proguard-rules.pro (no longer referenced since 5b0059f8)
The release buildType no longer wires any proguard file since the R8
revert. The Gson / androidx.window rules are dead config.
2026-06-29 16:52:22 +01:00
Imran Remtulla
5b0059f87b fix: revert R8 minification for release builds (added by 5ad3cb1)
Commit 5ad3cb1 added isMinifyEnabled/isShrinkResources/proguardFiles to
the release buildType, enabling R8 on the Android-native side. Without
comprehensive keep rules, R8 stripped plugin classes accessed reflectively
at launch (flutter_foreground_task, android_package_installer, shizuku,
etc. — 267 classes in usage.txt), causing an immediate
NoClassDefFoundError crash in production. Reverting to standard Flutter
defaults (no Android-native minification) to restore working release
builds.
2026-06-29 16:44:29 +01:00
Imran Remtulla
5ad3cb1f2d Fix release build: add androidx.window R8 keep rules, wire proguard-rules.pro
This Flutter SDK's Gradle plugin enables R8 release minification by default (FlutterPluginUtils.shouldShrinkResources() returns true), so release builds run minifyReleaseWithR8. R8 then fails on the optional androidx.window.extensions/sidecar classes - compile-time-only stubs referenced by the transitive androidx.window dependency and provided by the OEM at runtime.

- proguard-rules.pro: -dontwarn androidx.window.extensions/sidecar (per R8's own missing_rules.txt) - build.gradle.kts: make isMinifyEnabled/isShrinkResources explicit and add proguardFiles so proguard-rules.pro is actually applied (it was never referenced before, leaving its rules dormant)
2026-06-29 02:45:32 +01:00
Imran Remtulla
d9088de2f3 Android manifest: add supportsRtl, remove invalid exported on action element 2026-06-28 19:33:45 +01:00
hansjansen2
0f2439caed Enable async MTE in main/AndroidManifest.xml 2026-04-15 14:40:55 +02:00
Kris
4e4413d813 added basic android tv support / remote focus handling 2026-03-21 14:51:17 -04:00
Gregory Velichko
11892633e1 Updated native plugins 2026-01-19 19:45:03 +03:00
Imran Remtulla
dceb99be57 Allow for unsigned release builds 2026-01-16 21:35:32 -05:00
deminearchiver
73ee705275 The warning is shown only when building in release mode. 2025-12-15 13:31:11 +03:00
deminearchiver
a50f73fb4f Added more checks to the release signing config validation.
The following case is now properly being handled:
```
Execution failed for task ':app:packageRelease'.
> A failure occurred while executing com.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable
   > SigningConfig "release" is missing required property "storeFile".
```
2025-12-15 13:31:11 +03:00
deminearchiver
4cd2eefd7c Updated build.gradle.kts.
Renamed the flavor dimension to align with Flutter's recommendations. Changed keystore properties to casts, and allowed the store file to be nullable. Introduced handling of an absent key.properties file during release builds.
2025-12-15 13:31:10 +03:00
deminearchiver
1c9e00121d Upgraded project to Flutter 3.38.3.
- Bumped Dart SDK to 3.10.1
- Bumped Flutter SDK to 3.38.0
- Bumped NDK to 28.2.13676358
- Bumped com.android.application to 8.11.1
- Bumped org.jetbrains.kotlin.android to 2.2.20
- Bumped Java to 17
- Changed formatting in Gradle configuration files to align with a fresh Flutter project's
2025-12-15 13:31:09 +03:00
deminearchiver
60908ee89a Resolve deprecation warning about flavorDimensions. 2025-12-15 13:31:09 +03:00
Imran Remtulla
a34e45363b Fix versionCode issue (#2505) + Flutter upgrades 2025-09-12 15:13:20 -04:00
Imran Remtulla
bad76a1ee7 Remove unnecessary permission (#2467) 2025-08-20 18:57:53 -04:00
Imran Remtulla
918091ba54 Added foreground service option + other updates 2025-07-02 20:09:20 -04:00
Imran Remtulla
c88f55af5a Fix versionCode issue for universal builds (#2352) 2025-06-15 14:42:58 -04:00
Imran Remtulla
0a30bf6d8e Update to Java 21 + hardcode NDK to avoid warnings 2025-05-31 03:57:16 -04:00
Imran Remtulla
8bec3cf053 Update Android-side Gradle stuff + dependencies + upgrade all Flutter packages to latest 2025-05-31 03:35:29 -04:00
Imran Remtulla
6c3a496be1 Add missing update ownership permission (#2078) 2025-05-17 00:42:38 -04:00
Imran Remtulla
9954b68332 Upgrade to latest Flutter version (fix Gradle and other errors) 2025-01-11 22:35:40 +03:00
Rob Emery
25233f3259 App is now called debug so its easier to spot 2024-10-16 01:30:18 +01:00
Rob Emery
cff6b86997 App debug builds can now be installed side-by-side with non-debug 2024-10-16 01:22:57 +01:00
GitGitro
bd26b6514a Enable per-app language, closes #1430 2024-05-12 18:07:35 +02:00
Jonas Mörschbach
2570c8e289 Use applicationId for provider authorities
Fixes #1378

Instead of hardcoding the authority string, use the ${applicationId} to
always make the provider unique.
2024-04-21 21:49:33 +02:00
Gregory Velichko
7b882d9bd8 Move to plugins🐱🎉 2024-04-14 18:40:32 +03:00
Gregory
2289e58dda Move to fonts plugin 2024-03-31 14:18:21 +03:00
Gregory
5b5f922b54 Synced 2024-03-30 15:58:28 +03:00
Gregory
6545498c21 Return random request code 2024-03-30 15:39:48 +03:00
Imran Remtulla
f905aa7dfd Made required changes according to https://docs.flutter.dev/release/breaking-changes/flutter-gradle-plugin-apply 2024-03-17 05:12:31 -04:00
Imran Remtulla
db484f7b28 Don't remove storage permission (#1391) 2024-02-18 18:13:17 -05:00
Gregory
9717db0ca4 Probably fixed 2024-02-05 18:26:17 +03:00
Imran Remtulla
a3530ce6bb Remove READ_EXTERNAL_STORAGE again (#1309) + fix typo 2024-01-28 16:58:09 -05:00
Imran Remtulla
c9751227a5 Flutter upgrade + versionCode changes + increment version 2024-01-27 21:56:26 -05:00