Light- und Darkmode hinzugefügt
Some checks failed
Host-Based Deploy (Java 21 Fix) / build-and-run (push) Has been cancelled
@@ -38,11 +38,11 @@
|
||||
<div id="optionList"></div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:0.5rem;">
|
||||
<button onclick="addOption()" style="width:auto;margin:0;padding:0.3rem 0.75rem;font-size:0.8rem;">+ Option</button>
|
||||
<label class="multi-toggle"><input type="checkbox" id="multiChoice"> Mehrfachauswahl möglich</label>
|
||||
<label class="toggle-switch"><input type="checkbox" id="multiChoice"><span class="toggle-track"></span> Mehrfachauswahl möglich</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compose-footer">
|
||||
<label class="privacy-toggle"><input type="checkbox" id="isPublic"> Öffentlich</label>
|
||||
<label class="toggle-switch"><input type="checkbox" id="isPublic"><span class="toggle-track"></span> Öffentlich</label>
|
||||
<div style="display:flex;gap:0.5rem;align-items:center;">
|
||||
<button type="button" class="compose-action-btn" onclick="toggleEmojiPicker(this,'composeText')" title="Emoji">😊</button>
|
||||
<label class="compose-action-btn" title="Fotos">📷
|
||||
|
||||
@@ -105,9 +105,7 @@
|
||||
<div id="optionList"></div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:0.5rem;">
|
||||
<button onclick="addOption()" style="width:auto; margin:0; padding:0.3rem 0.75rem; font-size:0.8rem;">+ Option</button>
|
||||
<label class="multi-toggle">
|
||||
<input type="checkbox" id="multiChoice"> Mehrfachauswahl möglich
|
||||
</label>
|
||||
<label class="toggle-switch"><input type="checkbox" id="multiChoice"><span class="toggle-track"></span> Mehrfachauswahl möglich</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compose-footer">
|
||||
@@ -147,8 +145,11 @@
|
||||
<img id="editBildPreview" class="img-preview" alt="">
|
||||
<input type="hidden" id="editBildData">
|
||||
<div class="toggle-row">
|
||||
<input type="checkbox" id="editPrivate">
|
||||
<label for="editPrivate">Private Gruppe</label>
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="editPrivate">
|
||||
<span class="toggle-track"></span>
|
||||
Private Gruppe
|
||||
</label>
|
||||
</div>
|
||||
<button onclick="saveGruppe()" style="margin-top:0.75rem; width:auto; padding:0.4rem 1rem;">Speichern</button>
|
||||
<p class="message" id="saveMsg" style="display:none; margin-top:0.5rem;"></p>
|
||||
@@ -496,9 +497,7 @@
|
||||
</div>`).join('')}
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:0.3rem;" onclick="event.stopPropagation()">
|
||||
<button onmousedown="event.stopPropagation()" onclick="event.stopPropagation();gruppeEditAddOption('${beitragId}')" style="width:auto;margin:0;padding:0.3rem 0.75rem;font-size:0.8rem;">+ Option</button>
|
||||
<label class="multi-toggle" onmousedown="event.stopPropagation()" onclick="event.stopPropagation()">
|
||||
<input type="checkbox" id="gpmc-${beitragId}" ${post.multiChoice ? 'checked' : ''}> Mehrfachauswahl möglich
|
||||
</label>
|
||||
<label class="toggle-switch" onmousedown="event.stopPropagation()" onclick="event.stopPropagation()"><input type="checkbox" id="gpmc-${beitragId}" ${post.multiChoice ? 'checked' : ''}><span class="toggle-track"></span> Mehrfachauswahl möglich</label>
|
||||
</div>
|
||||
</div>`
|
||||
: '';
|
||||
|
||||
@@ -417,7 +417,7 @@ function renderPage() {
|
||||
<div id="locOptionList"></div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:0.5rem;">
|
||||
<button onclick="addLocOption()" style="width:auto;margin:0;padding:0.3rem 0.75rem;font-size:0.8rem;">+ Option</button>
|
||||
<label class="multi-toggle"><input type="checkbox" id="locMultiChoice"> Mehrfachauswahl möglich</label>
|
||||
<label class="toggle-switch"><input type="checkbox" id="locMultiChoice"><span class="toggle-track"></span> Mehrfachauswahl möglich</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compose-footer">
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
.compose-action-btn:hover{border-color:var(--color-primary);color:var(--color-primary);background:none}
|
||||
.compose-action-btn.active{border-color:var(--color-primary);color:var(--color-primary)}
|
||||
label.compose-action-btn{display:inline-flex;align-items:center}
|
||||
.multi-toggle{font-size:0.85rem;display:flex;align-items:center;gap:0.4rem}
|
||||
.privacy-toggle{font-size:0.85rem;display:flex;align-items:center;gap:0.4rem}
|
||||
|
||||
/* ── Umfrage-Compose ── */
|
||||
.umfrage-options{margin-top:0.5rem}
|
||||
|
||||
@@ -35,7 +35,7 @@ p {
|
||||
padding: 2.5rem;
|
||||
width: 100%;
|
||||
max-width: 380px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ button, .btn {
|
||||
}
|
||||
|
||||
button:hover:not(:disabled), .btn:hover {
|
||||
background: #c73652;
|
||||
background: var(--btn-primary-hover);
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
@@ -117,7 +117,7 @@ button.secondary {
|
||||
}
|
||||
|
||||
button.secondary:hover {
|
||||
background: #1a4a8a;
|
||||
background: var(--btn-secondary-hover);
|
||||
}
|
||||
|
||||
/* ── Messages ── */
|
||||
@@ -131,19 +131,19 @@ button.secondary:hover {
|
||||
}
|
||||
|
||||
.message.error {
|
||||
background: #3d0f1a;
|
||||
background: var(--msg-error-bg);
|
||||
border: 2px solid var(--color-primary);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.message.warning {
|
||||
background: #3a2c0a;
|
||||
border: 2px solid #f5c518;
|
||||
color: #f5c518;
|
||||
background: var(--msg-warning-bg);
|
||||
border: 2px solid var(--msg-warning-text);
|
||||
color: var(--msg-warning-text);
|
||||
}
|
||||
|
||||
.message.success {
|
||||
background: #0f3d1a;
|
||||
background: var(--msg-success-bg);
|
||||
border: 1px solid var(--color-success);
|
||||
color: var(--color-success);
|
||||
}
|
||||
@@ -180,7 +180,7 @@ body.app {
|
||||
background: var(--color-card);
|
||||
border: 1px solid var(--color-secondary);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -205,7 +205,7 @@ body.app {
|
||||
background: var(--color-card);
|
||||
border: 1px solid var(--color-secondary);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
@@ -338,7 +338,7 @@ body.app {
|
||||
.sidebar-overlay {
|
||||
display: none;
|
||||
position: fixed; inset: 0;
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
background: var(--overlay-bg);
|
||||
z-index: 90;
|
||||
}
|
||||
|
||||
@@ -375,7 +375,7 @@ body.app {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar-wrapper.open { transform: translateX(0); box-shadow: -4px 0 20px rgba(0, 0, 0, 0.5); }
|
||||
.sidebar-wrapper.open { transform: translateX(0); box-shadow: -4px 0 20px var(--overlay-bg); }
|
||||
|
||||
.sidebar {
|
||||
flex: none;
|
||||
@@ -414,7 +414,7 @@ body.app {
|
||||
background: var(--color-card);
|
||||
border: 1px solid var(--color-secondary);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-self: flex-start;
|
||||
@@ -508,7 +508,7 @@ body.app {
|
||||
background: var(--color-card);
|
||||
border: 1px solid var(--color-secondary);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
.sidebar-footer ul {
|
||||
@@ -572,7 +572,7 @@ body.app {
|
||||
background: var(--color-card);
|
||||
border: 1px solid var(--color-secondary);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
@@ -648,7 +648,7 @@ body.app {
|
||||
border: 1px solid var(--color-secondary);
|
||||
border-top: none;
|
||||
border-radius: 0 0 10px 10px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: var(--shadow);
|
||||
z-index: 600;
|
||||
max-height: 360px;
|
||||
overflow-y: auto;
|
||||
@@ -810,7 +810,7 @@ body.app {
|
||||
border: 1px solid var(--color-secondary);
|
||||
border-top: none;
|
||||
border-radius: 0 0 12px 12px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.65);
|
||||
box-shadow: var(--shadow);
|
||||
z-index: 550;
|
||||
width: 360px;
|
||||
max-height: 500px;
|
||||
@@ -1022,6 +1022,43 @@ body.app {
|
||||
.topbar-profile-link:hover { background: var(--color-secondary); }
|
||||
.topbar-profile-link--danger { color: var(--color-primary); }
|
||||
|
||||
.topbar-theme-row { cursor: pointer; justify-content: space-between; }
|
||||
|
||||
/* ── Toggle Switch ─────────────────────────────────────────────────────────── */
|
||||
.toggle-switch {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.toggle-switch input[type="checkbox"] { display: none; }
|
||||
.toggle-switch .toggle-track {
|
||||
width: 2.4rem;
|
||||
height: 1.35rem;
|
||||
background: var(--color-secondary);
|
||||
border-radius: 999px;
|
||||
position: relative;
|
||||
transition: background 0.2s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.toggle-switch input:checked ~ .toggle-track { background: var(--color-primary); }
|
||||
.toggle-switch .toggle-track::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0.15rem;
|
||||
left: 0.15rem;
|
||||
width: 1.05rem;
|
||||
height: 1.05rem;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.2s;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
|
||||
}
|
||||
.toggle-switch input:checked ~ .toggle-track::after { transform: translateX(1.05rem); }
|
||||
.toggle-switch input:disabled ~ .toggle-track { opacity: 0.45; }
|
||||
.toggle-switch:has(input:disabled) { cursor: default; }
|
||||
|
||||
/* ── Mobile: Topbar ausblenden, Content-Rahmen entfernen ── */
|
||||
@media (max-width: 768px) {
|
||||
.topbar { display: none; }
|
||||
|
||||
157
bin/main/static/css/variables.css
Normal file
@@ -0,0 +1,157 @@
|
||||
/* ──────────────────────────────────────────────────────────────────────────
|
||||
xXx Sphere – Design Tokens
|
||||
Dark ist der Default.
|
||||
Reihenfolge der Auflösung:
|
||||
1. :root → dark (Fallback, Spez. 0,1,0)
|
||||
2. @media prefers-light → light via OS (Spez. 0,1,0, überschreibt via Position)
|
||||
3. :root[data-theme=dark] → dark manuell (Spez. 0,2,0 – schlägt immer :root)
|
||||
4. :root[data-theme=light]→ light manuell (Spez. 0,2,0 – schlägt immer :root)
|
||||
JS setzt data-theme auf <html> und gewinnt damit immer.
|
||||
────────────────────────────────────────────────────────────────────────── */
|
||||
|
||||
/* ── 1. Dark mode – Default ───────────────────────────────────────────────── */
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
||||
/* Surfaces */
|
||||
--color-bg: #0e0c15;
|
||||
--color-card: #19162a;
|
||||
--color-secondary: #272338;
|
||||
--color-surface: #201d2f;
|
||||
|
||||
/* Text */
|
||||
--color-text: #eae8f0;
|
||||
--color-muted: #8a879a;
|
||||
|
||||
/* Brand */
|
||||
--color-primary: #e94560;
|
||||
--color-primary-rgb: 233, 69, 96;
|
||||
|
||||
/* Semantic */
|
||||
--color-success: #27ae60;
|
||||
--color-danger: #e74c3c;
|
||||
|
||||
/* Aliases */
|
||||
--color-border: #272338;
|
||||
--color-hover: #272338;
|
||||
|
||||
/* Shadows */
|
||||
--shadow: 0 8px 32px rgba(0, 0, 0, 0.55);
|
||||
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.35);
|
||||
|
||||
/* Overlay */
|
||||
--overlay-bg: rgba(0, 0, 0, 0.55);
|
||||
|
||||
/* Message boxes */
|
||||
--msg-error-bg: #3d0f1a;
|
||||
--msg-warning-bg: #3a2c0a;
|
||||
--msg-warning-text: #f5c518;
|
||||
--msg-success-bg: #0f3d1a;
|
||||
|
||||
/* Buttons */
|
||||
--btn-primary-hover: #c73652;
|
||||
--btn-secondary-hover: #1a3a6a;
|
||||
|
||||
/* Misc */
|
||||
--placeholder: rgba(234, 232, 240, 0.35);
|
||||
--unread: #e94560;
|
||||
--accept: #27ae60;
|
||||
--decline: #c0392b;
|
||||
--breakpoint-mobile: 768px;
|
||||
}
|
||||
|
||||
/* ── 2. Light mode via OS (CSS-Fallback, wenn JS nicht verfügbar) ─────────── */
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color-scheme: light;
|
||||
|
||||
--color-bg: #f2f0f9;
|
||||
--color-card: #ffffff;
|
||||
--color-secondary: #e9e6f5;
|
||||
--color-surface: #f7f5fc;
|
||||
--color-text: #1a1628;
|
||||
--color-muted: #6a677e;
|
||||
--color-primary: #c9324d;
|
||||
--color-primary-rgb: 201, 50, 77;
|
||||
--color-success: #1a8c4e;
|
||||
--color-danger: #c0392b;
|
||||
--color-border: #d8d4ed;
|
||||
--color-hover: #e9e6f5;
|
||||
--shadow: 0 4px 16px rgba(0, 0, 0, 0.10);
|
||||
--shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.06);
|
||||
--overlay-bg: rgba(0, 0, 0, 0.35);
|
||||
--msg-error-bg: #fde8ec;
|
||||
--msg-warning-bg: #fdf5e0;
|
||||
--msg-warning-text: #b38800;
|
||||
--msg-success-bg: #e0f5e8;
|
||||
--btn-primary-hover: #a82942;
|
||||
--btn-secondary-hover: #d8d4ed;
|
||||
--placeholder: rgba(26, 22, 40, 0.30);
|
||||
--unread: #c9324d;
|
||||
--accept: #1a8c4e;
|
||||
--decline: #c0392b;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 3+4. JS-Override via data-theme auf <html> ───────────────────────────── */
|
||||
/* :root[data-theme] hat Spezifität (0,2,0) und schlägt :root (0,1,0) immer. */
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
color-scheme: dark;
|
||||
|
||||
--color-bg: #0e0c15;
|
||||
--color-card: #19162a;
|
||||
--color-secondary: #272338;
|
||||
--color-surface: #201d2f;
|
||||
--color-text: #eae8f0;
|
||||
--color-muted: #8a879a;
|
||||
--color-primary: #e94560;
|
||||
--color-primary-rgb: 233, 69, 96;
|
||||
--color-success: #27ae60;
|
||||
--color-danger: #e74c3c;
|
||||
--color-border: #272338;
|
||||
--color-hover: #272338;
|
||||
--shadow: 0 8px 32px rgba(0, 0, 0, 0.55);
|
||||
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.35);
|
||||
--overlay-bg: rgba(0, 0, 0, 0.55);
|
||||
--msg-error-bg: #3d0f1a;
|
||||
--msg-warning-bg: #3a2c0a;
|
||||
--msg-warning-text: #f5c518;
|
||||
--msg-success-bg: #0f3d1a;
|
||||
--btn-primary-hover: #c73652;
|
||||
--btn-secondary-hover: #1a3a6a;
|
||||
--placeholder: rgba(234, 232, 240, 0.35);
|
||||
--unread: #e94560;
|
||||
--accept: #27ae60;
|
||||
--decline: #c0392b;
|
||||
}
|
||||
|
||||
:root[data-theme="light"] {
|
||||
color-scheme: light;
|
||||
|
||||
--color-bg: #f2f0f9;
|
||||
--color-card: #ffffff;
|
||||
--color-secondary: #e9e6f5;
|
||||
--color-surface: #f7f5fc;
|
||||
--color-text: #1a1628;
|
||||
--color-muted: #6a677e;
|
||||
--color-primary: #c9324d;
|
||||
--color-primary-rgb: 201, 50, 77;
|
||||
--color-success: #1a8c4e;
|
||||
--color-danger: #c0392b;
|
||||
--color-border: #d8d4ed;
|
||||
--color-hover: #e9e6f5;
|
||||
--shadow: 0 4px 16px rgba(0, 0, 0, 0.10);
|
||||
--shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.06);
|
||||
--overlay-bg: rgba(0, 0, 0, 0.35);
|
||||
--msg-error-bg: #fde8ec;
|
||||
--msg-warning-bg: #fdf5e0;
|
||||
--msg-warning-text: #b38800;
|
||||
--msg-success-bg: #e0f5e8;
|
||||
--btn-primary-hover: #a82942;
|
||||
--btn-secondary-hover: #d8d4ed;
|
||||
--placeholder: rgba(26, 22, 40, 0.30);
|
||||
--unread: #c9324d;
|
||||
--accept: #1a8c4e;
|
||||
--decline: #c0392b;
|
||||
}
|
||||
@@ -39,19 +39,16 @@
|
||||
}
|
||||
.game-timer.urgent { color: #e74c3c; }
|
||||
|
||||
.game-level-bar {
|
||||
.level-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
justify-content: center;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.game-level-dot {
|
||||
width: 10px; height: 10px;
|
||||
border-radius: 50%;
|
||||
background: var(--color-secondary);
|
||||
transition: background 0.3s;
|
||||
.level-display img {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.game-level-dot.active { background: var(--color-primary); }
|
||||
|
||||
.lock-messages {
|
||||
background: rgba(233,69,96,0.1);
|
||||
@@ -120,19 +117,14 @@
|
||||
#finisherBox h2 { font-size: 1.1rem; margin: 0 0 0.75rem; color: var(--color-primary); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" class="container" style="max-width:480px;margin:0 auto;padding:1rem;">
|
||||
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1.25rem;">
|
||||
<button id="btnBack" onclick="goBack()"
|
||||
style="background:none;border:none;color:var(--color-muted);font-size:1.3rem;cursor:pointer;padding:0.2rem 0.4rem;">‹</button>
|
||||
<h1 style="margin:0;font-size:1.15rem;font-weight:700;">🎯 Task Game</h1>
|
||||
</div>
|
||||
<body class="app">
|
||||
<div class="main">
|
||||
<div class="content">
|
||||
<h2 style="margin-bottom:1.25rem;">🎯 Task Game</h2>
|
||||
|
||||
<!-- Level-Anzeige -->
|
||||
<div class="game-level-bar" id="levelBar" style="display:none;">
|
||||
<span style="font-size:0.78rem;color:var(--color-muted);font-weight:600;">Level</span>
|
||||
<div id="levelDots" style="display:flex;gap:0.35rem;"></div>
|
||||
<span id="levelText" style="font-size:0.78rem;color:var(--color-muted);margin-left:auto;"></span>
|
||||
<div class="level-display" id="levelDisplay" style="display:none;">
|
||||
<img id="levelImg" src="" alt="Level">
|
||||
</div>
|
||||
|
||||
<!-- Freigegebene Locks (checkLocks-Meldungen) -->
|
||||
@@ -186,8 +178,11 @@
|
||||
</div>
|
||||
<div id="errorBox" style="display:none;background:rgba(231,76,60,0.1);border:1px solid rgba(231,76,60,0.3);
|
||||
border-radius:10px;padding:1rem;font-size:0.88rem;color:#e74c3c;margin-top:1rem;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/icons.js"></script>
|
||||
<script src="/js/nav.js"></script>
|
||||
<script>
|
||||
const params = new URLSearchParams(location.search);
|
||||
const lockId = params.get('lockId');
|
||||
@@ -411,13 +406,9 @@
|
||||
// ── Level-Bar ─────────────────────────────────────────────────────────────
|
||||
|
||||
function renderLevelBar(level) {
|
||||
const bar = document.getElementById('levelBar');
|
||||
const dots = document.getElementById('levelDots');
|
||||
dots.innerHTML = [1,2,3,4,5].map(i =>
|
||||
`<div class="game-level-dot${i <= level ? ' active' : ''}"></div>`
|
||||
).join('');
|
||||
document.getElementById('levelText').textContent = 'Level ' + Math.min(level, 5);
|
||||
show('levelBar');
|
||||
const lvl = Math.min(Math.max(level, 1), 5);
|
||||
document.getElementById('levelImg').src = `/img/lvl${lvl}.png`;
|
||||
show('levelDisplay');
|
||||
}
|
||||
|
||||
// ── Timer ─────────────────────────────────────────────────────────────────
|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 18 KiB |
@@ -1,4 +1,23 @@
|
||||
(function () {
|
||||
// ── Theme-Init (synchron, vor allem anderen) ──────────────────────────────
|
||||
window._applyTheme = function (theme) {
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
};
|
||||
(function () {
|
||||
const saved = localStorage.getItem('xxx-theme');
|
||||
if (saved === 'light' || saved === 'dark') {
|
||||
window._applyTheme(saved);
|
||||
} else {
|
||||
const prefersLight = window.matchMedia('(prefers-color-scheme: light)').matches;
|
||||
window._applyTheme(prefersLight ? 'light' : 'dark');
|
||||
}
|
||||
})();
|
||||
window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', function (e) {
|
||||
if (!localStorage.getItem('xxx-theme')) {
|
||||
window._applyTheme(e.matches ? 'light' : 'dark');
|
||||
}
|
||||
});
|
||||
|
||||
const path = window.location.pathname;
|
||||
const I = window.IC || function () { return ''; };
|
||||
|
||||
|
||||
@@ -496,8 +496,8 @@ function startPostEdit(cfg) {
|
||||
</div>`).join('')}
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:0.3rem;" onclick="event.stopPropagation()">
|
||||
<button onmousedown="event.stopPropagation()" onclick="event.stopPropagation();${addOptionFn}('${postId}')" style="width:auto;margin:0;padding:0.3rem 0.75rem;font-size:0.8rem;">+ Option</button>
|
||||
<label class="multi-toggle" onmousedown="event.stopPropagation()" onclick="event.stopPropagation()">
|
||||
<input type="checkbox" id="${prefix}mc-${postId}" ${data.multiChoice ? 'checked' : ''}> Mehrfachauswahl möglich
|
||||
<label class="toggle-switch" onmousedown="event.stopPropagation()" onclick="event.stopPropagation()">
|
||||
<input type="checkbox" id="${prefix}mc-${postId}" ${data.multiChoice ? 'checked' : ''}><span class="toggle-track"></span> Mehrfachauswahl möglich
|
||||
</label>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
(function () {
|
||||
if (document.querySelector('.topbar')) return;
|
||||
|
||||
function _applyTheme(theme) {
|
||||
window._applyTheme ? window._applyTheme(theme) : document.documentElement.setAttribute('data-theme', theme);
|
||||
}
|
||||
|
||||
window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', e => {
|
||||
if (!localStorage.getItem('xxx-theme')) {
|
||||
_applyTheme(e.matches ? 'light' : 'dark');
|
||||
}
|
||||
});
|
||||
|
||||
function esc(s) {
|
||||
return String(s ?? '')
|
||||
.replace(/&/g, '&').replace(/</g, '<')
|
||||
@@ -99,6 +109,13 @@
|
||||
<a id="topbarProfileLink" href="/community/benutzer.html" class="topbar-profile-link">
|
||||
<span>${IC('PROFILE')}</span> Mein Profil
|
||||
</a>
|
||||
<label class="topbar-profile-link topbar-theme-row" title="Dark / Light Mode">
|
||||
<span>☾ Dark Mode</span>
|
||||
<span class="toggle-switch" style="gap:0;">
|
||||
<input type="checkbox" id="topbarDarkModeCheck">
|
||||
<span class="toggle-track"></span>
|
||||
</span>
|
||||
</label>
|
||||
<a href="/konto/einstellungen.html" class="topbar-profile-link">
|
||||
<span>${IC('SETTINGS')}</span> Einstellungen
|
||||
</a>
|
||||
@@ -139,10 +156,37 @@
|
||||
}
|
||||
const profileLink = document.getElementById('topbarProfileLink');
|
||||
if (profileLink && user.userId) profileLink.href = '/community/benutzer.html?userId=' + user.userId;
|
||||
|
||||
// Theme aus DB anwenden (überschreibt OS-Fallback aus nav.js)
|
||||
let theme;
|
||||
if (user.darkMode === true) { theme = 'dark'; localStorage.setItem('xxx-theme', 'dark'); }
|
||||
else if (user.darkMode === false) { theme = 'light'; localStorage.setItem('xxx-theme', 'light'); }
|
||||
else { // null → OS-Präferenz, localStorage-Cache löschen
|
||||
localStorage.removeItem('xxx-theme');
|
||||
theme = window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
|
||||
}
|
||||
_applyTheme(theme);
|
||||
setupDarkModeCheckbox(theme === 'dark');
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
function setupDarkModeCheckbox(isDark) {
|
||||
const cb = document.getElementById('topbarDarkModeCheck');
|
||||
if (!cb) return;
|
||||
cb.checked = isDark;
|
||||
cb.addEventListener('change', () => {
|
||||
const dark = cb.checked;
|
||||
_applyTheme(dark ? 'dark' : 'light');
|
||||
localStorage.setItem('xxx-theme', dark ? 'dark' : 'light');
|
||||
fetch('/user/me/theme', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ darkMode: dark })
|
||||
}).catch(() => {});
|
||||
});
|
||||
}
|
||||
|
||||
// ── Suche ──
|
||||
function setupSearch() {
|
||||
const input = document.getElementById('topbarSearchInput');
|
||||
|
||||
@@ -382,10 +382,10 @@
|
||||
<div class="settings-row-desc">Einladungen zu Locks und Spielen, Annahmen und Ablehnungen</div>
|
||||
</div>
|
||||
<div class="notif-col-check">
|
||||
<input type="checkbox" id="notif-INVITATION-inApp" onchange="saveNotifications()">
|
||||
<label class="toggle-switch"><input type="checkbox" id="notif-INVITATION-inApp" onchange="saveNotifications()"><span class="toggle-track"></span></label>
|
||||
</div>
|
||||
<div class="notif-col-check">
|
||||
<input type="checkbox" id="notif-INVITATION-email" onchange="saveNotifications()">
|
||||
<label class="toggle-switch"><input type="checkbox" id="notif-INVITATION-email" onchange="saveNotifications()"><span class="toggle-track"></span></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -396,10 +396,10 @@
|
||||
<div class="settings-row-desc">Karten, Aufgaben, Verifikationen, Einfrierungen und andere Spielereignisse</div>
|
||||
</div>
|
||||
<div class="notif-col-check">
|
||||
<input type="checkbox" id="notif-GAME_STATE-inApp" onchange="saveNotifications()">
|
||||
<label class="toggle-switch"><input type="checkbox" id="notif-GAME_STATE-inApp" onchange="saveNotifications()"><span class="toggle-track"></span></label>
|
||||
</div>
|
||||
<div class="notif-col-check">
|
||||
<input type="checkbox" id="notif-GAME_STATE-email" onchange="saveNotifications()">
|
||||
<label class="toggle-switch"><input type="checkbox" id="notif-GAME_STATE-email" onchange="saveNotifications()"><span class="toggle-track"></span></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -410,10 +410,10 @@
|
||||
<div class="settings-row-desc">Notfall-Entsperrungen und dringende Meldungen</div>
|
||||
</div>
|
||||
<div class="notif-col-check">
|
||||
<input type="checkbox" id="notif-EMERGENCY-inApp" onchange="saveNotifications()">
|
||||
<label class="toggle-switch"><input type="checkbox" id="notif-EMERGENCY-inApp" onchange="saveNotifications()"><span class="toggle-track"></span></label>
|
||||
</div>
|
||||
<div class="notif-col-check">
|
||||
<input type="checkbox" id="notif-EMERGENCY-email" onchange="saveNotifications()">
|
||||
<label class="toggle-switch"><input type="checkbox" id="notif-EMERGENCY-email" onchange="saveNotifications()"><span class="toggle-track"></span></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -424,11 +424,10 @@
|
||||
<div class="settings-row-desc">Neue Freundschaftsanfragen von anderen Nutzern</div>
|
||||
</div>
|
||||
<div class="notif-col-check">
|
||||
<input type="checkbox" id="notif-FRIENDREQUEST-inApp" checked disabled
|
||||
title="In-App-Benachrichtigungen für Freundschaftsanfragen sind immer aktiv">
|
||||
<label class="toggle-switch" title="In-App-Benachrichtigungen für Freundschaftsanfragen sind immer aktiv"><input type="checkbox" id="notif-FRIENDREQUEST-inApp" checked disabled><span class="toggle-track"></span></label>
|
||||
</div>
|
||||
<div class="notif-col-check">
|
||||
<input type="checkbox" id="notif-FRIENDREQUEST-email" onchange="saveNotifications()">
|
||||
<label class="toggle-switch"><input type="checkbox" id="notif-FRIENDREQUEST-email" onchange="saveNotifications()"><span class="toggle-track"></span></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -484,8 +483,9 @@
|
||||
<div class="settings-row-label">Dating aktivieren</div>
|
||||
<div class="settings-row-desc">Zeige dein Profil im Dating-Bereich. Ein Standort ist erforderlich.</div>
|
||||
</div>
|
||||
<label style="display:flex;align-items:center;gap:0.5rem;cursor:pointer;">
|
||||
<input type="checkbox" id="datingAktiv" style="width:1.1rem;height:1.1rem;accent-color:var(--color-primary);cursor:pointer;" onchange="onDatingToggle()">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="datingAktiv" onchange="onDatingToggle()">
|
||||
<span class="toggle-track"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="datingSucheRow" style="display:none;">
|
||||
|
||||
@@ -365,16 +365,12 @@
|
||||
<div id="homeOptionList"></div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:0.5rem;">
|
||||
<button onclick="homeAddOption()" style="width:auto;margin:0;padding:0.3rem 0.75rem;font-size:0.8rem;">+ Option</button>
|
||||
<label class="multi-toggle">
|
||||
<input type="checkbox" id="homeMultiChoice"> Mehrfachauswahl möglich
|
||||
</label>
|
||||
<label class="toggle-switch"><input type="checkbox" id="homeMultiChoice"><span class="toggle-track"></span> Mehrfachauswahl möglich</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compose-footer">
|
||||
<div style="display:flex;gap:1rem;align-items:center;flex-wrap:wrap;">
|
||||
<label class="privacy-toggle">
|
||||
<input type="checkbox" id="homeIsPublic"> Öffentlich
|
||||
</label>
|
||||
<label class="toggle-switch"><input type="checkbox" id="homeIsPublic"><span class="toggle-track"></span> Öffentlich</label>
|
||||
</div>
|
||||
<div style="display:flex;gap:0.5rem;align-items:center;">
|
||||
<button type="button" class="compose-action-btn" onclick="toggleEmojiPicker(this,'homeComposeText')" title="Emoji einfügen">😊</button>
|
||||
|
||||