Skip to content

Add pinned notes: paper notes with a pushpin, composed in a Note Pad widget - #361

Merged
AllTerrainDeveloper merged 5 commits into
trunkfrom
add/pinned-notes
Jul 17, 2026
Merged

Add pinned notes: paper notes with a pushpin, composed in a Note Pad widget#361
AllTerrainDeveloper merged 5 commits into
trunkfrom
add/pinned-notes

Conversation

@AllTerrainDeveloper

@AllTerrainDeveloper AllTerrainDeveloper commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

What this adds

Notes.mov

A new, self-contained notes feature for the desktop. You write a note in the Note Pad widget, drag the sheet out of the pad, and drop it on the wallpaper, where it pins itself with an animated pushpin. The pin is the only drag handle. Dragging a note to the recycle bin soft-trashes it with an Undo toast. Marking a note public shows it, read-only and with author attribution, on every other desktop user's wallpaper.

This is separate from the Guidelines-backed sticky notes layer, which is untouched.

Data model (PHP)

  • wpd_note CPT: non-public, excluded from search, absent from core REST (includes/notes/cpt.php).
  • Visibility maps to post status: private (default) or publish (public). Only the owner can edit, move, recolor, or delete a note, and administrators do not bypass ownership. New-note creation is gated by the desktop_mode_notes_user_can_create filter.
  • Postmeta: position (_wpd_note_x/_wpd_note_y, normalized 0..1), paper color (_wpd_note_color, whitelist filterable via desktop_mode_notes_colors), z-order (_wpd_note_z), and a creation-time jitter seed (_wpd_note_seed, hashed from the initial text and never rewritten, so edits do not re-tilt the paper).
  • Custom REST controller at /desktop-mode/v1/notes (includes/notes/rest.php) with optimistic concurrency: a stale updatedAtMs token returns 409 with the server copy attached.
  • Heartbeat delta sync (includes/notes/heartbeat.php) streams cross-user changes; the client falls back to a full re-hydration when a delta overflows the server cap.

Client (TS)

  • Note Pad widget (src/plugins/notes-widget/, its own bundle): a pad of pastel paper. The top sheet is the draft; two peek sheets underneath advertise the next colors in the cycle; a folded corner cycles the color; six paper-dot swatches pick directly; a Public checkbox and a keyboard "Pin to desktop" path (Ctrl+Enter) round it out. Empty drafts refuse to lift with a small shake.
  • Notes layer (src/notes/, main bundle): renders the wall. Deterministic per-note jitter (paper tilt, pin offset and twist) from the creation seed. Owner chrome (color dot showing the next color, globe/lock visibility toggle) is hover-revealed; other users' notes render a steel pin that is scenery, not a handle.
  • Motion (src/notes/motion.ts): pin insertion thunk (fall, strike squash, spring settle, ripple), pull-out with a paper imprint left behind, pendulum swing while carried (driven by drag velocity), snap-back with overshoot on cancel, crumple-into-bin on trash. All gated behind prefers-reduced-motion.
  • Drop routing: the drop-target registry allows one target per element and the wallpaper plus bin surfaces are already claimed, so note payloads (note-draft, note) route through two small seams consulted by the existing targets: src/desktop-files/canvas-payloads.ts and src/desktop-files/recycle-bin-payloads.ts. File drops landing on top of a pinned note still fall through to the wallpaper canvas target.
  • Accessibility: keyboard move mode on the pin button (arrows to move, Enter to place, Escape to cancel, Delete to trash with confirm), aria-live announcements, focus rings outside the paper.

Review

A high-effort multi-agent review ran over the diff before this PR; the ten confirmed findings were all fixed in place, including: live nonce reads so long sessions survive the nonce_life rollover, newest-first list capping, truncated-delta re-hydration, flushing edits typed while the create POST was in flight, drag-listener leaks on click-only pin gestures, pinned notes no longer blocking wallpaper file drops, filter-added colors rendering unclamped, a creation capability filter, remote z-order changes applying on heartbeat, and visible failure feedback on the keyboard pin path.

Testing

  • PHPUnit: 24 tests (CPT registration flags, sanitizers, untrash status restore, ownership including admin denial, public/private visibility, 409 conflicts, trash/restore, heartbeat visibility and removals, creation filter).
  • Vitest: 31 tests (REST client and conflict error, layer rendering owner vs read-only, jitter stability across edits, heartbeat deltas and truncation fallback, drop routing and coordinate math, bin gating on canEdit, widget compose/tear-off/keyboard-pin flows).
  • npm run build, npm run lint, npm run typecheck, npm run test:js (1897 passing), npm run test:php (1113 passing) all green.
  • Manually tested on the local dev environment: create by drag and by keyboard, reposition, recolor, public visibility from a second user, trash and undo, reduced-motion variants.

Docs

docs/hooks-reference.md (both new filters), docs/javascript-reference.md (payload contracts, notesUrl config, desktop-mode-note-created event), docs/api-index.md, docs/architecture.md.

Open WordPress Playground Preview

…widget

Notes are a plugin-owned wpd_note CPT (non-public, custom REST controller
at /desktop-mode/v1/notes). Write a note in the Note Pad widget, drag the
sheet out of the pad, and drop it on the wallpaper, where it pins itself
with an animated pushpin. The pin is the only drag handle; dragging a note
to the recycle bin soft-trashes it with an Undo toast.

Highlights:

- Visibility maps to post status: private (default) or publish (public,
  read-only on every other desktop user's wallpaper, with an author chip
  and a steel-tinted pin). Only the owner can mutate a note, admins
  included; gate new-note creation via desktop_mode_notes_user_can_create.
- Position, color, z-order, and a creation-time jitter seed (hashed from
  the initial text, never rewritten on edits) persist in postmeta, so the
  owner's placement and each note's subtle paper tilt are canonical.
- Optimistic concurrency (updatedAtMs token, 409 with the server copy)
  plus Heartbeat delta sync for live cross-user updates, with a full
  re-hydration fallback when a delta overflows the server cap.
- Motion set in src/notes/motion.ts: pin insertion thunk, pull-out with a
  paper imprint, pendulum swing while carried, snap-back with overshoot,
  and crumple-into-bin, all gated behind prefers-reduced-motion.
- Drop routing goes through two new seams consulted by the existing
  targets (canvas-payloads.ts and recycle-bin-payloads.ts), since the
  drop-target registry allows one target per element. File drops landing
  on top of a note still reach the wallpaper canvas target.
- Six pastel papers with dark-scheme variants as CSS custom properties;
  the palette is filterable via desktop_mode_notes_colors and
  filter-added slugs render unclamped.
- Tests: 24 PHPUnit tests (CPT flags, ownership, conflicts, heartbeat
  visibility) and 31 Vitest tests (layer, drag payloads, drop routing,
  widget). Docs updated: hooks-reference, javascript-reference,
  api-index, architecture.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new “pinned notes” feature to Desktop Mode: users compose notes in a Note Pad widget, pin them to the wallpaper (pushpin is the drag handle), sync across users (public notes) via REST + Heartbeat deltas, and support soft-trash with Undo via the Recycle Bin.

Changes:

  • Introduces a new wpd_note CPT with a dedicated REST controller (/desktop-mode/v1/notes) and Heartbeat delta sync for cross-user updates.
  • Adds the client notes layer (rendering, drag/drop seams, motion/physics, trash flow) and a separate Note Pad widget bundle + styles.
  • Extends drop routing seams for the wallpaper canvas and recycle bin to support handler-owned payloads (notes) without claiming new drop targets.

Reviewed changes

Copilot reviewed 44 out of 46 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
vite.config.js Adds the widget-notes Vite build target for the Note Pad widget bundle.
package.json Adds build:widget-notes and includes it in the main build chain.
src/types.ts Extends DesktopConfig with optional notesUrl to gate client boot.
src/desktop.ts Boots the pinned-notes feature in the main shell bundle.
src/notes/index.ts Composes notes boot: installs REST deps, mounts layer, drop handlers, and cross-bundle creation event listener.
src/notes/types.ts Defines note wire shape, drag payload shapes, Heartbeat payloads, and the cross-bundle CustomEvent name.
src/notes/rest.ts Adds a tracked-fetch REST client with nonce handling and a typed 409 conflict error.
src/notes/heartbeat.ts Wires notes into the Heartbeat contribute/subscribe bus.
src/notes/colors.ts Adds built-in color cycle helpers and non-clamping slug sanitization for DOM rendering.
src/notes/pin.ts Centralizes pushpin sizing/anchor constants and <img> construction.
src/notes/motion.ts Implements pinned-note animation sequences and deterministic jitter.
src/notes/trash.ts Implements soft-trash + Undo flow using notes REST endpoints and toasts.
src/notes/drop-handlers.ts Registers note handlers into canvas/bin seams (create/reposition/trash) with ghost-offset coordinate math.
src/notes/layer.ts Implements the notes wall layer and per-note controller behavior (editability, drag, z-order, heartbeat updates).
src/plugins/notes-widget/index.ts Implements the Note Pad widget composer UI, drag tear-off payload, and keyboard pin path (POST + CustomEvent).
src/plugins/notes-widget/styles.css Adds Note Pad widget chrome styles (consumes shared note tokens).
src/desktop-files/canvas-payloads.ts Adds a payload-handler seam consulted by the existing wallpaper canvas drop target.
src/desktop-files/recycle-bin-payloads.ts Adds a payload-handler seam consulted by the existing recycle bin drop targets.
src/desktop-files/layer.ts Routes non-file payloads through the canvas payload seam; avoids grid preview for handler-owned payloads.
src/desktop-files/recycle-bin-targets.ts Routes unknown payloads through the recycle-bin payload seam (notes trash path).
includes/notes/bootstrap.php Bootstraps the server-side pinned-notes feature modules.
includes/notes/cpt.php Registers wpd_note CPT, meta, sanitizers, palette filter, and untrash status restoration.
includes/notes/rest.php Adds REST routes for list/create/update/delete/restore with owner-only mutation and optimistic concurrency.
includes/notes/heartbeat.php Adds server Heartbeat delta computation and visibility rules matching the REST list.
includes/notes/recycle-bin.php Opts notes into recycle bin capture and enforces owner-only bin visibility/restore/purge + badge count correction.
includes/widgets/widget-notes.php Registers/enqueues the widget’s assets and registers the Note Pad widget definition.
includes/assets.php Registers desktop-mode-notes stylesheet for pinned-notes layer visuals.
includes/render/assets.php Enqueues notes stylesheet and exposes notesUrl in desktopModeConfig.
includes/recycle-bin/capture.php Expands default captured post types to include non-builtin show_ui CPTs and dedupes the list.
includes/recycle-bin/store.php Improves recycle-bin row shaping for CPTs (menu dashicon + excerpt/content subtitle).
docs/javascript-reference.md Documents pinned-note drag payload types, the creation CustomEvent, and notesUrl config.
docs/hooks-reference.md Documents new notes filters and updated recycle-bin capture behavior.
docs/architecture.md Documents pinned notes feature architecture and the drop-routing seams.
docs/api-index.md Adds the pinned-notes creation CustomEvent to the API index.
desktop-mode.php Wires the new notes bootstrap and widget registration into plugin load.
tests/vitest/notes-rest.test.ts Adds REST client tests (URLs, payload mapping, typed 409 conflict handling).
tests/vitest/notes-layer.test.ts Adds layer tests (render modes, jitter stability, heartbeat deltas, trash/undo).
tests/vitest/notes-drop-handlers.test.ts Adds seam routing tests for canvas/bin drop paths and coordinate math.
tests/vitest/notes-widget.test.ts Adds widget composer tests (drag gating, payload shape, keyboard pin path event handoff).
tests/phpunit/tests/notesCpt.php Adds CPT + sanitizer + untrash status tests.
tests/phpunit/tests/notesRest.php Adds REST route tests (ownership, visibility, concurrency, trash/restore, heartbeat).
tests/phpunit/tests/notesRecycleBin.php Adds recycle-bin integration tests for notes ownership and CPT bin behavior.
assets/css/notes.css Adds pinned-notes shared tokens and the pinned note / ghost visuals, including reduced-motion handling.
assets/images/pushpin.svg Adds the pushpin asset with documented anchor geometry.
assets/js/widget-notes.css Adds built widget CSS output for the Note Pad widget.
assets/js/widget-notes.min.css Adds minified built widget CSS output.
Files not reviewed (1)
  • assets/js/widget-notes.min.css: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/notes/layer.ts
AllTerrainDeveloper and others added 3 commits July 17, 2026 11:45
…titles, and ensure owner attribution for unstamped trashed notes
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@AllTerrainDeveloper
AllTerrainDeveloper enabled auto-merge (squash) July 17, 2026 09:49
@AllTerrainDeveloper
AllTerrainDeveloper merged commit f271f68 into trunk Jul 17, 2026
5 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the add/pinned-notes branch July 17, 2026 09:51
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.

2 participants