From b787d85a458a8d3fb69a273c8288c3dbdb9fa299 Mon Sep 17 00:00:00 2001 From: "Evgeny @ SimpleX Chat" <259188159+evgeny-simplex@users.noreply.github.com> Date: Tue, 2 Jun 2026 21:07:28 +0000 Subject: [PATCH] color scheme --- .../Chat/Group/ChannelWebAccessView.swift | 1 + .../views/chat/group/ChannelWebPageView.kt | 1 + website/channel_sample.html | 3 + website/src/js/channel-preview.jsc | 157 +++++++++++------- 4 files changed, 106 insertions(+), 56 deletions(-) diff --git a/apps/ios/Shared/Views/Chat/Group/ChannelWebAccessView.swift b/apps/ios/Shared/Views/Chat/Group/ChannelWebAccessView.swift index 594a058aef..dd46b7a117 100644 --- a/apps/ios/Shared/Views/Chat/Group/ChannelWebAccessView.swift +++ b/apps/ios/Shared/Views/Chat/Group/ChannelWebAccessView.swift @@ -129,6 +129,7 @@ struct ChannelWebAccessView: View { data-channel-id="\(pg.publicGroupId)" data-relay-domains="\(relayDomains.joined(separator: ","))" data-app-download-buttons="on" + data-color-scheme="light" > """ diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelWebPageView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelWebPageView.kt index ead19a0981..98067e49dd 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelWebPageView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelWebPageView.kt @@ -180,6 +180,7 @@ private fun embedCode(groupRelays: List, groupInfo: GroupInfo): Stri data-channel-id="${pg.publicGroupId}" data-relay-domains="$domains" data-app-download-buttons="on" + data-color-scheme="light" > """ } diff --git a/website/channel_sample.html b/website/channel_sample.html index 86ed9d4813..7760d27c31 100644 --- a/website/channel_sample.html +++ b/website/channel_sample.html @@ -16,6 +16,9 @@ data-channel-id="YOUR_CHANNEL_ID" data-relay-domains="relay1.example.com" data-app-download-buttons="on" + + + > diff --git a/website/src/js/channel-preview.jsc b/website/src/js/channel-preview.jsc index 23f2bf2a5b..dfa0f98e28 100644 --- a/website/src/js/channel-preview.jsc +++ b/website/src/js/channel-preview.jsc @@ -6,11 +6,28 @@ const STYLE = ` .simplex-preview-container { + --sp-bg: var(--sp-light-bg, #fff); + --sp-text: #000; + --sp-text-secondary: #8b8786; + --sp-text-muted: #333; + --sp-text-small: #888; + --sp-bubble: #f5f5f6; + --sp-quote: #ececee; + --sp-border: #e5e5e5; + --sp-link: #0088ff; + --sp-link-hover: #0077e0; + --sp-btn: #0053D0; + --sp-btn-hover: #0047b3; + --sp-color-blue: #0053d0; + --sp-color-black: #000; + --sp-color-white: #000; + --sp-qr-fg: #062D56; + --sp-qr-bg: #ffffff; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; font-size: 15px; line-height: 1.4; - color: #000; - background: #fff; + color: var(--sp-text); + background: var(--sp-bg); width: 100%; height: 100%; padding: 0; @@ -19,12 +36,34 @@ const STYLE = ` justify-content: center; } +.simplex-preview-container.simplex-scheme-dark, +.dark .simplex-preview-container.simplex-scheme-site { + --sp-bg: var(--sp-dark-bg, #000832); + --sp-text: #FFFBFA; + --sp-text-secondary: #B3AFAE; + --sp-text-muted: #B3AFAE; + --sp-text-small: #aaa; + --sp-bubble: #262627; + --sp-quote: #373739; + --sp-border: #3A3A3C; + --sp-link: #70F0F9; + --sp-link-hover: #66D9E2; + --sp-btn: #70F0F9; + --sp-btn-hover: #66D9E2; + --sp-btn-text: #000; + --sp-color-blue: #70F0F9; + --sp-color-black: #fff; + --sp-color-white: #fff; + --sp-qr-fg: #FFFBFA; + --sp-qr-bg: transparent; +} + .simplex-preview-header { position: sticky; top: 0; z-index: 10; - background: #fff; - border-bottom: 1px solid #e5e5e5; + background: var(--sp-bg); + border-bottom: 1px solid var(--sp-border); padding: 8px 16px; display: flex; align-items: center; @@ -55,7 +94,7 @@ const STYLE = ` .simplex-preview-header-description { font-size: 13px; - color: #8b8786; + color: var(--sp-text-secondary); margin: 2px 0 0; white-space: nowrap; overflow: hidden; @@ -64,8 +103,8 @@ const STYLE = ` .simplex-preview-join-btn { flex-shrink: 0; - background: #0088ff; - color: #fff; + background: var(--sp-link); + color: var(--sp-btn-text, #fff); border: none; border-radius: 34px; padding: 6px 16px; @@ -78,7 +117,7 @@ const STYLE = ` } .simplex-preview-join-btn:hover { - background: #0077e0; + background: var(--sp-link-hover); } .simplex-preview-messages { @@ -89,7 +128,7 @@ const STYLE = ` text-align: center; padding: 8px 0; font-size: 12px; - color: #8b8786; + color: var(--sp-text-secondary); font-weight: 500; } @@ -99,7 +138,7 @@ const STYLE = ` .simplex-preview-msg-name { font-size: 13.5px; - color: #8b8786; + color: var(--sp-text-secondary); padding: 0 0 2px 0; margin-left: 39px; white-space: nowrap; @@ -137,7 +176,7 @@ const STYLE = ` .simplex-preview-bubble { position: relative; - background: #f5f5f6; + background: var(--sp-bubble); border-radius: 18px; min-width: 80px; overflow: visible; @@ -163,6 +202,7 @@ const STYLE = ` left: -9px; width: 9px; height: 16px; + color: var(--sp-bubble); } .simplex-preview-bubble.media-only { @@ -184,18 +224,18 @@ const STYLE = ` } .simplex-preview-forwarded-header { - background: #ececee; + background: var(--sp-quote); padding: 6px 12px 6px 8px; font-size: 12px; font-style: italic; - color: #8b8786; + color: var(--sp-text-secondary); display: flex; align-items: center; gap: 4px; } .simplex-preview-quote { - background: #ececee; + background: var(--sp-quote); display: flex; width: 100%; } @@ -208,7 +248,7 @@ const STYLE = ` .simplex-preview-quote-sender { font-size: 13.5px; - color: #8b8786; + color: var(--sp-text-secondary); margin-bottom: 2px; } @@ -230,7 +270,7 @@ const STYLE = ` .simplex-preview-quote-file-icon { padding: 6px 4px 0 0; flex-shrink: 0; - color: #8b8786; + color: var(--sp-text-secondary); } .simplex-preview-text { @@ -240,7 +280,7 @@ const STYLE = ` } .simplex-preview-text a { - color: #0088ff; + color: var(--sp-link); text-decoration: none; } @@ -288,7 +328,7 @@ const STYLE = ` .simplex-preview-link-card-description { font-size: 14px; line-height: 20px; - color: #333; + color: var(--sp-text-muted); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 12; @@ -297,7 +337,7 @@ const STYLE = ` .simplex-preview-link-card-uri { font-size: 12px; - color: #8b8786; + color: var(--sp-text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -308,7 +348,7 @@ const STYLE = ` display: flex; align-items: center; gap: 8px; - color: #8b8786; + color: var(--sp-text-secondary); } .simplex-preview-file-icon { @@ -319,12 +359,12 @@ const STYLE = ` .simplex-preview-file-name { font-size: 14px; - color: #000; + color: var(--sp-text); } .simplex-preview-file-size { font-size: 12px; - color: #8b8786; + color: var(--sp-text-secondary); } .simplex-preview-voice { @@ -332,14 +372,14 @@ const STYLE = ` display: flex; align-items: center; gap: 8px; - color: #8b8786; + color: var(--sp-text-secondary); font-size: 14px; } .simplex-preview-meta { float: right; font-size: 12px; - color: #8b8786; + color: var(--sp-text-secondary); padding: 0 2px 0 12px; margin-top: 4px; white-space: nowrap; @@ -367,18 +407,18 @@ const STYLE = ` .simplex-preview-reaction-count { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; - color: #8b8786; + color: var(--sp-text-secondary); font-size: 11.5px; } .simplex-preview-empty { text-align: center; padding: 48px 16px; - color: #8b8786; + color: var(--sp-text-secondary); } .simplex-preview-text .secret { - background: #8b8786; + background: var(--sp-text-secondary); color: transparent; border-radius: 4px; cursor: pointer; @@ -393,17 +433,17 @@ const STYLE = ` .simplex-preview-text .small-text { font-size: 13px; - color: #888; + color: var(--sp-text-small); } .simplex-preview-text .red { color: #DD0000; } .simplex-preview-text .green { color: #20BD3D; } -.simplex-preview-text .blue { color: #0053d0; } +.simplex-preview-text .blue { color: var(--sp-color-blue); } .simplex-preview-text .yellow { color: #DEBD00; } .simplex-preview-text .cyan { color: #0AC4D1; } .simplex-preview-text .magenta { color: magenta; } -.simplex-preview-text .black { color: #000; } -.simplex-preview-text .white { color: #000; } +.simplex-preview-text .black { color: var(--sp-color-black); } +.simplex-preview-text .white { color: var(--sp-color-white); } .simplex-preview-main { flex: 1; @@ -415,7 +455,7 @@ const STYLE = ` .simplex-preview-info { overflow-y: auto; - background: #fff; + background: var(--sp-bg); } .simplex-preview-info-close { @@ -440,7 +480,7 @@ const STYLE = ` .simplex-preview-info-descr { font-size: 14px; - color: #8b8786; + color: var(--sp-text-secondary); text-align: center; margin: 8px 0; word-wrap: break-word; @@ -449,7 +489,7 @@ const STYLE = ` .simplex-preview-info-subscribers { font-size: 14px; - color: #8b8786; + color: var(--sp-text-secondary); text-align: center; margin: 0 0 16px; } @@ -463,7 +503,7 @@ const STYLE = ` } .simplex-preview-info-section a { - color: #0088ff; + color: var(--sp-link); text-decoration: none; } @@ -472,7 +512,7 @@ const STYLE = ` } .simplex-preview-info-section .secret { - background: #8b8786; + background: var(--sp-text-secondary); color: transparent; border-radius: 4px; cursor: pointer; @@ -487,7 +527,7 @@ const STYLE = ` .simplex-preview-read-more { font-size: 13px; - color: #0088ff; + color: var(--sp-link); cursor: pointer; margin-top: 4px; user-select: none; @@ -510,7 +550,7 @@ const STYLE = ` .simplex-preview-divider { width: 100%; height: 1px; - background: #e5e5e5; + background: var(--sp-border); margin: 20px 0; } @@ -519,12 +559,11 @@ const STYLE = ` font-weight: 600; text-align: center; margin: 0 0 16px; - color: #000; } .simplex-preview-qr-toggle { font-size: 14px; - color: #0088ff; + color: var(--sp-link); cursor: pointer; text-decoration: none; } @@ -545,7 +584,6 @@ const STYLE = ` .simplex-preview-qr-caption { font-size: 14px; - color: #000; text-align: center; margin: 0; } @@ -571,12 +609,11 @@ const STYLE = ` .simplex-preview-copy-action { font-size: 14px; - color: #000; margin: 0; } .simplex-preview-copy-action a { - color: #0088ff; + color: var(--sp-link); text-decoration: none; cursor: pointer; } @@ -589,14 +626,13 @@ const STYLE = ` font-size: 14px; text-align: center; margin: 0 0 -8px; - color: #000; } .simplex-preview-open-btn { display: inline-block; text-align: center; - background: #0053D0; - color: #fff; + background: var(--sp-btn); + color: var(--sp-btn-text, #fff); border: none; border-radius: 34px; padding: 12px 32px; @@ -611,14 +647,14 @@ const STYLE = ` } .simplex-preview-open-btn:hover { - background: #0047b3; + background: var(--sp-btn-hover); } @media (min-width: 1000px) { .simplex-preview-info { width: 320px; flex-shrink: 0; - border-left: 1px solid #e5e5e5; + border-left: 1px solid var(--sp-border); padding: 24px; } .simplex-preview-header .simplex-preview-join-btn { @@ -651,7 +687,7 @@ const STYLE = ` background: none; border: none; font-size: 24px; - color: #8b8786; + color: var(--sp-text-secondary); cursor: pointer; padding: 4px 8px; line-height: 1; @@ -667,10 +703,8 @@ const STYLE = ` const DEFAULT_AVATAR = 'data:image/svg+xml,' + encodeURIComponent(''); -const TAIL_SVG_COLOR = '#f5f5f6'; - -function tailSvg(color) { - return ``; +function tailSvg() { + return ''; } const FILE_ICON_SVG = ``; @@ -687,6 +721,7 @@ function initChannelPreview(container) { const channelId = container.dataset.channelId || ''; const channelLink = container.dataset.channelLink || ''; const showAppBadges = container.dataset.appDownloadButtons !== 'off'; + const colorScheme = container.dataset.colorScheme || 'light'; if (!relayDomains.length || !channelId) { container.innerHTML = '

Missing configuration: data-relay-domains and data-channel-id required.

'; @@ -694,7 +729,13 @@ function initChannelPreview(container) { } injectStyles(); - container.classList.add('simplex-preview-container'); + container.classList.add('simplex-preview-container', 'simplex-scheme-' + colorScheme); + if (container.dataset.lightBackground) { + container.style.setProperty('--sp-light-bg', container.dataset.lightBackground); + } + if (container.dataset.darkBackground) { + container.style.setProperty('--sp-dark-bg', container.dataset.darkBackground); + } container.innerHTML = '

Loading channel...

'; fetchPreview(relayScheme, relayDomains, channelLink, channelId).then(data => { @@ -952,9 +993,13 @@ function renderDesktopConversion(container, channelLink, showAppBadges) { if (!canvas._rendered) { canvas._rendered = true; try { + var cs = getComputedStyle(container); QRCode.toCanvas(canvas, channelLink, { errorCorrectionLevel: 'M', - color: { dark: '#062D56' }, + color: { + dark: cs.getPropertyValue('--sp-qr-fg').trim() || '#062D56', + light: cs.getPropertyValue('--sp-qr-bg').trim() || '#ffffff' + }, width: 400, margin: 1 }).then(function() { @@ -1136,7 +1181,7 @@ function renderBubble(msg, member, showTail) { if (hasTail) { const tail = document.createElement('div'); tail.className = 'simplex-preview-bubble-tail'; - tail.innerHTML = tailSvg(TAIL_SVG_COLOR); + tail.innerHTML = tailSvg(); bubble.appendChild(tail); }