- use visible box-shadowing
- add translation for ZH - light/darkmode switcher
This commit is contained in:
1 parent
2214845361
commit
9200aac276
2 files changed
+218
-22
No files matched your search
@@ -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 |
+209
-22
@@ -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,58 +237,66 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
/*
|
||||||
body {
|
* Dark-Theme über die Klasse "dark" am html-Element.
|
||||||
|
* JS setzt sie anhand der gespeicherten Wahl oder der
|
||||||
|
* System-Einstellung (siehe detectTheme).
|
||||||
|
*/
|
||||||
|
:root.dark body {
|
||||||
background: #181818;
|
background: #181818;
|
||||||
color: #eee;
|
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,
|
||||||
|
:root.dark .download {
|
||||||
background: #303030;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root.dark .form-group input,
|
||||||
|
:root.dark .form-group textarea {
|
||||||
background: #303030;
|
background: #303030;
|
||||||
border-color: #555;
|
border-color: #555;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.success-message {
|
:root.dark .success-message {
|
||||||
background: #1a3a5a;
|
background: #1a3a5a;
|
||||||
color: #99ccff;
|
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();
|
||||||
|
|||||||
Reference in new issue
Block a user