mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
codex-mobile-touch-selection
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7d7654fcda |
feat(annotate): minimal-by-default HTML sessions with stale-preference decay (#1260)
* feat(annotate): minimal-by-default HTML sessions with stale-preference decay Raw-HTML annotate sessions now open minimal by default: Pinpoint input, tools hidden, left sidebar closed, and the right annotations drawer closed (the drawer joins the persisted HTML chrome state, previously it always opened on desktop). Explicit user choices still persist between HTML sessions, but the records now carry a timestamp and expire after 7 days without a refresh, so users who have not changed anything or annotated HTML in a while come back to the product defaults. Explicit changes and annotation activity both re-stamp the records, so active users keep their setup. Legacy untimestamped cookies are treated as expired (a one-time reset to the new defaults). The markdown surface keeps its own preference with no TTL, unchanged. Mutation-verified: disabling the TTL fails 4 tests. * test(annotate): stamp seeded chrome cookies and compare semantic fields The App-level chrome suite seeded legacy untimestamped cookies, which the stale-preference decay now treats as expired by design, and one assertion compared cookie bytes that re-stamping legitimately changes. Seeds carry a fresh savedAt and the write-integrity assertion compares the chrome fields. |
||
|
|
9ab5392bad |
feat(annotate): pinpoint-first raw-HTML sessions with element anchors and a minimal-first render (#1243)
* feat(annotate): rebuild HTML pinpoint mode with element anchors, pin badges, and a minimal-first render Raw-HTML annotate sessions now open as just the page: first-ever run hides all annotation chrome (toolstrip, tongue tabs, action cluster, sidebar) and the user's last chrome state is restored on every later session via the plannotator-html-chrome cookie. Pinpoint becomes the default input method on the HTML surface, persisted separately from the markdown preference. Pinpoint mechanics are rebuilt in the sandbox bridge, modeled on app-notes-extension and agentation: a fixed-position outline box + label replaces class writes on author elements, hover is identity-gated and re-hit-tested on scroll/resize via a rAF-coalesced reconcile pass, clicks pin the element (crosshair cursor, pinned outline while composing) and go straight to the comment popover. Each pin serializes a verified-unique CSS selector anchor (id > identity attrs > meaningful classes > nth-of-type path) with a text-snapshot fingerprint; restoration is anchor-first with fail-closed validation and falls back to document-wide text search. Element pins that cannot take an inline mark (SVG etc.) get numbered pin badges that track their element and re-acquire it after re-renders. All DOM inspection stays inside the bridge; only validated, size-capped DTOs cross postMessage. Annotation model is extended additively (htmlAnchor), so exported feedback, drafts, and share links keep working. * fix(annotate): harden HTML element anchors per adversarial review Four fixes from the pre-merge adversarial review of the pinpoint round: - Stable identity is now only the element's own #id or data-* rung, re-derived from the resolved element and compared whole instead of parsed out of the selector string. Behavioral attributes (role, href, aria-label, name, alt) no longer exempt an anchor from the text check, so a regenerated page can no longer bind an annotation to the wrong element. A weak anchor with a missing or empty snapshot is rejected, not exempted. - Restoration order: the document-wide text search now runs before the pin-badge fallback, so text that moved elsewhere in a regenerated page is followed rather than badging the stale container. Resolved SVG anchors still pin directly. - Selection text is capped at 10k chars on both sides of the bridge (truncated, not rejected); one pinpoint click on a huge pre/table no longer ships an unbounded page-controlled string into drafts, feedback, or share URLs. - buildAnchorSelector returns null instead of a terminal fallback path already proven non-unique; no anchor beats a known-ambiguous one. Also moves the HTML chrome restore out of the one-shot mount effect into a surface-transition effect, so a linked .html doc opened from a markdown session gets the minimal-first chrome and persists its state, and a markdown surface's sidebar use never leaks into the HTML cookie. * fix(annotate): skip the chrome save in the restore commit itself The reviewer's residual finding: htmlChromeRestoredRef flips synchronously inside the restore effect, but the restored state lands a commit later, so the save effect's run in the restore commit wrote pre-restore values over the remembered state (self-corrected next flush, but a page ending between the two writes would freeze the inverted value). The restore now arms a skip-one flag the writer consumes, so the stale write never happens. A follow-up save fires from the changed deps when the restore changed anything; when it changed nothing the cookie already holds those values. Regression test instruments every chrome cookie write on a returning-user mount and asserts none ever differs from the remembered state (mutation tested: removing the skip fails it). |
||
|
|
2739660fa6 |
feat: pinpoint mode for point-and-click annotations (#232)
* feat: add pinpoint mode for point-and-click annotations Adds a new input method toggle (Drag / Pinpoint) orthogonal to the existing annotation action modes (Selection / Comment / Redline). In pinpoint mode, hovering over blocks and inline elements shows a dashed outline with a label tooltip. Clicking auto-selects the element's text via highlighter.fromRange(), firing the same CREATE event as drag-selection — all downstream annotation flow is unchanged. New files: - blockTargeting.ts: resolves hover targets (inlines, cells, list items, blocks) - usePinpoint.ts: hover/click state machine with text-range bridge - PinpointOverlay.tsx: dashed outline + label badge - InputMethodToggle.tsx: Drag/Pinpoint segmented toggle - inputMethod.ts: cookie-based persistence Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: unified AnnotationToolstrip with smooth animations Merge InputMethodToggle + ModeSwitcher into a single compact toolbar with two pill groups: input method (Select/Pinpoint) and action mode (Markup/Comment/Redline). Buttons expand to show labels on hover/active with explicit pixel-width transitions. Suppress transitions on mount to prevent initial flash. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: keyboard shortcuts tab and settings reorganization Add Shortcuts tab to settings with OS-aware key cap styling and organized shortcut groups. Move Obsidian and Bear integrations to dedicated tabs under an Integrations sidebar group, leaving compact navigation links on the Saving tab. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: Alt/Option key to switch between Select and Pinpoint Hold Alt to temporarily switch input method (reverts on release). Double-tap Alt to permanently toggle. Added to keyboard shortcuts panel in settings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: remove md:py-8 to use consistent py-3 padding Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: toolbar polish — icon swap, full opacity active states, styling Move text-bracket icon to Select, pencil to Markup. Active buttons use full opacity backgrounds with contrasting foreground. Help link lowercase with updated styling. Revert md:py-8 padding. Add gap between buttons in pill groups. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: match toolbar button sizing to main branch Use text-xs (12px) and px-2.5 padding to match main branch button rendering. Active state uses bg-background with no color tint. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: smarter pinpoint hover — edge-zone tables, row targeting, list groups Table edge-zone detection: top/bottom edges target whole table, left/right edges target the specific row, interior targets individual cells. List group wrappers create hover zones in gaps between consecutive list items. Demo plan now includes sample tables for testing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove unused InputMethodToggle component Superseded by AnnotationToolstrip which unified input method + mode switching. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove unimplemented S3 paste store stub Never used — paste service runs on Cloudflare KV and local FS. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove dead ModeSwitcher component Replaced by AnnotationToolstrip which unified mode switching + input method toggle. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |