Replace the synthesized WAV blips with curated mp3 effects:
- error ("haiya") plays on LLM-down/timeout and save failures, debounced
and on-transition-only, with a reassuring bilingual bubble
- milestone (Chinese fanfare) now fires every 100 words
- all other notifications draw from a rotating pop pool that never repeats
the last sound, so batches of suggestions/tips stay lively
playPop() replaces the per-suggestion-type sound map; thread llmDown through
PetalCompanion -> useCompanion for the error cue. Old synth WAVs removed.
Claude-Session: https://claude.ai/code/session_016Yr6jELuRc7hyzYLccQKZd
73 lines
3.6 KiB
TypeScript
73 lines
3.6 KiB
TypeScript
// Bilingual companion copy — Mandarin first (she writes/reads in Mandarin), with
|
||
// a warm English subtitle. Kept gentle and encouraging, never scolding. The
|
||
// bubble renders zh prominently and en underneath. (Spec north star: CJK is
|
||
// first-class; Ask Petal & companion answer in Mandarin.)
|
||
|
||
export interface Line {
|
||
zh: string
|
||
en: string
|
||
}
|
||
|
||
// Played when a suggestion is accepted or a milestone hits — pure warmth.
|
||
export const ENCOURAGEMENTS: Line[] = [
|
||
{ zh: '好棒!这一句更顺了 🌸', en: 'Lovely — that reads so much smoother now.' },
|
||
{ zh: '你写得越来越好了 ✨', en: "You're getting better and better." },
|
||
{ zh: '我很喜欢这个改法 💕', en: 'I really like that change.' },
|
||
{ zh: '继续保持,加油!', en: 'Keep going — you’ve got this!' },
|
||
{ zh: '嗯嗯,这样清楚多了 👍', en: 'Mm, that’s much clearer.' },
|
||
]
|
||
|
||
// Gentle, generic writing/ESL tips — the fallback when the rules-based prose
|
||
// checker (prose.ts) finds nothing concrete to point at in her current text.
|
||
export const TIPS: Line[] = [
|
||
{ zh: '小贴士:英文句子短一点,会更清楚哦。', en: 'Tip: shorter English sentences often read clearer.' },
|
||
{ zh: '别忘了冠词 “the” 和 “a” 哦。', en: "Don't forget articles like “the” and “a”." },
|
||
{ zh: '过去的事情用过去式:go → went。', en: 'For the past, use past tense: go → went.' },
|
||
{ zh: '读出声音,能帮你发现奇怪的地方。', en: 'Reading aloud helps you catch awkward spots.' },
|
||
{ zh: '一个段落讲一个想法就好。', en: 'One idea per paragraph keeps it tidy.' },
|
||
{ zh: '不确定的地方,问问我就好啦 ✨', en: 'Not sure about something? Just ask me. ✨' },
|
||
{ zh: '复数别忘了加 s:two apples 🍎', en: 'Plurals take an “s”: two apples 🍎' },
|
||
]
|
||
|
||
// Shown after a long stretch of continuous writing.
|
||
export const BREAKS: Line[] = [
|
||
{ zh: '写了好一会儿啦,起来走走,让眼睛休息一下 🍵', en: "You've been writing a while — stretch and rest your eyes. 🍵" },
|
||
{ zh: '喝口水,休息五分钟好不好?', en: 'Sip some water and take five?' },
|
||
{ zh: '看看远方,放松一下眼睛 🌿', en: 'Look into the distance for a moment — give your eyes a break. 🌿' },
|
||
]
|
||
|
||
// First hello when the app opens.
|
||
export const GREETING: Line = {
|
||
zh: '嗨~我在这儿陪你写作哦 🐱',
|
||
en: "Hi! I'm right here keeping you company. 🐱",
|
||
}
|
||
|
||
// Welcome-back nudge after she returns from an idle pause.
|
||
export const WELCOME_BACK: Line = {
|
||
zh: '欢迎回来 ✨ 我们继续吧!',
|
||
en: 'Welcome back ✨ let’s keep going!',
|
||
}
|
||
|
||
// Gentle "haiya, something went wrong" lines — paired with the error sound when
|
||
// the LLM is unreachable or a save fails. Never alarming, always reassuring.
|
||
export const ERRORS: Line[] = [
|
||
{ zh: '哎呀~出了点小问题,你的字都还在哦。', en: 'Oops — a little hiccup, but your words are safe.' },
|
||
{ zh: '哎呀,我这边卡了一下,马上就好。', en: 'Haiya, I got stuck for a sec — back in a moment.' },
|
||
{ zh: '别担心,等一下再试试看 🍵', en: "Don't worry — let's try again in a bit. 🍵" },
|
||
]
|
||
|
||
// Word-count milestones worth a little cheer — every 100 words, on up.
|
||
export const MILESTONES = Array.from({ length: 100 }, (_, i) => (i + 1) * 100)
|
||
|
||
export function milestoneLine(n: number): Line {
|
||
return {
|
||
zh: `哇!已经 ${n} 个词了,太厉害了 🎉`,
|
||
en: `Wow — ${n} words already! Amazing. 🎉`,
|
||
}
|
||
}
|
||
|
||
// Deterministic-enough random pick (Math.random is fine in the browser runtime).
|
||
export function pick<T>(arr: T[]): T {
|
||
return arr[Math.floor(Math.random() * arr.length)]
|
||
}
|