feat: complete legacy UI and playout parity migration
This commit is contained in:
172
src/MBN_STOCK_WEBVIEW.LegacyParityApp/Web/playout-ui.js
Normal file
172
src/MBN_STOCK_WEBVIEW.LegacyParityApp/Web/playout-ui.js
Normal file
@@ -0,0 +1,172 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
const webview = window.chrome && window.chrome.webview;
|
||||
const connection = document.getElementById("playout-connection-state");
|
||||
const prepare = document.getElementById("playout-prepare");
|
||||
const takeIn = document.getElementById("playout-take-in");
|
||||
const next = document.getElementById("playout-next");
|
||||
const takeOut = document.getElementById("playout-take-out");
|
||||
const backgroundNone = document.getElementById("playout-background-none");
|
||||
const backgroundFile = document.getElementById("playout-background-file");
|
||||
const backgroundName = document.getElementById("playout-background-name");
|
||||
const fadeDuration = document.getElementById("playout-fade-duration");
|
||||
const status = document.getElementById("playout-status");
|
||||
const controls = [prepare, takeIn, next, takeOut, backgroundNone,
|
||||
backgroundFile, fadeDuration];
|
||||
let currentState = null;
|
||||
let localBusy = false;
|
||||
|
||||
function hasOpenDialog() {
|
||||
return Array.from(document.querySelectorAll("[role='dialog'], [role='alertdialog']"))
|
||||
.some(function (dialog) {
|
||||
const container = dialog.closest("[hidden]");
|
||||
return !container && !dialog.hidden;
|
||||
});
|
||||
}
|
||||
|
||||
function post(type, payload) {
|
||||
if (!webview || localBusy || hasOpenDialog()) return;
|
||||
localBusy = true;
|
||||
render(currentState);
|
||||
webview.postMessage({ type: type, payload: payload || {} });
|
||||
}
|
||||
|
||||
function setAllDisabled(disabled) {
|
||||
controls.forEach(function (control) {
|
||||
if (control) control.disabled = disabled;
|
||||
});
|
||||
}
|
||||
|
||||
function phaseLabel(phase) {
|
||||
if (phase === "prepared") return "PREPARED";
|
||||
if (phase === "program") return "PROGRAM";
|
||||
return "IDLE";
|
||||
}
|
||||
|
||||
function connectionLabel(playout) {
|
||||
if (!playout) return "미연결";
|
||||
if (playout.outcomeUnknown) return "결과 불명확";
|
||||
if (playout.mode === "disabled") return "송출 비활성";
|
||||
if (playout.mode === "dryRun") return "DRY RUN";
|
||||
if (playout.isConnected) return "Tornado2 연결됨";
|
||||
if (playout.isProcessRunning) return "Tornado2 감지됨";
|
||||
return "미연결";
|
||||
}
|
||||
|
||||
function pageLabel(playout) {
|
||||
if (!playout || playout.pageCount <= 0) return "";
|
||||
return " · Page " + String(playout.pageIndexZeroBased + 1) +
|
||||
"/" + String(playout.pageCount);
|
||||
}
|
||||
|
||||
function nextLabel(playout) {
|
||||
if (!playout || playout.nextKind === "none") return "";
|
||||
return playout.nextKind === "pageNext" ? " · 다음 페이지" : " · 다음 항목";
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
currentState = state || currentState;
|
||||
const playout = currentState && currentState.playout;
|
||||
const nativeBusy = !!(currentState && currentState.isBusy) ||
|
||||
!!(playout && playout.isBusy);
|
||||
const busy = localBusy || nativeBusy;
|
||||
if (!playout) {
|
||||
connection.textContent = "미연결";
|
||||
status.textContent = "송출 엔진 상태를 사용할 수 없습니다.";
|
||||
setAllDisabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const commandAvailable = playout.isCommandAvailable === true &&
|
||||
playout.outcomeUnknown !== true;
|
||||
const hasPlaylist = Array.isArray(currentState.playlist) &&
|
||||
currentState.playlist.some(function (row) { return row.isEnabled === true; });
|
||||
const liveTakeInAllowed = playout.mode !== "live" ||
|
||||
playout.liveTakeInAllowed === true;
|
||||
const canPrepareToggle = playout.phase === "idle" ? hasPlaylist :
|
||||
playout.phase === "prepared" || playout.phase === "program";
|
||||
|
||||
connection.textContent = connectionLabel(playout);
|
||||
connection.classList.toggle("connected", playout.isConnected === true);
|
||||
connection.classList.toggle("outcome-unknown", playout.outcomeUnknown === true);
|
||||
prepare.classList.toggle("active", playout.phase !== "idle");
|
||||
prepare.disabled = busy || !commandAvailable || !canPrepareToggle ||
|
||||
playout.isPlayCompletionPending === true;
|
||||
const canTakeIn = playout.phase === "prepared" ||
|
||||
(playout.phase === "idle" && hasPlaylist);
|
||||
takeIn.disabled = busy || !commandAvailable || !liveTakeInAllowed ||
|
||||
!canTakeIn || playout.isPlayCompletionPending === true;
|
||||
next.disabled = busy || !commandAvailable ||
|
||||
playout.phase !== "program" || playout.nextKind === "none" ||
|
||||
playout.isPlayCompletionPending === true;
|
||||
takeOut.disabled = busy || !commandAvailable ||
|
||||
(playout.phase !== "prepared" && playout.phase !== "program");
|
||||
backgroundNone.disabled = busy || playout.canChangeBackground !== true;
|
||||
backgroundFile.disabled = busy || playout.canChangeBackground !== true;
|
||||
fadeDuration.disabled = busy || playout.canChangeBackground !== true;
|
||||
backgroundNone.checked = playout.backgroundEnabled !== true;
|
||||
backgroundName.value = playout.backgroundEnabled === true
|
||||
? (playout.backgroundFileName || "선택한 배경") : "배경없음";
|
||||
fadeDuration.value = String(playout.fadeDuration);
|
||||
|
||||
const scene = playout.onAirCode || playout.preparedCode;
|
||||
const sceneLabel = scene ? " · " + scene : "";
|
||||
const refresh = playout.refreshActive
|
||||
? " · 자동 갱신 " + String(playout.refreshCompletedCount) + "회" : "";
|
||||
status.textContent = phaseLabel(playout.phase) + sceneLabel +
|
||||
pageLabel(playout) + nextLabel(playout) + refresh +
|
||||
(playout.message ? " · " + playout.message : "");
|
||||
}
|
||||
|
||||
prepare.addEventListener("click", function () {
|
||||
post("prepare-playout", {});
|
||||
});
|
||||
takeIn.addEventListener("click", function () {
|
||||
post("take-in", {});
|
||||
});
|
||||
next.addEventListener("click", function () {
|
||||
post("next-playout", {});
|
||||
});
|
||||
takeOut.addEventListener("click", function () {
|
||||
post("take-out", {});
|
||||
});
|
||||
backgroundFile.addEventListener("click", function () {
|
||||
post("choose-background", {});
|
||||
});
|
||||
backgroundNone.addEventListener("change", function () {
|
||||
post("toggle-background", {});
|
||||
});
|
||||
fadeDuration.addEventListener("change", function () {
|
||||
post("set-fade-duration", { duration: Number(fadeDuration.value) });
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.repeat || hasOpenDialog()) return;
|
||||
if (event.key === "F2") {
|
||||
event.preventDefault();
|
||||
if (!backgroundFile.disabled) backgroundFile.click();
|
||||
} else if (event.key === "F3") {
|
||||
event.preventDefault();
|
||||
if (!backgroundNone.disabled) backgroundNone.click();
|
||||
} else if (event.key === "F8") {
|
||||
event.preventDefault();
|
||||
if (!takeIn.disabled) takeIn.click();
|
||||
} else if (event.key === "Escape") {
|
||||
event.preventDefault();
|
||||
if (!takeOut.disabled) takeOut.click();
|
||||
}
|
||||
});
|
||||
|
||||
if (webview) {
|
||||
webview.addEventListener("message", function (event) {
|
||||
if (event.data && event.data.type === "state" && event.data.payload) {
|
||||
localBusy = false;
|
||||
render(event.data.payload);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setAllDisabled(true);
|
||||
status.textContent = "WebView2 송출 브리지를 사용할 수 없습니다.";
|
||||
}
|
||||
}());
|
||||
Reference in New Issue
Block a user