PageSourceSearch

https://www.hamienet.com/assets/SoundfontUploadPage-C9Pu1znK.js

js hamienet.com collected 2026-09-24 18:59:50 UTC 14,221 bytes, 235 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { a as api } from "./index-D0Bmh-UX.js";
3import { d4 as ShieldCheck, b1 as CircleAlert, bv as CircleCheckBig, b2 as Upload, cG as Tag, aW as X } from "./vendor-dVNaLJx_.js";
4import "./vendor-i18n-R-bMoYp_.js";
5const SoundfontUploadPage = ({ isAdmin, onNavigate }) => {
6  const fileInputRef = reactExports.useRef(null);
7  const [file, setFile] = reactExports.useState(null);
8  const [name, setName] = reactExports.useState("");
9  const [description, setDescription] = reactExports.useState("");
10  const [tags, setTags] = reactExports.useState([]);
11  const [tagInput, setTagInput] = reactExports.useState("");
12  const [eulaAccepted, setEulaAccepted] = reactExports.useState(false);
13  const [uploading, setUploading] = reactExports.useState(false);
14  const [error, setError] = reactExports.useState(null);
15  const handleFileSelect = (e) => {
16    if (e.target.files && e.target.files.length > 0) {
17      const selected = e.target.files[0];
18      const ext = selected.name.toLowerCase();
19      if (ext.endsWith(".sf2") || ext.endsWith(".sf3")) {
20        setFile(selected);
21        setError(null);
22        if (!name) {
23          setName(selected.name.replace(/\.h?sf[23]$/i, ""));
24        }
25      } else {
26        setFile(null);
27        setError("Only .sf2 and .sf3 files are supported.");
28      }
29    }
30  };
31  const handleAddTag = () => {
32    const val = tagInput.trim().toLowerCase();
33    if (val && !tags.includes(val) && tags.length < 5) {
34      setTags([...tags, val]);
35      setTagInput("");
36    }
37  };
38  const handleRemoveTag = (t) => {
39    setTags(tags.filter((tag) => tag !== t));
40  };
41  const handleSubmit = async (e) => {
42    var _a, _b;
43    e.preventDefault();
44    if (!file) {
45      setError("Please select a soundfont file.");
46      return;
47    }
48    if (!eulaAccepted) {
49      setError("You must accept the EULA to upload a soundfont.");
50      return;
51    }
52    setUploading(true);
53    setError(null);
54    try {
55      const formData = new FormData();
56      formData.append("soundfont", file);
57      formData.append("name", name);
58      formData.append("description", description);
59      formData.append("tags", JSON.stringify(tags));
60      formData.append("eulaAccepted", "true");
61      const res = await api.uploadSoundfont(formData);
62      if (res.success) {
63        onNavigate(`/soundfont/${res.soundfont.slug}`);
64      } else {
65        throw new Error("Upload failed");
66      }
67    } catch (err) {
68      console.error("Upload error:", err);
69      setError(((_b = (_a = err.response) == null ? void 0 : _a.data) == null ? void 0 : _b.error) || err.message || "An error occurred during upload.");
70      setUploading(false);
71    }
72  };
73  if (!isAdmin) {
74    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-4xl mx-auto py-24 px-6 text-center", children: [
75      /* @__PURE__ */ jsxRuntimeExports.jsx(ShieldCheck, { className: "w-24 h-24 mx-auto text-zinc-300 mb-6" }),
76      /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-3xl font-black mb-4", children: "Coming Soon" })
77    ] });
78  }
79  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-3xl mx-auto px-4 py-12", children: [
80    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-8 text-center", children: [
81      /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-4xl font-black text-zinc-900 dark:text-white mb-4", children: "Share a Soundfont" }),
82      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-lg text-zinc-600 dark:text-zinc-400 max-w-xl mx-auto", children: "Contribute to the community gallery. We'll extract, compress, and optimize it for web playback automatically." })
83    ] }),
84    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-white dark:bg-zinc-900 rounded-3xl shadow-xl overflow-hidden border border-zinc-200 dark:border-zinc-800", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("form", { onSubmit: handleSubmit, className: "p-8", children: [
85      error && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-8 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-2xl p-4 flex items-start gap-3 text-red-700 dark:text-red-400", children: [
86        /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "w-5 h-5 shrink-0 mt-0.5" }),
87        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium", children: error })
88      ] }),
89      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-8", children: [
90        /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-bold text-zinc-700 dark:text-zinc-300 mb-2", children: "Soundfont File (.sf2, .sf3)" }),
91        /* @__PURE__ */ jsxRuntimeExports.jsxs(
92          "div",
93          {
94            className: `border-2 border-dashed rounded-2xl p-8 text-center transition-all ${file ? "border-indigo-500 bg-indigo-50 dark:bg-indigo-900/20" : "border-zinc-300 dark:border-zinc-700 hover:border-indigo-400 hover:bg-zinc-50 dark:hover:bg-zinc-800/50"}`,
95            children: [
96              /* @__PURE__ */ jsxRuntimeExports.jsx(
97                "input",
98                {
99                  type: "file",
100                  ref: fileInputRef,
101                  onChange: handleFileSelect,
102                  accept: ".sf2,.sf3",
103                  className: "hidden"
104                }
105              ),
106              file ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center", children: [
107                /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "w-12 h-12 text-indigo-500 mb-3" }),
108                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-bold text-zinc-900 dark:text-white mb-1", children: file.name }),
109                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-zinc-500 font-medium", children: [
110                  (file.size / (1024 * 1024)).toFixed(1),
111                  " MB"
112                ] }),
113                /* @__PURE__ */ jsxRuntimeExports.jsx(
114                  "button",
115                  {
116                    type: "button",
117                    onClick: () => setFile(null),
118                    className: "mt-4 text-xs font-bold text-red-500 hover:text-red-600 transition-colors",
119                    children: "Remove file"
120                  }
121                )
122              ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center cursor-pointer", onClick: () => {
123                var _a;
124                return (_a = fileInputRef.current) == null ? void 0 : _a.click();
125              }, children: [
126                /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "w-12 h-12 text-zinc-400 mb-3" }),
127                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-bold text-zinc-900 dark:text-white mb-1", children: "Click to select a file" }),
128                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm text-zinc-500 font-medium", children: "Max 500MB. SF2 or SF3 formats only." })
129              ] })
130            ]
131          }
132        )
133      ] }),
134      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
135        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
136          /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-bold text-zinc-700 dark:text-zinc-300 mb-2", children: "Display Name" }),
137          /* @__PURE__ */ jsxRuntimeExports.jsx(
138            "input",
139            {
140              type: "text",
141              required: true,
142              value: name,
143              onChange: (e) => setName(e.target.value),
144              className: "w-full bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl px-4 py-3 text-zinc-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all font-medium",
145              placeholder: "e.g., Yamaha Grand Piano HQ"
146            }
147          )
148        ] }),
149        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
150          /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-bold text-zinc-700 dark:text-zinc-300 mb-2", children: "Description" }),
151          /* @__PURE__ */ jsxRuntimeExports.jsx(
152            "textarea",
153            {
154              value: description,
155              onChange: (e) => setDescription(e.target.value),
156              rows: 4,
157              className: "w-full bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl px-4 py-3 text-zinc-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all font-medium resize-none",
158              placeholder: "Describe the origin, quality, and instruments included in this soundfont..."
159            }
160          )
161        ] }),
162        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
163          /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-bold text-zinc-700 dark:text-zinc-300 mb-2", children: "Tags (Max 5)" }),
164          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
165            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex-1", children: [
166              /* @__PURE__ */ jsxRuntimeExports.jsx(Tag, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-zinc-400" }),
167              /* @__PURE__ */ jsxRuntimeExports.jsx(
168                "input",
169                {
170                  type: "text",
171                  value: tagInput,
172                  onChange: (e) => setTagInput(e.target.value),
173                  onKeyDown: (e) => e.key === "Enter" && (e.preventDefault(), handleAddTag()),
174                  disabled: tags.length >= 5,
175                  className: "w-full bg-zinc-50 dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-xl pl-10 pr-4 py-3 text-zinc-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all font-medium",
176                  placeholder: tags.length >= 5 ? "Tag limit reached" : "Add a tag (e.g. piano, 8-bit, orchestral) and press Enter"
177                }
178              )
179            ] }),
180            /* @__PURE__ */ jsxRuntimeExports.jsx(
181              "button",
182              {
183                type: "button",
184                onClick: handleAddTag,
185                disabled: tags.length >= 5 || !tagInput.trim(),
186                className: "px-6 py-3 bg-zinc-200 dark:bg-zinc-700 text-zinc-900 dark:text-white font-bold rounded-xl hover:bg-zinc-300 dark:hover:bg-zinc-600 transition-all disabled:opacity-50 disabled:cursor-not-allowed",
187                children: "Add"
188              }
189            )
190          ] }),
191          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-2", children: tags.map((tag) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 bg-indigo-50 dark:bg-indigo-900/30 text-indigo-700 dark:text-indigo-400 px-3 py-1.5 rounded-lg text-sm font-bold", children: [
192            "#",
193            tag,
194            /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: () => handleRemoveTag(tag), className: "ml-1 text-indigo-400 hover:text-indigo-600 dark:hover:text-indigo-200 transition-colors", children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })
195          ] }, tag)) })
196        ] }),
197        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pt-6 border-t border-zinc-100 dark:border-zinc-800", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-start gap-3 cursor-pointer group", children: [
198          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "relative flex items-center justify-center mt-0.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
199            "input",
200            {
201              type: "checkbox",
202              required: true,
203              checked: eulaAccepted,
204              onChange: (e) => setEulaAccepted(e.target.checked),
205              className: "w-5 h-5 rounded border-zinc-300 dark:border-zinc-600 text-indigo-600 focus:ring-indigo-500 dark:bg-zinc-800 transition-colors cursor-pointer"
206            }
207          ) }),
208          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm font-medium text-zinc-600 dark:text-zinc-400 leading-relaxed", children: [
209            "I confirm that I have the right to share this soundfont, and it does not violate any copyright or licensing agreements. I agree to the ",
210            /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "#", className: "text-indigo-600 dark:text-indigo-400 hover:underline", children: "Community Guidelines" }),
211            "."
212          ] })
213        ] }) })
214      ] }),
215      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-8 pt-8 border-t border-zinc-100 dark:border-zinc-800 flex justify-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
216        "button",
217        {
218          type: "submit",
219          disabled: uploading || !file || !eulaAccepted,
220          className: `flex items-center justify-center gap-2 px-10 py-4 font-bold rounded-2xl transition-all ${uploading || !file || !eulaAccepted ? "bg-zinc-200 dark:bg-zinc-800 text-zinc-500 cursor-not-allowed" : "bg-indigo-600 hover:bg-indigo-700 text-white shadow-lg hover:shadow-indigo-500/25 hover:-translate-y-0.5 active:scale-95"}`,
221          children: uploading ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
222            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
223            "Uploading..."
224          ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
225            /* @__PURE__ */ jsxRuntimeExports.jsx(Upload, { className: "w-5 h-5" }),
226            "Upload Soundfont"
227          ] })
228        }
229      ) })
230    ] }) })
231  ] });
232};
233export {
234  SoundfontUploadPage as default
235};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.