Repository navigation
feat(app): make everything free and add voluntary Ko-fi support - #12
Merged
Merged
Conversation
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.
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Glosso is now free for everyone, forever. The paid tier is removed completely, not switched off. The app never sold anything (it always ran in the open beta where the server unlocked everything), so there are no paying users to migrate.
Removed
App (
:shared,:androidApp, iOS)shared/.../billing/*(AccessPolicy, AccessController, ProductAccess, SubscriptionRepository, SubscriptionStatus, BillingPeriods/Text, SubscriptionPlan),PaywallSheet,SubscriptionViewModel, iOSNoSubscriptions.androidApp/.../billing/*, debug/releaseFakeBilling,FakeSubscriptionRepository, theBILLINGpermission,libs.billing, theverifyRelease*Entitlementtasks, theglossoBillingandglossoSubscriptionIdbuild inputs,PlatformActions.openSubscriptionManagement,ScreenshotProtection,PlatformActivity.androidApp/res.CourseOrderTest.Server
server/.../billing/*,POST /v1/billing/verify,POST /v1/billing/rtdn, the billing rate limit and RTDN auth gauge, plans/limits/pricing/founder config, paywall/purchase analytics events.EntitlementService/Store/JdbcEntitlementStorebecomeAccountService/AccountStore/JdbcAccountStore: device identity, Google sign-in, linked accounts and account moves (with profile merge) are kept. No new founder, grant or entitlement rows are written./v1/meand/v1/auth/googlenow return{"linkedAccounts":[...]}./v1/configreturnsflagsandclient, plus fixed"mode":"BETA"and"beta":{"active":true}so already installed app builds (which lock A2+ unless the beta reads as open) keep everything unlocked.entitlements,lifetime_grantsandbeta_founder*data stay untouched; an account move still carries them over instead of letting the cascade delete them.Added
KOFI_URLinshared/src/commonMain/kotlin/com/glosso/app/Support.kt(line 18), blank for now. While blank, the support entry is hidden everywhere.SupportGlossoTest: hidden with a blank URL, shown with one, copy present in every locale.Licensing
Runtime classpath lock and
licenses.jsonrefreshed (Play Billing, datatransport, Firebase encoders, play-services-location and javax.inject are gone).NOTICEnow only names Google Play services and Google Identity (googleid). The Play In-App Review entry was removed too: it was in the curated catalogue and NOTICE but is not on the runtime classpath.Tests
./gradlew :engine:jvmTest: 463 passed, 0 failedLC_ALL=en_US.UTF-8 ./gradlew :server:test: 347 passed, 0 failed (embedded Postgres included)./gradlew :androidApp:testDebugUnitTest: 283 passed, 0 failed./gradlew :shared:testDebugUnitTest: 142 passed, 0 failed./gradlew :androidApp:lintDebug: 0 errors, 73 warnings (all GradleDependency / AGP version / UseKtx / VectorPath / launcher icon, none in changed code)./gradlew :androidApp:assembleDebugand:shared:compileKotlinIosSimulatorArm64: OKpython3 -m unittest tools/licensing/collect_test.py: 24 passedKOFI_URL: Today, Lessons (A1 and A2), You, Library, Settings and About show no lock or Pro UI; the support row opens the browser.Env vars no longer used
GLOSSO_PLAY_SERVICE_ACCOUNT_JSON,GLOSSO_PLAY_SERVICE_ACCOUNT_JSON_BASE64,GLOSSO_PLAY_PACKAGE,GLOSSO_PLAY_PRODUCT_ID,GLOSSO_PLAY_TRIAL_OFFER_ID,GLOSSO_BILLING_CACHE_TTL_SECONDS,GLOSSO_RTDN_SECRET,GLOSSO_RTDN_SUBSCRIPTION,GLOSSO_PRODUCT_MODE,GLOSSO_BETA_END_DATE,GLOSSO_BETA_FOUNDER_ENABLED,GLOSSO_BETA_FOUNDER_UNTIL,GLOSSO_BETA_FOUNDER_BENEFIT_KIND,GLOSSO_BETA_FOUNDER_BENEFIT_VALUE,GLOSSO_BETA_FOUNDER_BENEFIT_LABEL,GLOSSO_PLANS_JSON,GLOSSO_LIMITS_JSON,GLOSSO_PRICING_JSON,GLOSSO_FLAG_BETA_BANNER,GLOSSO_FLAG_PRO,GLOSSO_FLAG_PERSONALIZED. Removed fromdeploy/docker-compose.yml;deploy/.env.examplewas not edited (not readable in this environment) and still lists them.