UI enhancements, i18n, history drawer, and requested features

This commit is contained in:
2026-06-04 00:01:32 +02:00
parent c3e167bde9
commit 3a2c738bd0
14 changed files with 598 additions and 288 deletions
+39 -25
View File
@@ -3,7 +3,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faCircleNotch,
faWandMagicSparkles,
faShuffle,
faFire,
faMicrophone,
faMusic,
@@ -89,42 +88,65 @@ export function InputPanel({
}
};
const fillExample = () => {
const ex = SURPRISE_PAIRS[Math.floor(Math.random() * SURPRISE_PAIRS.length)];
onChange({ ...values, idea: ex.idea, mood: values.mood || ex.mood, vocals: ex.vocals });
};
// "Surprise me" fills both idea AND style with a coherent pair
// "Surprise me" fills style. If idea is empty, fills a random idea too.
const handleSurpriseMe = async () => {
if (styleLoading) return;
// Try to get a random style from the server; also fill idea locally
const hasIdea = values.idea.trim().length > 0;
const ex = SURPRISE_PAIRS[Math.floor(Math.random() * SURPRISE_PAIRS.length)];
const ideaToUse = hasIdea ? values.idea : ex.idea;
const ctrl = new AbortController();
setStyleLoading("normal");
try {
const style = await randomStyle("normal", ctrl.signal);
onChange({ ...values, idea: ex.idea, style_hint: style, mood: ex.mood, vocals: ex.vocals });
const style = await randomStyle("normal", ctrl.signal, ideaToUse);
onChange({
...values,
idea: ideaToUse,
style_hint: style,
mood: hasIdea ? values.mood : ex.mood,
vocals: hasIdea ? values.vocals : ex.vocals
});
} catch (err) {
if (err instanceof DOMException && err.name === "AbortError") return;
// Fallback to local style if server fails
onChange({ ...values, idea: ex.idea, style_hint: ex.style, mood: ex.mood, vocals: ex.vocals });
onChange({
...values,
idea: ideaToUse,
style_hint: hasIdea ? values.style_hint : ex.style,
mood: hasIdea ? values.mood : ex.mood,
vocals: hasIdea ? values.vocals : ex.vocals
});
} finally {
setStyleLoading((curr) => (curr === "normal" ? null : curr));
}
};
// "Go crazy" fills both idea AND style with a wild pair
// "Go crazy" fills style wildly. If idea is empty, fills a wild idea too.
const handleGoCrazy = async () => {
if (styleLoading) return;
const hasIdea = values.idea.trim().length > 0;
const ex = CRAZY_PAIRS[Math.floor(Math.random() * CRAZY_PAIRS.length)];
const ideaToUse = hasIdea ? values.idea : ex.idea;
const ctrl = new AbortController();
setStyleLoading("crazy");
try {
const style = await randomStyle("crazy", ctrl.signal);
onChange({ ...values, idea: ex.idea, style_hint: style, mood: ex.mood, vocals: ex.vocals });
const style = await randomStyle("crazy", ctrl.signal, ideaToUse);
onChange({
...values,
idea: ideaToUse,
style_hint: style,
mood: hasIdea ? values.mood : ex.mood,
vocals: hasIdea ? values.vocals : ex.vocals
});
} catch (err) {
if (err instanceof DOMException && err.name === "AbortError") return;
onChange({ ...values, idea: ex.idea, style_hint: ex.style, mood: ex.mood, vocals: ex.vocals });
onChange({
...values,
idea: ideaToUse,
style_hint: hasIdea ? values.style_hint : ex.style,
mood: hasIdea ? values.mood : ex.mood,
vocals: hasIdea ? values.vocals : ex.vocals
});
} finally {
setStyleLoading((curr) => (curr === "crazy" ? null : curr));
}
@@ -151,15 +173,7 @@ export function InputPanel({
/>
{/* Example / Surprise / Crazy buttons */}
<div className="flex flex-wrap gap-2 pt-0.5">
<button
type="button"
onClick={fillExample}
disabled={anyLoading}
className="btn-fun bg-bg-card border-border text-fg-muted hover:text-fg hover:border-accent-primary/40"
>
<FontAwesomeIcon icon={faShuffle} className="w-3 h-3" />
{t.tryExample}
</button>
{/* Removed Try an Example button */}
<button
type="button"
onClick={handleSurpriseMe}