feat(mobile): persist collapsed connect CTAs on the new-session screen - #6189
Merged
Merged
Conversation
Surface: the mobile app (apps/mobile). The "connect x" CTAs for cloud agent sessions cannot be dismissed, so they take space on every visit. Let the user collapse them, and keep them collapsed across app restarts. Collapsed means the CTA is reduced, not deleted: the user can expand it again. Persist the state per CTA, in the app's own persistent storage. A CTA whose connection is later made is no longer shown at all, as today. Verify live: collapse each CTA, force-quit the app, reopen it, and show every CTA still collapsed. Then expand one and show it stays expanded across another restart. Capture the collapsed and expanded states. The bar is best-in-class UX. A change that works but feels worse than the rest of the app is not done: the states, the spacing, the motion and the wording match what the app already does well.
iscekic
marked this pull request as draft
September 15, 2026 22:13
Contributor
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryReviewed the mobile collapsed-connect-CTA feature across 10 changed files (4 production, 6 test); the controlled/uncontrolled split, the persisted store, the merge-on-load behavior, the sign-out clear, and the reduced-motion path all hold up, with no correctness, security, or leak defects found in changed lines. Overview
Verification Notes
Files Reviewed (10 files)
Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0 Review guidance: REVIEW.md from base branch |
eshurakov
approved these changes
Sep 16, 2026
This was referenced Sep 17, 2026
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.
Changelog for users
Changelog for maintainers
CollapsibleSectiongains optional controlled propsexpandedandonToggle; whenexpandedis supplied the parent owns the state and the section never flips it itself, and omitting it keeps the existing uncontrolled behavior.CollapsibleSectionalso acceptstitleClassNameandcontentClassNameso a call site can match its surrounding typography and spacing.collapsed-connect-ctas; it drops malformed, non-array, and unknown entries and de-duplicates the rest.CollapsibleSection, the merge-on-load behavior, and the reduced-motion branch.E2E proof
[e6] ux-check: Force-quit and relaunch, then open a new session: every CTA collapsed before the quit is still collapsed, with no frame that shows it expanded first. — android/emulator-5554. On the account with a live connect CTA, the GitLab card was collapsed before the quit (e6a.log 'SCENE e6a OK': 'android.widget.Button Connect GitLab tappable [76,1423][1004,1469]' immediately followed by 'android.widget.TextView Changes tappable [37,1555][1045,1601]', i.e. only the title row, no description or Open button) and is still collapsed after a real process restart (e6-pids.log 'before=31169 afterStop= afterLaunch=32108'; finalcheck3.log 'SCENE finalcheck3 OK' shows the same collapsed rows at [76,1423]/[37,1555]; e6b3.log repeats it after a third relaunch). The…
e6-reopen-collapsed.mp4
[e2] needs:seed — collapse the connect CTA(s), force-quit, relaunch, per-CTA persistence (android emulator-5554) — plan-defect: the Connect GitHub CTA the plan names never renders for this device account — its seeded platform_integrations row is re-created on the next repository fetch (e2-github-unreachable.log: 'github|active|2026-09-15 19:57:48.792799+00'), so the live digest lists only the Connect GitLab CTA; the reachable behaviour passed on android emulator-5554: collapse survived force-quit+relaunch ('SCENE persist1 OK' with only 'android.widget.Button Connect GitLab tappable' and no Open GitLab/description row in e2-restart-collapsed.log), tapping the header returned the description and Open GitLab…
e2-persistence.mp4.trim.mp4
[e9] ux-check: tapping a connect header still collapses/expands with Reduce Motion enabled — Android emulator-5554; Reduce Motion was enabled for the run and read back in e9-reduce-motion.log ('animator_duration_scale=0', 'transition_animation_scale=0', 'window_animation_scale=0' plus the app's low-power mode 'status: 3' / 'level: 15'), then reset; under it the collapse run 'SCENE e9c OK' ends (e9-collapsed.log) with only 'android.widget.Button Connect GitLab tappable [76,1423][1004,1469]' — description, 'Open GitLab' and 'Refresh repositories' hidden — and the expand run 'SCENE e9d OK' (e9-expanded.log) restores them with the header at the same y=1423, so the toggle still works…
e9-collapse-reduce-motion.mp4.trim.mp4
[e2] ux-check: cold-start app straight into a new session — connect cards do not appear late and push the 'Changes' segmented control, profile row, or Start button down (android emulator-5604) — android emulator-5604, account e2e-empty-collapse-connect-ctas-f9ff@example.com (the only signed-in state whose new-session screen renders a connect card; reached with login.sh, e2-login-empty.log, default account restored afterwards, e2-login-restore.log): after the declared force-stop+monkey trigger the app lands on Home and
TAP OK 'New coding task' matches=2(e2-tap.log) opens the new session, whose first sampled frame — e2-burst-summary.log#13 + 29.2scarryingGL=[76,1423][944,1469],Changes=[37,1818][1045,1864],Start=[442,2247][638,2274]— already contains the GitLab connect…e2-coldstart.mp4.trim.mp4
[e8] ux-check — cold start straight into a new session: connect cards do not appear late and push the Changes segmented control / profile row / Start button down — android emulator-5606: the title-sampled mount burst shows the pre-navigation frame with no card and no rows yet ('# 2 + 2.4s GitLab=- Changes=- Start=- NewTask=y') and the very next sampled frame already fully settled ('# 3 + 4.8s GitLab=[76,1423][1004,1469] Changes=[37,1818][1045,1864]'), identical at '# 60 +142.7s GitLab=[76,1423][1004,1469] Changes=[37,1818][1045,1864]' — so no late card and no row movement was observed; the scene ended 'SCENE e8 OK' (e8-digest.log) and e8.png plus e8-coldstart.mp4 are the captures for the visual reviewer, who owns the first-2.4s appearance judgement and…
e8-coldstart.mp4.trim.mp4
[e6] ux-check: Force-quit and relaunch, then open a new session: every CTA collapsed before the quit is still collapsed, with no frame that shows it expanded first. — android/emulator-5554. On the account with a live connect CTA, the GitLab card was collapsed before the quit (e6a.log 'SCENE e6a OK': 'android.widget.Button Connect GitLab tappable [76,1423][1004,1469]' immediately followed by 'android.widget.TextView Changes tappable [37,1555][1045,1601]', i.e. only the title row, no description or Open button) and is still collapsed after a real process restart (e6-pids.log 'before=31169 afterStop= afterLaunch=32108'; finalcheck3.log 'SCENE finalcheck3 OK' shows the same collapsed rows at [76,1423]/[37,1555]; e6b3.log repeats it after a third relaunch). The…
e6-collapse-relaunch.mp4.trim.mp4
[e6] ux-check: Force-quit and relaunch, then open a new session: every CTA collapsed before the quit is still collapsed, with no frame that shows it expanded first. — android/emulator-5554. On the account with a live connect CTA, the GitLab card was collapsed before the quit (e6a.log 'SCENE e6a OK': 'android.widget.Button Connect GitLab tappable [76,1423][1004,1469]' immediately followed by 'android.widget.TextView Changes tappable [37,1555][1045,1601]', i.e. only the title row, no description or Open button) and is still collapsed after a real process restart (e6-pids.log 'before=31169 afterStop= afterLaunch=32108'; finalcheck3.log 'SCENE finalcheck3 OK' shows the same collapsed rows at [76,1423]/[37,1555]; e6b3.log repeats it after a third relaunch). The…
e6-reopen-collapsed.mp4.trim.mp4
E2E proof — log excerpts
/home/igor_kilocode_ai/.local/share/kwf/sections/collapse-connect-ctas-f9ff/e2e-mobile-app/e1.log/home/igor_kilocode_ai/.local/share/kwf/sections/collapse-connect-ctas-f9ff/e2e-mobile-app/e1-collapsed-scene.log/home/igor_kilocode_ai/.local/share/kwf/sections/collapse-connect-ctas-f9ff/e2e-mobile-app/e1-restart.log/home/igor_kilocode_ai/.local/share/kwf/sections/collapse-connect-ctas-f9ff/e2e-mobile-app/e1-collapsed-restart-scene.log/home/igor_kilocode_ai/.local/share/kwf/sections/collapse-connect-ctas-f9ff/e2e-mobile-app/e1-expanded-restart.logOwner request
[e7] ux-check — collapse CTAs, restart, expand only GitLab, restart: per-CTA persistence (android emulator-5554) — plan-defect: only one connect CTA exists in this environment, so 'GitHub and Bitbucket stay collapsed' is unobservable — the e7-restart-expanded.log digest lists only the GitLab CTA ('android.widget.Button Connect GitLab tappable'); on android emulator-5554 the reachable user outcome held: after collapsing and a force-quit+relaunch the card was still collapsed ('SCENE e7a2 OK' with no Open GitLab row in e7-restart-collapsed.log), tapping the header expanded it again ('SCENE e7b2 OK' and 'android.widget.TextView Connect GitLab in your browser, then return here to pick a repository.' in…
[e4] ux-check: tap a connect card's title row on the new-session screen with at least two unconnected providers — Android emulator-5554, worktree-scoped empty account with two unconnected providers (Connect GitHub + Connect GitLab); pre-state e4-before-collapse.digest holds 'Open GitHub tappable [76,1501][870,1617]' and two 'Refresh repositories' rows, and after tapping the GitHub title row e4-collapse.log holds only 'android.widget.Button Connect GitHub tappable [76,1307][1004,1353]' plus 'Connect GitLab in your browser, then return here to pick a repository.' — description, 'Open GitHub' and that card's Refresh are gone (Refresh occurrences fall 2 -> 1), the GitLab card stays expanded, the tapped…
[e2] needs:seed — collapse the connect CTA(s), force-quit, relaunch, per-CTA persistence (android emulator-5554) — plan-defect: the Connect GitHub CTA the plan names never renders for this device account — its seeded platform_integrations row is re-created on the next repository fetch (e2-github-unreachable.log: 'github|active|2026-09-15 19:57:48.792799+00'), so the live digest lists only the Connect GitLab CTA; the reachable behaviour passed on android emulator-5554: collapse survived force-quit+relaunch ('SCENE persist1 OK' with only 'android.widget.Button Connect GitLab tappable' and no Open GitLab/description row in e2-restart-collapsed.log), tapping the header returned the description and Open GitLab…
[e5] ux-check: one provider collapsed, another expanded, tap the collapsed row — android emulator-5606, default account in organization context; e5-scene.log carries 'SCENE e5 OK' with the end state GitHub expanded ('Connect GitHub in your browser, then return here to pick a repository.' plus 'Open GitHub' at line 23) and Bitbucket still only its 'Connect Bitbucket' header at line 32 with no description before 'Changes', and e5.replay.json records the ordered steps tap GitHub -> assert-absent description -> tap Bitbucket -> assert-absent -> tap GitHub -> assert description+'Open GitHub' present -> assert Bitbucket description still absent -> assert GitLab description…
[e2] needs:seed — collapse the connect CTA(s), force-quit, relaunch, per-CTA persistence (android emulator-5554) — plan-defect: the Connect GitHub CTA the plan names never renders for this device account — its seeded platform_integrations row is re-created on the next repository fetch (e2-github-unreachable.log: 'github|active|2026-09-15 19:57:48.792799+00'), so the live digest lists only the Connect GitLab CTA; the reachable behaviour passed on android emulator-5554: collapse survived force-quit+relaunch ('SCENE persist1 OK' with only 'android.widget.Button Connect GitLab tappable' and no Open GitLab/description row in e2-restart-collapsed.log), tapping the header returned the description and Open GitLab…
[e7] ux-check — collapse CTAs, restart, expand only GitLab, restart: per-CTA persistence (android emulator-5554) — plan-defect: only one connect CTA exists in this environment, so 'GitHub and Bitbucket stay collapsed' is unobservable — the e7-restart-expanded.log digest lists only the GitLab CTA ('android.widget.Button Connect GitLab tappable'); on android emulator-5554 the reachable user outcome held: after collapsing and a force-quit+relaunch the card was still collapsed ('SCENE e7a2 OK' with no Open GitLab row in e7-restart-collapsed.log), tapping the header expanded it again ('SCENE e7b2 OK' and 'android.widget.TextView Connect GitLab in your browser, then return here to pick a repository.' in…
[e1] connect CTA collapse persists across restart — android emulator-5554: both connect cards painted expanded, each header tap collapsed it (titles kept, description + Open button gone, other card untouched) per e1.log, and after a real force-quit/relaunch (pid 10946/12315/15910 per e1-restart-trigger.log) both were still titles-only with no repositories listed per e1-collapsed.log; expanding persisted across another restart per e1-expanded-restart.log and e1-expanded-persist.log, with the on-device SecureStore key measured 19/10/2 plaintext bytes per e1-securestore.log; the declared no-connection start state needed one db.sh fixture row…
e1-collapse.mp4
[e4] ux-check: tap a connect card's title row on the new-session screen with at least two unconnected providers — Android emulator-5554, worktree-scoped empty account with two unconnected providers (Connect GitHub + Connect GitLab); pre-state e4-before-collapse.digest holds 'Open GitHub tappable [76,1501][870,1617]' and two 'Refresh repositories' rows, and after tapping the GitHub title row e4-collapse.log holds only 'android.widget.Button Connect GitHub tappable [76,1307][1004,1353]' plus 'Connect GitLab in your browser, then return here to pick a repository.' — description, 'Open GitHub' and that card's Refresh are gone (Refresh occurrences fall 2 -> 1), the GitLab card stays expanded, the tapped…
[e1] connect CTA collapse persists across restart — android emulator-5554: both connect cards painted expanded, each header tap collapsed it (titles kept, description + Open button gone, other card untouched) per e1.log, and after a real force-quit/relaunch (pid 10946/12315/15910 per e1-restart-trigger.log) both were still titles-only with no repositories listed per e1-collapsed.log; expanding persisted across another restart per e1-expanded-restart.log and e1-expanded-persist.log, with the on-device SecureStore key measured 19/10/2 plaintext bytes per e1-securestore.log; the declared no-connection start state needed one db.sh fixture row…
[e2] ux-check: cold-start app straight into a new session — connect cards do not appear late and push the 'Changes' segmented control, profile row, or Start button down (android emulator-5604) — android emulator-5604, account e2e-empty-collapse-connect-ctas-f9ff@example.com (the only signed-in state whose new-session screen renders a connect card; reached with login.sh, e2-login-empty.log, default account restored afterwards, e2-login-restore.log): after the declared force-stop+monkey trigger the app lands on Home and
TAP OK 'New coding task' matches=2(e2-tap.log) opens the new session, whose first sampled frame — e2-burst-summary.log#13 + 29.2scarryingGL=[76,1423][944,1469],Changes=[37,1818][1045,1864],Start=[442,2247][638,2274]— already contains the GitLab connect…[e1] ux-check: Collapse all three CTAs, force-quit, relaunch, then expand only GitLab and force-quit/relaunch again: GitLab stays expanded while GitHub and Bitbucket stay collapsed. — Android emulator-5554, organization context (three connect cards): the canonical replay ran as one script call and its log opens
SCENE e1 OK, ending after the second force-quit/relaunch with GitLab expanded -android.widget.Button Open GitLab tappable [76,1653][870,1768]- while GitHub and Bitbucket are title-onlyandroid.widget.Button Connect GitHub tappable [76,1307][1004,1353]andandroid.widget.Button Connect Bitbucket tappable [76,1874][1004,1920]; all-three-collapsed-across-a-restart is shown independently by e1-collapsed-restart.log (SCENE chk2 OK, `android.widget.Button…Follow-ups (not changed here)
adb -s <serial> shell am force-stop com.kilocode.kiloapp) and relaunch, then Agents → New session → Repository → tap 'Connect GitHub' to expand it (its description and 'Open GitHub' return) while 'Connect GitLab' stays collapsed; force-quit and relaunch once more, navigate Agents → New session → Repository: GitHub is still expanded and GitLab is still collapsed, so the state is per CTA and expanding persists. Captured (record.sh + shot): the expanded GitHub card beside the collapsed GitLab card. (no capture cited it)$KILO_WORKFLOW/e2e/login.sh <udid> e2e-empty-$(basename "$WT")@example.com), cold app on Home. Taps: Agents tab (2 of 3) → 'New session' → scroll to 'Repository' → both connect cards show expanded (titles 'Connect GitHub' and 'Connect GitLab' with their 'in your browser, then return here to pick a repository.' descriptions and their Open buttons). Tap 'Connect GitHub' → the GitHub description and 'Open GitHub' disappear, the 'Connect GitHub' title stays, the GitLab card is untouched. Tap 'Connect GitLab' → the same for GitLab. Force-quit (adb -s <serial> shell am force-stop com.kilocode.kiloapp), relaunch (adb -s <serial> shell monkey -p com.kilocode.kiloapp -c android.intent.category.LAUNCHER 1), navigate Agents → New session → Repository: both cards are still collapsed (titles only, no description, no Open button) and the section lists no repositories. Captured (record.sh + shot): the collapsed state after the restart. (no capture cited it)Open findings (not fixed here)
e9-collapse-reduce-motion.mp4
e8-coldstart.mp4
e2-persistence.mp4
e6-collapse-relaunch.mp4
e2-coldstart.mp4