feat(mobile): synchronized pill composer transitions and draft screen fixes
Drop the animated pill/composer morph in favor of instant swaps that are synchronized with the keyboard choreography: a new oc:keyboard-intent event collapses the composer (flushSync) before the hide compensation is measured, so keyboard travel and composer height change land as a single chat motion on both iOS and Android (Android also gains keyboard signals and deterministic re-pins around its native resize). The WKWebView caret is hidden during the transition so it no longer flies to its new position. Draft screen: starter chips hide instantly while the keyboard is up and the centered title rides the keyboard shift compensation instead of double-jumping; the composer drag handle also works in dictation mode; the highlight mirror is disabled on mobile so the caret matches the text. Fixes: worktree discovery and the GitHub auth probe now wait for the runtime connection (no more empty branch pickers / stale auth on cold start), worktree discovery merges per project instead of clobbering the persisted map, the cross-project session list resets on instance switch (with an in-flight load guard) so no stale sessions linger, and mobile overlay content contains its overscroll instead of bouncing the page.
This commit is contained in:
+34
-1
@@ -67,12 +67,13 @@ Options:
|
||||
--web-mode <hmr|hmr-lan|full>
|
||||
--mobile-mode <ios-sim-local|ios-sim-lan|android-local|android-lan>
|
||||
--mobile-task <task>
|
||||
--adb-address <host:port> Wireless ADB address for android-connect
|
||||
--vsix-cleanup <delete|keep>
|
||||
--version <semver>
|
||||
-h, --help
|
||||
|
||||
Mobile tasks:
|
||||
build, sync, android-devices, android-deploy-usb, android-run, android-logcat,
|
||||
build, sync, android-devices, android-connect, android-deploy-usb, android-run, android-logcat,
|
||||
ios-sim-build, ios-sim-run, ios-sim-serve, ios-sim-kill, ios-device-sync-debug
|
||||
`);
|
||||
}
|
||||
@@ -115,6 +116,9 @@ function parseArgs(argv) {
|
||||
case '--mobile-task':
|
||||
options.mobileTask = readValue();
|
||||
break;
|
||||
case '--adb-address':
|
||||
options.adbAddress = readValue();
|
||||
break;
|
||||
case '--vsix-cleanup':
|
||||
options.vsixCleanup = readValue();
|
||||
break;
|
||||
@@ -206,6 +210,29 @@ async function chooseValue(current, choices, message) {
|
||||
return value;
|
||||
}
|
||||
|
||||
async function chooseText(current, message, placeholder) {
|
||||
if (current) return current;
|
||||
ensurePromptable();
|
||||
const value = await text({ message, placeholder });
|
||||
if (isCancel(value)) {
|
||||
cancel('Operation cancelled.');
|
||||
process.exit(130);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function validateAdbAddress(address) {
|
||||
const normalized = String(address || '').trim();
|
||||
if (!/^[^\s:]+:\d{1,5}$/.test(normalized)) {
|
||||
throw new Error('Invalid wireless ADB address. Use host:port, e.g. 192.168.1.139:38181');
|
||||
}
|
||||
const port = Number(normalized.split(':').at(-1));
|
||||
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
||||
throw new Error('Invalid wireless ADB port. Use a port between 1 and 65535.');
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function detectLanIp() {
|
||||
for (const addresses of Object.values(os.networkInterfaces())) {
|
||||
for (const address of addresses || []) {
|
||||
@@ -432,6 +459,7 @@ async function mobileTools(options, config) {
|
||||
{ value: 'build', label: 'Build mobile web assets' },
|
||||
{ value: 'sync', label: 'Sync native projects' },
|
||||
{ value: 'android-devices', label: 'Android: list USB devices' },
|
||||
{ value: 'android-connect', label: 'Android: connect wireless ADB device' },
|
||||
{ value: 'android-deploy-usb', label: 'Android: rebuild + deploy to USB device' },
|
||||
{ value: 'android-run', label: 'Android: install + launch existing APK' },
|
||||
{ value: 'android-logcat', label: 'Android: logcat' },
|
||||
@@ -453,6 +481,11 @@ async function mobileTools(options, config) {
|
||||
case 'build': return mobileRun('Building mobile web assets', 'build');
|
||||
case 'sync': return mobileRun('Syncing native projects', 'sync');
|
||||
case 'android-devices': return mobileRun('Listing Android USB devices', 'android:devices');
|
||||
case 'android-connect': {
|
||||
const address = validateAdbAddress(await chooseText(options.adbAddress, 'Enter wireless ADB address', '192.168.1.139:38181'));
|
||||
step(`Connecting wireless ADB device at ${address}`, () => run('node', ['scripts/with-mobile-env.mjs', `adb connect ${quote(address)}`], { cwd: mobileCwd }));
|
||||
return mobileRun('Listing Android devices', 'android:devices');
|
||||
}
|
||||
case 'android-deploy-usb':
|
||||
mobileRun('Building Android debug APK', 'build:android:debug');
|
||||
return mobileRun('Installing and launching Android app on USB device', 'android:run');
|
||||
|
||||
Reference in New Issue
Block a user