Skip to content

[WIP] Enhance features in Darkroom Process Timer app#20

Draft
Copilot wants to merge 1 commit intomainfrom
copilot/enhance-darkroom-timer-features
Draft

[WIP] Enhance features in Darkroom Process Timer app#20
Copilot wants to merge 1 commit intomainfrom
copilot/enhance-darkroom-timer-features

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 13, 2026

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.

Darkroom Timer — Feature Enhancement Agent Prompt

Context & Ground Rules

You are enhancing an existing web app: Darkroom Process Timer
Live URL: https://abhinavkarhale7-ctrl.github.io/darkroom-timer/

Before writing a single line of code:

  1. Read every source file in the repository completely — HTML, JS, CSS, and any JSON/config files.
  2. Map the full data model: how processes, steps, history entries, and sync state are currently stored (localStorage keys, object shapes, all fields).
  3. Map the full event/state flow: how the timer ticks, how steps transition, how history is written, how save/load works.
  4. Map the existing tab structure: Setup, Timer, History, Metro, Sync.
  5. Do not assume anything. If a file is ambiguous, read it again.

Core constraints — never violate these:

  • Do not change the timer logic, step sequencing, or agitation system.
  • Do not change the existing dilution calculator, temp compensation, Ilford nomogram, or comparison table.
  • Do not change the cloud sync mechanism or passphrase model.
  • Do not change the metronome.
  • Do not rename or restructure existing localStorage keys — only add new ones alongside them.
  • Do not break any existing keyboard shortcuts (Space = start/pause, Esc = stop).
  • All new features must be additive — existing saved data must still load and work after your changes.
  • Every new UI element must respect the existing visual language (colors, typography, spacing, component style).
  • All new features must work fully offline. No external API calls except where the existing cloud sync already makes them.

Feature Implementation List

Implement all of the following features. Each section specifies exactly what to build, where to put it, and what data shape to use. Do not skip any item. Do not combine items in ways that break their individual specs.


1. Safelight / Red Mode

What: A full-UI red-on-black mode for use in an active darkroom. Replaces all colors with red tones on pure black to preserve night vision and avoid fogging paper.

Implementation:

  • Add a toggle button, always visible in the top navigation bar, labeled "🔴" or "SAFE" — present on every tab, no tab switch needed to activate it.
  • When active, apply a CSS class safelight to <body>. Use a single CSS block with CSS custom property overrides to remap all existing color variables to red equivalents. Do not inline styles on individual elements.
  • Safelight palette: background #000, all text #cc0000, borders #660000, button backgrounds #1a0000, button hover #2a0000, active/highlight #ff2200.
  • Persist the safelight preference in localStorage under key darkroom_safelight (boolean).
  • Safelight mode must also apply to any modals, overlays, or dynamically inserted elements.
  • Provide a smooth CSS transition (0.2s) when toggling.

2. Screen Wake Lock

What: Prevents the device screen from sleeping while the timer is running.

Implementation:

  • Use the Screen Wake Lock API (navigator.wakeLock.request('screen')).
  • Acquire the lock when the timer starts (on the same event that starts the countdown).
  • Release the lock when the timer stops or is paused. Re-acquire on resume.
  • Re-acquire automatically on visibilitychange if the timer is still running (the API releases locks when the page is hidden).
  • If the API is unsupported, fail silently — no error shown to the user.
  • Show a small indicator in the Timer tab status area: a screen icon, green when lock is held, grey when not. Tooltip: "Screen will stay on" / "Screen may sleep".
  • Do not add any new settings or toggles — wake lock is always on during an active timer.

3. Voice Announcements

What: Text-to-speech callouts at step transitions so the user does not need to look at the screen.

Implementation:

  • Use the Web Speech API (window.speechSynthesis). No library. No external service.
  • Announce at the moment each step begins: speak the step name and its duration. Example: "Developer. Eight minutes."
  • Announce at step end / transition: "Developer complete. Starting stop bath."
  • Announce at process completion: "Process complete."
  • Announce the last 10 seconds of each step, counting down: "Ten… nine… eight…" etc. (see Feature 4 for the beep — voice and beep run together).
  • Add a toggle button in the Timer tab controls area, labeled "🗣 Voice" — off by default.
  • Persist preference in localStorage under key darkroom_voice (boolean).
  • If speechSynthesis is unavailable, hide the toggle silently.
  • Respect the existing 🔊 mute button — if the app is muted, suppress voice announcements too.

4. Countdown Beeps (Final 10 Seconds)

What: An escalating beep every second for the last 10 seconds of each step.

Implementation:

  • Use the Web Audio API to generate a short beep tone (sine wave, ~880 Hz, ~80ms duration, ramp-out envelope to avoid clicks).
  • Trigger one beep per second from T-10 to T-1 of each step. The existing step-end beep fires at T-0 as it does now — do not remove or change it.
  • The countdown beeps must be distinct from the step-end beep in pitch or timbre. Use ~880 Hz for countdown, and leave the existing end-beep unchanged.
  • These beeps use the same audio context as the existing audio system if one already exists in the code — do not create a second audio context.
  • Countdown beeps are gated by the existing 🔊 mute button.
  • No new toggle needed — countdown beeps are always on (unless muted).

5. Large-Target / Gloves Mode

What: Increases all interactive element sizes for use with wet hands or nitrile gloves.

Implementation:

  • Add a toggle button in the top navigation bar alongside the safelight toggle, labeled "🧤" or "GLOVES".
  • When active, apply CSS class gloves-mode to <body>.
  • Under gloves-mode: all <button> elements minimum height 56px, minimum width 56px; all <input> and <select> elements minimum height 48px; font size on all interactive elements increased by 20%; spacing between controls increased by 8px.
  • Use CSS only — no JS layout changes.
  • Persist in localStorage under key darkroom_gloves (boolean).
  • Gloves mode and safelight mode must be independently toggleable and composable (both can be on simultaneously).

6. Share Process via URL

What: Encode a saved process as a compressed base64 URL parameter so it can be shared with anyone.

Implementation:

  • Add a "🔗 Share" button in the Save/Load section, next to the existing Save, Save Card, Reset buttons.
  • On click: take the currently loaded process object (name, type, steps, all metadata), JSON-serialize it, encode with btoa (base64), append as URL param ?process=<encoded>.
  • Copy the full URL to the clipboard using navigator.clipboard.writeText(). Show a brief "Copied!" confirmation inline (replace button text for 2 seconds, then restore).
  • On page load: check for ?process= param. If present, decode with atob, parse JSON, load the process into the Setup form (same path as existing "load process" logic). Show a banner: "Process loaded from shared link." with a dismiss button.
  • Validate the decoded JSON before loading — if malformed, show error "Invalid shared link" and do not modify current state.
  • Do not add the shared process to the saved list automatically — let the user choose to save it.

7. Drag-to-Reorder Steps

What: Allow steps to be reordered by dragging in the Setup tab.

Implementation:

  • Use the HTML5 Drag and Drop API. No external library.
  • Add a drag handle element (⠿ or ≡) to the left of each step row in the steps list.
  • Set draggable="true" on each step row. Implement dragstart, dragover, drop, dragend handlers.
  • On drop, reorder the underlying steps array and re-render the steps list. Do not use DOM mutation as the source of truth — always re-render from the data array.
  • Show a visual drop target indicator (a 2px colored line between rows) during drag.
  • Drag handle cursor: grab / grabbing.
  • Works in both desktop (mouse) and mobile (touch) contexts. For touch, implement touchstart/touchmove/touchend fallback drag logic.
  • After reorder, recalculate and update the total time display.

8. Pre-Soak / Countdown-to-Start

What: A configurable delay before the first step begins, so the user can hit Start, set the phone down, and pour chemicals.

Implementation:

  • Add a numeric input in the Setup tab, below the existing "Countdown between steps" field. Label: "Countdown before start (sec)". Default: 0 (disabled).
  • Range: 0–60 seconds. Step: 1.
  • When the timer starts and this value is > 0, show a full-screen (or large overlay) countdown displaying the remaining seconds in large text with the label "GET READY — POUR NOW".
  • During the pre-start countdown, play a tick beep every second (same as countdown beeps — 880 Hz) and a distinct beep at 0 (process start).
  • After the countdown completes, transition seamlessly into Step 1 as if Start had been pressed at that moment.
  • Persist this field as part of the process object under key preStartCountdown (integer, seconds).
  • If value is 0, no countdown — start immediately as today.

9. Quick Process Presets Library

What: A built-in read-only library of common processes that can be loaded and duplicated into a user's own saved processes.

Implementation:

  • Add a "📚 Presets" button in the Save/Load section.

  • On click, open a modal (styled to match existing UI) listing preset processes grouped by category: Film — B&W, Film — C41/E6, Alternative.

  • Include at minimum these presets (use accurate published times at 20°C):

    Film — B&W:

    • Kodak D-76 1+1 — HP5+ @ 400: Developer 11min, Stop 1min, Fix 5min, Wash 10min
    • Ilford ID-11 stock — FP4+ @ 125: Developer 7min, Stop 1min, Fix 5min, Wash 10min
    • Kodak HC-110 Dil B — Tri-X @ 400: Developer 7.5min, Stop 1min, Fix 5min, Wash 10min
    • Caffenol-C-H — HP5+ @ 400: Developer 15min, Stop 1min, Fix 8min, Wash 10min
    • Rodinal 1+50 — FP4+ @ 125: Developer 13min, Stop 1min, Fix 5min, Wash 10min
    • Ilford DD-X 1+4 — Delta 3200 @ 3200: Developer 12min, Stop 1min, Fix 5min, Wash 10min

    Film — C41:

    • Tetenal Colortec C41 — Color Negative @ 400: Developer 3min15s at 38°C, Blix 6min30s, Wash 3min, Stabilizer 1min

    Film — E6:

    • Tetenal Colortec E6 3-bath — Slide: First Developer 6min at 38°C, Color Developer 6min, Blix 8min, Wash 2min, Stabilizer 1min

    Alternative:

    • Van Dyke Brown: Coat 2min dry, Expose variable, Wash 5min, Fix 5min, Wash 10min, Tone optional
  • Each preset card shows: process name, film/paper, developer, base temp, total time.

  • A "Use This" button copies the preset into the Setup form (same code path as loading a saved process). User must then explicitly save it to keep it.

  • Presets are hardcoded JSON in the source — not user-editable. They are never written to localStorage.


10. Push Notification for Step End

What: A native browser notification fires when a step completes, so the user can work away from the screen.

Implementation:

  • Use the Notifications API + an existing or new Service Worker.
  • On first timer start: request notification permission if not already granted. If denied, show a one-time inline message "Enable notifications to get step alerts" and never ask again.
  • When a step ends: send a notification with title "Darkroom Timer" and body "{Step name} complete — {Next step name} starting." If it's the last step: "Process complete."
  • Notifications must fire even when the browser tab is in the background. This requires a Service Worker. If a service worker already exists in the project, extend it. If not, create sw.js and register it on page load.
  • Do not send notifications if the app tab is currently visible (use document.visibilityState).
  • Gate notifications with the existing 🔊 mute button — if muted, suppress notifications too.

11. Offline-First PWA

What: Make the app fully installable as a PWA with complete offline support.

Implementation:

  • If a manifest.json already exists, audit and complete it. If not, create one with: name, short_name, start_url, display: "standalone", background_color, theme_color, icons (at minimum 192×192 and 512×512 — create simple placeholder SVG icons if none exist).
  • If a Service Worker already exists, audit its cache strategy. If not, create sw.js.
  • The Service Worker must use a cache-first strategy for all app shell assets (HTML, CSS, JS, icons).
  • Cache name should be versioned (e.g. darkroom-v2) so it can be updated cleanly.
  • On install: pre-cache all static assets.
  • On activate: delete old caches.
  • Add a <link rel="manifest"> to the HTML <head> if not already present.
  • Add a one-time "Install App" prompt (using the beforeinstallprompt event) shown as a small banner at the bottom of the screen, dismissible, only shown once per browser.

12. Chemistry Batch Tracker

What: Track the useful life of each chemical batch by rolls/sheets processed and age since mixing.

Implementation:

  • Add a new tab: "🧪 Chem" between History and Metro (or at the end — match existing tab ordering convention).
  • Each chemical entry has:
    • id (uuid or timestamp)
    • name (string, e.g. "D-76 1+1")
    • type (enum: Developer / Stop / Fix / Other)
    • mixedOn (ISO date string)
    • maxRolls (integer, user-set, e.g. 24)
    • rollsUsed (integer, auto-incremented)
    • maxAgeDays (integer, user-set)
    • notes (string)
  • UI: a list of chemical cards. Each card shows: name, type, mixed date, age in days, rolls used / max rolls as a progress bar, a warning icon if rolls ≥ 80% of max or age ≥ 80% of maxAgeDays, a red alert if either limit is exceeded.
  • Controls per card: "+ Use" (increments rollsUsed by 1), "Edit", "Delete".
  • "Add Chemical" button opens an inline form.
  • In the Timer tab, after a process completes, show a prompt: "Log rolls processed?" with a dropdown of existing chemicals — selecting one increments its rollsUsed. Dismiss option available. Do not force this step.
  • Persist all chemistry data in localStorage under key darkroom_chemistry (array of chemical objects).

13. Film Stock Database

What: A personal registry of film stocks with individual exposure index ratings, attachable to processes.

Implementation:

  • Add a "Film Stocks" section inside the existing Setup tab, collapsible (▾ like Dilution Calc).
  • A film stock entry has: id, name (e.g. "HP5 Plus"), iso (box speed integer), personalEI (integer), format (35mm / 120 / 4x5 / Other), notes.
  • "Add Stock" opens an inline form. Stocks are listed in a compact table: Name | Box ISO | Personal EI | Format.
  • In the process Setup form, add an optional "Film Stock" dropdown populated from the user's film stock list. Selecting one associates that stock's id with the process.
  • When the process is logged to history, record the film stock id and name (snapshot the name at log time so renames don't corrupt history).
  • History entries that have a film stock attached show the stock name inline.
  • Persist film stocks in localStorage under key darkroom_filmstocks (array).

14. Session Notes & Negative Sleeve Label

What: Free-text notes on each history entry, plus a printable label linking to the session.

Implementation:

  • In the History tab, each history entry already exists. Add an expandable notes area to each entry — click a "📝" button on the entry to expand an inline <textarea>. Notes auto-save on blur (no save button needed).
  • Add a "🏷 Label" button on each history entry. On click, open a print-ready label in a new window (or a <dialog>) containing: session date/time, process name, film stock (if recorded), developer, push/pull, and a QR code encoding the session's localStorage key or a JSON summary.
  • For the QR code: use qrcode.js from cdnjs (https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js). Encode a compact JSON: {date, process, developer, pushPull, steps[]}.
  • Label is styled for printing at approximately 90mm × 50mm. Use @media print styles to hide everything except the label.
  • Persist notes in localStorage. The note is stored inside the history entry object under key notes. Use the existing history storage structure — add notes and filmStockName as new optional fields on existing history entry objects.

15. Multi-Bath Temperature Logging & Drift Graph

What: Log temperature at the start, middle, and end of each bath; show a sparkline per step in history.

Implementation:

  • In the Timer tab, the existing "Bath temp" input updates the current step. Extend this: add a "Log Temp" button next to the input. Each press records {timestamp, temp, stepIndex} into the current session's temp log array.
  • On session complete, save the temp log into the history entry under key tempLog (array of {t: relativeSeconds, temp: number, step: string}).
  • In History, if a history entry has a tempLog, render a sparkline SVG next to it — inline SVG, no library, showing temperature over time with step boundaries as vertical dashed lines.
  • The sparkline is compact (120px × 40px). X-axis: time. Y-axis: temperature. Color: green if within ±1°C of process target temp, yellow ±2°C, red beyond.
  • No new settings required.

16. Rotary / Jobo Mode

What: A correction factor for processes run in a rotary processor instead of a tray or inversion tank.

Implementation:

  • In the Setup tab, add a "Agitation System" selector (radio buttons or segmented control): Inversion tank (default) | Rotary/Jobo.
  • When Rotary/Jobo is selected, show a note: "Times adjusted for continuous agitation."
  • Apply a correction multiplier of 0.85 to all Developer steps and 1.0 to all other steps. Show adjusted time next to each step row (greyed, in parentheses) — do not modify the stored step times, only display the adjusted value.
  • In the Timer, use the adjusted time for the Developer step countdown if Rotary/Jobo is selected.
  • Persist the agitation system selection as part of the process object under key agitationSystem (string: "inversion" or "rotary").

17. Enlarger / Printing Timer Sub-Mode

What: A simple dedicated mode for darkroom printing: linear test strip timing and f-stop increment timing.

Implementation:

  • Add a "🖨 Print Timer" button in the Timer tab (secondary, smaller than the main controls). Opens a modal or overlay — does not replace the main timer.
  • The Print Timer has two sub-modes selectable by toggle: Linear and f-stop.
  • Linear mode: User sets a base time (seconds) and a strip count (2–10). Timer fires at equal intervals: e.g. 5s base × 5 strips = 5s, 10s, 15s, 20s, 25s. Each interval plays the existing beep. A visual strip indicator shows which strip is currently exposing.
  • f-stop mode: User sets a base time and a stop fraction (½ stop, ⅓ stop, 1 stop). Timer fires at geometrically increasing intervals: time × 2^(fraction) per strip. Show each strip's cumulative time.
  • The Print Timer is independent of the main process timer — they do not interact.
  • Close button dismisses the Print Timer. No persistence needed (it's a session tool).

18. Session Statistics Dashboard

What: A simple analytics view of historical session data.

Implementation:

  • Add a "📊 Stats" button at the top of the History tab. Clicking it toggles a stats panel above the history list.
  • Stats panel shows:
    • Total sessions logged (count of history entries)
    • Sessions per month — a simple bar chart (inline SVG, no library, 12 bars for last 12 months)
    • Most used process (process name with highest frequency in history)
    • Most used developer (developer name with highest frequency)
    • Average session duration (mean of total time across all history entries)
    • Total darkroom time (sum of all session durations, formatted as hours and minutes)
  • All computed from existing history data — no new data collection.
  • Stats panel is collapsible. Persist collapsed/expanded state in localStorage under key darkroom_stats_open (boolean).

19. Batch / Multiple Roll Logging

What: Tag a session with multiple rolls processed simultaneously, each with their own film stock.

Implementation:

  • In the Timer tab, before starting (or just after the process completes), add an optional "🎞 Rolls in this session" section.
  • User can add 1–6 roll entries, each with: roll label (free text, e.g. "Roll 1"), film stock (dropdown from Film Stock DB, Feature 13), and personal EI used.
  • This is logged into the history entry under key rolls (array of {label, filmStockName, ei}).
  • In History, if rolls is present, show a compact list of rolls under the entry header.
  • If only 1 roll and Film Stock DB is not set up, this collapses to nothing — do not show an empty UI.
  • Roll logging is optional — a "Skip" button dismisses it. Never block timer operation waiting for roll input.

20. Accessibility Pass

What: Make all controls keyboard-navigable and screen-reader friendly.

Implementation:

  • Audit every <button> in the app. Any button whose label is an emoji, icon, or abbreviation must have an aria-label describing its action in plain English. Examples: aria-label="Save process", aria-label="Delete saved process", aria-label="Toggle safelight mode".
  • All <input> elements must have associated <label> elements (either explicit for/id pairing, or wrapping label). No placeholder-only labeling.
  • All modal/overlay elements must: trap focus while open, return focus to the triggering element on close, have role="dialog" and aria-modal="true", have an aria-labelledby pointing to their title.
  • Tab order must follow visual order on every tab.
  • All dynamic status changes (step transitions, timer state, temp warnings) must use aria-live="polite" regions so screen readers announce them.
  • Add a "Skip to main content" anchor as the very first focusable element in the DOM.
  • Test: every single interactive element must be reachable and operable using Tab, Shift+Tab, Enter, Space, and arrow keys as appropriate.

21. Undo / Redo for Process Edits

What: A simple undo stack on the Setup tab so accidental step deletions or time changes can be reversed.

Implementation:

  • Maintain an in-memory undo stack (array of process state snapshots) and redo stack.
  • Capture a snapshot on every user-initiated change in the Setup tab: adding/removing a step, editing a step's name/time/tip, changing process name, developer, push/pull, notes, cycles.
  • Maximum stack depth: 30 snapshots.
  • Add "↩ Undo" and "↪ Redo" buttons in the Setup tab toolbar (small, secondary style). Disable (not hide) when the respective stack is empty.
  • Undo/Redo do not persist across page loads — in-memory only.
  • Keyboard shortcuts: Ctrl+Z for Undo, Ctrl+Shift+Z for Redo. Do not conflict with browser native undo in text inputs — only intercept these shortcuts when focus is outside a text input.

22. °F / oz Unit Toggle

What: Allow Fahrenheit and fluid ounce units throughout the app.

Implementation:

  • Add a Units toggle in a new "⚙ Preferences" section at the bottom of the Setup tab (or in a persistent settings area). Two settings: Temperature (°C / °F) and Volume (ml / fl oz).
  • When °F is selected: all temperature displays, inputs, and the temp compensation calculator convert on the fly. Store temperatures internally always in °C — convert only for display and input parsing.
  • When fl oz is selected: the dilution calculator's "Total volume needed" input and its Stock/Water output values convert. 1 fl oz = 29.5735 ml. Round to 1 decimal place.
  • The temp compensation "Reference Temp" and "Actual Temp" fields must also respect the unit selection.
  • Persist both preferences in localStorage under keys darkroom_unit_temp ("C" or "F") and darkroom_unit_vol ("ml" or "floz").
  • Apply units consistently everywhere temperatures or volumes appear — audit every display location.

23. Process Scheduling / Countdown to Session

What: Set a future start time and get a browser notification when it's time to begin.

Implementation:

  • In the Save/Load section, add a "⏰ Schedule Session" button (secondary, small).
  • Opens a small inline form: a datetime-local input ("Start at:") and a "Set Reminder" button.
  • On submit: use setTimeout (or a Service Worker setTimeout equivalent for background reliability) to fire a notification: "Time to start your darkroom session! {Process name} is ready." at the scheduled time.
  • Show a persistent small banner below the Save/Load section when a session is scheduled: "Session scheduled for {time}. [Cancel]".
  • On cancel or on page reload: clear the scheduled notification. Persist the scheduled time in localStorage under key darkroom_scheduled (ISO string or null) so it survives a refresh.
  • If the scheduled time has already passed on page load, clear it silently.
  • Requires notification permission (same path as Feature 10).

Implementation Order

Implement in this order to minimize integration risk:

  1. Accessibility Pass (20) — foundational, affects all elements, do this first so new elements are built correctly
  2. Safelight Mode (1) — CSS only, no data model changes
  3. Gloves Mode (5) — CSS only
  4. Wake Lock (2) — purely additive to timer start/stop events
  5. Countdown Beeps (4) — additive to existing timer tick
  6. Voice Announcements (3) — additive to step transition events
  7. Drag-to-Reorder Steps (7) — modifies Setup UI, no data model change
  8. Undo/Redo (21) — wraps Setup state, no persistence
  9. Pre-Start Countdown (8) — new process field + timer pre-phase
  10. °F / oz Units (22) — display layer only
  11. Share via URL (6) — read-only serialization of existing process object
  12. Rotary/Jobo Mode (16) — new process field + display modifier
  13. Quick Presets (9) — hardcoded data, read-only modal
  14. Film Stock Database (13) — new localStorage key, new Setup section
  15. Chemistry Tracker (12) — new tab, new localStorage key
  16. Batch Roll Logging (19) — extends history entry, depends on Film Stock DB
  17. Session Notes & Label (14) — extends history entry
  18. Temp Logging & Graph (15) — extends Timer tab and history entry
  19. Session Stats (18) — reads existing history, new UI panel
  20. Enlarger Print Timer (17) — self-contained modal, no shared state
  21. PWA / Offline (11) — service worker, manifest
  22. Push Notifications (10) — requires service worker from step 21
  23. Process Scheduling (23) — requires notifications from step 22

Data Model Additions Reference

All new localStorage keys introduced by these features:

Key Type Feature
darkroom_safelight boolean 1
darkroom_voice boolean 3
darkroom_gloves boolean 5
darkroom_chemistry ChemicalEntry[] 12
darkroom_filmstocks FilmStock[] 13
darkroom_stats_open boolean 18
darkroom_unit_temp "C" | "F" 22
darkroom_unit_vol "ml" | "floz" 22
darkroom_scheduled ISO string | null 23

All new fields added to process objects (existing save/load structure):

Field Type Feature
preStartCountdown number (seconds) 8
agitationSystem "inversion" | "rotary" 16
filmStockId string | null 13

All new fields added to history entry objects:

Field Type Feature
notes string 14
filmStockName string | null 13
tempLog {t, temp, step}[] 15
rolls {label, filmStockName, ei}[] 19

Quality Checks Before Finishing

Before submitting your changes, verify:

  • All existing saved processes load without errors.
  • The timer starts, runs all steps, and completes without any regression.
  • Safelight + Gloves can both be active simultaneously with no visual corruption.
  • The app passes Lighthouse PWA checklist (installable, offline-capable, manifest valid).
  • Every button has a visible label or aria-label.
  • No new console.error or unhandled promise rejections on normal usage paths.
  • All localStorage reads use try/catch (data may be malformed from older versions).
  • The Share URL round-trips correctly: encode → copy → paste → load → all fields match.
  • Push notifications fire in a background tab.
  • Undo/Redo does not capture text-input keystrokes (only captures on blur/change events).
  • °F and fl oz display correctly in every location where temp and volume appear.
  • All preset times are accurate to published manufacturer data at 20°C.
  • The Print Timer modal is fully independent — opening/closing it does not affect main timer state.

📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

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