Fixed minor issues with the Archetypes

This commit is contained in:
2026-02-22 19:38:57 +02:00
parent ba89102f71
commit 9437307e0f
4 changed files with 61 additions and 23 deletions

View File

@@ -196,7 +196,8 @@ async def build_binary(melody_id: str) -> BuiltMelodyInDB:
_ensure_storage_dir()
values = steps_string_to_values(row["steps"])
bsm_path = STORAGE_DIR / f"{melody_id}.bsm"
file_name = f"{row['pid']}.bsm" if row.get("pid") else f"{melody_id}.bsm"
bsm_path = STORAGE_DIR / file_name
with open(bsm_path, "wb") as f:
for value in values:
value = value & 0xFFFF

View File

@@ -459,12 +459,12 @@ export default function MelodyDetail() {
const binaryFilename = `${binaryPid}.bsm`;
// Derive a display name: for firebase URLs extract the filename portion
let displayName = binaryFilename;
let downloadName = binaryFilename;
if (!files.binary_url && melody.url) {
try {
const urlPath = decodeURIComponent(new URL(melody.url).pathname);
const parts = urlPath.split("/");
displayName = parts[parts.length - 1] || binaryFilename;
downloadName = parts[parts.length - 1] || binaryFilename;
} catch { /* keep binaryFilename */ }
}
@@ -484,7 +484,7 @@ export default function MelodyDetail() {
const objectUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = objectUrl;
a.download = displayName;
a.download = downloadName;
a.click();
URL.revokeObjectURL(objectUrl);
} catch (err) {
@@ -493,18 +493,37 @@ export default function MelodyDetail() {
};
return (
<span className="inline-flex items-center gap-2">
<a
href={binaryUrl}
onClick={handleDownload}
className="underline"
style={{ color: "var(--accent)" }}
>
{displayName}
</a>
{!files.binary_url && melody.url && (
<span className="text-xs px-1.5 py-0.5 rounded" style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-muted)" }}>
via URL
<span className="inline-flex flex-col gap-0.5">
<span className="inline-flex items-center gap-2">
{builtMelody?.name ? (
<strong style={{ color: "var(--text-heading)" }}>{builtMelody.name}</strong>
) : (
<a
href={binaryUrl}
onClick={handleDownload}
className="underline"
style={{ color: "var(--accent)" }}
>
{downloadName}
</a>
)}
{!files.binary_url && melody.url && (
<span className="text-xs px-1.5 py-0.5 rounded" style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-muted)" }}>
via URL
</span>
)}
</span>
{builtMelody?.name && (
<span className="text-xs" style={{ color: "var(--text-muted)" }}>
file:{" "}
<a
href={binaryUrl}
onClick={handleDownload}
className="underline font-mono"
style={{ color: "var(--accent)" }}
>
{downloadName}
</a>
</span>
)}
</span>

View File

@@ -93,6 +93,7 @@ export default function MelodyForm() {
const [showPlayback, setShowPlayback] = useState(false);
const [builtMelody, setBuiltMelody] = useState(null);
const [assignedBinaryName, setAssignedBinaryName] = useState(null);
const [assignedBinaryPid, setAssignedBinaryPid] = useState(null);
// Metadata / Admin Notes
const [adminNotes, setAdminNotes] = useState([]);
@@ -145,6 +146,7 @@ export default function MelodyForm() {
const bm = await api.get(`/builder/melodies/for-melody/${id}`);
setBuiltMelody(bm || null);
setAssignedBinaryName(bm?.name || null);
setAssignedBinaryPid(bm?.pid || null);
} catch {
setBuiltMelody(null);
}
@@ -391,7 +393,12 @@ export default function MelodyForm() {
<>
<button
type="button"
onClick={() => navigate("/melodies")}
onClick={async () => {
if (savedMelodyId) {
try { await api.delete(`/melodies/${savedMelodyId}`); } catch { /* best-effort */ }
}
navigate("/melodies");
}}
className="px-4 py-2 text-sm rounded-md transition-colors"
style={{ backgroundColor: "var(--btn-neutral)", color: "var(--text-white)" }}
>
@@ -648,11 +655,20 @@ export default function MelodyForm() {
<div>
<label className="block text-sm font-medium mb-1" style={labelStyle}>Binary File (.bsm / .bin)</label>
{existingFiles.binary_url && (
<p className="text-xs mb-1" style={{ color: "var(--success)" }}>
{assignedBinaryName
? <><strong>{assignedBinaryName}.bsm</strong> is set. Selecting a new file will replace it.</>
: "Current file uploaded. Selecting a new file will replace it."}
</p>
<div className="text-xs mb-1" style={{ color: "var(--success)" }}>
{assignedBinaryName ? (
<>
<p><strong>{assignedBinaryName}</strong> has been assigned. Selecting a new file will replace it.</p>
{assignedBinaryPid && (
<p className="mt-0.5" style={{ color: "var(--text-muted)" }}>
filename: <span className="font-mono">{assignedBinaryPid}.bsm</span>
</p>
)}
</>
) : (
<p>Current file uploaded. Selecting a new file will replace it.</p>
)}
</div>
)}
<input type="file" accept=".bin,.bsm" onChange={(e) => setBinaryFile(e.target.files[0] || null)} className="w-full text-sm" style={mutedStyle} />
<div className="flex gap-2 mt-2">
@@ -806,6 +822,7 @@ export default function MelodyForm() {
onSuccess={(archetype) => {
setShowSelectBuilt(false);
setAssignedBinaryName(archetype.name);
setAssignedBinaryPid(archetype.pid || null);
if (!pid.trim() && archetype.pid) setPid(archetype.pid);
if (archetype.steps != null) updateInfo("steps", archetype.steps);
if (archetype.totalNotes != null) updateInfo("totalNotes", archetype.totalNotes);
@@ -838,6 +855,7 @@ export default function MelodyForm() {
onSuccess={(archetype) => {
setShowBuildOnTheFly(false);
setAssignedBinaryName(archetype.name);
setAssignedBinaryPid(archetype.pid || null);
if (!pid.trim() && archetype.pid) setPid(archetype.pid);
if (archetype.steps != null) updateInfo("steps", archetype.steps);
if (archetype.totalNotes != null) updateInfo("totalNotes", archetype.totalNotes);

View File

@@ -54,7 +54,7 @@ export default function SelectArchetypeModal({ open, melodyId, currentMelody, cu
});
if (!res.ok) throw new Error(`Failed to download binary: ${res.statusText}`);
const blob = await res.blob();
const file = new File([blob], `${archetype.name}.bsm`, { type: "application/octet-stream" });
const file = new File([blob], `${archetype.pid || archetype.name}.bsm`, { type: "application/octet-stream" });
await api.upload(`/melodies/${melodyId}/upload/binary`, file);
await api.post(`/builder/melodies/${archetype.id}/assign?firestore_melody_id=${melodyId}`);