branding och namechange

This commit is contained in:
larssand
2026-08-28 20:56:58 +02:00
parent 5cab3a0e17
commit 3cf68cf34a
23 changed files with 146 additions and 89 deletions

View File

@@ -30,6 +30,8 @@ import { renderTeamStintLog as renderTeamStintLogHelper, renderSessionChannelAna
import { getManualCorrectionSummary as getManualCorrectionSummaryLogic, applyCompetitorCorrection as applyCompetitorCorrectionLogic, recalculateCompetitorFromPassings as recalculateCompetitorFromPassingsLogic, invalidateCompetitorLastLap as invalidateCompetitorLastLapLogic, restoreCompetitorLastInvalidLap as restoreCompetitorLastInvalidLapLogic, findPassingByUndoMarker as findPassingByUndoMarkerLogic, undoJudgingAdjustment as undoJudgingAdjustmentLogic, getJudgeFilteredRows as getJudgeFilteredRowsLogic, getJudgeFilteredLog as getJudgeFilteredLogLogic } from "./judging_logic.js";
const PRODUCT_NAME = "RC RaceCore";
const renderRaceFormatFieldView = (labelKey, hintKey, controlHtml, options = {}) => renderRaceFormatField(labelKey, hintKey, controlHtml, options, { t });
const renderRaceFormatContextCardView = (titleKey, hintKey) => renderRaceFormatContextCard(titleKey, hintKey, { t });
const renderManageStatusBadgeView = (status) => renderManageStatusBadge(status, { t });
@@ -327,8 +329,8 @@ const TRANSLATIONS = {
"ui.theme_dark": "Mörk",
"ui.theme_nord": "Nord",
"ui.theme_light": "Ljus",
"brand.title": "JMK RB RaceController",
"brand.subtitle": "RC Timing System",
"brand.title": "RC RaceCore",
"brand.subtitle": "Live Timing & Race Control",
"ui.no_active_session": "Ingen aktiv session",
"ui.event": "Event",
"ui.decoder_online": "Decoder online",
@@ -1074,7 +1076,9 @@ const TRANSLATIONS = {
"settings.test_audio": "Testa ljud",
"settings.audio_note": "Browsern kräver oftast ett klick först innan ljud/tal tillåts.",
"settings.voice_note": "Rösterna kommer från operativsystemet. På Windows ger Microsofts svenska röst oftast bäst uttal. Ange vid behov ett särskilt uttalsnamn under Förare.",
"settings.branding": "Klubbinfo / PDF",
"settings.branding": "Klubbbranding / UI / PDF",
"settings.branding_note": "Klubbnamn, klubbtext och logotyp används i huvudmenyn, overlay, publik träningsprofil och PDF-export.",
"settings.save_branding": "Spara branding",
"settings.club_name": "Klubbnamn",
"settings.club_tagline": "Klubbtext",
"settings.pdf_footer": "PDF-footer",
@@ -1082,10 +1086,10 @@ const TRANSLATIONS = {
"settings.pdf_theme_classic": "Classic",
"settings.pdf_theme_minimal": "Minimal",
"settings.pdf_theme_motorsport": "Motorsport",
"settings.logo": "Logo / overlay",
"settings.logo": "Klubblogotyp",
"settings.logo_upload": "Ladda logo",
"settings.logo_clear": "Rensa logo",
"settings.logo_note": "Logon visas i overlay. PDF-export försöker bädda in loggan automatiskt via backend.",
"settings.logo_note": "Logotypen visas i huvudmenyn, overlay och publik träningsprofil. PDF-export försöker bädda in den via backend.",
"settings.storage": "Lagring",
"settings.race_presets": "Klubb-presetar",
"settings.race_presets_note": "Exportera eller importera lokala klubb-presetar mellan installationer.",
@@ -1320,7 +1324,7 @@ const TRANSLATIONS = {
"overlay.subtitle": "Extern leaderboard-skärm",
"overlay.no_active": "Ingen aktiv session vald.",
"overlay.last_passings": "Senaste passeringar",
"overlay.window_title": "JMK RB RaceController Overlay",
"overlay.window_title": "RC RaceCore Overlay",
"overlay.mode_leaderboard": "Leaderboard",
"overlay.mode_speaker": "Speaker",
"overlay.mode_results": "Resultat",
@@ -1447,8 +1451,8 @@ const TRANSLATIONS = {
"ui.theme_dark": "Dark",
"ui.theme_nord": "Nord",
"ui.theme_light": "Light",
"brand.title": "JMK RB RaceController",
"brand.subtitle": "RC Timing System",
"brand.title": "RC RaceCore",
"brand.subtitle": "Live Timing & Race Control",
"ui.no_active_session": "No Active Session",
"ui.event": "Event",
"ui.decoder_online": "Decoder Online",
@@ -2194,7 +2198,9 @@ const TRANSLATIONS = {
"settings.test_audio": "Test audio",
"settings.audio_note": "Browsers usually require a click first before sound/speech is allowed.",
"settings.voice_note": "Voices are provided by the operating system. Select a matching local voice and set a separate spoken name under Drivers when pronunciation needs help.",
"settings.branding": "Club Info / PDF",
"settings.branding": "Club branding / UI / PDF",
"settings.branding_note": "Club name, tagline, and logo are used in the main menu, overlays, public training profiles, and PDF exports.",
"settings.save_branding": "Save branding",
"settings.club_name": "Club name",
"settings.club_tagline": "Club tagline",
"settings.pdf_footer": "PDF footer",
@@ -2202,10 +2208,10 @@ const TRANSLATIONS = {
"settings.pdf_theme_classic": "Classic",
"settings.pdf_theme_minimal": "Minimal",
"settings.pdf_theme_motorsport": "Motorsport",
"settings.logo": "Logo / overlay",
"settings.logo": "Club logo",
"settings.logo_upload": "Upload logo",
"settings.logo_clear": "Clear logo",
"settings.logo_note": "The logo is shown in overlay. PDF export attempts to embed the logo automatically via the backend.",
"settings.logo_note": "The logo is shown in the main menu, overlays, and public training profiles. PDF export attempts to embed it via the backend.",
"settings.storage": "Storage",
"settings.race_presets": "Club presets",
"settings.race_presets_note": "Export or import local club presets between installations.",
@@ -2440,7 +2446,7 @@ const TRANSLATIONS = {
"overlay.subtitle": "External leaderboard screen",
"overlay.no_active": "No active session selected.",
"overlay.last_passings": "Recent passings",
"overlay.window_title": "JMK RB RaceController Overlay",
"overlay.window_title": "RC RaceCore Overlay",
"overlay.mode_leaderboard": "Leaderboard",
"overlay.mode_speaker": "Speaker",
"overlay.mode_results": "Results",
@@ -2909,16 +2915,19 @@ function seedDefaultData() {
state.settings.speakerFinishCueEnabled = true;
}
if (!state.settings.clubName) {
state.settings.clubName = "JMK RB RaceController";
const storedClubName = String(state.settings.clubName || "").trim();
if (!storedClubName || ["JMK RB RaceController", "RC RaceCore"].includes(storedClubName)) {
state.settings.clubName = "JMK RB";
}
if (!state.settings.clubTagline) {
state.settings.clubTagline = "RC Timing System";
const storedClubTagline = String(state.settings.clubTagline || "").trim();
if (!storedClubTagline || storedClubTagline === "RC Timing System") {
state.settings.clubTagline = "Live Timing & Race Control";
}
if (!state.settings.pdfFooter) {
state.settings.pdfFooter = "Generated by JMK RB RaceController";
const storedPdfFooter = String(state.settings.pdfFooter || "").trim();
if (!storedPdfFooter || storedPdfFooter === "Generated by JMK RB RaceController") {
state.settings.pdfFooter = "Generated by RC RaceCore";
}
if (!state.settings.pdfTheme) {
@@ -2996,9 +3005,9 @@ function loadState() {
speakerBestLapCueEnabled: parsed.settings?.speakerBestLapCueEnabled !== false,
speakerTop3CueEnabled: parsed.settings?.speakerTop3CueEnabled === true,
speakerSessionStartCueEnabled: parsed.settings?.speakerSessionStartCueEnabled !== false,
clubName: parsed.settings?.clubName || "JMK RB RaceController",
clubTagline: parsed.settings?.clubTagline || "RC Timing System",
pdfFooter: parsed.settings?.pdfFooter || "Generated by JMK RB RaceController",
clubName: parsed.settings?.clubName || "JMK RB",
clubTagline: parsed.settings?.clubTagline || "Live Timing & Race Control",
pdfFooter: parsed.settings?.pdfFooter || "Generated by RC RaceCore",
pdfTheme: parsed.settings?.pdfTheme || "classic",
logoDataUrl: parsed.settings?.logoDataUrl || "",
racePresets: Array.isArray(parsed.settings?.racePresets)
@@ -3062,9 +3071,9 @@ function loadState() {
speakerBestLapCueEnabled: true,
speakerTop3CueEnabled: false,
speakerSessionStartCueEnabled: true,
clubName: "JMK RB RaceController",
clubTagline: "RC Timing System",
pdfFooter: "Generated by JMK RB RaceController",
clubName: "JMK RB",
clubTagline: "Live Timing & Race Control",
pdfFooter: "Generated by RC RaceCore",
pdfTheme: "classic",
logoDataUrl: "",
racePresets: [],
@@ -3143,14 +3152,7 @@ function setupLanguageControl() {
if (label) {
label.textContent = t("ui.language");
}
const brandTitle = document.getElementById("brandTitle");
if (brandTitle) {
brandTitle.textContent = t("brand.title");
}
const brandSubtitle = document.getElementById("brandSubtitle");
if (brandSubtitle) {
brandSubtitle.textContent = t("brand.subtitle");
}
updateAppBranding();
const select = document.getElementById("languageSelect");
if (!(select instanceof HTMLSelectElement)) {
@@ -3168,6 +3170,27 @@ function setupLanguageControl() {
};
}
function updateAppBranding() {
const clubName = String(state.settings?.clubName || "").trim() || PRODUCT_NAME;
const clubTagline = String(state.settings?.clubTagline || "").trim() || t("brand.subtitle");
const logoDataUrl = String(state.settings?.logoDataUrl || "").trim();
const hasLogo = /^data:image\/(?:png|jpeg|webp);base64,/i.test(logoDataUrl);
const brandTitle = document.getElementById("brandTitle");
const brandSubtitle = document.getElementById("brandSubtitle");
const brandMark = document.getElementById("brandMark");
const brandLogo = document.getElementById("brandLogo");
if (brandTitle) brandTitle.textContent = clubName;
if (brandSubtitle) brandSubtitle.textContent = clubTagline;
if (brandMark) brandMark.classList.toggle("has-logo", hasLogo);
if (brandLogo instanceof HTMLImageElement) {
brandLogo.hidden = !hasLogo;
if (hasLogo) brandLogo.src = logoDataUrl;
else brandLogo.removeAttribute("src");
}
document.title = clubName === PRODUCT_NAME ? PRODUCT_NAME : `${clubName} | ${PRODUCT_NAME}`;
}
function buildPersistableState() {
syncTrainingLedger();
return {
@@ -3193,7 +3216,7 @@ function normalizeImportedClass(classItem) {
function buildExportMeta(exportType) {
return {
app: "JMK RB RaceController",
app: "RC RaceCore",
schemaVersion: EXPORT_SCHEMA_VERSION,
exportType,
exportedAt: new Date().toISOString(),
@@ -3571,6 +3594,7 @@ function updateViewUrl(view, driverId = "", classId = "") {
}
function renderView() {
updateAppBranding();
if (currentView === "settings") settingsDraftActive = false;
clearModalEscapeHandler();
const navMeta = NAV_ITEMS.find((x) => x.id === currentView);