Files
agatha 7d49c12ce2 Feat: Add Copy URL button and reusable toast notification system
Detail page now has a "Copy URL" button that copies the image's direct
file URL to the clipboard. A toast service (BehaviorSubject-backed,
auto-dismissing after 3s) confirms success or failure. ToastComponent
is registered at the app root and available to all future features.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 22:21:48 +00:00

3.6 KiB

Implementation Plan: Copy URL & Toast Notifications

Branch: 016-copy-url-toast | Date: 2026-05-09 | Spec: spec.md Input: Feature specification from specs/016-copy-url-toast/spec.md

Summary

Add a "Copy URL" button to the image detail page that copies the image's direct file URL to the clipboard, with a reusable toast notification service wired to confirm success or failure. All changes are UI-only; no API changes are required.

Technical Context

Language/Version: TypeScript (strict mode), Angular latest stable Primary Dependencies: Angular (@angular/core, @angular/common), RxJS (BehaviorSubject), browser Clipboard API (navigator.clipboard.writeText) Storage: N/A Testing: Karma/Jasmine (ng test) Target Platform: Browser (modern; Clipboard API requires HTTPS — already in place) Project Type: Angular standalone SPA Performance Goals: Copy action completes in < 100ms perceived latency; toast appears within 300ms of action Constraints: TypeScript strict mode, ChangeDetectionStrategy.OnPush on all components, no new npm dependencies Scale/Scope: Two new files (service + component), two modified files (detail + app component)

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

Principle Status Notes
§2.1 Strict separation of concerns ✓ PASS Pure UI change; no API knowledge in UI beyond what's already in ImageRecord.file_url
§2.6 No speculative abstraction ✓ PASS Toast service is justified: used immediately by this feature and explicitly planned for reuse (upload confirmation, delete confirmation, filter feedback). Two concrete use cases exist.
§5.1 Tests alongside implementation ✓ PASS Tests required for ToastService and the copy button on DetailComponent
§5.2 Test pyramid ✓ PASS Unit tests only (no API/DB involved); Karma/Jasmine
§6 Tech stack ✓ PASS Angular, TypeScript strict — no new dependencies
§7.3 Linting ✓ PASS ng lint must pass before task is done
§8 Scope boundaries ✓ PASS No multi-user, no embeds, no public sharing infrastructure — just a clipboard copy

Post-design re-check: No violations. Feature is entirely additive.

Project Structure

Documentation (this feature)

specs/016-copy-url-toast/
├── plan.md              ← this file
├── research.md          ← Phase 0 output
├── quickstart.md        ← Phase 1 output
├── contracts/
│   └── toast-service.md ← Phase 1 output
└── tasks.md             ← /speckit-tasks output

Source Code

ui/src/app/
├── app.component.ts              ← modified: add <app-toast> to template
├── services/
│   └── toast.service.ts          ← new: singleton toast service
├── toast/
│   └── toast.component.ts        ← new: toast display component
└── detail/
    └── detail.component.ts       ← modified: add Copy URL button + inject ToastService

ui/src/app/services/
    toast.service.spec.ts         ← new: unit tests for ToastService

ui/src/app/toast/
    toast.component.spec.ts       ← new: unit tests for ToastComponent

ui/src/app/detail/
    detail.component.spec.ts      ← modified: tests for copy button behaviour

Structure Decision: Single-project Angular SPA. Toast service lives in services/ alongside ImageService and TagService. Toast component gets its own toast/ directory following the existing component-per-directory convention.