mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-26 12:08:15 +00:00
fix(extension): unify status UX and theme design
This commit is contained in:
@@ -25,6 +25,22 @@
|
||||
--text-muted: var(--text-secondary);
|
||||
--border: var(--border-strong);
|
||||
--radius: 8px;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
html.theme-light {
|
||||
--bg-base: oklch(0.965 0.012 105);
|
||||
--surface: oklch(0.995 0.006 100);
|
||||
--surface-deep: oklch(0.935 0.018 110);
|
||||
--surface-alt: oklch(0.91 0.022 115);
|
||||
--border-soft: oklch(0.28 0.035 140 / 0.10);
|
||||
--border-strong: oklch(0.73 0.035 125);
|
||||
--text-primary: oklch(0.21 0.03 140);
|
||||
--text-secondary: oklch(0.43 0.03 135);
|
||||
--accent-green: oklch(0.52 0.13 155);
|
||||
--accent-green-hover: oklch(0.45 0.12 155);
|
||||
--text-on-green: oklch(0.98 0.005 100);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
* {
|
||||
@@ -100,6 +116,10 @@ h2 {
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
html.theme-light .panel {
|
||||
box-shadow: 0 12px 30px oklch(0.22 0.035 140 / 0.09);
|
||||
}
|
||||
|
||||
.muted-panel {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
@@ -142,12 +162,12 @@ h2 {
|
||||
transition: border-color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
.preset-card:hover {
|
||||
border-color: rgba(86, 174, 108, 0.4);
|
||||
border-color: color-mix(in oklch, var(--accent), transparent 60%);
|
||||
}
|
||||
|
||||
.preset-card:has(input:checked) {
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 1px rgba(86, 174, 108, 0.35);
|
||||
box-shadow: 0 0 0 1px color-mix(in oklch, var(--accent), transparent 65%);
|
||||
}
|
||||
|
||||
.preset-card input {
|
||||
@@ -158,8 +178,8 @@ h2 {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
background: rgba(16, 25, 14, 0.58);
|
||||
border: 1px solid rgba(163, 162, 148, 0.16);
|
||||
background: var(--surface-deep);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: var(--radius);
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>KoalaSync Audio Settings</title>
|
||||
<script src="theme-init.js"></script>
|
||||
<link rel="stylesheet" href="audio-options.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
+129
-48
@@ -40,6 +40,10 @@
|
||||
--success: var(--success-green);
|
||||
--warning: var(--warning-amber);
|
||||
--error: var(--danger);
|
||||
--status-success-text: oklch(0.84 0.12 140);
|
||||
--status-warning-text: oklch(0.86 0.13 80);
|
||||
--status-error-text: oklch(0.78 0.13 25);
|
||||
--status-neutral-text: oklch(0.76 0.02 110);
|
||||
--radius: 12px;
|
||||
--star: var(--warning);
|
||||
color-scheme: dark;
|
||||
@@ -62,6 +66,10 @@
|
||||
--danger: oklch(0.57 0.17 25);
|
||||
--text-on-green: oklch(0.16 0.03 140);
|
||||
--text-on-warm: oklch(0.18 0.03 45);
|
||||
--status-success-text: oklch(0.39 0.13 140);
|
||||
--status-warning-text: oklch(0.43 0.12 75);
|
||||
--status-error-text: oklch(0.46 0.16 25);
|
||||
--status-neutral-text: oklch(0.43 0.02 120);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
@@ -316,6 +324,11 @@
|
||||
animation: pulseGreen 2s infinite ease-in-out;
|
||||
}
|
||||
.status-offline { background: var(--error); }
|
||||
.status-connecting {
|
||||
background: var(--warning);
|
||||
box-shadow: 0 0 8px color-mix(in oklch, var(--warning), transparent 30%);
|
||||
}
|
||||
.status-idle { background: var(--status-neutral-text); }
|
||||
|
||||
@keyframes pulseGreen {
|
||||
0% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--success), transparent 30%); }
|
||||
@@ -337,12 +350,12 @@
|
||||
}
|
||||
.badge-ready {
|
||||
background: color-mix(in oklch, var(--success), transparent 85%);
|
||||
color: var(--success);
|
||||
color: var(--status-success-text);
|
||||
border: 1px solid color-mix(in oklch, var(--success), transparent 70%);
|
||||
}
|
||||
.badge-loading {
|
||||
background: color-mix(in oklch, var(--warning), transparent 85%);
|
||||
color: var(--warning);
|
||||
color: var(--status-warning-text);
|
||||
border: 1px solid color-mix(in oklch, var(--warning), transparent 70%);
|
||||
}
|
||||
.lobby-peer-item {
|
||||
@@ -364,15 +377,48 @@
|
||||
overflow-y: auto;
|
||||
font-size: 10px;
|
||||
font-family: monospace;
|
||||
background: #000;
|
||||
background: var(--surface-deep);
|
||||
padding: 8px;
|
||||
border-radius: 8px;
|
||||
color: #ccc;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.log-entry { margin-bottom: 4px; }
|
||||
.log-error { color: var(--error); }
|
||||
.log-success { color: var(--success); }
|
||||
.log-error { color: var(--status-error-text); }
|
||||
.log-success { color: var(--status-success-text); }
|
||||
|
||||
.conn-ping {
|
||||
min-width: 48px;
|
||||
min-height: 24px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 3px 7px;
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 999px;
|
||||
background: var(--surface-deep);
|
||||
color: var(--status-neutral-text);
|
||||
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
.conn-ping:empty { display: none; }
|
||||
.conn-ping-good {
|
||||
border-color: color-mix(in oklch, var(--success), transparent 70%);
|
||||
background: color-mix(in oklch, var(--success), var(--surface-deep) 88%);
|
||||
color: var(--status-success-text);
|
||||
}
|
||||
.conn-ping-warning {
|
||||
border-color: color-mix(in oklch, var(--warning), transparent 62%);
|
||||
background: color-mix(in oklch, var(--warning), var(--surface-deep) 86%);
|
||||
color: var(--status-warning-text);
|
||||
}
|
||||
.conn-ping-bad {
|
||||
border-color: color-mix(in oklch, var(--error), transparent 62%);
|
||||
background: color-mix(in oklch, var(--error), var(--surface-deep) 87%);
|
||||
color: var(--status-error-text);
|
||||
}
|
||||
|
||||
/* Invite Link */
|
||||
.invite-box {
|
||||
@@ -509,7 +555,7 @@
|
||||
width: 14px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: #a3a294;
|
||||
background-color: var(--status-neutral-text);
|
||||
transition: .3s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
@@ -521,47 +567,38 @@
|
||||
background-color: white;
|
||||
}
|
||||
.popup-footer {
|
||||
margin-top: 18px;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: var(--radius);
|
||||
background: color-mix(in oklch, var(--card), var(--accent) 5%);
|
||||
}
|
||||
.footer-support {
|
||||
margin-top: 16px;
|
||||
padding: 11px 2px 2px;
|
||||
border-top: 1px solid var(--border-soft);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid var(--border-soft);
|
||||
}
|
||||
.footer-prompt {
|
||||
margin: 0;
|
||||
color: var(--text);
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
gap: 10px;
|
||||
}
|
||||
.footer-review {
|
||||
flex: none;
|
||||
min-height: 30px;
|
||||
padding: 7px 10px;
|
||||
border-radius: 8px;
|
||||
background: var(--warning);
|
||||
color: var(--text-on-warm) !important;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
min-height: 26px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid color-mix(in oklch, var(--warning), transparent 68%);
|
||||
border-radius: 7px;
|
||||
background: color-mix(in oklch, var(--warning), transparent 91%);
|
||||
color: var(--status-warning-text) !important;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.footer-links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
padding-top: 8px;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.footer-links a {
|
||||
min-height: 28px;
|
||||
padding: 6px 9px;
|
||||
border-radius: 7px;
|
||||
min-height: 26px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 7px;
|
||||
border-radius: 6px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -721,6 +758,51 @@
|
||||
text-align: left;
|
||||
text-align-last: left;
|
||||
}
|
||||
.theme-picker {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
width: 154px;
|
||||
padding: 3px;
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: 10px;
|
||||
background: var(--surface-deep);
|
||||
}
|
||||
.theme-picker select {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
.theme-choice {
|
||||
min-width: 0;
|
||||
min-height: 32px;
|
||||
margin: 0;
|
||||
padding: 0 4px;
|
||||
border: 0;
|
||||
border-radius: 7px;
|
||||
background: transparent;
|
||||
color: var(--text-muted);
|
||||
font-family: inherit;
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;
|
||||
}
|
||||
.theme-choice:hover {
|
||||
color: var(--text);
|
||||
}
|
||||
.theme-choice.active {
|
||||
background: var(--surface-alt);
|
||||
color: var(--text);
|
||||
box-shadow: 0 1px 5px oklch(0.08 0.02 150 / 0.32), inset 0 0 0 1px var(--border-soft);
|
||||
}
|
||||
.settings-row .toggle-switch {
|
||||
justify-self: end;
|
||||
margin: 0 2px 0 0;
|
||||
@@ -846,11 +928,10 @@
|
||||
background-color: white;
|
||||
}
|
||||
html.theme-light .popup-footer {
|
||||
border-color: var(--border-soft);
|
||||
box-shadow: 0 8px 24px oklch(0.22 0.035 140 / 0.07);
|
||||
border-top-color: var(--border-soft);
|
||||
}
|
||||
html.theme-light .tab-btn.active {
|
||||
color: #fff;
|
||||
color: var(--text-on-green);
|
||||
}
|
||||
.feature-hint {
|
||||
display: inline-block;
|
||||
@@ -1059,13 +1140,16 @@
|
||||
</div>
|
||||
<div class="settings-row">
|
||||
<label id="themeLabel" for="themeSelector" title="Follow the system theme or choose a fixed appearance">Appearance</label>
|
||||
<span class="settings-select">
|
||||
<select id="themeSelector" class="settings-control" aria-label="Appearance">
|
||||
<div class="theme-picker" role="group" aria-labelledby="themeLabel">
|
||||
<select id="themeSelector" aria-label="Appearance" tabindex="-1">
|
||||
<option id="themeOptionSystem" value="system">System</option>
|
||||
<option id="themeOptionDark" value="dark">Dark</option>
|
||||
<option id="themeOptionLight" value="light">Light</option>
|
||||
</select>
|
||||
</span>
|
||||
<button id="themeChoiceSystem" class="theme-choice" type="button" data-theme-value="system">System</button>
|
||||
<button id="themeChoiceDark" class="theme-choice" type="button" data-theme-value="dark">Dark</button>
|
||||
<button id="themeChoiceLight" class="theme-choice" type="button" data-theme-value="light">Light</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-row">
|
||||
<label for="langSelector" data-i18n="LABEL_LANGUAGE" data-i18n-title="LABEL_LANGUAGE_TOOLTIP" title="Choose your preferred extension language">App Language</label>
|
||||
@@ -1175,7 +1259,7 @@
|
||||
<span id="connText">Disconnected</span>
|
||||
<span id="connInfo" data-i18n-title="STATUS_IDLE_TOOLTIP" title="KoalaSync is ready. Join or create a room to connect and start syncing." style="display:none; cursor:help; flex:none; width:15px; height:15px; line-height:14px; text-align:center; border-radius:50%; border:1px solid var(--text-muted); color:var(--text-muted); font-size:10px; font-weight:700; font-style:normal;">i</span>
|
||||
</span>
|
||||
<span id="connPing" style="font-size:11px; font-family:monospace; font-weight:600; opacity:0.8;"></span>
|
||||
<span id="connPing" class="conn-ping"></span>
|
||||
<button id="retryBtn" class="secondary" style="display:none; width: auto; padding: 4px 8px; font-size: 10px; margin: 0;" title="Attempt to reconnect to the server" data-i18n="BTN_RETRY" data-i18n-title="BTN_RETRY_TOOLTIP">RETRY</button>
|
||||
<button id="copyLogs" class="btn secondary" style="width: auto; padding: 4px 10px; font-size: 11px; margin: 0;" title="Copy logs to clipboard for sharing" data-i18n="BTN_COPY_LOGS" data-i18n-title="BTN_COPY_LOGS_TOOLTIP">Copy Logs</button>
|
||||
</div>
|
||||
@@ -1212,14 +1296,11 @@
|
||||
</div>
|
||||
|
||||
<div class="popup-footer">
|
||||
<div class="footer-support">
|
||||
<p class="footer-prompt" data-i18n="FOOTER_SUPPORT_PROMPT">Enjoying KoalaSync? Leave a review!</p>
|
||||
<a id="settingsReviewLink" class="footer-review" href="#" target="_blank" data-i18n="FOOTER_REVIEW">★ Rate us</a>
|
||||
</div>
|
||||
<nav class="footer-links" aria-label="KoalaSync links">
|
||||
<a href="https://github.com/Shik3i/KoalaSync" target="_blank" data-i18n="LABEL_GITHUB">GitHub</a>
|
||||
<a id="settingsSupportLink" href="#" target="_blank" data-i18n="FOOTER_SUPPORT">Support</a>
|
||||
</nav>
|
||||
<a id="settingsReviewLink" class="footer-review" href="#" target="_blank" data-i18n="FOOTER_REVIEW">★ Rate us</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
+48
-40
@@ -149,13 +149,28 @@ function localizeThemeSelector(locale) {
|
||||
const systemEl = document.getElementById('themeOptionSystem');
|
||||
const darkEl = document.getElementById('themeOptionDark');
|
||||
const lightEl = document.getElementById('themeOptionLight');
|
||||
const systemButton = document.getElementById('themeChoiceSystem');
|
||||
const darkButton = document.getElementById('themeChoiceDark');
|
||||
const lightButton = document.getElementById('themeChoiceLight');
|
||||
if (labelEl) labelEl.textContent = label;
|
||||
if (systemEl) systemEl.textContent = system;
|
||||
if (darkEl) darkEl.textContent = dark;
|
||||
if (lightEl) lightEl.textContent = light;
|
||||
if (systemButton) systemButton.textContent = system;
|
||||
if (darkButton) darkButton.textContent = dark;
|
||||
if (lightButton) lightButton.textContent = light;
|
||||
if (elements.themeSelector) elements.themeSelector.setAttribute('aria-label', label);
|
||||
}
|
||||
|
||||
function syncThemePicker() {
|
||||
const activeMode = elements.themeSelector?.value || 'system';
|
||||
document.querySelectorAll('.theme-choice').forEach(button => {
|
||||
const active = button.dataset.themeValue === activeMode;
|
||||
button.classList.toggle('active', active);
|
||||
button.setAttribute('aria-pressed', String(active));
|
||||
});
|
||||
}
|
||||
|
||||
async function updateFeatureHints() {
|
||||
const data = await chrome.storage.sync.get(['dismissedHints']);
|
||||
const dismissed = Array.isArray(data.dismissedHints) ? data.dismissedHints : [];
|
||||
@@ -242,6 +257,7 @@ async function init() {
|
||||
|
||||
if (elements.langSelector) elements.langSelector.value = activeLang;
|
||||
if (elements.themeSelector) elements.themeSelector.value = ['dark', 'light'].includes(localData.themeMode) ? localData.themeMode : 'system';
|
||||
syncThemePicker();
|
||||
|
||||
let username = localData.username;
|
||||
if (!username) {
|
||||
@@ -555,7 +571,7 @@ function updateLastActionUI(state, peers) {
|
||||
if (pId === localPeerId) return;
|
||||
const pName = (typeof peer === 'object' && peer.username) ? peer.username : pId.substring(0, 4);
|
||||
const isAcked = safeAcks.includes(pId) || pId === state.senderId;
|
||||
const color = isAcked ? 'var(--success)' : '#4c5142';
|
||||
const color = isAcked ? 'var(--success)' : 'var(--border-strong)';
|
||||
const icon = isAcked ? '✓' : '...';
|
||||
const avatar = getAvatarForName(pName);
|
||||
|
||||
@@ -705,7 +721,7 @@ function updatePeerList(peers) {
|
||||
|
||||
const peerItem = document.createElement('div');
|
||||
peerItem.className = 'peer-item';
|
||||
peerItem.style.cssText = 'position:relative; display:block; padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,0.05);';
|
||||
peerItem.style.cssText = 'position:relative; display:block; padding: 8px 0; border-bottom: 1px solid var(--border-soft);';
|
||||
|
||||
const header = document.createElement('div');
|
||||
header.style.cssText = 'display:flex; justify-content:space-between; align-items:center; padding-right: 24px;';
|
||||
@@ -715,7 +731,7 @@ function updatePeerList(peers) {
|
||||
const avatar = getAvatarForName(pUsername || pId);
|
||||
if (pUsername) {
|
||||
const u = document.createElement('span');
|
||||
u.style.cssText = 'font-weight:600; color:white; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; display: inline-block;';
|
||||
u.style.cssText = 'font-weight:600; color:var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; display: inline-block;';
|
||||
u.textContent = `${avatar} ${pUsername}`;
|
||||
const i = document.createElement('span');
|
||||
i.style.cssText = 'font-size:10px; opacity:0.6; font-style:italic; white-space: nowrap; flex-shrink: 0;';
|
||||
@@ -1040,25 +1056,8 @@ function applyConnectionStatus(status) {
|
||||
const idle = status === 'idle';
|
||||
|
||||
if (elements.connDot) {
|
||||
elements.connDot.className = 'status-dot ' + (connected ? 'status-online' : ((connecting || reconnecting) ? 'status-online' : 'status-offline'));
|
||||
|
||||
if (reconnecting) {
|
||||
elements.connDot.style.background = '#c96736';
|
||||
elements.connDot.style.boxShadow = '0 0 8px #c96736';
|
||||
} else if (connecting) {
|
||||
elements.connDot.style.background = '#de7949';
|
||||
elements.connDot.style.boxShadow = '0 0 8px #de7949';
|
||||
} else if (idle) {
|
||||
// Neutral grey — ready, not failed.
|
||||
elements.connDot.style.background = '#bcb7a9';
|
||||
elements.connDot.style.boxShadow = 'none';
|
||||
} else if (!connected) {
|
||||
elements.connDot.style.background = '#b94642';
|
||||
elements.connDot.style.boxShadow = 'none';
|
||||
} else {
|
||||
elements.connDot.style.background = '';
|
||||
elements.connDot.style.boxShadow = '';
|
||||
}
|
||||
const dotStatus = connected ? 'status-online' : ((connecting || reconnecting) ? 'status-connecting' : (idle ? 'status-idle' : 'status-offline'));
|
||||
elements.connDot.className = `status-dot ${dotStatus}`;
|
||||
}
|
||||
|
||||
if (elements.connText) {
|
||||
@@ -1095,16 +1094,16 @@ function updatePingDisplay(pingMs) {
|
||||
if (!elements.connPing) return;
|
||||
if (pingMs === null || pingMs === undefined || typeof pingMs !== 'number' || !Number.isFinite(pingMs)) {
|
||||
elements.connPing.textContent = '';
|
||||
elements.connPing.style.color = '';
|
||||
elements.connPing.className = 'conn-ping';
|
||||
return;
|
||||
}
|
||||
elements.connPing.textContent = `${Math.round(pingMs)}ms`;
|
||||
if (pingMs < 50) {
|
||||
elements.connPing.style.color = '#56ae6c';
|
||||
if (pingMs < 75) {
|
||||
elements.connPing.className = 'conn-ping conn-ping-good';
|
||||
} else if (pingMs < 150) {
|
||||
elements.connPing.style.color = '#c96736';
|
||||
elements.connPing.className = 'conn-ping conn-ping-warning';
|
||||
} else {
|
||||
elements.connPing.style.color = '#b94642';
|
||||
elements.connPing.className = 'conn-ping conn-ping-bad';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1122,10 +1121,10 @@ function updateHistory(history) {
|
||||
const actionLabel = item.action.toUpperCase().replace('FORCE_SYNC_', '');
|
||||
|
||||
const entry = document.createElement('div');
|
||||
entry.style.cssText = 'margin-bottom: 4px; border-bottom: 1px solid rgba(255,255,255,0.05); padding-bottom: 2px;';
|
||||
entry.style.cssText = 'margin-bottom: 4px; border-bottom: 1px solid var(--border-soft); padding-bottom: 2px;';
|
||||
|
||||
const timeSpan = document.createElement('span');
|
||||
timeSpan.style.color = '#6b705e';
|
||||
timeSpan.style.color = 'var(--text-muted)';
|
||||
timeSpan.textContent = `[${time}] `;
|
||||
|
||||
const actionBold = document.createElement('b');
|
||||
@@ -1168,7 +1167,7 @@ function updateRoomList(rooms) {
|
||||
rooms.forEach(r => {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'room-item';
|
||||
item.style.cssText = 'display:flex; justify-content:space-between; align-items:center; padding: 8px; border-bottom: 1px solid rgba(255,255,255,0.05); cursor:pointer;';
|
||||
item.style.cssText = 'display:flex; justify-content:space-between; align-items:center; padding: 8px; border-bottom: 1px solid var(--border-soft); cursor:pointer;';
|
||||
item.dataset.id = r.id;
|
||||
|
||||
const leftSide = document.createElement('div');
|
||||
@@ -1307,9 +1306,18 @@ if (elements.themeSelector) {
|
||||
const themeMode = elements.themeSelector.value;
|
||||
window.koalaTheme?.setMode(themeMode);
|
||||
chrome.storage.local.set({ themeMode });
|
||||
syncThemePicker();
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('.theme-choice').forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
if (!elements.themeSelector) return;
|
||||
elements.themeSelector.value = button.dataset.themeValue;
|
||||
elements.themeSelector.dispatchEvent(new window.Event('change'));
|
||||
});
|
||||
});
|
||||
|
||||
if (elements.audioSettingsLink) {
|
||||
elements.audioSettingsLink.addEventListener('click', async (event) => {
|
||||
event.preventDefault();
|
||||
@@ -2343,7 +2351,7 @@ function refreshDebugInfo() {
|
||||
|
||||
const addSection = (title) => {
|
||||
const div = document.createElement('div');
|
||||
div.style.cssText = 'margin: 8px 0 4px 0; border-bottom: 1px solid #2f3625; padding-bottom: 2px; color: var(--accent); font-weight: bold; font-size: 10px; text-transform: uppercase;';
|
||||
div.style.cssText = 'margin: 8px 0 4px 0; border-bottom: 1px solid var(--border-soft); padding-bottom: 2px; color: var(--accent); font-weight: bold; font-size: 10px; text-transform: uppercase;';
|
||||
div.textContent = title;
|
||||
elements.videoDebug.appendChild(div);
|
||||
};
|
||||
@@ -2352,7 +2360,7 @@ function refreshDebugInfo() {
|
||||
// No video found — show diagnostic info
|
||||
addSection('Video Detection');
|
||||
const notFound = document.createElement('div');
|
||||
notFound.style.cssText = 'color: #b94642; font-weight: 700; margin-bottom: 8px;';
|
||||
notFound.style.cssText = 'color: var(--status-error-text); font-weight: 700; margin-bottom: 8px;';
|
||||
notFound.textContent = 'NO VIDEO ELEMENT FOUND';
|
||||
elements.videoDebug.appendChild(notFound);
|
||||
|
||||
@@ -2370,7 +2378,7 @@ function refreshDebugInfo() {
|
||||
}
|
||||
|
||||
const hint = document.createElement('div');
|
||||
hint.style.cssText = 'margin-top: 12px; padding: 8px; background: rgba(222,121,73,0.12); border-left: 3px solid #de7949; border-radius: 4px; font-size: 10px; color: var(--text-muted);';
|
||||
hint.style.cssText = 'margin-top: 12px; padding: 8px; background: color-mix(in oklch, var(--warning), transparent 88%); border-left: 3px solid var(--warning); border-radius: 4px; font-size: 10px; color: var(--text);';
|
||||
hint.textContent = 'Is a video currently playing? The extension only detects <video> elements. Ensure media is actively loaded on the page.';
|
||||
elements.videoDebug.appendChild(hint);
|
||||
return;
|
||||
@@ -2378,12 +2386,12 @@ function refreshDebugInfo() {
|
||||
|
||||
// Video found — full debug
|
||||
addSection('Playback');
|
||||
addField('State', state.paused ? 'PAUSED' : 'PLAYING', state.paused ? 'var(--text-muted)' : '#56ae6c');
|
||||
addField('State', state.paused ? 'PAUSED' : 'PLAYING', state.paused ? 'var(--text-muted)' : 'var(--status-success-text)');
|
||||
addField('Time', `${state.currentTime.toFixed(2)}s / ${(state.duration || 0).toFixed(2)}s`);
|
||||
addField('ReadyState', `${state.readyState} (${state.readyStateLabel || '?'})`,
|
||||
state.readyState >= 3 ? '#56ae6c' : '#de7949');
|
||||
state.readyState >= 3 ? 'var(--status-success-text)' : 'var(--status-warning-text)');
|
||||
addField('Network', `${state.networkState} (${state.networkStateLabel || '?'})`,
|
||||
state.networkState === 1 ? '#56ae6c' : state.networkState === 3 ? '#b94642' : 'var(--text-muted)');
|
||||
state.networkState === 1 ? 'var(--status-success-text)' : state.networkState === 3 ? 'var(--status-error-text)' : 'var(--text-muted)');
|
||||
addField('Buffered', state.buffered || '?');
|
||||
if (state.nativeCurrentTime != null || state.nativeDuration != null) {
|
||||
addField('Native Time', `${state.nativeCurrentTime ?? '?'}s / ${state.nativeDuration ?? '?'}s`);
|
||||
@@ -2407,18 +2415,18 @@ function refreshDebugInfo() {
|
||||
|
||||
addSection('Dimensions');
|
||||
const dimsOk = state.videoWidth > 0 && state.videoHeight > 0;
|
||||
addField('Resolution', `${state.videoWidth}x${state.videoHeight}`, dimsOk ? '#56ae6c' : '#b94642');
|
||||
addField('Resolution', `${state.videoWidth}x${state.videoHeight}`, dimsOk ? 'var(--status-success-text)' : 'var(--status-error-text)');
|
||||
if (!dimsOk) {
|
||||
const dimHint = document.createElement('div');
|
||||
dimHint.style.cssText = 'color: #de7949; font-size: 9px; margin: 2px 0 6px 12px;';
|
||||
dimHint.style.cssText = 'color: var(--status-warning-text); font-size: 9px; margin: 2px 0 6px 12px;';
|
||||
dimHint.textContent = '0x0 = video element hidden or not yet loaded';
|
||||
elements.videoDebug.appendChild(dimHint);
|
||||
}
|
||||
|
||||
if (state.error) {
|
||||
addSection('Media Error');
|
||||
addField('Code', String(state.error.code), '#b94642');
|
||||
addField('Message', state.error.message || '?', '#b94642');
|
||||
addField('Code', String(state.error.code), 'var(--status-error-text)');
|
||||
addField('Message', state.error.message || '?', 'var(--status-error-text)');
|
||||
}
|
||||
|
||||
addSection('Detection');
|
||||
|
||||
Reference in New Issue
Block a user