mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-06-28 20:41:48 +00:00
adb3fb8cb2
* plan: web previews for channels
* types for recipient side to support channel web previews and domain names
* fix
* migrations
* update schema and api types
* update schema
* rename migrations
* core: render channel preview data
* core: render channel preview data in relays
* website: use cpp to inject JS functions
* JSC files
* remove directory.js
* channel preview renderer
* Revert "cli: fix redraw slowness (#6735)"
This reverts commit b801d77c74.
* sample channel page
* default avatar
* rename options
* better layout
* layout
* images
* some fixes
* tails
* markdown colors
* image sizes
* reactions
* fix reactions
* fewer avatars
* forward icon
* command to change group access parameters
* view public group access changes in CLI
* media metadata color
* ios: group web access ui
* update ui
* add init
* kotlin, labels
* update page
* update relay base URL
* fix
* ios update channel web page info
* update kotlin layout
* use cards
* update layout
* use domains for relay data, path is fixed
* update embed code
* fix bots api
* include only history items and senders
* update preview JS/HTML
* show different error if link is different
* remove stale json files
* better layout
* layout fixes
* improve layout
* improve layout
* update embed code
* web cta
* better layout
* buttons
* layout
* paddings
* desktop cta
* desktop cta
* cta layout
* fonts
* paddings
* paddings
* more paddings
* copy link
* read more
* hide avatar and placeholder when all messages are from channel
* color scheme
* fix color
* improve
* layout
* welcome message
* dark mode colors
* padding
* font size
* overscroll
* font
* logo on button
* better join
* buttons
* refactor
* another logo
* text
* desktop button
* button text
* center
* fix svg
* padding
* smaller gap
* render channel on any message changes etc
* fixes
* atomic file updates, escape attributes
* fix tests
* more tests
* more efficient rendering
* improve security
* sanitize links, include mentioned members
* schema
* fixes
* improve rendering
* fix showing correct subscribers count
* fix member names
---------
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
170 lines
6.3 KiB
Swift
170 lines
6.3 KiB
Swift
//
|
|
// ChannelWebAccessView.swift
|
|
// SimpleX (iOS)
|
|
//
|
|
// Created by simplex.chat on 31/05/2026.
|
|
// Copyright © 2026 SimpleX Chat. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import SimpleXChat
|
|
|
|
struct ChannelWebAccessView: View {
|
|
@EnvironmentObject var theme: AppTheme
|
|
@Environment(\.dismiss) var dismiss: DismissAction
|
|
@Binding var groupInfo: GroupInfo
|
|
@State private var webPage: String
|
|
@State private var allowEmbedding: Bool
|
|
@State private var saving = false
|
|
@State private var groupRelays: [GroupRelay] = []
|
|
|
|
init(groupInfo: Binding<GroupInfo>) {
|
|
_groupInfo = groupInfo
|
|
let access = groupInfo.wrappedValue.groupProfile.publicGroup?.publicGroupAccess
|
|
_webPage = State(initialValue: access?.groupWebPage ?? "")
|
|
_allowEmbedding = State(initialValue: access?.allowEmbedding ?? false)
|
|
}
|
|
|
|
var body: some View {
|
|
List {
|
|
if let code = embedCode {
|
|
webpageInfo("Create a webpage to show your channel preview to visitors before they subscribe. Host it yourself or use any static hosting.")
|
|
|
|
Section {
|
|
ScrollView {
|
|
Text(code)
|
|
.font(.system(.caption, design: .monospaced))
|
|
.textSelection(.enabled)
|
|
}
|
|
.frame(maxHeight: 88)
|
|
Button {
|
|
UIPasteboard.general.string = code
|
|
} label: {
|
|
Label("Copy code", systemImage: "doc.on.doc")
|
|
}
|
|
} header: {
|
|
Text("Webpage code")
|
|
} footer: {
|
|
Text("Add this code to your webpage. It will display the preview of your channel / group.")
|
|
}
|
|
} else {
|
|
webpageInfo("Used chat relays do not support webpages.")
|
|
}
|
|
|
|
Section {
|
|
TextField("https://", text: $webPage)
|
|
.keyboardType(.URL)
|
|
.autocapitalization(.none)
|
|
.disableAutocorrection(true)
|
|
} header: {
|
|
Text("Enter webpage URL")
|
|
} footer: {
|
|
Text("It will be shown to subscribers and used to allow loading the preview.")
|
|
}
|
|
|
|
Section {
|
|
Toggle("Allow anyone to embed", isOn: $allowEmbedding)
|
|
} footer: {
|
|
Text(allowEmbedding ? "Any webpage can show the preview." : "Only your page above can show the preview.")
|
|
}
|
|
|
|
Section {
|
|
Button {
|
|
saveAccess()
|
|
} label: {
|
|
HStack {
|
|
Text(groupInfo.isChannel ? "Save and notify subscribers" : "Save and notify members")
|
|
if saving { Spacer(); ProgressView() }
|
|
}
|
|
}
|
|
.disabled(!hasChanges || saving)
|
|
}
|
|
}
|
|
.modifier(ThemedBackground(grouped: true))
|
|
.onAppear {
|
|
Task {
|
|
let relays = await apiGetGroupRelays(groupInfo.groupId)
|
|
await MainActor.run { groupRelays = relays }
|
|
}
|
|
}
|
|
.onDisappear {
|
|
if hasChanges {
|
|
showAlert(
|
|
title: NSLocalizedString("Save webpage settings?", comment: "alert title"),
|
|
message: NSLocalizedString("Webpage settings were changed. If you save, the updated settings will be sent to subscribers.", comment: "alert message"),
|
|
buttonTitle: NSLocalizedString("Save", comment: "alert button"),
|
|
buttonAction: saveAccess,
|
|
cancelButton: true
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func webpageInfo(_ text: LocalizedStringKey) -> some View {
|
|
Section {
|
|
Text(text).foregroundColor(theme.colors.secondary)
|
|
}
|
|
.listRowBackground(Color.clear)
|
|
.listRowSeparator(.hidden)
|
|
.listRowInsets(EdgeInsets(top: 8, leading: 16, bottom: 0, trailing: 16))
|
|
}
|
|
|
|
private var hasChanges: Bool {
|
|
let access = groupInfo.groupProfile.publicGroup?.publicGroupAccess
|
|
let currentWebPage = access?.groupWebPage ?? ""
|
|
let currentEmbedding = access?.allowEmbedding ?? false
|
|
return webPage != currentWebPage || allowEmbedding != currentEmbedding
|
|
}
|
|
|
|
private var relayDomains: [String] {
|
|
groupRelays.compactMap { $0.relayCap.webDomain }
|
|
}
|
|
|
|
private var embedCode: String? {
|
|
if let pg = groupInfo.groupProfile.publicGroup,
|
|
!relayDomains.isEmpty {
|
|
"""
|
|
<div data-simplex-channel-preview
|
|
data-channel-link="\(pg.groupLink)"
|
|
data-channel-id="\(pg.publicGroupId)"
|
|
data-relay-domains="\(relayDomains.joined(separator: ","))"
|
|
data-app-download-buttons="on"
|
|
data-color-scheme="light"
|
|
></div>
|
|
<script src="https://simplex.chat/js/channel-preview.js"></script>
|
|
"""
|
|
} else {
|
|
nil
|
|
}
|
|
}
|
|
|
|
private func saveAccess() {
|
|
saving = true
|
|
Task {
|
|
do {
|
|
var gp = groupInfo.groupProfile
|
|
if var pg = gp.publicGroup {
|
|
let trimmedPage = webPage.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let existingAccess = pg.publicGroupAccess
|
|
pg.publicGroupAccess = PublicGroupAccess(
|
|
groupWebPage: trimmedPage.isEmpty ? nil : trimmedPage,
|
|
groupDomain: existingAccess?.groupDomain,
|
|
domainWebPage: existingAccess?.domainWebPage ?? false,
|
|
allowEmbedding: allowEmbedding
|
|
)
|
|
gp.publicGroup = pg
|
|
}
|
|
let gInfo = try await apiUpdateGroup(groupInfo.groupId, gp)
|
|
await MainActor.run {
|
|
groupInfo = gInfo
|
|
ChatModel.shared.updateGroup(gInfo)
|
|
saving = false
|
|
}
|
|
} catch {
|
|
logger.error("ChannelWebAccessView apiUpdateGroup error: \(responseError(error))")
|
|
await MainActor.run { saving = false }
|
|
}
|
|
}
|
|
}
|
|
}
|