OptionsModal.tsx
⎇
Raw
1import { type Accessor, createEffect, createSignal, type Setter, on } from "solid-js";
2import type { AppOptions } from "../types";
3import "./OptionsModal.css";
4import "./Dialog.css";
5import "toastify-js/src/toastify.css";
6import { toast } from "../utils";
7import { MediaFormat } from "music-server-shared/types";
8
9interface OptionsModalProps {
10 showOptions: Accessor<boolean>;
11 setShowOptions: Setter<boolean>;
12 options: Accessor<AppOptions>;
13 setOptions: (options: AppOptions) => void;
14}
15
16export default function OptionsModal(props: OptionsModalProps) {
17 const [newOptions, setNewOptions] = createSignal<AppOptions>(props.options());
18 let dialogElement!: HTMLDialogElement;
19 let formElement!: HTMLFormElement;
20
21 createEffect(
22 on(props.showOptions, () => {
23 if (props.showOptions()) {
24 dialogElement.showModal();
25 setNewOptions({ ...props.options() });
26 }
27 }),
28 );
29
30 function handleSave() {
31 if (!formElement.reportValidity()) return;
32 toast("Saved changes", "sucess");
33 props.setOptions(newOptions());
34 handleClose();
35 }
36
37 function handleClose() {
38 dialogElement.close();
39 props.setShowOptions(false);
40 }
41
42 async function deleteServerCache() {
43 const response = await fetch("/reset-cache", { method: "POST" }).catch(() => {});
44 if (!response || response.status !== 200) {
45 toast("Clearing server cache failed", "error");
46 } else {
47 toast("Server cache cleared", "info");
48 }
49 }
50
51 return (
52 <dialog ref={dialogElement} onClose={handleClose}>
53 <form class="option-content" ref={formElement}>
54 <div class="title">Player Options</div>
55 <div>
56 <label for="remember-dir-checkbox">Remember last directory:</label>
57 <input
58 id="remember-dir-checkbox"
59 type="checkbox"
60 checked={newOptions()?.rememberDir}
61 onChange={(e) => setNewOptions({ ...newOptions(), rememberDir: e.target.checked })}
62 />
63 </div>
64 <div>
65 <label for="transcoding-checkbox">Enable transcoding:</label>
66 <input
67 id="transcoding-checkbox"
68 type="checkbox"
69 checked={newOptions()?.enableTranscoding}
70 onChange={(e) => setNewOptions({ ...newOptions(), enableTranscoding: e.target.checked })}
71 />
72 </div>
73 <div>
74 <label for="bitrate-select">Bitrate:</label>
75 <select
76 id="bitrate-select"
77 value={newOptions()?.bitrate}
78 onChange={(e) =>
79 setNewOptions({
80 ...newOptions(),
81 bitrate: Number.parseInt(e.target.value),
82 })
83 }
84 disabled={!newOptions()?.enableTranscoding}
85 >
86 <option value="32000">32 kbps</option>
87 <option value="48000">48 kbps</option>
88 <option value="64000">64 kbps</option>
89 <option value="96000">96 kbps</option>
90 <option value="128000">128 kbps</option>
91 <option value="192000">192 kbps</option>
92 <option value="320000">320 kbps</option>
93 </select>
94 </div>
95 <div>
96 <label for="codec-select">Format:</label>
97 <select
98 id="codec-select"
99 value={newOptions()?.format}
100 onChange={(e) =>
101 setNewOptions({
102 ...newOptions(),
103 format: e.target.value as MediaFormat,
104 })
105 }
106 disabled={!newOptions()?.enableTranscoding}
107 >
108 <option>{MediaFormat["opus/ogg"]}</option>
109 <option>{MediaFormat["opus/webm"]}</option>
110 <option>{MediaFormat.mp3}</option>
111 <option>{MediaFormat.vorbis}</option>
112 </select>
113 </div>
114 <div>
115 <label for="max-downloads-input">Max concurrent downloads:</label>
116 <input
117 id="max-downloads-input"
118 type="number"
119 min={0}
120 required
121 value={newOptions()?.maxDownloads}
122 onChange={(e) => setNewOptions({ ...newOptions(), maxDownloads: e.target.valueAsNumber })}
123 />
124 </div>
125 <div>
126 <label for="max-transcodes-input">Max concurrent transcodes:</label>
127 <input
128 id="max-transcodes-input"
129 type="number"
130 min={0}
131 required
132 value={newOptions()?.maxTranscodes}
133 onChange={(e) => setNewOptions({ ...newOptions(), maxTranscodes: e.target.valueAsNumber })}
134 />
135 </div>
136 <div class="option-buttons">
137 <button title="Clear server caches" type="button" class="cache-button" onclick={deleteServerCache}>
138 Clear server caches
139 </button>
140 <button title="Save settings" type="button" onClick={handleSave}>
141 Save
142 </button>
143 <button title="Cancel changes settings" type="button" class="cancel-button" onClick={handleClose}>
144 Cancel
145 </button>
146 </div>
147 </form>
148 </dialog>
149 );
150}
151