175 build - идентификатор для кнопки
This commit is contained in:
@@ -9412,6 +9412,7 @@ async function openHockeyPrematchButtonsEditor({ section = "buttons", panelId =
|
||||
<label>Иконка<input type="text" maxlength="32" data-panel-title-button-field="icon" data-panel-title-button-id="${escapeHtml(button.id)}" value="${escapeHtml(button.icon)}" placeholder="▶ ★ 📊 👤"></label>
|
||||
<label class="shortcut-inline-check"><input type="checkbox" data-panel-title-button-field="icon_only" data-panel-title-button-id="${escapeHtml(button.id)}" ${button.icon_only ? "checked" : ""}> Только иконка</label>
|
||||
<label class="panel-title-button-description">Подсказка<input type="text" maxlength="300" data-panel-title-button-field="description" data-panel-title-button-id="${escapeHtml(button.id)}" value="${escapeHtml(button.description)}" placeholder="Например: крупная статистика игрока"></label>
|
||||
<label class="panel-title-button-text">Надпись в титре<input type="text" maxlength="512" data-panel-title-button-field="title_text" data-panel-title-button-id="${escapeHtml(button.id)}" value="${escapeHtml(button.title_text || "")}" placeholder="Например: СТАТИСТИКА ЗА СЕЗОН"></label>
|
||||
<div class="player-selection-editor-order"><button type="button" class="mini-btn" data-panel-title-button-up="${escapeHtml(button.id)}" ${index <= 0 ? "disabled" : ""}>↑</button><button type="button" class="mini-btn" data-panel-title-button-down="${escapeHtml(button.id)}" ${index >= draftPanelTitleButtons.length - 1 ? "disabled" : ""}>↓</button></div>
|
||||
<button type="button" class="icon-btn danger" data-panel-title-button-delete="${escapeHtml(button.id)}" title="Удалить кнопку">×</button>
|
||||
</article>`;
|
||||
@@ -9477,7 +9478,7 @@ async function openHockeyPrematchButtonsEditor({ section = "buttons", panelId =
|
||||
</section>
|
||||
` : `
|
||||
<section class="panel-title-button-editor prematch-editor-section" data-prematch-editor-section="panel_titles">
|
||||
<header><div><span>PLAYER BLOCK → VMIX PREVIEW</span><strong>Кнопки титров под блоками игроков</strong><small>Один блок может иметь несколько кнопок. Перед Preview обновляется Mapping выбранного блока, затем выбранный vMix Input отправляется в Preview.</small></div><div class="prematch-editor-head-actions"><button type="button" class="btn" data-panel-title-refresh-inputs>↻ Inputs</button><button type="button" class="btn btn-accent" data-panel-title-button-add>+ Кнопка титра</button></div></header>
|
||||
<header><div><span>PLAYER BLOCK → VMIX PREVIEW</span><strong>Кнопки титров под блоками игроков</strong><small>Нескольким кнопкам можно назначить один Input. В Mapping свяжите текстовое поле с title_button.text; ID нажатой кнопки доступен как title_button.id (в SQL — :title_button_id). Данные обновляются до Preview.</small></div><div class="prematch-editor-head-actions"><button type="button" class="btn" data-panel-title-refresh-inputs>↻ Inputs</button><button type="button" class="btn btn-accent" data-panel-title-button-add>+ Кнопка титра</button></div></header>
|
||||
<div class="panel-title-button-editor-list">${draftPanelTitleButtons.length ? draftPanelTitleButtons.map(renderPanelTitleButtonRow).join("") : `<div class="prematch-group-empty">Кнопок титров пока нет. Создайте блок игроков, затем назначьте ему один или несколько vMix Input.</div>`}</div>
|
||||
</section>
|
||||
`}
|
||||
@@ -10402,6 +10403,7 @@ function normalisePlayerPanelTitleButtons(source) {
|
||||
id,
|
||||
panel_id: panelId,
|
||||
label,
|
||||
title_text: String(button?.title_text || "").trim().slice(0, 512),
|
||||
description: String(button?.description || "").trim().slice(0, 300),
|
||||
icon: String(button?.icon || "▶").trim().slice(0, 32) || "▶",
|
||||
icon_only: button?.icon_only === true,
|
||||
@@ -10450,8 +10452,23 @@ async function hockeySavePlayerPanelTitleButtons(buttons) {
|
||||
}
|
||||
}
|
||||
|
||||
function hockeyRefreshPlayerPanelTitleButtonState() {
|
||||
const values = hockeyMatchRuntimeValues();
|
||||
const panels = hockeyPlayerSelectionPanels();
|
||||
document.querySelectorAll("[data-player-panel-title-button]").forEach((node) => {
|
||||
const panel = panels.find((item) => item.id === node.dataset.playerPanelId);
|
||||
const filled = panel && Array.from({ length: panel.slots }, (_, index) => hockeyPlayerSelectionSlot(panel, index + 1))
|
||||
.some((slot) => slot.id || slot.dbId);
|
||||
node.disabled = !hockeyCanControl() || state.playerPanelTitleBusy.size > 0 || !filled;
|
||||
const selected = values["title_button.id"] === node.dataset.playerPanelTitleButton
|
||||
&& values["title_button.panel_id"] === node.dataset.playerPanelId;
|
||||
node.classList.toggle("is-selected", selected);
|
||||
node.setAttribute("aria-pressed", String(selected));
|
||||
});
|
||||
}
|
||||
|
||||
async function hockeyPreviewPlayerPanelTitle(panel, button) {
|
||||
if (!panel || !button || !hockeyCanControl() || state.playerPanelTitleBusy.has(panel.id)) return false;
|
||||
if (!panel || !button || !hockeyCanControl() || state.playerPanelTitleBusy.size) return false;
|
||||
if (!button.input) {
|
||||
toast(`Для «${button.label}» не назначен vMix Input`, true);
|
||||
return false;
|
||||
@@ -10462,22 +10479,24 @@ async function hockeyPreviewPlayerPanelTitle(panel, button) {
|
||||
return false;
|
||||
}
|
||||
state.playerPanelTitleBusy.add(panel.id);
|
||||
const syncBusy = () => {
|
||||
document.querySelectorAll("[data-player-panel-title-button]").forEach((node) => {
|
||||
if (node.dataset.playerPanelId === panel.id) node.disabled = state.playerPanelTitleBusy.has(panel.id) || !slots.some((slot) => slot.id || slot.dbId);
|
||||
});
|
||||
};
|
||||
syncBusy();
|
||||
hockeyRefreshPlayerPanelTitleButtonState();
|
||||
const gameId = hockeyTimerSelectedGameId();
|
||||
try {
|
||||
// Publish which panel button is being used before PreviewInput. SQL/Mapping
|
||||
// can therefore distinguish several graphics that use the same selected
|
||||
// player block while the player identifiers themselves stay unchanged.
|
||||
await hockeySetMatchValues({
|
||||
const saved = await hockeySetMatchValues({
|
||||
"title_button.id": button.id,
|
||||
"title_button.label": button.label,
|
||||
"title_button.text": button.title_text || "",
|
||||
"title_button.panel_id": panel.id,
|
||||
"title_button.input": button.input,
|
||||
[`player_select.${panel.id}._preview_button_id`]: button.id,
|
||||
[`player_select.${panel.id}._preview_button_label`]: button.label,
|
||||
[`player_select.${panel.id}._preview_button_text`]: button.title_text || "",
|
||||
[`player_select.${panel.id}._preview_input`]: button.input,
|
||||
}, { refreshMapping: false });
|
||||
if (!saved || gameId !== hockeyTimerSelectedGameId() || !hockeyCanControl()) throw new Error("Выбранный матч или права управления изменились");
|
||||
if (!(await hockeyRefreshQuickPanelMapping())) throw new Error("Не удалось обновить данные титра в vMix");
|
||||
if (gameId !== hockeyTimerSelectedGameId() || !hockeyCanControl()) throw new Error("Выбранный матч изменился");
|
||||
const result = await sendRuntimeVmixSequence([{ Function: "PreviewInput", Input: button.input }]);
|
||||
@@ -10489,7 +10508,7 @@ async function hockeyPreviewPlayerPanelTitle(panel, button) {
|
||||
return false;
|
||||
} finally {
|
||||
state.playerPanelTitleBusy.delete(panel.id);
|
||||
syncBusy();
|
||||
hockeyRefreshPlayerPanelTitleButtonState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10822,6 +10841,7 @@ function renderHockeyPlayerSelectionWindows() {
|
||||
}
|
||||
}));
|
||||
}
|
||||
hockeyRefreshPlayerPanelTitleButtonState();
|
||||
setTimeout(() => hockeyEnsurePlayerSelectionRuntimeValues().catch(() => {}), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7574,6 +7574,12 @@ body.hockey-navigation-open .runtime-viewport.has-hockey-pbp { gap: 14px !import
|
||||
border-color:#54e5c4;
|
||||
background:#48dfbd;
|
||||
}
|
||||
.hockey-player-select-title-preview.is-selected {
|
||||
border-color:#54e5c4;
|
||||
box-shadow:inset 0 0 0 1px #54e5c4;
|
||||
color:#b6ffed;
|
||||
}
|
||||
.hockey-player-select-title-preview.is-selected:hover:not(:disabled) { color:#061713; }
|
||||
.hockey-player-select-title-preview:disabled { opacity:.42; cursor:not-allowed; }
|
||||
.hockey-player-select-title-preview.is-sending { opacity:.7; cursor:wait; }
|
||||
.hockey-player-select-footer-tools {
|
||||
@@ -8442,6 +8448,7 @@ body.hockey-navigation-open .runtime-viewport.has-hockey-pbp { gap: 14px !import
|
||||
.panel-title-button-editor-row > label:nth-of-type(6) { grid-column:5; grid-row:2; }
|
||||
.panel-title-button-editor-row > label:nth-of-type(7) { grid-column:6 / 9; grid-row:2; }
|
||||
.panel-title-button-editor-row > .panel-title-button-description { grid-column:3 / 9; grid-row:3; }
|
||||
.panel-title-button-editor-row > .panel-title-button-text { grid-column:3 / 9; grid-row:4; }
|
||||
|
||||
/* BUILD166: the account's dock size scales every control, including the score. */
|
||||
.runtime-button-dock {
|
||||
|
||||
Reference in New Issue
Block a user