- use visible box-shadowing

- add translation for ZH
- light/darkmode switcher
This commit is contained in:
stefan.tollkuehn committed 2026-09-30 17:30:35 +02:00
1 parent 2214845361
commit 9200aac276
2 files changed
+245 -49

No files matched your search

+9
View File
@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600">
<rect width="900" height="600" fill="#EE1C25"/>
<path id="star" d="M0,-1 L0.225,-0.309 L0.951,-0.309 L0.363,0.118 L0.588,0.809 L0,0.382 L-0.588,0.809 L-0.363,0.118 L-0.951,-0.309 L-0.225,-0.309 Z" fill="#FFDE00"/>
<use href="#star" transform="translate(150,150) scale(90)"/>
<use href="#star" transform="translate(300,60) scale(30)"/>
<use href="#star" transform="translate(360,120) scale(30)"/>
<use href="#star" transform="translate(360,210) scale(30)"/>
<use href="#star" transform="translate(300,270) scale(30)"/>
</svg>

After

Width:  |  Height:  |  Size: 602 B

+236 -49
View File
@@ -7,7 +7,11 @@
<style> <style>
:root { :root {
color-scheme: light dark; color-scheme: light;
}
:root.dark {
color-scheme: dark;
} }
body { body {
@@ -108,7 +112,7 @@
padding: 32px; padding: 32px;
background: white; background: white;
border-radius: 14px; border-radius: 14px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.10); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.30), 0 12px 40px rgba(0, 0, 0, 0.45);
text-align: center; text-align: center;
} }
@@ -233,57 +237,65 @@
} }
} }
@media (prefers-color-scheme: dark) { /*
body { * Dark-Theme über die Klasse "dark" am html-Element.
background: #181818; * JS setzt sie anhand der gespeicherten Wahl oder der
color: #eee; * System-Einstellung (siehe detectTheme).
} */
:root.dark body {
background: #181818;
color: #eee;
}
.card { :root.dark .card {
background: #242424; background: #242424;
} }
.lang-dropdown { :root.dark .lang-dropdown {
background: #242424; background: #242424;
} }
.lang-dropdown button:hover { :root.dark .lang-dropdown button:hover {
background: #303030; background: #303030;
} }
.lang-dropdown button.active { :root.dark .lang-dropdown button.active {
background: #1a3a5a; background: #1a3a5a;
} }
p { :root.dark p {
color: #bbb; color: #bbb;
} }
.secondary { :root.dark .secondary {
background: #444; background: #444;
color: #eee; color: #eee;
} }
.status, .download { :root.dark .status,
background: #303030; :root.dark .download {
} background: #303030;
}
.spinner { :root.dark .spinner {
border-color: #555; border-color: #555;
border-top-color: #ddd; border-top-color: #ddd;
} }
.form-group input, :root.dark .form-group label {
.form-group textarea { color: #ddd;
background: #303030; }
border-color: #555;
color: #eee;
}
.success-message { :root.dark .form-group input,
background: #1a3a5a; :root.dark .form-group textarea {
color: #99ccff; background: #303030;
} border-color: #555;
color: #eee;
}
:root.dark .success-message {
background: #1a3a5a;
color: #99ccff;
} }
</style> </style>
</head> </head>
@@ -306,8 +318,18 @@
<button type="button" data-lang="en"><img class="lang-flag" src="assets/uk.svg" alt="">English</button> <button type="button" data-lang="en"><img class="lang-flag" src="assets/uk.svg" alt="">English</button>
<button type="button" data-lang="de"><img class="lang-flag" src="assets/de.svg" alt="">Deutsch</button> <button type="button" data-lang="de"><img class="lang-flag" src="assets/de.svg" alt="">Deutsch</button>
<button type="button" data-lang="fr"><img class="lang-flag" src="assets/fr.svg" alt="">Français</button> <button type="button" data-lang="fr"><img class="lang-flag" src="assets/fr.svg" alt="">Français</button>
<button type="button" data-lang="zh"><img class="lang-flag" src="assets/cn.svg" alt="">中文</button>
</div> </div>
</div> </div>
<button id="themeButton" class="button secondary" type="button" aria-label="Toggle dark mode">
<svg id="themeIconMoon" class="theme-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/>
</svg>
<svg id="themeIconSun" class="theme-icon hidden" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="4"/>
<path d="M12 2v2m0 16v2M4.9 4.9l1.4 1.4m11.4 11.4 1.4 1.4M2 12h2m16 0h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/>
</svg>
</button>
</nav> </nav>
<div class="container"> <div class="container">
@@ -831,6 +853,89 @@
organizerRequired: "Veuillez entrer un email d'organisateur", organizerRequired: "Veuillez entrer un email d'organisateur",
organizerInvalid: "Veuillez entrer une adresse email d'organisateur valide" organizerInvalid: "Veuillez entrer une adresse email d'organisateur valide"
} }
},
zh: {
pageTitle: "Jitsi 会议",
impressum: "法律声明",
launcher: {
title: "Jitsi 会议",
meetingPrefix: "会议",
meetingSuffix: "即将打开。",
openButton: "加入会议"
},
starting: {
title: "正在启动 Jitsi Meet …",
status: "正在打开 Jitsi Meet 桌面客户端。"
},
fallback: {
title: "无法打开 Jitsi Meet",
description: "Jitsi Meet 桌面客户端可能尚未启动。",
retryButton: "重试"
},
downloads: {
windows: {
title: "适用于 Windows 的 Jitsi Meet",
description: "请安装 Jitsi Meet 桌面客户端,然后再次尝试打开会议。",
button: "下载 Windows 版 Jitsi"
},
macos: {
title: "适用于 macOS 的 Jitsi Meet",
description: "请安装 Jitsi Meet 桌面客户端,然后再次尝试打开会议。",
button: "下载 macOS 版 Jitsi"
},
linux: {
title: "适用于 Linux 的 Jitsi Meet",
description: "请安装 Jitsi Meet 桌面客户端,然后再次尝试打开会议。",
button: "下载 Linux 版 Jitsi"
},
other: {
title: "Jitsi Meet 桌面版",
description: "没有为您的操作系统配置桌面版下载。"
}
},
browser: {
title: "在浏览器中加入",
description: "您也可以直接通过浏览器加入会议。",
button: "在浏览器中加入"
},
error: {
title: "未指定会议",
description: "请使用参数指定会议",
descriptionSuffix: "。",
invalidTitle: "会议名称无效",
invalidDescription: "仅允许使用字母、数字和连字符:"
},
creator: {
title: "创建新会议",
meetingNameLabel: "会议名称",
meetingDescriptionLabel: "描述",
meetingStartLabel: "开始日期和时间",
meetingEndLabel: "结束日期和时间",
meetingOrganizerLabel: "组织者邮箱",
createButton: "创建会议",
cancelButton: "取消",
successMessage: "会议已创建!请下载您的日历文件。",
downloadButton: "下载 ICS 文件",
createNewButton: "创建新会议",
meetingNameRequired: "请输入会议名称",
meetingNameInvalid: "会议名称只能包含字母、数字和连字符",
startTimeRequired: "请选择开始时间",
endTimeRequired: "请选择结束时间",
endAfterStart: "结束时间必须晚于开始时间",
organizerRequired: "请输入组织者邮箱",
organizerInvalid: "请输入有效的组织者邮箱地址"
}
} }
}; };
@@ -940,13 +1045,15 @@
const LANGUAGE_NAMES = { const LANGUAGE_NAMES = {
en: "English", en: "English",
de: "Deutsch", de: "Deutsch",
fr: "Français" fr: "Français",
zh: "中文"
}; };
const LANGUAGE_FLAGS = { const LANGUAGE_FLAGS = {
en: "assets/uk.svg", en: "assets/uk.svg",
de: "assets/de.svg", de: "assets/de.svg",
fr: "assets/fr.svg" fr: "assets/fr.svg",
zh: "assets/cn.svg"
}; };
function updateLanguageMenu() { function updateLanguageMenu() {
@@ -997,6 +1104,66 @@
langButton.setAttribute("aria-expanded", "false"); langButton.setAttribute("aria-expanded", "false");
} }
/* ============================================================
* THEME
* ============================================================
*/
const THEME_KEY = "jitsiLauncherTheme";
function savedTheme() {
try {
const saved = localStorage.getItem(THEME_KEY);
if (saved === "dark" || saved === "light") {
return saved;
}
} catch (error) {
/*
* localStorage kann z.B. im Privat-Modus blockiert sein.
*/
}
return null;
}
function systemIsDark() {
return window.matchMedia("(prefers-color-scheme: dark)").matches;
}
function detectTheme() {
/*
* Gespeicherte Wahl hat Vorrang, sonst System-Einstellung.
*/
return savedTheme() || (systemIsDark() ? "dark" : "light");
}
let currentTheme = detectTheme();
function updateThemeToggle() {
themeIconSun.classList.toggle("hidden", currentTheme !== "dark");
themeIconMoon.classList.toggle("hidden", currentTheme === "dark");
}
function applyTheme() {
document.documentElement.classList.toggle("dark", currentTheme === "dark");
updateThemeToggle();
}
function toggleTheme() {
currentTheme = currentTheme === "dark" ? "light" : "dark";
try {
localStorage.setItem(THEME_KEY, currentTheme);
} catch (error) {
/*
* localStorage kann z.B. im Privat-Modus blockiert sein.
*/
}
applyTheme();
}
/* ============================================================ /* ============================================================
* BACKGROUND IMAGE * BACKGROUND IMAGE
* ============================================================ * ============================================================
@@ -1079,6 +1246,11 @@
const logoBar = document.getElementById("logoBar"); const logoBar = document.getElementById("logoBar");
const logoImage = document.getElementById("logoImage"); const logoImage = document.getElementById("logoImage");
/* Theme DOM elements */
const themeButton = document.getElementById("themeButton");
const themeIconSun = document.getElementById("themeIconSun");
const themeIconMoon = document.getElementById("themeIconMoon");
/* ============================================================ /* ============================================================
* GET ROOM FROM QUERY-PARAMETER * GET ROOM FROM QUERY-PARAMETER
* ============================================================ * ============================================================
@@ -1683,10 +1855,6 @@ END:VCALENDAR`;
* Kein room-Parameter: Meldungen ausblenden, * Kein room-Parameter: Meldungen ausblenden,
* nur den Create-Button anzeigen. * nur den Create-Button anzeigen.
*/ */
/*
* Kein room-Parameter: keine Fehlermeldung,
* nur den Create-Button anzeigen.
*/
if (room === null) { if (room === null) {
missingRoomTitle.classList.add("hidden"); missingRoomTitle.classList.add("hidden");
missingRoomError.classList.add("hidden"); missingRoomError.classList.add("hidden");
@@ -1827,12 +1995,31 @@ END:VCALENDAR`;
} }
); );
/* Theme events */
themeButton.addEventListener(
"click",
toggleTheme
);
/*
* Ohne gespeicherte Wahl dem System folgen.
*/
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", () => {
if (savedTheme() === null) {
currentTheme = systemIsDark() ? "dark" : "light";
applyTheme();
}
});
/* ============================================================ /* ============================================================
* START * START
* ============================================================ * ============================================================
*/ */
applyTranslations(); applyTranslations();
applyTheme();
applyBackgroundImage(); applyBackgroundImage();
applyLogo(); applyLogo();
updateLanguageMenu(); updateLanguageMenu();