Commit graph

1263 commits

Author SHA1 Message Date
Fini b849766cc2 fix(ai): fill placeholder frames from image search 2026-05-30 07:26:13 +08:00
Fini 1f6dac0b9c fix(ai): prefill builtin provider presets 2026-05-30 07:12:18 +08:00
Fini fc0fdc1132 fix(ai): hide assistant tool xml 2026-05-30 07:02:39 +08:00
Fini 52f69fadc5 fix(ai): use full width assistant transcript 2026-05-30 06:58:49 +08:00
Fini bb7e59e6eb fix(ai): lift chat panel surface 2026-05-30 06:44:12 +08:00
Fini 52f13a6149 fix(ai): use openverse credentials for image search 2026-05-30 06:41:08 +08:00
Fini 04746248a7 fix(ai): edit openverse image search credentials 2026-05-30 06:37:17 +08:00
Fini 3e843e4afa fix(ai): search model groups by label 2026-05-30 06:26:38 +08:00
Fini 8b28d7e51f fix(ai): show chat step details 2026-05-30 06:21:34 +08:00
Fini 9498e8d37d fix(ai): edit image generation profiles 2026-05-30 06:17:14 +08:00
Fini 54aff64327 fix(ai): add image generation profile rows 2026-05-30 06:10:04 +08:00
Fini a7db763268 fix(ai): surface tool call metadata 2026-05-30 05:47:27 +08:00
Fini 22b3d89855 fix(ai): pin chat step checklist 2026-05-30 05:32:12 +08:00
Fini 32a4134336 fix(ai): parse chat step progress tags 2026-05-30 05:25:50 +08:00
Fini 0ecd2a6a0e fix(editor): fit blank frame on startup 2026-05-30 05:16:04 +08:00
Fini 46673b9d76 fix(ai): add system auto update toggle 2026-05-30 05:06:33 +08:00
Fini cf26ccfdbc fix(ai): disable mcp port while running 2026-05-30 03:30:35 +08:00
Fini a91645642d fix(ai): label builtin model groups 2026-05-30 03:26:28 +08:00
Fini 4249721d98 fix(renderer): defer desktop gl startup 2026-05-30 03:08:58 +08:00
Fini 1b97bdea45 fix(ai): enable desktop image search 2026-05-30 02:27:35 +08:00
Fini d7d80270e0 fix(ai): render design progress as steps 2026-05-30 02:19:22 +08:00
Fini 78b0388c9a fix(editor): compact settings sidebar 2026-05-30 02:13:16 +08:00
Fini 3cb62317d7 fix(ai): add searchable model picker 2026-05-30 01:10:37 +08:00
Fini dec0c94710 fix(ai): tighten empty chat cards 2026-05-30 00:56:28 +08:00
Fini c0dada1a59 fix(editor): align starter frame and layer hover 2026-05-30 00:49:10 +08:00
Fini 8d0e3b04ba feat(ai): add built-in providers and align chat ui 2026-05-30 00:21:34 +08:00
Kayshen-X 9a716f09fb feat(panels): wire git empty-state cards (init / open / clone)
The onboarding cards are now actionable:
- 新建/Init → `GitRepo::init` at the saved doc's directory, then
  rebind the session so the doc is tracked (disabled until saved);
- 打开/Open → native folder picker → `GitRepo::discover` + a new
  `GitSession::bind_repo` (tracks the doc when it's under the repo);
- 克隆/Clone → info dialog for now (needs the in-panel URL form — a
  follow-up).

Adds GitPanelHit::{EmptyInit,EmptyOpen,EmptyClone},
GitPanelAction::{InitRepo,OpenRepo,CloneRepo}, host press dispatch +
binary drain, `git_panel.has_saved_file` tracked on every rebind, and
a hit-test test. EN/ZH strings for the two new messages.
2026-05-29 23:09:22 +08:00
Kayshen-X b1d8ca03b0 feat(panels): rich git empty-state (TS parity), visual
Replace the bare "不是 Git 仓库。" text with the TS onboarding empty
state: a History clock glyph in a rounded box, the
"这份文件还没有版本历史" heading, three cards (新建/打开/克隆 with
FilePlus/FolderOpen/GitFork icons + descriptions), and the "Git is
optional" note — laid out centred in a 380×284 panel.

- new History/FilePlus/GitFork icons;
- `GitPanelState.has_saved_file` dims the Init card when the doc is
  unsaved (matching TS);
- `empty_state_rects` shared for the upcoming card hit-test.

Card actions (init/open/clone) wired in a follow-up.
2026-05-29 22:56:07 +08:00
Kayshen-X 1f77d3875c fix(panels): compile out the git button on web (no git backend)
The web/wasm build has no git backend and never paints GitPanel, so
the top-bar git button toggled an invisible panel (Codex stop-time
review). Gate the button's paint + hit-test on a `GIT_BUTTON_AVAILABLE`
const (`!cfg!(target_arch = "wasm32")`) so it only exists on desktop.
2026-05-29 22:23:37 +08:00
Kayshen-X 89b74604ba feat(panels): add git-panel button to the top bar
The top bar had no affordance to open the git panel (only a
keyboard/menu path). Add a TS-style git button just right of the file
name: a `GitBranch` glyph + the current branch name when in a repo.
Always shown (per request) — a click toggles the git panel, which
offers `init` when the doc isn't yet a repo.

- new `Icon::GitBranch` lucide glyph;
- `TopBar.git_branch` from `git_panel.branch`; `git_button_rect`
  (CJK-aware width estimate so it clears a CJK file name) shared by
  paint + hit-test; `TopBarHit::ToggleGitPanel`;
- native host mirrors `main.rs` toggle bookkeeping (per-frame refresh
  does the scan); web host toggles `git_panel.open`.
2026-05-29 22:12:38 +08:00
Kayshen-X 6ad9a6a674 fix(host): render Korean (Hangul) text in chrome
Hangul codepoints were routed to the shared CJK typeface, which is
resolved from a Han ideograph (a Chinese font with no Hangul glyphs),
so 한국어 painted as blank .notdef boxes in the locale picker while
Chinese/Japanese/Hindi/Thai/Vietnamese rendered fine. Add a dedicated
`is_hangul_codepoint` split + a cached `korean_typeface` (resolved from
'한' → Apple SD Gothic Neo / Noto Sans KR) and route Hangul there in
both typeface-resolution paths.
2026-05-29 21:40:37 +08:00
Kayshen-X d4e035d03f fix(panels): keep file-menu dropdown anchor in sync with the divider
The new sidebar↔file-menu divider shifted the folder button right, but
`TopBar::file_menu_rect` (the dropdown anchor) still used the pre-divider
x, so the file menu opened left of its button (Codex stop-time review).
Route the anchor through the divider span and have hit_test reuse
`file_menu_rect` so paint / hit-test / anchor can't drift again.
2026-05-29 21:23:46 +08:00
Kayshen-X 3eb70ba4ce style(panels): align top-bar glyphs + smaller icons + left dividers
Match the TS top bar and the user's refinement feedback:
- icons 16→14px, chevron 12→10px (top-bar-local consts; other widgets
  keep their own sizes) — a touch smaller / more refined;
- route every glyph through `glyph_top(center_y, size)` and center the
  agent chip's icon + 11px text on the shared center line (fixes the
  off-axis drift);
- add a divider between the sidebar toggle and the file-menu (user
  request) and unify all three dividers via `paint_divider`
  (1×14, border@60%, 4px gaps) — TS `w-px h-3.5 bg-border/60 mx-1`;
- keep paint + hit-test in sync for the new divider spans.
2026-05-29 21:16:48 +08:00
Kayshen-X 8e4515f0e0 feat(host): web parity for zoom-to-fit + rename caret
Mirror the native host on the web backend:
- ArrowLeft/Right move the inline-rename caret (`apply_rename_caret`)
  before falling through to node-nudge;
- StatusBar search icon frames the active page content
  (`status_bar_search_hit` + `zoom_to_fit`, reusing `canvas_region` +
  `LayoutScene::content_bounds` + `Viewport::fit_to`).

Type-checks on the host target; the wasm bundle build still needs EMSDK.
2026-05-29 21:00:14 +08:00
Kayshen-X 6af2ef853b style(panels): refine top-bar agent chip to match TS
- add a 1px×14px divider between the agent/MCP chip and the locale
  button (TS `w-px h-3.5 bg-border/60`) so the status chip reads as a
  separate group;
- chip text 12→11px in muted-foreground, status dot 8→6px in
  emerald-500 (#10b981) — matches the TS chip density/colour.

Note: the chip showing "Agents & MCP" vs "N agent · M MCP" is
connection state (0 connected agents/MCP → the set-up label), not a
layout bug.
2026-05-29 20:52:54 +08:00
Kayshen-X 88428ae72c fix(canvas): apply node opacity to raster images
Node-level opacity was folded into fill/stroke/gradient/shadow alpha at
scene-build, but rasters carry no colour to bake into, so image nodes
rendered fully opaque (codex stop-time review). Carry cumulative opacity
on `SceneNode` and modulate the image paint's alpha in the native draw
path (`draw_image_with_options` gains an `opacity` arg; trait default +
web fall back to opaque).
2026-05-29 20:46:23 +08:00
Kayshen-X 0b9bae6709 chore: bump casement to fix(macos) traffic-light reposition idempotent across resize + fullscreen exit 2026-05-29 20:25:25 +08:00
Kayshen-X 9cac369d15 feat(editor): node opacity, path gradient/inner-shadow fills, zoom-to-fit, rename caret
- canvas: fold node-level `opacity` into resolved fill/stroke/gradient/
  shadow alpha at scene-build (was dropped entirely); render linear/radial
  gradients on SVG path nodes (native skia shader; solid first-stop fallback
  on backends without one); render inset (inner) shadows on path nodes via
  clip + DstOut blur. Fixes the risk-monitor pedestal vs the TS reference.
- editor: StatusBar search icon frames the active page's content in the
  viewport (`Viewport::fit_to` + `LayoutScene::content_bounds`); inline-rename
  input supports ArrowLeft/Right caret movement with char-based mid-string
  insert/delete (CJK-safe).
- also carries in-progress flip/text canvas transforms, web backend, and
  figma-probe tweaks already present in the working tree, plus a clippy
  needless-borrow/closure cleanup in op-orchestrator (1.94 gate).
2026-05-29 20:24:36 +08:00
Fini 95e551fee7 chore: bump casement to fix(macos) launch on demand 2026-05-28 00:10:24 +08:00
Fini 52a10cee32 fix(orchestrator): clamp mobile status-bar levels to root width
The mobile status-bar chrome injected by `mobile_status_bar_json`
hardcoded levels.x=286 — the right-aligned cellular/wifi/battery
group, sized for a 390-wide iPhone reference. When the C2 plan
work started honouring explicit prompt sizes via
`explicit_mobile_size` (accepts 240..=520 wide), a 320 x 568
iPhone-SE prompt rendered the chrome at x=286..364 — 44 px past
the right edge.

Take root `width` as an argument and derive levels.x as
`width - 78 - 26` (78 = chrome width, 26 = iOS safe-area gutter,
matches the existing 390 reference: 390 - 104 = 286). New test
exercises 320-wide root to lock in the no-overflow contract.
2026-05-27 23:19:49 +08:00
Fini 6c7b352e41 refactor(host): split tests + trim comments for 800-line cap
chat_subprocess.rs (850) and design_session.rs (807) blew past
the ceiling after the Codex provider + design-viewport work
landed in 63f787c3. Move their inline `mod tests` bodies out to
sibling `*_tests.rs` files via `#[cfg(test)] #[path = …]
mod tests;`.

app_handler.rs (805) is one bare `impl ApplicationHandler` with
no natural split point; trim the file-level doc and two inline
comments in `exiting` to land at exactly 800.

After: chat_subprocess.rs 650, design_session.rs 508,
app_handler.rs 800. 114 host-desktop tests pass.
2026-05-27 23:19:48 +08:00
Fini f873c61a65 refactor(orchestrator): split tests into sibling files for 800-line cap
cleanup.rs / prompt.rs / scaffold.rs all blew past the repo's
800-line ceiling after the typography + mobile-screen work landed
in d26b5685. Move each file's inline `mod tests` body out to a
sibling `*_tests.rs` and re-attach via `#[cfg(test)] #[path = …]
mod tests;` — same pattern the existing `cleanup_tests_c1.rs`
uses.

After split: cleanup.rs 772, prompt.rs 313, scaffold.rs 422.
Test counts unchanged (612 orchestrator tests pass).
2026-05-27 23:19:47 +08:00
Fini b118e45d62 feat(host): wire Codex CLI provider and polish design-turn launch
- chat_subprocess: wire Codex CLI through SubprocessProvider via
  `codex exec --json` + positional-arg prompt, and parse the new
  `item.completed` agent_message events into TextDelta
- chat_session: route chat_selected_agent=1 through the Codex
  provider; on design-turn launch, clear the fresh starter frame
  so generated nodes don't stack on top of the demo content
- design_session: fit_design_viewport_to_content keeps generated
  designs centred while the orchestrator streams nodes
- app_handler: thread viewport size through pump_commands so the
  fit step has canvas dimensions to work with
2026-05-27 23:19:46 +08:00
Fini 6fb5ff58cd feat(orchestrator): mobile screen plans, typography cleanup, parse fixes
- plan: when the prompt looks like a mobile screen (or carries an
  explicit WxH), emit a top-summary + main-content fallback plan
  instead of the generic three-section split
- cleanup_typography: new module + repair_overbold_text_hierarchy
  to soften LLM over-bolding when >=65% of text nodes come back as
  weight >=700
- parse: default missing/null image src to "" so generated image
  nodes no longer fail strict deserialization
- plan_normalize / scaffold / prompt / subagent: associated reworks
  feeding the above paths
2026-05-27 23:19:45 +08:00
Fini f9bdec5fe9 refactor(editor): collapse panels and drop unused host modules
Bundle three cleanups that share glue files (widget_host, lib.rs,
widgets/mod.rs) and so must land together:

- collapse variables_panel/{header,paint,tests}.rs into
  variables_panel.rs and fold the four host variables_panel_*.rs
  modules into the main widget_host
- remove property_panel_font_picker along with the system_fonts
  loader thread and the system_font_rx plumbing on WidgetHostNative
- delete the widget_host keyboard_motion module and roll its logic
  into keyboard.rs

Drops the now-orphan themed-variable scalar setters,
variables.type{Color,Number,String} i18n keys (×15 locales), and
the Cmd+V / Cmd+D shortcuts that targeted the removed panels.
2026-05-27 23:19:44 +08:00
Kayshen-X 46e7e8d792 fix(editor): improve rust parity and figma import performance 2026-05-27 21:51:57 +08:00
Kayshen-X 14c3aaa09b feat(editor): improve native panel parity 2026-05-26 21:36:03 +08:00
Fini 37d0998b03 fix(canvas): align rust z-order with renderer 2026-05-26 07:02:32 +08:00
Kayshen-X 19652f0724 feat(panels): improve native property controls and icons 2026-05-24 23:30:00 +08:00
Fini def3a50d32 fix(host): inline orchestrator system prompt into user message
Codex stop-time review caught a silent prompt drop in the
`ChatProviderLlmClient` adapter from the previous commit. I put the
orchestrator's `CallRequest.system_prompt` into
`ChatRequest.system_prompt`, but all three CLI-backed `ChatProvider`
impls (`ClaudeCodeProvider`, `CopilotProvider`, `SubprocessProvider`)
ignore that field — they drive their respective CLIs through
subprocess / SDK channels with no per-turn system-prompt slot. Net
effect: the planner / sub-agent role prompt was discarded and the
model only saw the bare user prompt.

Fix matches the precedent in `chat_runtime::BuiltInProvider::send`
(line 138): prepend the system prompt to the user message with a
`\n\n---\n\n` separator, then leave `ChatRequest.system_prompt`
empty. If a CLI later grows a real system-prompt channel, unwrap the
prepend back into the field.

cargo test -p op-host-desktop 106 passed; fmt + clippy clean.
2026-05-24 20:45:45 +08:00