kryten-webqueue 0.23.1__tar.gz → 0.24.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/CHANGELOG.md +9 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/PKG-INFO +1 -1
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/static/css/main.css +40 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/user/dashboard.html +96 -2
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/pyproject.toml +1 -1
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/.github/workflows/python-publish.yml +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/.github/workflows/release.yml +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/.gitignore +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/README.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/config.example.json +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/deploy/kryten-webqueue.service +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/deploy/nginx-queue.conf +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/IMPLEMENTATION_SPEC.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/IMPL_API_GATE.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/IMPL_ECONOMY.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/IMPL_KRYTEN_PY.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/IMPL_ROBOT.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/PLAN_PRESENCE_AND_PROMOS.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/PRE_PLAN_GAPS.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/PRODUCT_PLAN.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/SPEC_JOBS_AND_BROWSE.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/docs/UX_POLISH_PLAN.md +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/__main__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/api_gate/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/api_gate/client.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/app.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/auth/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/auth/otp.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/auth/rate_limit.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/auth/session.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/catalog/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/catalog/db.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/catalog/images.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/catalog/mediacms.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/catalog/sync.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/config.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/_common.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/enrichmeta.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/enrichtitles.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/enrichtv.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/fetchurls.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/ytpipe/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/ytpipe/downloader.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/jobs/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/jobs/fetchurls_auth.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/jobs/manager.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/jobs/tasks.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/logging_config.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/playlists/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/playlists/bulk_add.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/playlists/fire.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/playlists/importer.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/playlists/ordering.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/playlists/scheduler.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/promos/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/promos/director.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/queue/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/queue/ordering.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/queue/poller.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/queue/presence.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/queue/shadow.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/admin_catalog.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/admin_jobs.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/admin_playlists.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/admin_promos.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/admin_queue.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/admin_schedules.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/auth.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/catalog.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/pages.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/queue.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/routes/user.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/static/js/main.js +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/index.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/playlists.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/promos.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/queue_mgmt.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/schedules.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/auth/login.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/base.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/catalog/browse.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/catalog/item_detail.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/catalog/item_not_found.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/queue/index.html +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/ws/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/ws/handler.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/ws/manager.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/__init__.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_config_persistence.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_fetchurls_sharepoint.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_phase1.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_phase2_jobs.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_phase3_jobs.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_phase4_live_fixes.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_playlist_import.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_presence_refund.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_promo_director.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_promo_pool_exclusion.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_queue_announce.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_save_results_to_playlist.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_schedule_lock.py +0 -0
- {kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/tests/test_search_facets.py +0 -0
|
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.24.0] — 2026-06-21
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Live readability preview for the chat-color picker.** The dashboard's chat-color editor now previews the chosen color exactly as it renders in chat — a sample chat line (gray timestamp, username, message) on the near-black chat background (`#111`) — and scores it as you pick, mirroring kryten-economy's server-side guard (combined APCA lightness contrast × red-chroma penalty). A contrast badge reports **ok / warn / reject**: colors that fail the readability threshold (very dark colors and harsh pure reds) show a **reject** badge and the **Save button is disabled**, so users can't buy a color the server would refuse; borderline colors get a non-blocking **warn**. The thresholds (`reject < 30`, `warn < 40`) and background match the economy service so the dashboard and server always agree.
|
|
13
|
+
|
|
14
|
+
[0.24.0]: https://github.com/grobertson/kryten-webqueue/releases/tag/v0.24.0
|
|
15
|
+
|
|
7
16
|
## [0.23.1] — 2026-06-21
|
|
8
17
|
|
|
9
18
|
### Changed
|
|
@@ -1009,6 +1009,46 @@ a.np-chip {
|
|
|
1009
1009
|
text-transform: uppercase;
|
|
1010
1010
|
}
|
|
1011
1011
|
|
|
1012
|
+
/* Chat-color live preview + readability badge */
|
|
1013
|
+
.color-preview {
|
|
1014
|
+
background: #111;
|
|
1015
|
+
border: 1px solid var(--border);
|
|
1016
|
+
border-radius: var(--radius);
|
|
1017
|
+
padding: 0.6rem 0.75rem;
|
|
1018
|
+
margin: 0 0 0.6rem;
|
|
1019
|
+
font-size: 0.95rem;
|
|
1020
|
+
line-height: 1.5;
|
|
1021
|
+
}
|
|
1022
|
+
.color-preview .cp-ts { color: #AAA; }
|
|
1023
|
+
.color-preview .cp-name { font-weight: 700; }
|
|
1024
|
+
.color-preview .cp-msg { /* color set inline to the chosen value */ }
|
|
1025
|
+
.contrast-badge {
|
|
1026
|
+
display: flex;
|
|
1027
|
+
align-items: flex-start;
|
|
1028
|
+
gap: 0.5rem;
|
|
1029
|
+
font-size: 0.82rem;
|
|
1030
|
+
padding: 0.5rem 0.6rem;
|
|
1031
|
+
border-radius: var(--radius);
|
|
1032
|
+
margin-bottom: 0.75rem;
|
|
1033
|
+
border: 1px solid var(--border);
|
|
1034
|
+
}
|
|
1035
|
+
.contrast-badge .cb-icon { flex-shrink: 0; line-height: 1.3; }
|
|
1036
|
+
.contrast-badge.cb-ok {
|
|
1037
|
+
background: rgba(0, 184, 148, 0.10);
|
|
1038
|
+
border-color: var(--success, #00b894);
|
|
1039
|
+
color: var(--success, #00b894);
|
|
1040
|
+
}
|
|
1041
|
+
.contrast-badge.cb-warn {
|
|
1042
|
+
background: rgba(253, 203, 110, 0.12);
|
|
1043
|
+
border-color: var(--warning, #fdcb6e);
|
|
1044
|
+
color: var(--warning, #fdcb6e);
|
|
1045
|
+
}
|
|
1046
|
+
.contrast-badge.cb-reject {
|
|
1047
|
+
background: rgba(225, 112, 85, 0.12);
|
|
1048
|
+
border-color: var(--danger, #e17055);
|
|
1049
|
+
color: var(--danger, #e17055);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1012
1052
|
/* Transaction filter toggle */
|
|
1013
1053
|
.tx-toggle {
|
|
1014
1054
|
display: flex;
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/user/dashboard.html
RENAMED
|
@@ -293,15 +293,92 @@ async function saveGreeting() {
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
+
// ── Chat-color readability scoring (mirrors kryten-economy contrast.py) ──
|
|
297
|
+
// The economy server is authoritative and re-checks on purchase; this gives
|
|
298
|
+
// instant local preview/feedback. Defaults match the economy config defaults.
|
|
299
|
+
const CONTRAST_BG = '#111111';
|
|
300
|
+
const CONTRAST_MIN = 30.0; // reject below this combined score
|
|
301
|
+
const CONTRAST_WARN = 40.0; // warn below this
|
|
302
|
+
const CHROMA_KNEE = 160; // green+blue at which the red penalty clears
|
|
303
|
+
|
|
304
|
+
function _hexRgb(h) {
|
|
305
|
+
let s = h.replace('#', '');
|
|
306
|
+
if (s.length === 3) s = s.split('').map(c => c + c).join('');
|
|
307
|
+
return [parseInt(s.slice(0,2),16), parseInt(s.slice(2,4),16), parseInt(s.slice(4,6),16)];
|
|
308
|
+
}
|
|
309
|
+
function _screenY(h) {
|
|
310
|
+
const [r,g,b] = _hexRgb(h);
|
|
311
|
+
return 0.2126729*Math.pow(r/255,2.4) + 0.7151522*Math.pow(g/255,2.4) + 0.0721750*Math.pow(b/255,2.4);
|
|
312
|
+
}
|
|
313
|
+
function _apcaLc(textHex, bgHex) {
|
|
314
|
+
let yt = _screenY(textHex), yb = _screenY(bgHex);
|
|
315
|
+
if (yt <= 0.022) yt += Math.pow(0.022 - yt, 1.414);
|
|
316
|
+
if (yb <= 0.022) yb += Math.pow(0.022 - yb, 1.414);
|
|
317
|
+
if (Math.abs(yb - yt) < 0.0005) return 0;
|
|
318
|
+
let out;
|
|
319
|
+
if (yb > yt) { const s = (Math.pow(yb,0.56)-Math.pow(yt,0.57))*1.14; out = s < 0.1 ? 0 : s - 0.027; }
|
|
320
|
+
else { const s = (Math.pow(yb,0.65)-Math.pow(yt,0.62))*1.14; out = s > -0.1 ? 0 : s + 0.027; }
|
|
321
|
+
return Math.abs(out * 100);
|
|
322
|
+
}
|
|
323
|
+
function _chromaFactor(h) {
|
|
324
|
+
const [, g, b] = _hexRgb(h);
|
|
325
|
+
return Math.min(g + b, CHROMA_KNEE) / CHROMA_KNEE;
|
|
326
|
+
}
|
|
327
|
+
function classifyColor(hex) {
|
|
328
|
+
const lc = _apcaLc(hex, CONTRAST_BG);
|
|
329
|
+
const score = Math.round(lc * _chromaFactor(hex) * 10) / 10;
|
|
330
|
+
let level;
|
|
331
|
+
if (score < CONTRAST_MIN) level = 'reject';
|
|
332
|
+
else if (score < CONTRAST_WARN) level = 'warn';
|
|
333
|
+
else level = 'ok';
|
|
334
|
+
return { score, level };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function updateColorPreview(hex) {
|
|
338
|
+
const msg = document.getElementById('cp-msg');
|
|
339
|
+
const sw = document.getElementById('color-input');
|
|
340
|
+
const badge = document.getElementById('contrast-badge');
|
|
341
|
+
const save = document.getElementById('color-save');
|
|
342
|
+
const valid = /^#[0-9A-Fa-f]{6}$/.test(hex);
|
|
343
|
+
if (msg) msg.style.color = valid ? hex : '#FFFFFF';
|
|
344
|
+
if (!valid || !badge || !save) return;
|
|
345
|
+
const { score, level } = classifyColor(hex);
|
|
346
|
+
if (level === 'reject') {
|
|
347
|
+
badge.className = 'contrast-badge cb-reject';
|
|
348
|
+
badge.innerHTML = '<span class="cb-icon">⛔</span><span>Too hard to read on the dark chat background. ' +
|
|
349
|
+
'Try a lighter shade, or add some green/blue (e.g. pink instead of pure red).</span>';
|
|
350
|
+
save.disabled = true;
|
|
351
|
+
save.title = 'This color is too low-contrast to use';
|
|
352
|
+
} else if (level === 'warn') {
|
|
353
|
+
badge.className = 'contrast-badge cb-warn';
|
|
354
|
+
badge.innerHTML = '<span class="cb-icon">⚠️</span><span>Readable, but low-contrast — viewers with vision ' +
|
|
355
|
+
'issues may struggle to read your chat lines.</span>';
|
|
356
|
+
save.disabled = false;
|
|
357
|
+
save.title = '';
|
|
358
|
+
} else {
|
|
359
|
+
badge.className = 'contrast-badge cb-ok';
|
|
360
|
+
badge.innerHTML = '<span class="cb-icon">✅</span><span>Good contrast on the chat background.</span>';
|
|
361
|
+
save.disabled = false;
|
|
362
|
+
save.title = '';
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
296
366
|
function editColor() {
|
|
297
367
|
if (!accountState) return;
|
|
298
368
|
const sym = accountState.currency_symbol || 'Z';
|
|
299
369
|
const cur = (accountState.vanity && accountState.vanity.custom_color) || '';
|
|
300
370
|
const cost = (accountState.vanity_costs && accountState.vanity_costs.custom_color) || 0;
|
|
301
371
|
const seed = /^#[0-9A-Fa-f]{6}$/.test(cur) ? cur : '#6C5CE7';
|
|
372
|
+
const uname = (accountState.username) || 'You';
|
|
302
373
|
showModal(`
|
|
303
374
|
<h3>Chat color</h3>
|
|
304
375
|
<p class="muted">Pick a color for your chat messages. Cost: ${fmt(cost, sym)} per update.</p>
|
|
376
|
+
<div class="color-preview">
|
|
377
|
+
<span class="cp-ts">[12:34:56]</span>
|
|
378
|
+
<span class="cp-name" id="cp-name">${escapeHtml(uname)}:</span>
|
|
379
|
+
<span class="cp-msg" id="cp-msg">This is how your chat messages will look.</span>
|
|
380
|
+
</div>
|
|
381
|
+
<div class="contrast-badge cb-ok" id="contrast-badge"></div>
|
|
305
382
|
<div class="color-picker-row">
|
|
306
383
|
<input type="color" id="color-input" value="${seed}">
|
|
307
384
|
<input type="text" id="color-hex" class="color-hex" value="${escapeHtml(cur || seed)}" maxlength="7" placeholder="#RRGGBB">
|
|
@@ -312,14 +389,25 @@ function editColor() {
|
|
|
312
389
|
</div>`);
|
|
313
390
|
const picker = document.getElementById('color-input');
|
|
314
391
|
const hex = document.getElementById('color-hex');
|
|
315
|
-
|
|
392
|
+
const normalize = (v) => {
|
|
393
|
+
v = v.trim();
|
|
394
|
+
if (!v.startsWith('#')) v = '#' + v;
|
|
395
|
+
return v.toUpperCase();
|
|
396
|
+
};
|
|
397
|
+
picker.addEventListener('input', () => {
|
|
398
|
+
hex.value = picker.value.toUpperCase();
|
|
399
|
+
updateColorPreview(picker.value.toUpperCase());
|
|
400
|
+
});
|
|
316
401
|
hex.addEventListener('input', () => {
|
|
317
402
|
const val = hex.value.trim();
|
|
318
403
|
if (/^#?[0-9A-Fa-f]{6}$/.test(val)) {
|
|
319
|
-
|
|
404
|
+
const norm = normalize(val);
|
|
405
|
+
picker.value = norm;
|
|
406
|
+
updateColorPreview(norm);
|
|
320
407
|
}
|
|
321
408
|
});
|
|
322
409
|
document.getElementById('color-save').addEventListener('click', saveColor);
|
|
410
|
+
updateColorPreview(normalize(cur || seed));
|
|
323
411
|
}
|
|
324
412
|
|
|
325
413
|
async function saveColor() {
|
|
@@ -329,6 +417,12 @@ async function saveColor() {
|
|
|
329
417
|
return;
|
|
330
418
|
}
|
|
331
419
|
if (!value.startsWith('#')) value = '#' + value;
|
|
420
|
+
value = value.toUpperCase();
|
|
421
|
+
// Block locally on reject (the server enforces this too).
|
|
422
|
+
if (classifyColor(value).level === 'reject') {
|
|
423
|
+
showToast('That color is too low-contrast to use on the chat background', 'error');
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
332
426
|
const btn = document.getElementById('color-save');
|
|
333
427
|
btn.disabled = true;
|
|
334
428
|
let resp;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/__init__.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/_common.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/enrichtv.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/cmsutils/fetchurls.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/ytpipe/__init__.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/integrations/ytpipe/downloader.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/index.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/playlists.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/promos.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/queue_mgmt.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/admin/schedules.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/catalog/browse.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/catalog/item_detail.html
RENAMED
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.23.1 → kryten_webqueue-0.24.0}/kryten_webqueue/templates/queue/index.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|