diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index b0b8324..f11faac 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -7,8 +7,8 @@ export function Footer() { Generate Suno song assets with AI

- All generation runs in your browser — your API key never leaves this - device. + Generation runs on the MelodyMuse server — your API key never reaches + the browser.

diff --git a/src/components/HistoryPanel.tsx b/src/components/HistoryPanel.tsx index 429e80a..91482fc 100644 --- a/src/components/HistoryPanel.tsx +++ b/src/components/HistoryPanel.tsx @@ -1,13 +1,14 @@ -import { useEffect, useState } from 'react'; -import { Clock, History, Trash2, X } from 'lucide-react'; +import { useEffect, useState } from "react"; +import { Clock, History, Trash2, X } from "lucide-react"; import { clearHistory, formatRelative, + HISTORY_UPDATED_EVENT, loadHistory, removeFromHistory, type HistoryEntry, -} from '../lib/history'; -import type { InputValues } from '../lib/types'; +} from "../lib/history"; +import type { InputValues } from "../lib/types"; interface HistoryPanelProps { onLoad: (entry: HistoryEntry) => void; @@ -17,13 +18,23 @@ export function HistoryPanel({ onLoad }: HistoryPanelProps) { const [open, setOpen] = useState(false); const [entries, setEntries] = useState([]); - // Refresh the list whenever the panel is opened, so newly-saved generations - // appear without needing a full page refresh. + // Refresh the list whenever the panel is opened. useEffect(() => { if (!open) return; setEntries(loadHistory()); }, [open]); + // And whenever the history is updated from elsewhere in the app (after a + // successful generation, or a delete/clear from a different panel). + useEffect(() => { + const handler = () => { + if (!open) return; + setEntries(loadHistory()); + }; + window.addEventListener(HISTORY_UPDATED_EVENT, handler); + return () => window.removeEventListener(HISTORY_UPDATED_EVENT, handler); + }, [open]); + if (entries.length === 0 && !open) { return null; } @@ -43,7 +54,7 @@ export function HistoryPanel({ onLoad }: HistoryPanelProps) { ({entries.length}) )} - {open ? 'Hide' : 'Show'} + {open ? "Hide" : "Show"} {open && ( @@ -130,6 +141,6 @@ function HistoryRow({ function summarizeInput(v: InputValues): string { const idea = v.idea.trim(); const max = 90; - if (idea.length <= max) return idea || '(no idea text)'; - return idea.slice(0, max - 1) + '…'; + if (idea.length <= max) return idea || "(no idea text)"; + return idea.slice(0, max - 1) + "…"; } diff --git a/src/components/InputPanel.tsx b/src/components/InputPanel.tsx index 0555469..0dca226 100644 --- a/src/components/InputPanel.tsx +++ b/src/components/InputPanel.tsx @@ -228,6 +228,7 @@ export function InputPanel({ loading={styleLoading} onChange={(v) => set("style_hint", v)} onRandom={handleStyleRandom} + onCmdEnter={onKeyDown} />
@@ -324,7 +325,15 @@ interface StyleFieldProps { onRandom: (mode: "normal" | "crazy") => void; } -function StyleField({ value, loading, onChange, onRandom }: StyleFieldProps) { +function StyleField({ + value, + loading, + onChange, + onRandom, + onCmdEnter, +}: StyleFieldProps & { + onCmdEnter: (e: KeyboardEvent) => void; +}) { return (