v6.8.1: the downloads point at desktop 1.0.3
Desktop 1.0.3 fixes video on a call placed after a group call — the two shared one peer connection, the second call opened a second video section, and the two H264 profiles collided, so the call carried sound and no picture. It also ships the STUN and TURN list this client uses, which is what lets a browser and a desktop agree on a path instead of one of them offering no relay at all. The version lives in two places on this side (the landing page and the download grid), and the consistency test also reads the README badge, the changelog and the cryptography document, so all of them move together. Riding along: the group status dot now takes its colour from the theme in the call and group views, which is what the desktop's copy of groupsStore.js was compared against. Claude-Session: https://claude.ai/code/session_019RCW2Fm7dkAaU2zeHDksei
This commit is contained in:
+12
-10
@@ -1351,6 +1351,8 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
const isAnswerCred = !isCreate && showAnswerStep && !showVerification;
|
||||
const atIntro = !showVerification && !isGenerating && !isOfferCred && !isAnswerCred;
|
||||
const accent = isCreate ? C_ORANGE : C_GREEN;
|
||||
// Same pair as a mark: fa() puts `color` on the icon's stroke.
|
||||
const accentSolid = isCreate ? C_ORANGE_SOLID : C_GREEN_SOLID;
|
||||
const kicker = showVerification
|
||||
? t('step.verification')
|
||||
: ((isOfferCred || isAnswerCred) ? t('step.exchange') : t('step.open'));
|
||||
@@ -1552,7 +1554,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
]);
|
||||
|
||||
const showQrButton = qrCodeUrl && h('button', { key: 'showqr', onClick: () => setQrModalOpen(true), style: { width: '100%', display: 'flex', alignItems: 'center', gap: '13px', padding: '15px 16px', borderRadius: '14px', border: `1px solid ${isCreate ? 'rgba(var(--sb-orange-rgb), 0.3)' : 'rgba(var(--sb-green-rgb), 0.3)'}`, background: isCreate ? 'rgba(var(--sb-orange-rgb), 0.06)' : 'rgba(var(--sb-green-rgb), 0.06)', color: 'inherit', fontFamily: 'inherit', cursor: 'pointer', textAlign: 'start', marginBottom: '14px' } }, [
|
||||
h('span', { key: 'ic', style: { flex: 'none', width: '42px', height: '42px', borderRadius: '12px', display: 'grid', placeItems: 'center', background: isCreate ? 'rgba(var(--sb-orange-rgb), 0.12)' : 'rgba(var(--sb-green-rgb), 0.12)', border: `1px solid ${isCreate ? 'rgba(var(--sb-orange-rgb), 0.28)' : 'rgba(var(--sb-green-rgb), 0.28)'}` } }, fa('fa-qrcode', { color: accent, fontSize: '18px' })),
|
||||
h('span', { key: 'ic', style: { flex: 'none', width: '42px', height: '42px', borderRadius: '12px', display: 'grid', placeItems: 'center', background: isCreate ? 'rgba(var(--sb-orange-rgb), 0.12)' : 'rgba(var(--sb-green-rgb), 0.12)', border: `1px solid ${isCreate ? 'rgba(var(--sb-orange-rgb), 0.28)' : 'rgba(var(--sb-green-rgb), 0.28)'}` } }, fa('fa-qrcode', { color: accentSolid, fontSize: '18px' })),
|
||||
h('span', { key: 'tx', style: { flex: 1 } }, [
|
||||
h('span', { key: 't', style: { display: 'block', fontSize: '14.5px', fontWeight: 700, color: 'var(--sb-text-1)' } }, t('qr.showTitle')),
|
||||
h('span', { key: 's', style: { display: 'block', fontSize: '12.5px', color: 'var(--sb-text-7)', marginTop: '1px' } }, (qrFramesTotal || 0) > 1 ? t('qr.showSubtitleFrames', { frames: qrFramesTotal }) : t('qr.showSubtitle'))
|
||||
@@ -1568,14 +1570,14 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
inner = h('div', { key: 'verify', style: { animation: 'sbUp .3s ease' } }, [
|
||||
!verified && backButton('vback'),
|
||||
h('div', { key: 'head', style: { display: 'flex', alignItems: 'center', gap: '11px', marginBottom: '8px' } }, [
|
||||
h('div', { key: 'i', style: { width: '34px', height: '34px', flex: 'none', borderRadius: '10px', display: 'grid', placeItems: 'center', background: 'rgba(var(--sb-green-rgb), 0.1)', border: '1px solid rgba(var(--sb-green-rgb), 0.25)' } }, fa('fa-shield-alt', { color: C_GREEN })),
|
||||
h('div', { key: 'i', style: { width: '34px', height: '34px', flex: 'none', borderRadius: '10px', display: 'grid', placeItems: 'center', background: 'rgba(var(--sb-green-rgb), 0.1)', border: '1px solid rgba(var(--sb-green-rgb), 0.25)' } }, fa('fa-shield-alt', { color: C_GREEN_SOLID })),
|
||||
h('h2', { key: 't', style: { margin: 0, fontSize: '21px', fontWeight: 800, letterSpacing: '-0.4px', color: 'var(--sb-text-1)' } }, t('verify.title'))
|
||||
]),
|
||||
h('p', { key: 'sub', style: { margin: '0 0 18px', fontSize: '13.5px', lineHeight: 1.55, color: 'var(--sb-text-7)' } }, t('verify.desc')),
|
||||
h('div', { key: 'cells', dir: 'ltr', style: { display: 'flex', gap: '6px', justifyContent: 'center', marginBottom: '20px', flexWrap: 'wrap' } }, cells),
|
||||
verified
|
||||
? h('div', { key: 'ok', style: { display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', padding: '24px 16px', borderRadius: '16px', border: '1px solid rgba(var(--sb-green-rgb), 0.25)', background: 'rgba(var(--sb-green-rgb), 0.06)', animation: 'sbUp .3s ease' } }, [
|
||||
h('div', { key: 'i', style: { width: '54px', height: '54px', borderRadius: '16px', display: 'grid', placeItems: 'center', background: 'rgba(var(--sb-green-rgb), 0.14)', border: '1px solid rgba(var(--sb-green-rgb), 0.35)', marginBottom: '14px' } }, fa('fa-check', { color: C_GREEN, fontSize: '24px' })),
|
||||
h('div', { key: 'i', style: { width: '54px', height: '54px', borderRadius: '16px', display: 'grid', placeItems: 'center', background: 'rgba(var(--sb-green-rgb), 0.14)', border: '1px solid rgba(var(--sb-green-rgb), 0.35)', marginBottom: '14px' } }, fa('fa-check', { color: C_GREEN_SOLID, fontSize: '24px' })),
|
||||
h('div', { key: 't', style: { fontSize: '18px', fontWeight: 800, color: 'var(--sb-text-1)' } }, t('verify.verified')),
|
||||
h('div', { key: 's', style: { fontSize: '13.5px', color: 'var(--sb-text-7)', marginTop: '5px' } }, t('verify.bothConfirmed'))
|
||||
])
|
||||
@@ -1603,7 +1605,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
const genSteps = [t('handshake.step1'), t('handshake.step2'), t('handshake.step3')];
|
||||
inner = h('div', { key: 'gen', style: { animation: 'sbUp .28s ease' } }, [
|
||||
h('div', { key: 'head', style: { display: 'flex', alignItems: 'center', gap: '13px', marginBottom: '22px' } }, [
|
||||
h('div', { key: 'sp', style: { width: '44px', height: '44px', flex: 'none', display: 'grid', placeItems: 'center' } }, fa('fa-circle-notch', { color: C_ORANGE, fontSize: '32px', animation: 'sbSpin 1s linear infinite' })),
|
||||
h('div', { key: 'sp', style: { width: '44px', height: '44px', flex: 'none', display: 'grid', placeItems: 'center' } }, fa('fa-circle-notch', { color: C_ORANGE_SOLID, fontSize: '32px', animation: 'sbSpin 1s linear infinite' })),
|
||||
h('div', { key: 'tx' }, [
|
||||
h('h2', { key: 't', style: { margin: 0, fontSize: '20px', fontWeight: 800, letterSpacing: '-0.4px', color: 'var(--sb-text-1)' } }, isCreate ? t('handshake.securingTitle') : t('handshake.answerTitle')),
|
||||
h('p', { key: 's', style: { margin: '3px 0 0', fontSize: '13px', color: 'var(--sb-text-7)' } }, t('handshake.securingDesc'))
|
||||
@@ -1616,7 +1618,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
return h('div', { key: i, style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '13px 15px', borderTop: i ? '1px solid rgba(var(--sb-ink), 0.05)' : 'none', transition: 'background .3s', background: done ? 'rgba(var(--sb-green-rgb), 0.04)' : 'transparent' } }, [
|
||||
h('div', { key: 'd', style: { flex: 'none', width: '20px', height: '20px', borderRadius: '50%', display: 'grid', placeItems: 'center', background: done ? 'rgba(var(--sb-green-rgb), 0.12)' : (active ? 'rgba(var(--sb-orange-rgb), 0.12)' : 'rgba(var(--sb-ink), 0.04)'), border: `1px solid ${done ? 'rgba(var(--sb-green-rgb), 0.3)' : (active ? 'rgba(var(--sb-orange-rgb), 0.3)' : 'rgba(var(--sb-ink), 0.1)')}`, transition: 'all .3s' } },
|
||||
done
|
||||
? fa('fa-check', { color: C_GREEN, fontSize: '11px' })
|
||||
? fa('fa-check', { color: C_GREEN_SOLID, fontSize: '11px' })
|
||||
: h('span', { style: { width: '6px', height: '6px', borderRadius: '50%', background: active ? C_ORANGE_SOLID : 'var(--sb-text-faint)', animation: active ? 'sbBlink 1s ease-in-out infinite' : 'none' } })),
|
||||
h('span', { key: 'l', style: { fontSize: '13.5px', color: done ? 'var(--sb-text-4)' : (active ? 'var(--sb-text-2)' : 'var(--sb-text-9)'), transition: 'color .3s' } }, label)
|
||||
]);
|
||||
@@ -1640,7 +1642,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
])
|
||||
]),
|
||||
isAnswerCred && h('div', { key: 'answerextra', style: { marginTop: '4px', display: 'flex', alignItems: 'center', gap: '10px', padding: '12px 14px', borderRadius: '12px', border: '1px solid rgba(var(--sb-green-rgb), 0.18)', background: 'rgba(var(--sb-green-rgb), 0.05)' } }, [
|
||||
fa('fa-circle-notch', { key: 'i', color: C_GREEN, animation: 'sbSpin 1.4s linear infinite' }),
|
||||
fa('fa-circle-notch', { key: 'i', color: C_GREEN_SOLID, animation: 'sbSpin 1.4s linear infinite' }),
|
||||
h('span', { key: 't', style: { fontSize: '13px', color: 'var(--sb-text-4)', fontWeight: 500 } }, t('handshake.answerSentNote'))
|
||||
])
|
||||
]);
|
||||
@@ -1657,7 +1659,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
h('h2', { key: 'h', style: { margin: '0 0 6px', fontSize: '23px', fontWeight: 800, letterSpacing: '-0.5px', color: 'var(--sb-text-1)' } }, t('intro.joinTitle')),
|
||||
h('p', { key: 'p', style: { margin: '0 0 16px', fontSize: '14px', lineHeight: 1.55, color: 'var(--sb-text-7)' } }, "Scan your peer's QR with your camera, or paste their invitation code."),
|
||||
h('button', { key: 'scan', className: 'sb-scan-btn', onClick: () => { requestNotificationPermissionOnInteraction(); setShowQRScannerModal(true); }, style: { width: '100%', display: 'flex', alignItems: 'center', gap: '13px', padding: '15px 16px', borderRadius: '14px', border: '1px solid rgba(var(--sb-green-rgb), 0.3)', background: 'rgba(var(--sb-green-rgb), 0.06)', color: 'inherit', fontFamily: 'inherit', cursor: 'pointer', textAlign: 'start', marginBottom: '14px' } }, [
|
||||
h('span', { key: 'ic', style: { flex: 'none', width: '42px', height: '42px', borderRadius: '12px', display: 'grid', placeItems: 'center', background: 'rgba(var(--sb-green-rgb), 0.12)', border: '1px solid rgba(var(--sb-green-rgb), 0.28)' } }, fa('fa-camera', { color: C_GREEN, fontSize: '18px' })),
|
||||
h('span', { key: 'ic', style: { flex: 'none', width: '42px', height: '42px', borderRadius: '12px', display: 'grid', placeItems: 'center', background: 'rgba(var(--sb-green-rgb), 0.12)', border: '1px solid rgba(var(--sb-green-rgb), 0.28)' } }, fa('fa-camera', { color: C_GREEN_SOLID, fontSize: '18px' })),
|
||||
h('span', { key: 'tx', style: { flex: 1 } }, [
|
||||
h('span', { key: 't', style: { display: 'block', fontSize: '14.5px', fontWeight: 700, color: 'var(--sb-text-1)' } }, t('intro.scanTitle')),
|
||||
h('span', { key: 's', style: { display: 'block', fontSize: '12.5px', color: 'var(--sb-text-7)', marginTop: '1px' } }, t('intro.scanSubtitle'))
|
||||
@@ -1687,7 +1689,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
// /download/v0.3.0/SecureBit.Chat_0.1.0_x64-setup.exe, a file that never
|
||||
// existed, and the download 404s. A pinned tag keeps serving a real
|
||||
// installer instead.
|
||||
const SB_DESKTOP_VERSION = '1.0.1';
|
||||
const SB_DESKTOP_VERSION = '1.0.3';
|
||||
const SB_DESKTOP_RELEASE = `https://github.com/SecureBitChat/securebit-desktop/releases/download/v${SB_DESKTOP_VERSION}`;
|
||||
const DOWNLOADS = {
|
||||
mac: { name: 'macOS', format: '.dmg · Apple Silicon & Intel', icon: 'fab fa-apple', url: `${SB_DESKTOP_RELEASE}/SecureBit.Chat_${SB_DESKTOP_VERSION}_x64.dmg` },
|
||||
@@ -1720,7 +1722,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
h('span', { key: 'n', style: { display: 'block', fontSize: '13.5px', fontWeight: 700, color: 'var(--sb-text-1)' } }, DOWNLOADS[detectedOS].name),
|
||||
h('span', { key: 'f', style: { display: 'block', fontSize: '11px', color: 'var(--sb-orange-3)', marginTop: '1px' } }, `Recommended for this device · ${DOWNLOADS[detectedOS].format}`)
|
||||
]),
|
||||
fa('fa-download', { color: C_ORANGE })
|
||||
fa('fa-download', { color: C_ORANGE_SOLID })
|
||||
])),
|
||||
h('div', { key: 'others', style: { padding: '0 12px 8px', display: 'flex', flexDirection: 'column', gap: '2px' } },
|
||||
otherOS.map((k) => h('button', { key: k, onClick: () => dlLink(DOWNLOADS[k].url), style: { width: '100%', display: 'flex', alignItems: 'center', gap: '12px', padding: '11px 14px', borderRadius: '11px', border: 'none', background: 'transparent', color: 'inherit', fontFamily: 'inherit', cursor: 'pointer', textAlign: 'start' } }, [
|
||||
@@ -1739,7 +1741,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
|
||||
|
||||
const footer = h('div', { key: 'footer', className: 'sb-conn-footer', style: { position: 'relative', marginTop: '30px', paddingTop: '18px', borderTop: '1px solid rgba(var(--sb-ink), 0.06)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '12px', flexWrap: 'wrap' } }, [
|
||||
h('button', { key: 'dl', onClick: () => setPlatformsOpen((v) => !v), style: { display: 'inline-flex', alignItems: 'center', gap: '9px', paddingBlock: '8px', paddingInlineStart: '9px', paddingInlineEnd: '13px', borderRadius: '10px', border: `1px solid ${platformsOpen ? 'rgba(var(--sb-orange-rgb), 0.4)' : 'rgba(var(--sb-ink), 0.08)'}`, background: platformsOpen ? 'rgba(var(--sb-orange-rgb), 0.06)' : 'rgba(var(--sb-ink), 0.02)', color: 'inherit', fontFamily: 'inherit', cursor: 'pointer', transition: 'all .15s' } }, [
|
||||
fa('fa-download', { key: 'i', color: C_ORANGE }),
|
||||
fa('fa-download', { key: 'i', color: C_ORANGE_SOLID }),
|
||||
h('span', { key: 't', style: { fontSize: '12.5px', fontWeight: 700, color: 'var(--sb-text-2)' } }, t('action.downloadDesktop')),
|
||||
fa('fa-chevron-down', { key: 'c', color: 'var(--sb-text-9)', style: { fontSize: '11px', transform: platformsOpen ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform .2s' } })
|
||||
]),
|
||||
|
||||
@@ -124,18 +124,20 @@ const CallUIComponent = ({ webrtcManager, peerTitle }) => {
|
||||
|
||||
// Connection-quality indicator — driven by the adaptation controller's
|
||||
// getStats (loss + RTT). Signal bars + label; hidden until there's data.
|
||||
// `color` labels the quality in words; `solid` fills the signal bars. A bar is a
|
||||
// mark, so it keeps the brand colour in both themes — see src/styles/theme.css.
|
||||
const QUALITY = {
|
||||
excellent: { bars: 4, color: 'var(--sb-green)', label: t('call.qualityExcellent') },
|
||||
good: { bars: 3, color: 'var(--sb-green)', label: t('call.qualityGood') },
|
||||
fair: { bars: 2, color: 'var(--sb-yellow)', label: t('call.qualityFair') },
|
||||
poor: { bars: 1, color: 'var(--sb-red)', label: t('call.qualityWeak') },
|
||||
excellent: { bars: 4, color: 'var(--sb-green)', solid: 'var(--sb-green-solid)', label: t('call.qualityExcellent') },
|
||||
good: { bars: 3, color: 'var(--sb-green)', solid: 'var(--sb-green-solid)', label: t('call.qualityGood') },
|
||||
fair: { bars: 2, color: 'var(--sb-yellow)', solid: 'var(--sb-yellow-solid)', label: t('call.qualityFair') },
|
||||
poor: { bars: 1, color: 'var(--sb-red)', solid: 'var(--sb-red-solid)', label: t('call.qualityWeak') },
|
||||
};
|
||||
const qualityIndicator = (compact) => {
|
||||
const q = QUALITY[call.quality];
|
||||
if (!q) return null;
|
||||
const bars = h('span', { key: 'bars', style: { display: 'inline-flex', alignItems: 'flex-end', gap: '2px', height: '14px' } },
|
||||
[0, 1, 2, 3].map(i => h('span', {
|
||||
key: i, style: { width: '3px', height: (5 + i * 3) + 'px', borderRadius: '1px', background: i < q.bars ? q.color : 'rgba(var(--sb-ink), 0.18)' }
|
||||
key: i, style: { width: '3px', height: (5 + i * 3) + 'px', borderRadius: '1px', background: i < q.bars ? q.solid : 'rgba(var(--sb-ink), 0.18)' }
|
||||
})));
|
||||
if (compact) return bars;
|
||||
return h('span', { key: 'q', title: t('call.quality'), style: { display: 'inline-flex', alignItems: 'center', gap: '6px', fontSize: '11.5px', fontWeight: 600, color: q.color } }, [bars, q.label]);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// The tag is pinned rather than using /releases/latest/download/: the filenames
|
||||
// carry the version, so a `latest` link 404s the moment a newer release exists,
|
||||
// whereas a pinned tag keeps serving a working (if older) installer.
|
||||
const DESKTOP_VERSION = '1.0.1';
|
||||
const DESKTOP_VERSION = '1.0.3';
|
||||
const DESKTOP_RELEASE = `https://github.com/SecureBitChat/securebit-desktop/releases/download/v${DESKTOP_VERSION}`;
|
||||
|
||||
const DownloadApps = () => {
|
||||
|
||||
@@ -55,11 +55,13 @@ const minimizeBtn = {
|
||||
color: '#fff', cursor: 'pointer', transition: 'all .15s',
|
||||
};
|
||||
|
||||
// `color` labels the quality in words; `solid` fills the signal bars. A bar is a
|
||||
// mark, so it keeps the brand colour in both themes — see src/styles/theme.css.
|
||||
const QUALITY = {
|
||||
excellent: { bars: 4, color: 'var(--sb-green)' },
|
||||
good: { bars: 3, color: 'var(--sb-green)' },
|
||||
fair: { bars: 2, color: 'var(--sb-yellow)' },
|
||||
poor: { bars: 1, color: 'var(--sb-red)' },
|
||||
excellent: { bars: 4, color: 'var(--sb-green)', solid: 'var(--sb-green-solid)' },
|
||||
good: { bars: 3, color: 'var(--sb-green)', solid: 'var(--sb-green-solid)' },
|
||||
fair: { bars: 2, color: 'var(--sb-yellow)', solid: 'var(--sb-yellow-solid)' },
|
||||
poor: { bars: 1, color: 'var(--sb-red)', solid: 'var(--sb-red-solid)' },
|
||||
};
|
||||
|
||||
function qualityBars(quality) {
|
||||
@@ -70,7 +72,7 @@ function qualityBars(quality) {
|
||||
key: i,
|
||||
style: {
|
||||
width: '2.5px', height: (4 + i * 2.6) + 'px', borderRadius: '1px',
|
||||
background: i < q.bars ? q.color : 'rgba(var(--sb-ink), 0.18)',
|
||||
background: i < q.bars ? q.solid : 'rgba(var(--sb-ink), 0.18)',
|
||||
},
|
||||
})));
|
||||
}
|
||||
|
||||
@@ -23,10 +23,19 @@ const C = {
|
||||
ink: 'var(--sb-text-1)',
|
||||
ink2: 'var(--sb-text-5b)',
|
||||
ink3: 'var(--sb-text-9)',
|
||||
// Two forms of each accent. The plain one is for text and darkens in the light
|
||||
// theme so it clears 4.5:1 on white; the -Solid one is for anything painted — a
|
||||
// button's ground, a checkbox, a dot, the safety code — and is the brand colour in
|
||||
// both themes, because what sits on it is near-black either way. Reaching for the
|
||||
// wrong one is how every accent button in this file came out brown.
|
||||
accent: 'var(--sb-orange)',
|
||||
good: 'var(--sb-green)',
|
||||
warn: 'var(--sb-yellow-2)',
|
||||
bad: 'var(--sb-red)',
|
||||
accentSolid: 'var(--sb-orange-solid)',
|
||||
goodSolid: 'var(--sb-green-solid)',
|
||||
warnSolid: 'var(--sb-yellow-2-solid)',
|
||||
badSolid: 'var(--sb-red-solid)',
|
||||
mono: "'JetBrains Mono', ui-monospace, monospace",
|
||||
};
|
||||
|
||||
@@ -52,7 +61,7 @@ const btn = (accent = false) => ({
|
||||
padding: '11px 18px', borderRadius: '10px', cursor: 'pointer',
|
||||
fontFamily: 'inherit', fontSize: '14px', fontWeight: 700,
|
||||
border: accent ? 'none' : `1px solid ${C.line2}`,
|
||||
background: accent ? C.accent : 'transparent',
|
||||
background: accent ? C.accentSolid : 'transparent',
|
||||
color: accent ? 'var(--sb-on-accent)' : C.ink2,
|
||||
});
|
||||
|
||||
@@ -175,7 +184,7 @@ export function GroupSasModal({ group, onConfirm, onCancel }) {
|
||||
dir: 'ltr',
|
||||
style: {
|
||||
fontFamily: C.mono, fontSize: 'clamp(30px, 9vw, 42px)', fontWeight: 700,
|
||||
letterSpacing: '9px', color: C.accent, unicodeBidi: 'isolate',
|
||||
letterSpacing: '9px', color: C.accentSolid, unicodeBidi: 'isolate',
|
||||
},
|
||||
}, group.sasCode)),
|
||||
|
||||
@@ -302,8 +311,8 @@ export function CreateGroupModal({ candidates, relayOnly, onCreate, onCancel })
|
||||
key: 'tick',
|
||||
style: {
|
||||
flex: 'none', width: '18px', height: '18px', borderRadius: '5px',
|
||||
background: on ? C.accent : 'transparent',
|
||||
border: `1px solid ${on ? C.accent : C.line2}`,
|
||||
background: on ? C.accentSolid : 'transparent',
|
||||
border: `1px solid ${on ? C.accentSolid : C.line2}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
@@ -430,8 +439,8 @@ export function AddMembersModal({ candidates, remaining, onAdd, onCancel }) {
|
||||
key: 'tick',
|
||||
style: {
|
||||
flex: 'none', width: '18px', height: '18px', borderRadius: '5px',
|
||||
background: on ? C.accent : 'transparent',
|
||||
border: `1px solid ${on ? C.accent : C.line2}`,
|
||||
background: on ? C.accentSolid : 'transparent',
|
||||
border: `1px solid ${on ? C.accentSolid : C.line2}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
@@ -504,8 +513,8 @@ function MemberStrip({ group, onRemove, isAdmin }) {
|
||||
}, group.members.map((m) => {
|
||||
const self = m.state === MEMBER_STATE.SELF;
|
||||
const lost = m.state === MEMBER_STATE.LOST;
|
||||
const dot = self || m.state === MEMBER_STATE.LINKED ? C.good
|
||||
: m.state === MEMBER_STATE.PENDING ? C.warn : C.bad;
|
||||
const dot = self || m.state === MEMBER_STATE.LINKED ? C.goodSolid
|
||||
: m.state === MEMBER_STATE.PENDING ? C.warnSolid : C.badSolid;
|
||||
const via = m.state === MEMBER_STATE.PENDING;
|
||||
return h('span', {
|
||||
key: m.fp,
|
||||
|
||||
Reference in New Issue
Block a user