Skip to content

feat(app): F-Droid flavor without Google libraries, and model import from a file - #13

Closed
IgnacioLD wants to merge 2 commits into
mainfrom
feat/fdroid-flavor
Closed

IgnacioLD wants to merge 2 commits into
mainfrom
feat/fdroid-flavor

Conversation

@IgnacioLD

Copy link
Copy Markdown
Owner

Stacked on #12 (feat/free-for-all-kofi). This branch is based on it, so the diff against main also shows #12's commit until #12 is merged. Merge #12 first, then this one. The change this PR adds is the top commit, 57bcb9a.

What

Prepares the Android app for F-Droid. The rules that apply, with sources, are in docs/FDROID.md.

  • Product flavors playstore (today's behaviour) and fdroid in :androidApp.
    • androidx.credentials, credentials-play-services-auth and googleid move from :shared to playstoreImplementation.
    • GoogleSignIn moves to androidApp/src/playstore.
    • accountSignIn in :shared is now a plain var that defaults to UnavailableSignIn. Only the playstore Flavor.install() replaces it, so "Change phone" is hidden in fdroid.
  • Usage statistics are off by default in fdroid (Tracking anti-feature: opt-in and disabled by default). Onboarding shows a new notice saying so. Playstore is unchanged.
  • dependenciesInfo.includeInApk = false. The Play-encrypted dependency block is flagged by fdroid scanner. AABs keep it.
  • Import the on-device scoring model from a file, in both flavors.
    • New "Import from a file" action wherever the model download is offered (Settings, Offline, onboarding).
    • Uses the system picker (SAF), so no storage permission is needed.
    • Each picked file is copied while its SHA-256 is computed. It is installed only if the digest matches the pinned digest of the released pack or the one the server publishes, which is the same check a download uses.
    • File names do not matter. Anything else is deleted, and a localized error is shown.
    • Lesson packs are not importable: they have no file format yet.
  • Licensing gate: one runtime-classpath lock per flavor (tools/licensing/runtime-classpath-{fdroid,playstore}.txt). Each flavor's preBuild checks its own lock. The catalogue covers the union of both, and licenses.json is unchanged.
  • F-Droid metadata:
    • fastlane/metadata/android/{en-US,es-ES,fr-FR,de-DE}: title, short and full description, and changelogs/2226.txt.
    • Three en-US phone screenshots.
    • Draft recipe metadata/me.shirobyte42.glosso.yml (AntiFeatures: TetheredNet).
  • Docs: README build instructions for both flavors, the NOTICE Play-services entry, CONTRIBUTING, and task names that no longer exist with flavors (testDebugUnitTest, lintDebug, installDebug, connectedDebugAndroidTest).

Proof

  • fdroid release runtime classpath (:androidApp:dependencies --configuration fdroidReleaseRuntimeClasspath):
    • 0 matches for com.google.android.gms, com.google.firebase, com.google.android.libraries.identity, com.android.billingclient, com.google.android.play, credentials-play-services.
    • The only com.google artifacts are accompanist-drawablepainter and guava:listenablefuture (both Apache-2.0).
    • The playstore classpath has 32 matching lines.
  • fdroid release APK: none of those packages appears in its dex. fdroid scanner (fdroidserver 2.4.5, refreshed signatures) reports 0 problems.
  • Source scan: the fdroidserver source scanner, run with gradle: [fdroid] on the unmodified tree, reports 0 problems. As a control, moving googleid to a plain implementation gives 1. So the recipe needs no prebuild stripping.
  • Recipe: fdroid readmeta and fdroid lint pass, using fdroiddata's config/.

Tests

Check Result
:engine:jvmTest 463 passed
LC_ALL=en_US.UTF-8 :server:test 347 passed
:androidApp:testFdroidDebugUnitTest 292 passed
:androidApp:testPlaystoreDebugUnitTest 291 passed
:shared:testDebugUnitTest 142 passed
:androidApp:lintFdroidDebug 0 errors, 73 warnings, the same 73 as on the base branch
:androidApp:assembleFdroidRelease, :androidApp:assemblePlaystoreDebug OK
:shared:compileKotlinIosSimulatorArm64 OK
gitleaks dir . --redact only the 2 known false positives

New tests:

  • ModelPackImportTest:
    • valid files in any order install;
    • a corrupt or truncated file is rejected and leaves nothing behind;
    • a partial pick reports the pack as incomplete;
    • an unreadable file leaves no partial copy.
  • FdroidFlavorTest:
    • no sign-in is installed;
    • no googleid, Play services or credentials-play-services class is on the classpath;
    • statistics default to off.
  • PlaystoreFlavorTest: Google sign-in is still wired.
  • An AnalyticsTest case for the default-off build.

UI check on emulator-5558 (1080x2340, density 480), fdroid debug build:

  • the onboarding statistics-off notice shows;
  • importing a corrupt file is rejected with the error;
  • importing the real model plus vocabulary installs it ("Ready on this device");
  • Settings has no Account / "Change phone" section and the statistics switch is off.

Open decisions for the owner

  • TetheredNet: an in-app server URL setting would remove it.
  • NonFreeAssets risk: the licence of the lesson texts and audio (glosso-data) needs to be stated.
  • Signing: F-Droid signs with its own key (the default), or developer-signed reproducible builds (Binaries + AllowedAPKSigningKeys). This has to be decided before the first F-Droid release.
  • Donate field: left out of the recipe because the Ko-fi URL is still empty.

https://claude.ai/code/session_01FcVpZoyr8VdRLp1QecX1Ng

Glosso is free for everyone, forever. Remove the paid tier completely
instead of switching it off:

- app: drop the paywall, Pro locks and badges, AccessPolicy/AccessController,
  the subscription repository, Play Billing and its debug/release fakes, the
  release entitlement guard tasks and the glossoBilling/glossoSubscriptionId
  build inputs; every lesson, story, exercise, personalized practice and the
  phonetic profile is simply available. Remove the beta/founder banner.
- server: drop Play purchase verification and RTDN, plans, lifetime grants
  and Beta Founder marking. EntitlementService/Store become
  AccountService/Store and keep device identity, Google sign-in and account
  moves. /v1/config keeps mode=BETA and beta.active=true for older app builds.
  No migration drops tables or data.
- add a "Support Glosso" entry in About and You, hidden while KOFI_URL is
  blank, translated in every app language.
- refresh the license lock and catalogue, NOTICE, README and docs.
…mport from a file

- Split :androidApp into `playstore` and `fdroid` product flavors. Credential
  Manager, its Play services provider and googleid move from :shared to
  playstoreImplementation; Google sign-in lives in src/playstore and :shared
  defaults to UnavailableSignIn, so "Change phone" is hidden in fdroid.
- fdroid starts with usage statistics off (F-Droid Tracking anti-feature);
  onboarding says so.
- Leave AGP's Play-encrypted dependency block out of APKs.
- Import the on-device scoring pack from files picked with the system picker
  (SAF, no storage permission), installed only when the SHA-256 matches the
  pinned or the server-published digest. Available in both flavors.
- One runtime classpath lock per flavor for the licensing gate.
- Fastlane metadata for every app locale, a draft fdroiddata recipe and
  docs/FDROID.md with the rules that apply.

Claude-Session: https://claude.ai/code/session_01FcVpZoyr8VdRLp1QecX1Ng
@IgnacioLD

Copy link
Copy Markdown
Owner Author

Superseded by the rebased PR (same diff on top of the squashed #12).

@IgnacioLD IgnacioLD closed this Nov 10, 2026
@IgnacioLD
IgnacioLD deleted the feat/fdroid-flavor branch November 10, 2026 13:49
IgnacioLD added a commit that referenced this pull request Nov 10, 2026
…mport from a file (#14)

## What

Prepares the Android app for F-Droid. The rules that apply, with
sources, are in `docs/FDROID.md`.

- **Product flavors** `playstore` (today's behaviour) and `fdroid` in
`:androidApp`.
- `androidx.credentials`, `credentials-play-services-auth` and
`googleid` move from `:shared` to `playstoreImplementation`.
  - `GoogleSignIn` moves to `androidApp/src/playstore`.
- `accountSignIn` in `:shared` is now a plain `var` that defaults to
`UnavailableSignIn`. Only the playstore `Flavor.install()` replaces it,
so "Change phone" is hidden in fdroid.
- **Usage statistics are off by default in fdroid** (Tracking
anti-feature: opt-in and disabled by default). Onboarding shows a new
notice saying so. Playstore is unchanged.
- **`dependenciesInfo.includeInApk = false`**. The Play-encrypted
dependency block is flagged by `fdroid scanner`. AABs keep it.
- **Import the on-device scoring model from a file**, in both flavors.
- New "Import from a file" action wherever the model download is offered
(Settings, Offline, onboarding).
  - Uses the system picker (SAF), so no storage permission is needed.
- Each picked file is copied while its SHA-256 is computed. It is
installed only if the digest matches the pinned digest of the released
pack or the one the server publishes, which is the same check a download
uses.
- File names do not matter. Anything else is deleted, and a localized
error is shown.
  - Lesson packs are not importable: they have no file format yet.
- **Licensing gate:** one runtime-classpath lock per flavor
(`tools/licensing/runtime-classpath-{fdroid,playstore}.txt`). Each
flavor's `preBuild` checks its own lock. The catalogue covers the union
of both, and `licenses.json` is unchanged.
- **F-Droid metadata:**
- `fastlane/metadata/android/{en-US,es-ES,fr-FR,de-DE}`: title, short
and full description, and `changelogs/2226.txt`.
  - Three en-US phone screenshots.
- Draft recipe `metadata/me.shirobyte42.glosso.yml` (AntiFeatures:
`TetheredNet`).
- **Docs:** README build instructions for both flavors, the NOTICE
Play-services entry, CONTRIBUTING, and task names that no longer exist
with flavors (`testDebugUnitTest`, `lintDebug`, `installDebug`,
`connectedDebugAndroidTest`).

## Proof

- **fdroid release runtime classpath** (`:androidApp:dependencies
--configuration fdroidReleaseRuntimeClasspath`):
- 0 matches for `com.google.android.gms`, `com.google.firebase`,
`com.google.android.libraries.identity`, `com.android.billingclient`,
`com.google.android.play`, `credentials-play-services`.
- The only `com.google` artifacts are `accompanist-drawablepainter` and
`guava:listenablefuture` (both Apache-2.0).
  - The playstore classpath has 32 matching lines.
- **fdroid release APK:** none of those packages appears in its dex.
`fdroid scanner` (fdroidserver 2.4.5, refreshed signatures) reports 0
problems.
- **Source scan:** the fdroidserver source scanner, run with `gradle:
[fdroid]` on the unmodified tree, reports 0 problems. As a control,
moving `googleid` to a plain `implementation` gives 1. So the recipe
needs no `prebuild` stripping.
- **Recipe:** `fdroid readmeta` and `fdroid lint` pass, using
fdroiddata's `config/`.

## Tests

| Check | Result |
|---|---|
| `:engine:jvmTest` | 463 passed |
| `LC_ALL=en_US.UTF-8 :server:test` | 347 passed |
| `:androidApp:testFdroidDebugUnitTest` | 292 passed |
| `:androidApp:testPlaystoreDebugUnitTest` | 291 passed |
| `:shared:testDebugUnitTest` | 142 passed |
| `:androidApp:lintFdroidDebug` | 0 errors, 73 warnings, the same 73 as
on the base branch |
| `:androidApp:assembleFdroidRelease`,
`:androidApp:assemblePlaystoreDebug` | OK |
| `:shared:compileKotlinIosSimulatorArm64` | OK |
| `gitleaks dir . --redact` | only the 2 known false positives |

New tests:
- `ModelPackImportTest`:
  - valid files in any order install;
  - a corrupt or truncated file is rejected and leaves nothing behind;
  - a partial pick reports the pack as incomplete;
  - an unreadable file leaves no partial copy.
- `FdroidFlavorTest`:
  - no sign-in is installed;
- no googleid, Play services or credentials-play-services class is on
the classpath;
  - statistics default to off.
- `PlaystoreFlavorTest`: Google sign-in is still wired.
- An `AnalyticsTest` case for the default-off build.

**UI check** on emulator-5558 (1080x2340, density 480), fdroid debug
build:
- the onboarding statistics-off notice shows;
- importing a corrupt file is rejected with the error;
- importing the real model plus vocabulary installs it ("Ready on this
device");
- Settings has no Account / "Change phone" section and the statistics
switch is off.

## Open decisions for the owner

- **TetheredNet:** an in-app server URL setting would remove it.
- **NonFreeAssets risk:** the licence of the lesson texts and audio
(glosso-data) needs to be stated.
- **Signing:** F-Droid signs with its own key (the default), or
developer-signed reproducible builds (`Binaries` +
`AllowedAPKSigningKeys`). This has to be decided before the first
F-Droid release.
- **Donate field:** left out of the recipe because the Ko-fi URL is
still empty.

https://claude.ai/code/session_01FcVpZoyr8VdRLp1QecX1Ng

Replaces #13, rebased onto main after #12 was squash-merged (same diff,
single commit).

https://claude.ai/code/session_01FcVpZoyr8VdRLp1QecX1Ng

Co-authored-by: IgnacioLD <178957758+IgnacioLD@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant