mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-04 17:31:42 +00:00
web cta
This commit is contained in:
@@ -128,6 +128,7 @@ struct ChannelWebAccessView: View {
|
||||
data-channel-link="\(pg.groupLink)"
|
||||
data-channel-id="\(pg.publicGroupId)"
|
||||
data-relay-domains="\(relayDomains.joined(separator: ","))"
|
||||
data-app-download-buttons="on"
|
||||
></div>
|
||||
<script src="https://simplex.chat/js/channel-preview.js"></script>
|
||||
"""
|
||||
|
||||
+1
@@ -179,6 +179,7 @@ private fun embedCode(groupRelays: List<GroupRelay>, groupInfo: GroupInfo): Stri
|
||||
data-channel-link="${pg.groupLink}"
|
||||
data-channel-id="${pg.publicGroupId}"
|
||||
data-relay-domains="$domains"
|
||||
data-app-download-buttons="on"
|
||||
></div>
|
||||
<script src="https://simplex.chat/js/channel-preview.js"></script>"""
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
data-channel-link="YOUR_CHANNEL_LINK"
|
||||
data-channel-id="YOUR_CHANNEL_ID"
|
||||
data-relay-domains="relay1.example.com"
|
||||
data-app-download-buttons="on"
|
||||
<!-- data-relay-scheme="https" -->
|
||||
></div>
|
||||
<script src="https://simplex.chat/js/channel-preview.js"></script>
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
(function() {
|
||||
|
||||
#include "qrcode.js"
|
||||
|
||||
const STYLE = `
|
||||
.simplex-preview-container {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
@@ -72,6 +74,7 @@ const STYLE = `
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.simplex-preview-join-btn:hover {
|
||||
@@ -497,6 +500,122 @@ const STYLE = `
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.simplex-preview-conversion {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.simplex-preview-qr-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.simplex-preview-qr-container canvas {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.simplex-preview-qr-caption {
|
||||
font-size: 13px;
|
||||
color: #8b8786;
|
||||
text-align: center;
|
||||
margin: 8px 0 0;
|
||||
}
|
||||
|
||||
.simplex-preview-badges {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin: 16px 0 0;
|
||||
}
|
||||
|
||||
.simplex-preview-badges a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.simplex-preview-badges a img {
|
||||
height: 36px;
|
||||
width: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.simplex-preview-copy-section {
|
||||
font-size: 13px;
|
||||
color: #8b8786;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.simplex-preview-copy-section a {
|
||||
color: #0088ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.simplex-preview-copy-section a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.simplex-preview-copy-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: 6px;
|
||||
background: #f5f5f6;
|
||||
border-radius: 8px;
|
||||
padding: 6px 10px;
|
||||
}
|
||||
|
||||
.simplex-preview-copy-link {
|
||||
flex: 1;
|
||||
font-size: 11px;
|
||||
color: #333;
|
||||
word-break: break-all;
|
||||
font-family: monospace;
|
||||
min-width: 0;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.simplex-preview-copy-btn {
|
||||
flex-shrink: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
color: #8b8786;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.simplex-preview-copy-btn:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.simplex-preview-step-label {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
margin: 20px 0 8px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.simplex-preview-open-btn {
|
||||
display: block;
|
||||
text-align: center;
|
||||
background: #0053D0;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 34px;
|
||||
padding: 12px 32px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.simplex-preview-open-btn:hover {
|
||||
background: #0047b3;
|
||||
}
|
||||
|
||||
@media (min-width: 1000px) {
|
||||
.simplex-preview-info {
|
||||
width: 320px;
|
||||
@@ -562,11 +681,14 @@ const VOICE_ICON_SVG = `<svg class="simplex-preview-file-icon" viewBox="0 0 24 2
|
||||
|
||||
const FORWARD_ICON_SVG = `<svg width="14" height="14" viewBox="0 -960 960 960" fill="currentColor"><path transform="scale(-1,1) translate(-960,0)" d="m236.5-495.5 142.5 143q8.5 8.5 8.25 20.25T378.5-312q-9 8.5-21 8.5t-20.5-9L145.5-504q-9-8.5-9-20t9-20.5L338-737q9-9 20.75-8.75T379.5-737q8.5 8.5 8.5 20.5t-8.5 20.5l-143 143h403q84 0 139.75 56T835-357.5V-234q0 12.5-8.25 20.75T806.5-205q-12.5 0-20.75-8.25T777.5-234v-123.5q0-60-39-99t-99-39h-403Z"/></svg>`;
|
||||
|
||||
const COPY_ICON_SVG = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`;
|
||||
|
||||
function initChannelPreview(container) {
|
||||
const relayDomains = (container.dataset.relayDomains || '').split(',').map(u => u.trim()).filter(Boolean);
|
||||
const relayScheme = container.dataset.relayScheme || 'https';
|
||||
const channelId = container.dataset.channelId || '';
|
||||
const channelLink = container.dataset.channelLink || '';
|
||||
const showAppBadges = container.dataset.appDownloadButtons !== 'off';
|
||||
|
||||
if (!relayDomains.length || !channelId) {
|
||||
container.innerHTML = '<p class="simplex-preview-empty">Missing configuration: data-relay-domains and data-channel-id required.</p>';
|
||||
@@ -586,7 +708,7 @@ function initChannelPreview(container) {
|
||||
container.innerHTML = '<p class="simplex-preview-empty">Failed to load channel preview.</p>';
|
||||
return;
|
||||
}
|
||||
render(container, data, channelLink);
|
||||
render(container, data, channelLink, showAppBadges);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -620,7 +742,7 @@ async function fetchPreview(relayScheme, relayDomains, channelLink, channelId) {
|
||||
return linkMismatch ? 'link_mismatch' : null;
|
||||
}
|
||||
|
||||
function render(container, data, channelLink) {
|
||||
function render(container, data, channelLink, showAppBadges) {
|
||||
const { channel, members, messages } = data;
|
||||
const membersMap = {};
|
||||
for (const m of members) {
|
||||
@@ -652,13 +774,12 @@ function render(container, data, channelLink) {
|
||||
|
||||
const infoContent = document.createElement('div');
|
||||
infoContent.className = 'simplex-preview-info-content';
|
||||
renderInfoContent(infoContent, data, channelLink, members.length);
|
||||
renderInfoContent(infoContent, data, channelLink, members.length, showAppBadges);
|
||||
info.appendChild(infoContent);
|
||||
|
||||
container.appendChild(info);
|
||||
|
||||
header.addEventListener('click', (e) => {
|
||||
if (e.target.closest('.simplex-preview-join-btn')) return;
|
||||
header.addEventListener('click', () => {
|
||||
if (window.innerWidth < 1000) {
|
||||
info.classList.add('open');
|
||||
main.style.overflow = 'hidden';
|
||||
@@ -704,22 +825,16 @@ function renderHeader(channel, channelLink, subscriberCount) {
|
||||
header.appendChild(info);
|
||||
|
||||
if (channelLink) {
|
||||
const btn = document.createElement('a');
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'simplex-preview-join-btn';
|
||||
btn.textContent = 'Join';
|
||||
try {
|
||||
btn.href = platformSimplexUri(channelLink);
|
||||
} catch(e) {
|
||||
btn.href = channelLink;
|
||||
}
|
||||
btn.target = '_blank';
|
||||
header.appendChild(btn);
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
function renderInfoContent(container, data, channelLink, subscriberCount) {
|
||||
function renderInfoContent(container, data, channelLink, subscriberCount, showAppBadges) {
|
||||
const { channel } = data;
|
||||
|
||||
const avatar = document.createElement('img');
|
||||
@@ -765,19 +880,116 @@ function renderInfoContent(container, data, channelLink, subscriberCount) {
|
||||
}
|
||||
|
||||
if (channelLink) {
|
||||
const btn = document.createElement('a');
|
||||
btn.className = 'simplex-preview-join-btn';
|
||||
btn.textContent = 'Join';
|
||||
try {
|
||||
btn.href = platformSimplexUri(channelLink);
|
||||
} catch(e) {
|
||||
btn.href = channelLink;
|
||||
const conversion = document.createElement('div');
|
||||
conversion.className = 'simplex-preview-conversion';
|
||||
if (isMobile.any()) {
|
||||
renderMobileConversion(conversion, channelLink, showAppBadges);
|
||||
} else {
|
||||
renderDesktopConversion(conversion, channelLink, showAppBadges);
|
||||
}
|
||||
btn.target = '_blank';
|
||||
container.appendChild(btn);
|
||||
container.appendChild(conversion);
|
||||
}
|
||||
}
|
||||
|
||||
function renderDesktopConversion(container, channelLink, showAppBadges) {
|
||||
const qrContainer = document.createElement('div');
|
||||
qrContainer.className = 'simplex-preview-qr-container';
|
||||
const canvas = document.createElement('canvas');
|
||||
qrContainer.appendChild(canvas);
|
||||
|
||||
const caption = document.createElement('p');
|
||||
caption.className = 'simplex-preview-qr-caption';
|
||||
caption.textContent = 'Scan from mobile app to join';
|
||||
qrContainer.appendChild(caption);
|
||||
container.appendChild(qrContainer);
|
||||
|
||||
try {
|
||||
QRCode.toCanvas(canvas, channelLink, {
|
||||
errorCorrectionLevel: 'M',
|
||||
color: { dark: '#062D56' },
|
||||
width: 400,
|
||||
margin: 1
|
||||
}).then(function() {
|
||||
canvas.style.width = '200px';
|
||||
canvas.style.height = '200px';
|
||||
}).catch(function() {
|
||||
qrContainer.style.display = 'none';
|
||||
});
|
||||
} catch(e) {
|
||||
qrContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
if (showAppBadges) {
|
||||
const badges = document.createElement('div');
|
||||
badges.className = 'simplex-preview-badges';
|
||||
badges.innerHTML =
|
||||
'<a href="https://apps.apple.com/us/app/simplex-chat/id1605771084" target="_blank"><img src="https://simplex.chat/img/new/apple_store.svg" alt="App Store"></a>' +
|
||||
'<a href="https://play.google.com/store/apps/details?id=chat.simplex.app" target="_blank"><img src="https://simplex.chat/img/new/google_play.svg" alt="Google Play"></a>';
|
||||
container.appendChild(badges);
|
||||
}
|
||||
|
||||
const copySection = document.createElement('div');
|
||||
copySection.className = 'simplex-preview-copy-section';
|
||||
copySection.innerHTML = 'Or copy link for <a href="https://simplex.chat/downloads" target="_blank">desktop app</a>:';
|
||||
|
||||
const copyRow = document.createElement('div');
|
||||
copyRow.className = 'simplex-preview-copy-row';
|
||||
|
||||
const linkText = document.createElement('span');
|
||||
linkText.className = 'simplex-preview-copy-link';
|
||||
linkText.textContent = channelLink;
|
||||
copyRow.appendChild(linkText);
|
||||
|
||||
const copyBtn = document.createElement('button');
|
||||
copyBtn.className = 'simplex-preview-copy-btn';
|
||||
copyBtn.innerHTML = COPY_ICON_SVG;
|
||||
copyBtn.title = 'Copy to clipboard';
|
||||
copyBtn.addEventListener('click', function() {
|
||||
navigator.clipboard.writeText(channelLink).then(function() {
|
||||
copyBtn.title = 'Copied!';
|
||||
setTimeout(function() { copyBtn.title = 'Copy to clipboard'; }, 2000);
|
||||
});
|
||||
});
|
||||
copyRow.appendChild(copyBtn);
|
||||
|
||||
copySection.appendChild(copyRow);
|
||||
container.appendChild(copySection);
|
||||
}
|
||||
|
||||
function renderMobileConversion(container, channelLink, showAppBadges) {
|
||||
if (showAppBadges) {
|
||||
const stepLabel = document.createElement('p');
|
||||
stepLabel.className = 'simplex-preview-step-label';
|
||||
stepLabel.textContent = 'Install SimpleX App';
|
||||
container.appendChild(stepLabel);
|
||||
|
||||
const badges = document.createElement('div');
|
||||
badges.className = 'simplex-preview-badges';
|
||||
|
||||
if (isMobile.Android()) {
|
||||
badges.innerHTML =
|
||||
'<a href="https://play.google.com/store/apps/details?id=chat.simplex.app" target="_blank"><img src="https://simplex.chat/img/new/google_play.svg" alt="Google Play"></a>' +
|
||||
'<a href="https://simplex.chat/fdroid" target="_blank"><img src="https://simplex.chat/img/new/f_droid.svg" alt="F-Droid"></a>' +
|
||||
'<a href="https://github.com/simplex-chat/simplex-chat/releases/latest/download/simplex-aarch64.apk" target="_blank"><img src="https://simplex.chat/img/design_3/android-dark.png" alt="APK Download"></a>';
|
||||
} else if (isMobile.iOS()) {
|
||||
badges.innerHTML =
|
||||
'<a href="https://apps.apple.com/us/app/simplex-chat/id1605771084" target="_blank"><img src="https://simplex.chat/img/new/apple_store.svg" alt="App Store"></a>' +
|
||||
'<a href="https://testflight.apple.com/join/DWuT2LQu" target="_blank"><img src="https://simplex.chat/img/design_3/testflight-dark.png" alt="TestFlight"></a>';
|
||||
} else {
|
||||
badges.innerHTML =
|
||||
'<a href="https://apps.apple.com/us/app/simplex-chat/id1605771084" target="_blank"><img src="https://simplex.chat/img/new/apple_store.svg" alt="App Store"></a>' +
|
||||
'<a href="https://play.google.com/store/apps/details?id=chat.simplex.app" target="_blank"><img src="https://simplex.chat/img/new/google_play.svg" alt="Google Play"></a>';
|
||||
}
|
||||
container.appendChild(badges);
|
||||
}
|
||||
|
||||
const openBtn = document.createElement('a');
|
||||
openBtn.className = 'simplex-preview-open-btn';
|
||||
openBtn.textContent = 'Open SimpleX App';
|
||||
openBtn.href = channelLink;
|
||||
container.appendChild(openBtn);
|
||||
}
|
||||
|
||||
function setupExpandCollapse(section, readMore) {
|
||||
if (section._measured) return;
|
||||
const lineHeight = parseFloat(getComputedStyle(section).lineHeight);
|
||||
|
||||
Reference in New Issue
Block a user