Feature 15: Recipe Detail and Kitchen Reading Mode (#162)
CI / ci (push) Successful in 6m44s
CI / ci (push) Successful in 6m44s
Co-authored-by: orchestrator-agent <20+orchestrator-agent@code.cubecraftcreations.com>
This commit was merged in pull request #162.
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
import { useState } from 'react'
|
||||
|
||||
// TEXT_SIZE_KEY is the localStorage key remembering, on this device, the text
|
||||
// size chosen in Kitchen reading mode.
|
||||
export const TEXT_SIZE_KEY = 'mealquest.readingTextSize'
|
||||
|
||||
export const TEXT_SIZES = ['small', 'medium', 'large'] as const
|
||||
|
||||
export type TextSize = (typeof TEXT_SIZES)[number]
|
||||
|
||||
// DEFAULT_TEXT_SIZE is the size of a device that has never chosen one: the
|
||||
// handoff's 18 px ingredients and steps.
|
||||
export const DEFAULT_TEXT_SIZE: TextSize = 'medium'
|
||||
|
||||
// TextSizeState is the text size, and the storage failure, if any, that
|
||||
// stopped us reading or saving it.
|
||||
type TextSizeState = {
|
||||
size: TextSize
|
||||
failure: { action: 'read' | 'write'; message: string } | null
|
||||
}
|
||||
|
||||
function isTextSize(value: string): value is TextSize {
|
||||
return (TEXT_SIZES as readonly string[]).includes(value)
|
||||
}
|
||||
|
||||
// Storage can be unavailable (blocked by the browser or privacy settings), in
|
||||
// which case using it throws, and can hold a value MealQuest did not save.
|
||||
// Either is reported, never treated as a remembered size.
|
||||
function readTextSize(): TextSizeState {
|
||||
try {
|
||||
const saved = window.localStorage.getItem(TEXT_SIZE_KEY)
|
||||
if (saved === null) return { size: DEFAULT_TEXT_SIZE, failure: null }
|
||||
if (!isTextSize(saved)) throw new Error(`"${saved}" is not a text size MealQuest saved`)
|
||||
return { size: saved, failure: null }
|
||||
} catch (err) {
|
||||
return { size: DEFAULT_TEXT_SIZE, failure: { action: 'read', message: String(err) } }
|
||||
}
|
||||
}
|
||||
|
||||
function writeTextSize(size: TextSize): TextSizeState {
|
||||
try {
|
||||
window.localStorage.setItem(TEXT_SIZE_KEY, size)
|
||||
return { size, failure: null }
|
||||
} catch (err) {
|
||||
return { size, failure: { action: 'write', message: String(err) } }
|
||||
}
|
||||
}
|
||||
|
||||
export const textSizeFailureText = {
|
||||
read: 'Could not read the text size chosen on this device',
|
||||
write: 'Could not remember the text size on this device',
|
||||
}
|
||||
|
||||
// useTextSize is Kitchen reading mode's text size on this device: the size,
|
||||
// the storage failure if any, choose, which saves a size, and retry, which
|
||||
// reads or saves again whatever failed. A size that could not be saved is
|
||||
// still used until the screen is left.
|
||||
export function useTextSize() {
|
||||
const [state, setState] = useState<TextSizeState>(readTextSize)
|
||||
const choose = (size: TextSize) => setState(writeTextSize(size))
|
||||
const retry = () => setState(state.failure?.action === 'write' ? writeTextSize(state.size) : readTextSize())
|
||||
return { ...state, choose, retry }
|
||||
}
|
||||
Reference in New Issue
Block a user