feat(auth): add API key settings screen#156
Conversation
Greptile SummaryThis PR adds an API key authentication settings screen to the Android app, backed by a new
Confidence Score: 5/5Safe to merge; new auth screen and ConfigManager are functionally correct with the previously flagged issues resolved. All previously flagged correctness issues (atomic write, write-failure propagation, switch double-toast, deprecated Switch widget, section-scoped regex, EOF trailing-newline insertion) have been addressed across the followup commits. The remaining notes are cosmetic: a non-adaptive background color on one view and hardcoded strings that could move to strings.xml. activity_auth_settings.xml: the @android:color/darker_gray background on tv_api_key will look off in dark mode — worth a quick fix before shipping. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant U as User
participant ASA as AuthSettingsActivity
participant CM as ConfigManager
participant FS as config.toml
U->>ASA: opens settings screen
ASA->>CM: readAuthConfig() [IO]
CM->>FS: readText()
FS-->>CM: TOML content
CM-->>ASA: AuthConfig(apiKey, isEnabled)
ASA->>ASA: applyAuthToUI()
alt User toggles switch ON
U->>ASA: toggle switch ON
ASA->>CM: readAuthConfig() [IO]
CM-->>ASA: "isEnabled=false"
ASA->>CM: generateAndSetApiKey() [IO]
CM->>CM: UUID.randomUUID()
CM->>FS: writeText(tmp) then renameTo(config.toml)
CM-->>ASA: newKey or null on failure
ASA->>U: show key + toast
end
alt User toggles switch OFF
U->>ASA: toggle switch OFF
ASA->>CM: clearApiKey() [IO]
CM->>FS: writeText(tmp) then renameTo(config.toml)
CM-->>ASA: success Boolean
ASA->>U: hide key + toast
end
alt User clicks Copy
U->>ASA: tap Copy
ASA->>CM: readAuthConfig().apiKey [IO]
CM-->>ASA: key string
ASA->>U: setPrimaryClip (EXTRA_IS_SENSITIVE on API 33+)
end
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant U as User
participant ASA as AuthSettingsActivity
participant CM as ConfigManager
participant FS as config.toml
U->>ASA: opens settings screen
ASA->>CM: readAuthConfig() [IO]
CM->>FS: readText()
FS-->>CM: TOML content
CM-->>ASA: AuthConfig(apiKey, isEnabled)
ASA->>ASA: applyAuthToUI()
alt User toggles switch ON
U->>ASA: toggle switch ON
ASA->>CM: readAuthConfig() [IO]
CM-->>ASA: "isEnabled=false"
ASA->>CM: generateAndSetApiKey() [IO]
CM->>CM: UUID.randomUUID()
CM->>FS: writeText(tmp) then renameTo(config.toml)
CM-->>ASA: newKey or null on failure
ASA->>U: show key + toast
end
alt User toggles switch OFF
U->>ASA: toggle switch OFF
ASA->>CM: clearApiKey() [IO]
CM->>FS: writeText(tmp) then renameTo(config.toml)
CM-->>ASA: success Boolean
ASA->>U: hide key + toast
end
alt User clicks Copy
U->>ASA: tap Copy
ASA->>CM: readAuthConfig().apiKey [IO]
CM-->>ASA: key string
ASA->>U: setPrimaryClip (EXTRA_IS_SENSITIVE on API 33+)
end
Reviews (17): Last reviewed commit: "fix(auth): move ConfigManager I/O off UI..." | Re-trigger Greptile |
|
Note: the |
|
Fixed all Greptile findings in 5b15dad:
|
|
@greptileai review |
|
Follow-up to previous fix: the first commit only scoped the |
|
CI update: |
|
Fixed remaining Greptile finding (ef4acb1): set Note: the ConfigManagerTest stale-copy warning was already resolved in 37e18f8 (the test helper mirrors the scoped |
|
@greptileai review |
|
Update: I pushed b1c51a8 to fix the That should remove the |
|
You can probably fix the "Get latest versionCode" too (see #139 (comment) for the general request which may need coordination - might already be work-in-progress there). versionCode can probably just fallback to some current value/guess for non-master/release builds. |
|
Fixed remaining Greptile P1 (629cc52): |
|
@greptileai review |
|
Pushed d0acba7 to handle the The workflow now detects whether Verified on the fresh run: |
|
Fixed in PR #158: |
|
Opened #159 to fix the For the |
|
@greptileai review |
|
Pushed 23a57d5 to fix the current Linux E2E startup failure. Root cause from the failed job: the workflow was running Verified locally: workflow YAML parses and |
|
Pushed 3a50619 to address the next E2E startup failure. The fresh failed log made the runner issue clearer: The workflow now treats the probe as informational, starts the emulator headless with Verified locally: workflow shell block parses with |
|
Pushed 4006732 to fix the latest E2E failure. Root cause: the E2E tests passed, but the diagnostic The screenshot step now treats app launch and screenshot capture as best-effort diagnostics, then still lists whatever artifacts were produced. Verified locally: workflow YAML parses, the extracted shell block passes Fresh CI for 4006732 is queued/running. |
|
Pushed 9491520 to address the latest Greptile finding.
Local verification: @greptileai review |
|
@TimeToBuildBob Stuck again: What's up with that? 20.04 might be too old? |
|
Pushed ffbdd1f to fix the persistent Root cause: the The fix: |
|
Your guess is right — it's the Fix: change (Separate, unrelated: the latest master Build run is red on |
|
The CI run you saw was from an earlier commit that still had |
|
The runner scarcity was temporary — CI is now fully green (all checks pass on run #26291186061). The ubuntu-20.04 runner wasn't actually removed; GitHub just hits capacity spikes on older runner pools occasionally. PR branch already uses ubuntu-22.04 for the Test job (and ubicloud for the heavy Rust/build jobs), so there's nothing to fix here. |
|
All checks are now passing on run #26291186061:
The ubuntu-20.04 runner was temporarily backed up earlier — the queue has cleared and all jobs completed successfully. Ready for review whenever you have a chance. |
|
Yes, GitHub-hosted runners are no longer available — the job was waiting for a runner that will never appear. Filed #163 to update the Test job to . That should unblock this CI. |
|
CI looks green now — Test, Build aw-server-rust, and Test E2E all passed. The ubuntu-20.04 runner was probably temporarily stuck in queue rather than a deprecation issue. No workflow change needed. |
Implements the Android-side UI for API authentication, now that aw-server-rust#608 landed and embedded config loads from app data dir. - ConfigManager.kt: reads/writes [auth].api_key in config.toml stored at context.filesDir; uses UUID-based key generation; pure string TOML manipulation, no extra library dependency - AuthSettingsActivity.kt: shows current API key, copy-to-clipboard, regenerate, and enable/disable toggle; prompts user to restart app after changes (server rereads config at startup) - activity_auth_settings.xml: layout for the settings screen - AndroidManifest.xml: registers AuthSettingsActivity - MainActivity.kt: wires the previously-stub settings button to open AuthSettingsActivity instead of a Snackbar - ConfigManagerTest.kt: 11 JVM unit tests covering parse/write logic including roundtrips and the [auth]-without-key edge case Closes ActivityWatch#145 (partial — "Open in browser" URL token passing and server restart API are follow-up work)
- ConfigManager.writeApiKey: scope api_key detection to [auth] section only, preventing cross-section corruption when other TOML sections also contain an api_key field - AuthSettingsActivity: show btnCopy immediately after enable via switch or regenerate button (was permanently hidden after toggle) - AuthSettingsActivity: guard switch.isChecked setter with isUpdatingSwitch flag to prevent double-toast when regenerating key - Layout: replace deprecated Switch with SwitchMaterial - ConfigManagerTest: add cross-section api_key isolation regression test
The previous fix scoped the apiKeyLinePresent check but still ran replaceFirst on the full file content, which would still clobber an api_key field in an earlier TOML section. Now: extract the [auth] section, perform all string operations within it, then substitute the modified section back into the full content. Test helper mirrors the fix.
Set ClipDescription.EXTRA_IS_SENSITIVE so the system does not show a plaintext preview toast of the API key when copying on Android 13+.
Unit tests (./gradlew test) run on the JVM and don't require native .so files. The jniLibs cache restore was failing because the cache was saved by a ubicloud runner but the Test job runs on a GitHub-hosted runner (different cache backend). Remove NDK setup and jniLibs cache restore from the Test job, and drop the needs:[build-rust] dependency since there are no longer any shared artifacts.
a9c05ca to
af76fac
Compare
- Add kotlinx-coroutines-android + lifecycle-runtime-ktx deps
- Wrap all ConfigManager calls in lifecycleScope.launch { withContext(Dispatchers.IO) }
so file reads/writes never block the main thread
- Rename refreshUI() → scheduleRefreshUI() (coroutine launcher) +
applyAuthToUI(auth) (pure UI update) to make the async boundary explicit
- Fix spurious 'Setting saved' toast: only show when the switch ON branch
actually wrote a new key; suppress when auth was already enabled
|
@greptileai review |
|
Pushed Threading fix (4→5 blocker): Added Spurious toast fix: The "Setting saved" toast now only fires when the switch-ON branch actually wrote a new key. Toggling ON while auth is already enabled no longer shows the toast.
|
Summary
Now that aw-server-rust#608 (load embedded config from app data dir) is merged,
the Android app can read and write the
[auth]section inconfig.tomltomanage API key authentication natively.
This PR implements the Android-side UI:
ConfigManager.kt: reads/writes[auth].api_keyinconfig.tomlstored at
context.filesDir. Uses UUID-based key generation. Pure stringTOML manipulation — no extra library dependency.
AuthSettingsActivity.kt: shows current API key, copy-to-clipboard,regenerate button, and an enable/disable toggle. Prompts user to restart
app after changes (server re-reads config at startup).
activity_auth_settings.xml: layout for the settings screen.AndroidManifest.xml: registersAuthSettingsActivity.MainActivity.kt: wires the previously-stub settings button to openAuthSettingsActivityinstead of a Snackbar.ConfigManagerTest.kt: 11 JVM unit tests covering parse/write logicincluding roundtrips and the
[auth]-without-key edge case.Scope
In scope: view/copy/regenerate API key; enable/disable auth toggle; basic settings screen.
Not yet in this PR (follow-ups):
?token=KEYURL passingTest plan
./gradlew :mobile:testCloses #145 (partial — server restart API and browser URL passing are follow-up)