mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-23 17:13:10 +00:00
ios: group web access ui
This commit is contained in:
1 parent
ac8503b75f
commit
3d0f5ff590
3 files changed
+156
No files matched your search
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// 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 {
|
||||
Section {
|
||||
TextField("Web page URL", text: $webPage)
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
Toggle("Allow embedding", isOn: $allowEmbedding)
|
||||
} header: {
|
||||
Text("Web access")
|
||||
} footer: {
|
||||
Text("Set a web page URL where your channel preview is hosted. Allow embedding to let any website embed the preview.")
|
||||
}
|
||||
|
||||
if let code = embedCode {
|
||||
Section {
|
||||
Text(code)
|
||||
.font(.system(.caption, design: .monospaced))
|
||||
.textSelection(.enabled)
|
||||
Button {
|
||||
UIPasteboard.general.string = code
|
||||
} label: {
|
||||
Label("Copy embed code", systemImage: "doc.on.doc")
|
||||
}
|
||||
} header: {
|
||||
Text("Embed code")
|
||||
}
|
||||
}
|
||||
|
||||
Section {
|
||||
Button {
|
||||
saveAccess()
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Save")
|
||||
if saving { Spacer(); ProgressView() }
|
||||
}
|
||||
}
|
||||
.disabled(!hasChanges || saving)
|
||||
}
|
||||
}
|
||||
.modifier(ThemedBackground(grouped: true))
|
||||
.onAppear {
|
||||
Task {
|
||||
let relays = await apiGetGroupRelays(groupInfo.groupId)
|
||||
await MainActor.run { groupRelays = relays }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 relayUrls: [String] {
|
||||
groupRelays.compactMap { $0.relayCap.baseWebUrl }
|
||||
}
|
||||
|
||||
private var embedCode: String? {
|
||||
guard let pg = groupInfo.groupProfile.publicGroup else { return nil }
|
||||
guard !relayUrls.isEmpty else { return nil }
|
||||
let publicGroupId = pg.publicGroupId
|
||||
let groupLink = pg.groupLink
|
||||
let urls = relayUrls.joined(separator: ",")
|
||||
return """
|
||||
<div data-simplex-group-preview
|
||||
data-relay-urls="\(urls)"
|
||||
data-public-group-id="\(publicGroupId)"
|
||||
data-group-link="\(groupLink)"></div>
|
||||
<script src="https://simplex.chat/js/channel-preview.js"></script>
|
||||
"""
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,6 +112,7 @@ struct GroupChatInfoView: View {
|
||||
// TODO [relays] allow other owners to manage channel link (requires protocol changes to share link ownership)
|
||||
if groupInfo.isOwner && groupLink != nil {
|
||||
channelLinkButton()
|
||||
channelWebAccessButton()
|
||||
} else if let link = groupInfo.groupProfile.publicGroup?.groupLink {
|
||||
SimpleXLinkQRCode(uri: link)
|
||||
Button {
|
||||
@@ -325,6 +326,15 @@ struct GroupChatInfoView: View {
|
||||
.lineLimit(4)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
if let webPage = groupInfo.groupProfile.publicGroup?.publicGroupAccess?.groupWebPage,
|
||||
let url = URL(string: webPage) {
|
||||
Link(destination: url) {
|
||||
Text(webPage)
|
||||
.font(.subheadline)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
}
|
||||
}
|
||||
if groupInfo.useRelays,
|
||||
let count = groupInfo.groupSummary.publicMemberCount,
|
||||
count > 0 {
|
||||
@@ -648,6 +658,16 @@ struct GroupChatInfoView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func channelWebAccessButton() -> some View {
|
||||
NavigationLink {
|
||||
ChannelWebAccessView(groupInfo: $groupInfo)
|
||||
.navigationBarTitle("Web access")
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
} label: {
|
||||
Label("Web page", systemImage: "globe")
|
||||
}
|
||||
}
|
||||
|
||||
private func groupLinkDestinationView() -> some View {
|
||||
GroupLinkView(
|
||||
groupId: groupInfo.groupId,
|
||||
|
||||
@@ -169,6 +169,7 @@
|
||||
648679AB2BC96A74006456E7 /* ChatItemForwardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648679AA2BC96A74006456E7 /* ChatItemForwardingView.swift */; };
|
||||
6495D7042F48CFC50060512B /* ChannelMembersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6495D7032F48CFC50060512B /* ChannelMembersView.swift */; };
|
||||
6495D7062F48CFFD0060512B /* ChannelRelaysView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6495D7052F48CFFD0060512B /* ChannelRelaysView.swift */; };
|
||||
E5E418022F83D2CA00252B9E /* ChannelWebAccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5E418032F83D2CA00252B9E /* ChannelWebAccessView.swift */; };
|
||||
6495D7082F48D0000060512B /* AddGroupRelayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6495D7072F48D0000060512B /* AddGroupRelayView.swift */; };
|
||||
649BCDA0280460FD00C3A862 /* ComposeImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCD9F280460FD00C3A862 /* ComposeImageView.swift */; };
|
||||
649BCDA22805D6EF00C3A862 /* CIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649BCDA12805D6EF00C3A862 /* CIImageView.swift */; };
|
||||
@@ -547,6 +548,7 @@
|
||||
6493D667280ED77F007A76FB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
6495D7032F48CFC50060512B /* ChannelMembersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelMembersView.swift; sourceTree = "<group>"; };
|
||||
6495D7052F48CFFD0060512B /* ChannelRelaysView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelRelaysView.swift; sourceTree = "<group>"; };
|
||||
E5E418032F83D2CA00252B9E /* ChannelWebAccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelWebAccessView.swift; sourceTree = "<group>"; };
|
||||
6495D7072F48D0000060512B /* AddGroupRelayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddGroupRelayView.swift; sourceTree = "<group>"; };
|
||||
649BCD9F280460FD00C3A862 /* ComposeImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeImageView.swift; sourceTree = "<group>"; };
|
||||
649BCDA12805D6EF00C3A862 /* CIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIImageView.swift; sourceTree = "<group>"; };
|
||||
@@ -1175,6 +1177,7 @@
|
||||
64A779FD2DC3AFF200FDEF2F /* MemberSupportChatToolbar.swift */,
|
||||
6495D7032F48CFC50060512B /* ChannelMembersView.swift */,
|
||||
6495D7052F48CFFD0060512B /* ChannelRelaysView.swift */,
|
||||
E5E418032F83D2CA00252B9E /* ChannelWebAccessView.swift */,
|
||||
6495D7072F48D0000060512B /* AddGroupRelayView.swift */,
|
||||
);
|
||||
path = Group;
|
||||
@@ -1636,6 +1639,7 @@
|
||||
8C9BC2652C240D5200875A27 /* ThemeModeEditor.swift in Sources */,
|
||||
647B15E82F4C8D2500EB431E /* AddChannelView.swift in Sources */,
|
||||
6495D7062F48CFFD0060512B /* ChannelRelaysView.swift in Sources */,
|
||||
E5E418022F83D2CA00252B9E /* ChannelWebAccessView.swift in Sources */,
|
||||
6495D7082F48D0000060512B /* AddGroupRelayView.swift in Sources */,
|
||||
5CB346E92869E8BA001FD2EF /* PushEnvironment.swift in Sources */,
|
||||
5C55A91F283AD0E400C4E99E /* CallManager.swift in Sources */,
|
||||
|
||||
Reference in new issue
Block a user