Skip to content

refactor(sticker): the sticker tool is the third feature module, with a canvas overlay, a sidebar view and a layer source - #259

Merged
YIWANG3 merged 2 commits into
mainfrom
feat/feature-module-sticker
Nov 3, 2026
Merged

YIWANG3 merged 2 commits into
mainfrom
feat/feature-module-sticker

Conversation

@YIWANG3

@YIWANG3 YIWANG3 commented Nov 2, 2026

Copy link
Copy Markdown
Owner

PR 3 of docs/feature-modules-plan.md §8, after #257 (LUT) and #258 (AI Repaint). From main, zero behaviour change.

Moved (git mv)

  • electron/ipc/stickers.js → features/sticker/electron/stickers.js. The helper path comes from host.nativeBin now instead of an isPackaged branch of its own. New stickers.test.js (5 tests): channels match the manifest; save → list → star → delete round trip with thumbnails; thumbnail backfill; detect's three refusals; scratch cleanup only removes the feature's own folders.
  • StickerPanel.jsx, StickerRegionOverlay.jsx, StickerView.jsx, hooks/useStickerViewKeys.js → features/sticker/renderer/. state/useStickerRegion.js moved and became useStickerTool.js (the tool's whole state). The old state/useStickerTool.js is deleted: it only composed the region with useStickerImageCache, and the image cache is the editor core's (layers carry stickers whether or not this module is present), so EditorOverlay calls useStickerImageCache(layers) directly.

New manifest fields, and who reads them

field reader
helper: "extract-sticker" electron/features.js → capability off when the binary is missing; capabilities.js's hand-written table is down to depth / people
editorTool.overlay: true features/index.js adds Overlay to the editorToolFeatures row; EditorOverlay renders the active tool's overlay with { imageRect, tool } (featureTools = { lut, sticker } keyed by rail key)
sidebarView: { id: "stickers", labelKey, unavailable: "locked" } sidebarViews table; Sidebar.jsx maps it (props activeView / onOpenView(id) replace stickerMode / onOpenStickerBrowser); App.jsx hosts <View> / <Inspector> and takes the Lightbox items, index and keyboard handler from the feature's useView; show_in_app's view enum is built from the manifests (same 5 values)
layerSource: { id: "stickers", labelKey, hideLabelKey } layerSources table; TextPanel renders one picker button per row, StickerPickerModal takes a source and uses source.list() / source.thumbUrl()

Decisions §8 left open

  • Hooks stay explicit imports. Three samples in, each is one import line and one call; featureTools and featureViewStates hand the results to the table-driven parts. A useFeatureTools with an eslint exception can wait for the manifest freeze.
  • Panels are not table-driven (props differ per tool); the sticker panel is a lazy chunk in <Suspense> like LUT's. mount: "always" stays hand-written.
  • editorStateModel untouched: the region never enters history.

Not moved

native/extract-sticker.swift (build scripts know the path); i18n (stickerView namespace, sidebar.stickers, sticker.* — after the three PRs, per §11); the Library settings' "sticker library" open-folder row (a cache-storage row backed by the host's appSettings.js kind table, shown on Windows too); the web bridge's stickerList: async () => []. IPC_METHODS is still 183 rows.

Verified

  • npm run lint clean; test:electron 295 (was 290); test:renderer 432; npm run build (StickerPanel is its own chunk).
  • Acceptance specs 02-navigation, 03-editor, 04-sticker, 08-mcp-http, 19-editor-layers, 24-handwriting, 31-ui-regressions, 43-sticker-library: 44 passed.
  • Full npm run e2e is running; result in the thread.
  • Not done: e2e:coverage, npm run pack.

Docs: plan status line, §8 as-built record and timetable; docs/README.md rows; apps/desktop/features/README.md layout and reader list.

🤖 Generated with Claude Code

YIWANG3 and others added 2 commits November 2, 2026 11:24
… a canvas overlay, a sidebar view and a layer source

PR 3 of docs/feature-modules-plan.md (§8). Zero behaviour change: the
rail, the Stickers view, the Text tool's sticker picker, the agent's
show_in_app and the IPC table all do what they did.

Moved (git mv): electron/ipc/stickers.js → features/sticker/electron/
(the helper path now comes from host.nativeBin), and StickerPanel,
StickerRegionOverlay, StickerView, useStickerViewKeys and the region hook
(now useStickerTool, the tool's whole state) → features/sticker/renderer/.
The old state/useStickerTool.js is gone: the decoded-image cache it
composed is the editor core's, so EditorOverlay calls
useStickerImageCache(layers) itself.

New manifest fields and the tables that read them (features/index.js):
- helper: "extract-sticker" — capabilities.js's hand-written table is
  down to depth and people;
- editorTool.overlay — editorToolFeatures rows carry an Overlay, and
  EditorOverlay mounts the active tool's one with { imageRect, tool };
- sidebarView — Sidebar.jsx lists sidebarViews (activeView / onOpenView
  props replace stickerMode / onOpenStickerBrowser), App.jsx hosts the
  active one's View and Inspector and takes the Lightbox items and the
  keys from the feature's useView; show_in_app's enum is built from the
  manifests;
- layerSource — TextPanel shows a button per layerSources row and
  StickerPickerModal lists the chosen source's images.

Hooks stay explicit imports (the decision §8 left open), with two small
tables (featureTools, featureViewStates) feeding the table-driven parts.
i18n, the Library settings' sticker-folder row and the Swift source stay
where they are. features/sticker/electron/stickers.test.js covers the
moved handlers; the IPC, capability and tool-schema guards pass as
before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@YIWANG3
YIWANG3 merged commit 89f6597 into main Nov 3, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant