mirror of
https://github.com/Pandipipas/scoreko-dev.git
synced 2026-06-06 03:32:06 +00:00
Permite cambiar skin de scoreboard en tiempo real con misma URL
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"scoreboardSkin": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "scoreboard/main.html"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["scoreboardSkin"],
|
||||||
|
"default": {
|
||||||
|
"scoreboardSkin": "scoreboard/main.html"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,5 +12,6 @@ const thisBundle = 'scoreko-dev';
|
|||||||
export const exampleReplicant = useReplicant<Schemas.ExampleReplicant>('exampleReplicant', thisBundle);
|
export const exampleReplicant = useReplicant<Schemas.ExampleReplicant>('exampleReplicant', thisBundle);
|
||||||
export const playersReplicant = useReplicant<Schemas.Players>('players', thisBundle);
|
export const playersReplicant = useReplicant<Schemas.Players>('players', thisBundle);
|
||||||
export const scoreboardReplicant = useReplicant<Schemas.Scoreboard>('scoreboard', thisBundle);
|
export const scoreboardReplicant = useReplicant<Schemas.Scoreboard>('scoreboard', thisBundle);
|
||||||
|
export const graphicsSettingsReplicant = useReplicant<Schemas.GraphicsSettings>('graphicsSettings', thisBundle);
|
||||||
|
|
||||||
export const commentaryReplicant = useReplicant<Schemas.Commentary>('commentary', thisBundle);
|
export const commentaryReplicant = useReplicant<Schemas.Commentary>('commentary', thisBundle);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useHead } from '@unhead/vue';
|
import { useHead } from '@unhead/vue';
|
||||||
import { computed, ref, watchEffect } from 'vue';
|
import { computed, ref, watch, watchEffect } from 'vue';
|
||||||
|
import { graphicsSettingsReplicant } from '../../../browser_shared/replicants';
|
||||||
import { t } from '../i18n';
|
import { t } from '../i18n';
|
||||||
|
|
||||||
defineOptions({ name: 'GraphicsView' });
|
defineOptions({ name: 'GraphicsView' });
|
||||||
@@ -24,17 +25,14 @@ type GraphicCard = {
|
|||||||
|
|
||||||
useHead(() => ({ title: t('graphicsTitle') }));
|
useHead(() => ({ title: t('graphicsTitle') }));
|
||||||
|
|
||||||
const graphics = computed<GraphicConfig[]>(
|
const graphics = computed<GraphicConfig[]>(() => bundlePackage.nodecg?.graphics ?? []);
|
||||||
() => bundlePackage.nodecg?.graphics ?? [],
|
|
||||||
);
|
|
||||||
|
|
||||||
const baseUrl = computed(() => {
|
const baseUrl = computed(() => {
|
||||||
const bundleName = bundlePackage.name ?? 'bundle';
|
const bundleName = bundlePackage.name ?? 'bundle';
|
||||||
return `${window.location.origin}/bundles/${bundleName}/graphics/`;
|
return `${window.location.origin}/bundles/${bundleName}/graphics/`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const buildGraphicUrl = (graphic: GraphicConfig) =>
|
const buildGraphicUrl = (graphic: GraphicConfig) => `${baseUrl.value}${graphic.file}`;
|
||||||
`${baseUrl.value}${graphic.file}`;
|
|
||||||
|
|
||||||
const buildGraphicName = (graphic: GraphicConfig) => {
|
const buildGraphicName = (graphic: GraphicConfig) => {
|
||||||
const cleaned = graphic.file.replace(/\/?main\.html$/i, '');
|
const cleaned = graphic.file.replace(/\/?main\.html$/i, '');
|
||||||
@@ -49,6 +47,13 @@ const scoreboardGraphics = computed(() =>
|
|||||||
graphics.value.filter((graphic) => getGraphicKey(graphic).includes('scoreboard')),
|
graphics.value.filter((graphic) => getGraphicKey(graphic).includes('scoreboard')),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const canonicalScoreboardGraphic = computed(() => {
|
||||||
|
const explicitDefault = scoreboardGraphics.value.find(
|
||||||
|
(graphic) => getGraphicKey(graphic) === 'scoreboard',
|
||||||
|
);
|
||||||
|
return explicitDefault ?? scoreboardGraphics.value[0];
|
||||||
|
});
|
||||||
|
|
||||||
const commentaryGraphic = computed(() =>
|
const commentaryGraphic = computed(() =>
|
||||||
graphics.value.find((graphic) => getGraphicKey(graphic).includes('commentary')),
|
graphics.value.find((graphic) => getGraphicKey(graphic).includes('commentary')),
|
||||||
);
|
);
|
||||||
@@ -56,34 +61,56 @@ const commentaryGraphic = computed(() =>
|
|||||||
const selectedScoreboardSkin = ref<string>('');
|
const selectedScoreboardSkin = ref<string>('');
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (scoreboardGraphics.value.length === 0) {
|
const availableSkins = scoreboardGraphics.value;
|
||||||
|
|
||||||
|
if (availableSkins.length === 0) {
|
||||||
selectedScoreboardSkin.value = '';
|
selectedScoreboardSkin.value = '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasCurrentSkin = scoreboardGraphics.value.some(
|
const replicatedSkin = graphicsSettingsReplicant?.data?.scoreboardSkin ?? '';
|
||||||
|
const hasReplicatedSkin = availableSkins.some((graphic) => graphic.file === replicatedSkin);
|
||||||
|
if (hasReplicatedSkin && selectedScoreboardSkin.value !== replicatedSkin) {
|
||||||
|
selectedScoreboardSkin.value = replicatedSkin;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasCurrentSkin = availableSkins.some(
|
||||||
(graphic) => graphic.file === selectedScoreboardSkin.value,
|
(graphic) => graphic.file === selectedScoreboardSkin.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!hasCurrentSkin) {
|
if (!hasCurrentSkin) {
|
||||||
selectedScoreboardSkin.value = scoreboardGraphics.value[0]!.file;
|
selectedScoreboardSkin.value = availableSkins[0]!.file;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedScoreboardGraphic = computed(() =>
|
watch(
|
||||||
scoreboardGraphics.value.find(
|
selectedScoreboardSkin,
|
||||||
(graphic) => graphic.file === selectedScoreboardSkin.value,
|
(value) => {
|
||||||
) ?? scoreboardGraphics.value[0],
|
if (!value || !graphicsSettingsReplicant) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graphicsSettingsReplicant.data?.scoreboardSkin === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
graphicsSettingsReplicant.data = {
|
||||||
|
scoreboardSkin: value,
|
||||||
|
};
|
||||||
|
graphicsSettingsReplicant.save();
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const cards = computed<GraphicCard[]>(() => {
|
const cards = computed<GraphicCard[]>(() => {
|
||||||
const result: GraphicCard[] = [];
|
const result: GraphicCard[] = [];
|
||||||
|
|
||||||
if (selectedScoreboardGraphic.value) {
|
if (canonicalScoreboardGraphic.value) {
|
||||||
result.push({
|
result.push({
|
||||||
id: 'scoreboard',
|
id: 'scoreboard',
|
||||||
label: t('graphicsScoreboard'),
|
label: t('graphicsScoreboard'),
|
||||||
graphic: selectedScoreboardGraphic.value,
|
graphic: canonicalScoreboardGraphic.value,
|
||||||
skinOptions: scoreboardGraphics.value.map((graphic) => ({
|
skinOptions: scoreboardGraphics.value.map((graphic) => ({
|
||||||
label: graphic.title ?? buildGraphicName(graphic),
|
label: graphic.title ?? buildGraphicName(graphic),
|
||||||
value: graphic.file,
|
value: graphic.file,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useHead } from '@unhead/vue';
|
import { useHead } from '@unhead/vue';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { playersReplicant, scoreboardReplicant } from '../../browser_shared/replicants';
|
import { graphicsSettingsReplicant, playersReplicant, scoreboardReplicant } from '../../browser_shared/replicants';
|
||||||
import { resolveCountryCode } from '../../shared/countries';
|
import { resolveCountryCode } from '../../shared/countries';
|
||||||
import { getCharactersByGame } from '../../shared/fighting-characters';
|
import { getCharactersByGame } from '../../shared/fighting-characters';
|
||||||
import type { Schemas } from '../../types';
|
import type { Schemas } from '../../types';
|
||||||
@@ -15,6 +15,20 @@ const defaultScoreboard: Schemas.Scoreboard = {
|
|||||||
|
|
||||||
const players = computed<Schemas.Players>(() => playersReplicant?.data ?? {});
|
const players = computed<Schemas.Players>(() => playersReplicant?.data ?? {});
|
||||||
const scoreboard = computed<Schemas.Scoreboard>(() => scoreboardReplicant?.data ?? defaultScoreboard);
|
const scoreboard = computed<Schemas.Scoreboard>(() => scoreboardReplicant?.data ?? defaultScoreboard);
|
||||||
|
const scoreboardSkin = computed(() => graphicsSettingsReplicant?.data?.scoreboardSkin ?? 'scoreboard-2xko/main.html');
|
||||||
|
|
||||||
|
watch(
|
||||||
|
scoreboardSkin,
|
||||||
|
(skin) => {
|
||||||
|
if (skin !== 'scoreboard-2xko/main.html') {
|
||||||
|
const targetUrl = new URL('../scoreboard/main.html', window.location.href).toString();
|
||||||
|
if (window.location.href !== targetUrl) {
|
||||||
|
window.location.replace(targetUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
const leftName = computed(() => scoreboard.value.leftNameOverride || players.value[scoreboard.value.leftPlayerId]?.gamertag || 'PLAYER 1');
|
const leftName = computed(() => scoreboard.value.leftNameOverride || players.value[scoreboard.value.leftPlayerId]?.gamertag || 'PLAYER 1');
|
||||||
const rightName = computed(() => scoreboard.value.rightNameOverride || players.value[scoreboard.value.rightPlayerId]?.gamertag || 'PLAYER 2');
|
const rightName = computed(() => scoreboard.value.rightNameOverride || players.value[scoreboard.value.rightPlayerId]?.gamertag || 'PLAYER 2');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useHead } from '@unhead/vue';
|
import { useHead } from '@unhead/vue';
|
||||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||||
import { playersReplicant, scoreboardReplicant } from '../../browser_shared/replicants';
|
import { graphicsSettingsReplicant, playersReplicant, scoreboardReplicant } from '../../browser_shared/replicants';
|
||||||
import { resolveCountryCode } from '../../shared/countries';
|
import { resolveCountryCode } from '../../shared/countries';
|
||||||
import type { Schemas } from '../../types';
|
import type { Schemas } from '../../types';
|
||||||
|
|
||||||
@@ -26,6 +26,20 @@ const defaultScoreboard: Schemas.Scoreboard = {
|
|||||||
|
|
||||||
const players = computed<Schemas.Players>(() => playersReplicant?.data ?? {});
|
const players = computed<Schemas.Players>(() => playersReplicant?.data ?? {});
|
||||||
const scoreboard = computed<Schemas.Scoreboard>(() => scoreboardReplicant?.data ?? defaultScoreboard);
|
const scoreboard = computed<Schemas.Scoreboard>(() => scoreboardReplicant?.data ?? defaultScoreboard);
|
||||||
|
const scoreboardSkin = computed(() => graphicsSettingsReplicant?.data?.scoreboardSkin ?? 'scoreboard/main.html');
|
||||||
|
|
||||||
|
watch(
|
||||||
|
scoreboardSkin,
|
||||||
|
(skin) => {
|
||||||
|
if (skin !== 'scoreboard/main.html') {
|
||||||
|
const targetUrl = new URL('../scoreboard-2xko/main.html', window.location.href).toString();
|
||||||
|
if (window.location.href !== targetUrl) {
|
||||||
|
window.location.replace(targetUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
const leftName = computed(() => {
|
const leftName = computed(() => {
|
||||||
if (scoreboard.value.leftNameOverride) {
|
if (scoreboard.value.leftNameOverride) {
|
||||||
|
|||||||
Vendored
+1
@@ -7,5 +7,6 @@
|
|||||||
export type { Commentary } from './schemas/commentary.d.ts';
|
export type { Commentary } from './schemas/commentary.d.ts';
|
||||||
export type { Configschema } from './schemas/configschema.d.ts';
|
export type { Configschema } from './schemas/configschema.d.ts';
|
||||||
export type { ExampleReplicant } from './schemas/exampleReplicant.d.ts';
|
export type { ExampleReplicant } from './schemas/exampleReplicant.d.ts';
|
||||||
|
export type { GraphicsSettings } from './schemas/graphicsSettings.d.ts';
|
||||||
export type { Players } from './schemas/players.d.ts';
|
export type { Players } from './schemas/players.d.ts';
|
||||||
export type { Scoreboard } from './schemas/scoreboard.d.ts';
|
export type { Scoreboard } from './schemas/scoreboard.d.ts';
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
/* prettier-ignore */
|
||||||
|
/* eslint-disable */
|
||||||
|
/**
|
||||||
|
* This file was automatically generated by json-schema-to-typescript.
|
||||||
|
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||||
|
* and run json-schema-to-typescript to regenerate this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface GraphicsSettings {
|
||||||
|
scoreboardSkin: string;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user