diff --git a/wailsv3-plan.md b/wailsv3-plan.md new file mode 100644 index 0000000..b453b1b --- /dev/null +++ b/wailsv3-plan.md @@ -0,0 +1,87 @@ +# AniTrack → Wails v3 + Android plan + +Goal: run this same app on my Android phone for personal use. Sideload the APK. No Play Store. No official F-Droid. + +Non-goals: no rewrite of AniList / MAL / Simkl logic. No iOS. No store releases. + +## Big picture (3 steps) + +1. **Desktop parity** — get v3 building and acting like v2 on Linux. +2. **Android storage** — swap where tokens are saved on Android only. +3. **Android login** — replace the localhost login callback with a deep link. + +Each step must run before moving on. If a step fails, stay on the previous one. + +## Step 0 — Done on main (already in this branch) + +Fixed ignored errors in the 3 login files. Same wallet (`ServiceName: AniTrack`), same keys, per-file helpers: + +- `AniListUserFunctions.go`: `aniRingReady()` + `aniRingSet()`, `keyring.Open` error logged, `Set` errors logged with key name, bad `ExpiresIn` logged instead of silently kept. +- `MALUserFunctions.go`: `malRingReady()` + `malRingSet()`, same treatment, including refresh-token saves. +- `SimklUserFunctions.go`: `simklRingReady()` + `simklRingSet()`, same treatment. +- Logouts still clear in-memory JWT even if storage is missing. No more nil-pointer panic when storage fails. + +## Step 1 — Desktop v3 parity (mechanical, no logic changes) + +What changes and nothing else: + +- `main.go`: `wails.Run(options.App{Bind: app})` → `application.New(Services: [app])` + `Window.New()`. +- `app.go`: move the 4 runtime calls to v3 equivalents — `WindowSetTitle`, `WindowUnminimise/Show`, `EventsEmit`, `MessageDialog`. +- Go login files: `BrowserOpenURL` and `MessageDialog` imports change from `wails/v2/pkg/runtime` to v3. Logic stays. +- Frontend (11 files import `wailsjs/go/main/App`, 2 import `wailsjs/runtime`): regenerate with `wails3 generate bindings`, script-replace the import paths. No Svelte rewrites. +- `wails.json` → v3 `Taskfile + build/config.yml`. `Makefile` `wails build` → `wails3 task build`. + +Check: `wails3 doctor`, then desktop app logs in/out of all 3 services exactly like v2. + +## Step 2 — Android token storage (per-file shims) + +Why: `99designs/keyring` is desktop-only (macOS Keychain / WinCred / Linux Secret Service). No Android backend. On Android `Open` returns “no backend”. + +Keep your organization: one file per service, same function names. Only the helper body changes by platform: + +- Desktop files (`//go:build !android`): keep calling `keyring` via `aniRingSet / malRingSet / simklRingSet`. +- Android files (`//go:build android`): same helper names, but call `application.Android.SecureSet / SecureGet / SecureDelete` (backed by EncryptedSharedPreferences). +- Keys stay the same strings (`anilistAccessToken`, `MyAnimeListRefreshToken`, `SimklScope`, …). + +Check: `GOOS=android` compiles; login persists after app restart on emulator. + +## Step 3 — Android login callback (the one redesign) + +Why: today each login opens the browser then listens on `http://localhost:6734/callback` (`AniList:77`, `MAL:127`, `Simkl:71`). Android WebView serves assets in-process — no localhost server, no open ports. + +New flow per service (same order, different plumbing): + +1. App opens system browser to AniList / MAL / Simkl authorize URL. +2. Provider redirects to `anitrack://callback?code=...` instead of `http://localhost:6734/callback`. +3. Android activity receives the deep link, hands `code` to the existing `get*AuthorizationToken()` function. +4. Rest is unchanged: save with `*RingSet()`, same in-memory JWT. + +Requires: add `anitrack://callback` redirect URI in each provider dashboard (AniList, MAL, Simkl), add intent-filter in `build/android`, keep desktop on localhost. + +Start with ONE provider (suggest AniList) to prove the pattern, then copy to the other two. + +## Step 4 — Run it on my phone + +Need: JDK 21, Android SDK 35 + NDK 26.3.x, `ANDROID_HOME` set. `wails3 doctor` confirms. + +```bash +wails3 task android:run # emulator +wails3 task android:run:device # my phone via adb, debug APK +wails3 task android:package # release APK I sideload manually +``` + +Updates: drop APKs in GitHub Releases, point Obtainium at it. No stores. + +## Rules for AI doing this work + +- Small diffs, one step at a time. Never rewrite domain logic to “clean it up”. +- `AniList*` stays in `AniListUserFunctions.go`, MAL in its file, Simkl in its file. +- New platform code goes in new `//go:build` files, not edits to shared logic. +- Every step ends with a runnable check (see “Check” lines). Stop if it fails. +- Go stays plain Go: services are thin facades over existing funcs. No frameworks, no inheritance. + +## Open decisions (mine) + +- [ ] First Android login: AniList only, or all 3 day one? +- [ ] Keep desktop building in parallel on this branch? +- [ ] New `anitrack://callback` URIs registered yet in the 3 dashboards?