Skip to content

feat(components): select and export chat messages as PNG - #492

Merged
wibus-wee merged 7 commits into
mainfrom
feat/chat-share-image
Sep 8, 2026
Merged

feat(components): select and export chat messages as PNG#492
wibus-wee merged 7 commits into
mainfrom
feat/chat-share-image

Conversation

@wibus-wee

@wibus-wee wibus-wee commented Sep 8, 2026

Copy link
Copy Markdown
Member

Related issue

Same-repository feature branch; no linked issue.

Problem / pressure

Users need to choose individual messages in the existing conversation before
exporting a styled PNG. The card must reflect the selected history,
including folded working content in token estimates, rather than the current
composer model or whole-session context usage.

Summary

  • Add local message selection with drag rectangles, Shift ranges, Ctrl/Command inversion, edge scrolling, and a preview action that preserves the composer draft.
  • Add configurable conversation cards and preview dialogs, including readable light/dark cards without a backdrop.
  • Export the full card through lazy-loaded @zumer/snapdom, with browser PNG downloads and the existing Electron native save dialog. Wait for assets and support retry after errors.
  • Snapshot selected prose and estimated tokens, use the last selected assistant's recorded model, and show configured custom Runtime names.
  • Add synthetic tests and complete light/dark conversation stories: enter selection through the real header menu, drag/select, preview, export, return to selection, and restore the composer draft. Message submission is local to the story.

Before / after

Before After
No integrated conversation image-export workflow Select messages in chat, style the card, and save PNG
Current session settings can mislabel historical content Model metadata follows the selected assistant history
Folded working content is absent from prose-only counts Token estimates include stored working content without rendering it

Test plan

  • Passed workspace typechecks and type-aware lint under Node 22 with pinned submodules.
  • Passed all CI test stages: script tests, workspace tests (including 3,228 component tests and 1,041 shared tests), and Electron tests. Temporary test repositories ran with Git commit signing disabled; Electron was installed before rerunning its test stage.
  • Passed translation checks, import/platform/public-boundary guards, documentation checks, and whitespace validation. Ran workspace formatting.
  • Frozen-lockfile installation passed. Automated screenshot verification was intentionally omitted; the interactive stories use synthetic data.
  • Follow-up complete-conversation stories passed component typecheck and targeted lint; the existing Storybook indexed both entries and compiled the story module successfully.
  • PNG export passed component typecheck, 4 focused download/save tests, static/boundary checks, and frozen-lockfile installation. These tests mock rasterization; pixel fidelity and a native save-dialog round trip were not verified.

Context handoff

Instructions for reviewing agents

  • Review focus: Selection identity across flattened assistant rows, selected-message metadata, and complete-card capture/save behavior.
  • Decisions to challenge: Using the last selected assistant model and a stored-text token estimate while keeping image rendering prose-only.
  • Plausible failures / evidence gaps: Cross-theme rendering, very tall card capture, and drag ergonomics have Storybook coverage but no automated pixel acceptance; save tests mock native IPC.

Authoring context

  • User goal / directives: Add IM-style selection, drag feedback, historical labels, complete-conversation stories, and PNG export using @zumer/snapdom.
  • Constraints / non-goals: Keep the workflow local, preserve drafts, omit multiple-model aggregation and clipboard copying, and reuse the existing Storybook without screenshot automation.
  • Risk-bearing decisions: Assistant virtual rows share one message selection; token estimates include working text but are not provider billing data.
  • Destructive or irreversible behavior: Export writes a user-requested image through browser download or the native save dialog; there are no conversation writes, migrations, deletions, or remote publication.
  • Deliberately not done or tested: No screenshot automation, clipboard copying, or deployed desktop acceptance testing.
  • Unknowns / confidence: Synthetic behavior tests cover selection and metadata; the draft specification leaves human acceptance explicit.

Add message selection, configurable share cards, and historical model/runtime metadata with working-content token estimates.

Model: gpt-6
@wibus-wee wibus-wee changed the title feat(components): select chat messages for image previews feat(components): select and export chat messages as PNG Sep 8, 2026
@wibus-wee
wibus-wee marked this pull request as ready for review September 8, 2026 04:47
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-08T04:55:00.684707Z 5de5d6e Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@wibus-wee
wibus-wee merged commit cdae88d into main Sep 8, 2026
7 checks passed
@wibus-wee
wibus-wee deleted the feat/chat-share-image branch September 8, 2026 04:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5de5d6ec03

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

onShareWithTeam={
showSessionSharing ? () => handleRequestShareSession(activeSession) : undefined
}
onShareAsImage={activeDraftTab ? undefined : handleShareAsImage}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the image-share action to the mobile menu

On responsive mobile, SessionDetail returns through the MobileSessionMenuSheet path before this desktop toolbar is rendered, but mobileMenuActions never adds an action that calls handleShareAsImage. Consequently, every non-draft mobile conversation lacks any entry point to the new selection/export workflow even though the same shared package serves mobile surfaces; wire the action into the mobile menu as well.

AGENTS.md reference: packages/components/AGENTS.md:L6-L8

Useful? React with 👍 / 👎.

Comment on lines +215 to +218
const observer = new MutationObserver(() => {
if (!applying) schedule();
});
observer.observe(root, { childList: true, subtree: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop the collapse observer from scheduling itself

When a code block exceeds collapseAfter, applyCollapse removes and then appends [data-share-collapse-ui] children. Those mutations invoke this observer after applying has returned to false, scheduling another animation frame that performs the same mutations again. Thus enabling code collapse on the exact long blocks it targets creates a permanent 60 Hz DOM rebuild loop while the preview is open, causing sustained main-thread load and potentially interfering with export; ignore mutations produced by the collapse pass or only mutate when the derived state changed.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant