's'
This commit is contained in:
@@ -71,6 +71,7 @@ export function LiveYoutubeUnmannedView({
|
||||
const [proUrlDraft, setProUrlDraft] = useState("");
|
||||
const [urlAutoRefresh, setUrlAutoRefresh] = useState(true);
|
||||
const [urlReloading, setUrlReloading] = useState(false);
|
||||
const [urlOptimizing, setUrlOptimizing] = useState(false);
|
||||
const [urlFetchNote, setUrlFetchNote] = useState<string | null>(null);
|
||||
const urlListDirtyRef = useRef(false);
|
||||
|
||||
@@ -260,6 +261,32 @@ export function LiveYoutubeUnmannedView({
|
||||
await saveYoutubeIniToServer(body);
|
||||
};
|
||||
|
||||
const applyYoutubeBalancedPreset = async () => {
|
||||
setYtIniLoading(true);
|
||||
setYtIniStatus(null);
|
||||
try {
|
||||
const source = youtubeIniText || buildYoutubeIniFromFields(ytFields);
|
||||
const data = await fetchJson<{ message?: string; content?: string }>("/config_optimize", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
root: "app-config",
|
||||
path: "youtube.ini",
|
||||
content: source,
|
||||
action: "youtube_balanced_preset",
|
||||
}),
|
||||
});
|
||||
const next = data.content ?? source;
|
||||
setYoutubeIniText(next);
|
||||
setYtFields(parseYoutubeIniFields(next));
|
||||
setYtIniStatus(data.message || t("已应用 YouTube 预设", "Applied YouTube preset"));
|
||||
} catch (e) {
|
||||
setYtIniStatus((e as Error).message);
|
||||
} finally {
|
||||
setYtIniLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const syncFieldsFromText = () => {
|
||||
setYtFields(parseYoutubeIniFields(youtubeIniText));
|
||||
setYtIniStatus(t("已从下方原文同步到表单", "Synced from raw"));
|
||||
@@ -292,6 +319,36 @@ export function LiveYoutubeUnmannedView({
|
||||
}
|
||||
};
|
||||
|
||||
const dedupeUrlDraft = async () => {
|
||||
const source = mode === "single" ? urlConfig : proUrlDraft;
|
||||
setUrlOptimizing(true);
|
||||
setUrlFetchNote(null);
|
||||
try {
|
||||
const data = await fetchJson<{ message?: string; content?: string }>("/config_optimize", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
root: "app-config",
|
||||
path: "URL_config.ini",
|
||||
content: source,
|
||||
action: "dedupe_urls",
|
||||
}),
|
||||
});
|
||||
const next = data.content ?? source;
|
||||
if (mode === "single") setUrlConfig(next);
|
||||
else {
|
||||
setProUrlDraft(next);
|
||||
if (active) updateActive({ urlLines: next });
|
||||
}
|
||||
urlListDirtyRef.current = true;
|
||||
setUrlFetchNote(data.message || t("已去重当前 URL 列表", "Deduplicated current URL list"));
|
||||
} catch (e) {
|
||||
setUrlFetchNote((e as Error).message);
|
||||
} finally {
|
||||
setUrlOptimizing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const pushProStreamKeyToServer = async () => {
|
||||
if (!active) return;
|
||||
const base = parseYoutubeIniFields(youtubeIniText || buildYoutubeIniFromFields(ytFields));
|
||||
@@ -306,7 +363,7 @@ export function LiveYoutubeUnmannedView({
|
||||
updateActive({ streamKey: f.key });
|
||||
};
|
||||
|
||||
const lock = busy || ytIniLoading || urlReloading;
|
||||
const lock = busy || ytIniLoading || urlReloading || urlOptimizing;
|
||||
|
||||
const urlToolbar = (
|
||||
<div className="mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400">
|
||||
@@ -327,6 +384,14 @@ export function LiveYoutubeUnmannedView({
|
||||
>
|
||||
{t("手动重新读取", "Reload from server")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
disabled={lock}
|
||||
onClick={() => void dedupeUrlDraft()}
|
||||
className="rounded-lg border border-cyan-500/20 bg-cyan-500/10 px-3 py-1.5 text-cyan-100 hover:bg-cyan-500/15"
|
||||
>
|
||||
{urlOptimizing ? t("去重中...", "Deduplicating...") : t("智能去重", "Deduplicate")}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -564,6 +629,14 @@ export function LiveYoutubeUnmannedView({
|
||||
{ytIniLoading ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
|
||||
{t("保存 youtube.ini", "Save youtube.ini")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
disabled={lock}
|
||||
onClick={() => void applyYoutubeBalancedPreset()}
|
||||
className="rounded-xl border border-cyan-500/20 bg-cyan-500/10 px-4 py-2 text-sm text-cyan-100"
|
||||
>
|
||||
{t("平衡预设", "Balanced preset")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
disabled={lock}
|
||||
|
||||
Reference in New Issue
Block a user