fix(dashboard): mobile polish, modal layout fixes, keyboard-aware terminal + add 0.7.1 changeset
- WorkflowStepManager: fix React error #310 ("Rendered more hooks than during the previous render") that broke the workflow steps panel from loading. `useOverlayDismiss` was being called after `if (!isOpen) return null`, so the hook count differed between open/closed renders. Move the hook above the early return. - ModelOnboardingModal: API-key input + Save button now span the full card width on mobile via negative inline margins that bleed past the card's horizontal padding, so the form sits flush to the card edges instead of picking up a chunky left indent from the icon-row's flex start position. - TerminalModal: same desktop-min-width-pinning bug as the onboarding modal. Reset min-width/min-height to 0 on mobile with `!important` so persisted desktop sizes from useModalResizePersist cannot re-pin the modal at 480×320 on smaller phones. Also add `!important` to the keyboard-overlap height/ max-height so the visual-viewport adjustment wins against the new fullscreen rule — without this the terminal stayed at 100dvh while the mobile keyboard covered the bottom of the screen. - Add 0.7.1 changeset covering the full mobile polish + paperclip CLI parity + plugin runtime registry fallback + SCHEMA_VERSION bump series. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
41
.changeset/mobile-polish-0-7-1.md
Normal file
41
.changeset/mobile-polish-0-7-1.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
"runfusion.ai": patch
|
||||||
|
"@fusion/core": patch
|
||||||
|
"@fusion/dashboard": patch
|
||||||
|
"@fusion/desktop": patch
|
||||||
|
"@fusion/engine": patch
|
||||||
|
"@fusion/mobile": patch
|
||||||
|
"@fusion/pi-claude-cli": patch
|
||||||
|
"@fusion/plugin-sdk": patch
|
||||||
|
"@fusion-plugin-examples/auto-label": patch
|
||||||
|
"@fusion-plugin-examples/ci-status": patch
|
||||||
|
"@fusion-plugin-examples/notification": patch
|
||||||
|
"@fusion-plugin-examples/settings-demo": patch
|
||||||
|
"@fusion-plugin-examples/hermes-runtime": patch
|
||||||
|
"@fusion-plugin-examples/openclaw-runtime": patch
|
||||||
|
"@fusion-plugin-examples/paperclip-runtime": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(0.7.1): mobile polish, modal layout fixes, paperclip CLI parity, schema migration
|
||||||
|
|
||||||
|
Mobile / dashboard:
|
||||||
|
|
||||||
|
- ModelOnboardingModal: dialog was off-screen on phones because the desktop `min-width: 640px` won over the mobile `max-width: 100%`. Reset min-width/min-height to 0 in the mobile media query (with `!important` so persisted desktop sizes from `useModalResizePersist` cannot re-pin it). Compact provider cards: keep the icon inline beside the name + description, shrink the icon container, drop name/description font sizes, and rely on flex-wrap so the API-key actions still drop to their own row underneath. The API-key input + Save button now live on a single row at the full card width — input grows left-aligned, Save shrinks to the right with a hairline of inline padding.
|
||||||
|
- NewAgentDialog: the dialog's top was rendering hidden behind the in-page Agents header on mobile. Render the dialog through `createPortal(..., document.body)` so the overlay escapes the `.agents-view` stacking context. Mobile media query also drops the overlay padding, fills 100vw / 100dvh with safe-area insets on header/footer for iOS notch + home indicator, and fixes the classic flex `min-height: auto` bug that prevented `overflow-y: auto` on the body from activating.
|
||||||
|
- TerminalModal: same root cause as the onboarding modal — desktop `min-width: 480px` / `min-height: 320px` pinned the modal off-screen on phones. Reset to 0 in the mobile rule with `!important` so persisted desktop sizes can't override.
|
||||||
|
- WorkflowStepManager: fix React error #310 ("Rendered more hooks than during the previous render") that prevented the workflow steps panel from loading. `useOverlayDismiss` was being called after an `if (!isOpen) return null` early return, so the hook count differed between open/closed renders. Moved the hook above the early return.
|
||||||
|
- SettingsModal auth panel: tightened `.auth-panel-body` horizontal padding from `--space-xl` (24px) to `--space-md` (12px), giving each provider card more horizontal room.
|
||||||
|
|
||||||
|
Paperclip runtime:
|
||||||
|
|
||||||
|
- CLI parity: in the dashboard's "Local CLI" tab, Test / fetch companies / fetch agents now actually shell out to `paperclipai` instead of making HTTP calls through a derived URL. New CLI-backed variants (`probePaperclipViaCli`, `listCompaniesViaCli`, `listCompanyAgentsViaCli`, `createIssueViaCli`, `getIssueViaCli`, `agentsMeViaCli`) drive every Paperclip call that has a CLI counterpart; the runtime adapter routes through them when `transport=cli`. `getIssueComments` / `wakeAgent` / `getRunEvents` continue using HTTP (no matching `paperclipai` subcommands) but rely on the apiKey discovered from the local paperclipai config so CLI mode works end-to-end.
|
||||||
|
- New dashboard routes `/providers/paperclip/cli-status`, `/cli-companies`, `/cli-agents` exposing the CLI helpers.
|
||||||
|
|
||||||
|
Plugin runtime registry:
|
||||||
|
|
||||||
|
- `GET /api/plugins/runtimes` now merges a bundled hermes/openclaw/paperclip fallback list on top of installed plugins, so the NewAgentDialog "Plugin Runtime" dropdown populates without requiring `fn plugin install` on a fresh setup. Installed plugins override the bundled entry by `runtimeId`. Coalesced the optional `version` field to `"0.0.0"` to satisfy the bundled-runtime type.
|
||||||
|
|
||||||
|
Core:
|
||||||
|
|
||||||
|
- Schema migration fix: bumped `SCHEMA_VERSION` from 48 → 49 so migration 49 (per-task `nodeId` column for remote-node routing) actually runs. Existing DBs at version 48 hit the early-return guard, never created the column, and `TaskStore.listTasks` crashed at startup with `no such column: nodeId` — the dashboard exited before initialization. The bump unblocks app startup on any pre-existing 0.7.0 install.
|
||||||
@@ -1348,8 +1348,19 @@
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bleed the API-key form past the card's horizontal padding so the input
|
||||||
|
and the Save button span the full width of the card on mobile. Without
|
||||||
|
this the form sat inside the 12px card padding (and on Safari sometimes
|
||||||
|
inherited the icon-row's start indent), which read as a chunky left
|
||||||
|
margin on phones. Width = 100% + 2*card-padding cancels the padding
|
||||||
|
out; matching negative inline margins re-anchor it to the card edges.
|
||||||
|
A tiny --space-xs inline padding keeps the input from kissing the
|
||||||
|
border. */
|
||||||
.onboarding-provider-card__actions--api-key {
|
.onboarding-provider-card__actions--api-key {
|
||||||
width: 100%;
|
width: calc(100% + 2 * var(--space-md));
|
||||||
|
margin-inline: calc(-1 * var(--space-md));
|
||||||
|
padding-inline: var(--space-xs);
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When actions are simple buttons (Connect / Skip), make them split the
|
/* When actions are simple buttons (Connect / Skip), make them split the
|
||||||
|
|||||||
@@ -839,18 +839,21 @@
|
|||||||
/* === Terminal Modal Mobile Responsive === */
|
/* === Terminal Modal Mobile Responsive === */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.modal.terminal-modal {
|
.modal.terminal-modal {
|
||||||
width: 100% !important;
|
/* Reset the desktop min-width: 480px / min-height: 320px — they pin the
|
||||||
max-width: 100%;
|
modal at 480×320 on phones narrower than 480px and force horizontal
|
||||||
min-height: 100vh;
|
overflow. The fullscreen width/height below then take effect normally.
|
||||||
min-height: 100dvh;
|
!important is required because useModalResizePersist writes inline
|
||||||
height: 100vh !important;
|
width/height from saved desktop sessions, and inline styles would
|
||||||
|
otherwise win over the media query. */
|
||||||
|
min-width: 0 !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
width: 100vw !important;
|
||||||
|
max-width: 100vw !important;
|
||||||
height: 100dvh !important;
|
height: 100dvh !important;
|
||||||
max-height: 100vh;
|
max-height: 100dvh !important;
|
||||||
max-height: 100dvh;
|
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border: none;
|
border: none;
|
||||||
/* Disable user resize on mobile — fullscreen layout. !important above
|
/* Disable user resize on mobile — fullscreen layout. */
|
||||||
overrides any persisted desktop dimensions. */
|
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1004,13 +1007,19 @@
|
|||||||
shrink below the full-viewport mobile default when the keyboard
|
shrink below the full-viewport mobile default when the keyboard
|
||||||
is open. Without this, min-height keeps the modal taller than
|
is open. Without this, min-height keeps the modal taller than
|
||||||
the available space and the bottom overlaps the keyboard. */
|
the available space and the bottom overlaps the keyboard. */
|
||||||
min-height: auto;
|
min-height: auto !important;
|
||||||
/* Apply both height and max-height so the modal is *exactly* the
|
/* Apply both height and max-height so the modal is *exactly* the
|
||||||
visual viewport height — not just capped at it. Using height
|
visual viewport height — not just capped at it. Using height
|
||||||
ensures the element cannot be taller than max-height due to
|
ensures the element cannot be taller than max-height due to
|
||||||
inherited min-height or flex layout. */
|
inherited min-height or flex layout.
|
||||||
height: var(--vv-height, calc(100dvh - var(--keyboard-overlap, 0px)));
|
!important is required because the mobile fullscreen rule above
|
||||||
max-height: var(--vv-height, calc(100dvh - var(--keyboard-overlap, 0px)));
|
sets `height: 100dvh !important` to defeat persisted desktop
|
||||||
|
sizes from useModalResizePersist; without `!important` here, the
|
||||||
|
keyboard-aware shrink would lose the specificity battle and the
|
||||||
|
terminal would stay at 100dvh while the keyboard covered the
|
||||||
|
bottom of the viewport. */
|
||||||
|
height: var(--vv-height, calc(100dvh - var(--keyboard-overlap, 0px))) !important;
|
||||||
|
max-height: var(--vv-height, calc(100dvh - var(--keyboard-overlap, 0px))) !important;
|
||||||
/* Clip any content that exceeds the constrained height during
|
/* Clip any content that exceeds the constrained height during
|
||||||
the keyboard-open transition so the terminal doesn't poke out
|
the keyboard-open transition so the terminal doesn't poke out
|
||||||
below the visible area while xterm re-fits. */
|
below the visible area while xterm re-fits. */
|
||||||
|
|||||||
@@ -371,10 +371,17 @@ export function WorkflowStepManager({ isOpen, onClose, addToast, projectId }: Wo
|
|||||||
}
|
}
|
||||||
}, [addToast, loadSteps]);
|
}, [addToast, loadSteps]);
|
||||||
|
|
||||||
|
// useOverlayDismiss MUST be called before any early return — otherwise the
|
||||||
|
// hook count differs between isOpen=false (returns early after the existing
|
||||||
|
// useState/useEffect/useCallback hooks) and isOpen=true (also calls
|
||||||
|
// useOverlayDismiss), which trips React error #310 the moment the modal
|
||||||
|
// is opened. That bug currently breaks the workflow steps panel from
|
||||||
|
// loading at all.
|
||||||
|
const overlayDismissProps = useOverlayDismiss(onClose);
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
const isEditing = isCreating || editingId !== null;
|
const isEditing = isCreating || editingId !== null;
|
||||||
const overlayDismissProps = useOverlayDismiss(onClose);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="modal-overlay open" {...overlayDismissProps} data-testid="workflow-step-manager">
|
<div className="modal-overlay open" {...overlayDismissProps} data-testid="workflow-step-manager">
|
||||||
|
|||||||
Reference in New Issue
Block a user