import SwiftUI extension ChannelsSettings { func formSection(_ title: String, @ViewBuilder content: () -> some View) -> some View { GroupBox(title) { VStack(alignment: .leading, spacing: 10) { content() } .frame(maxWidth: .infinity, alignment: .leading) } } @ViewBuilder func channelHeaderActions(_ channel: ChannelItem) -> some View { HStack(spacing: 8) { if channel.id == "whatsapp" { Button("Logout") { Task { await self.store.logoutWhatsApp() } } .buttonStyle(.bordered) .disabled(self.store.whatsappBusy) } if channel.id == "telegram" { Button("Logout") { Task { await self.store.logoutTelegram() } } .buttonStyle(.bordered) .disabled(self.store.telegramBusy) } Button { Task { await self.store.refresh(probe: true) } } label: { if self.store.isRefreshing { ProgressView().controlSize(.small) } else { Text("Refresh") } } .buttonStyle(.bordered) .disabled(self.store.isRefreshing) } .controlSize(.small) } var whatsAppSection: some View { VStack(alignment: .leading, spacing: 16) { self.formSection("Linking") { if let message = self.store.whatsappLoginMessage { Text(message) .font(.caption) .foregroundStyle(.secondary) .fixedSize(horizontal: false, vertical: true) } if let qr = self.store.whatsappLoginQrDataUrl, let image = self.qrImage(from: qr) { Image(nsImage: image) .resizable() .interpolation(.none) .frame(width: 180, height: 180) .cornerRadius(8) } HStack(spacing: 12) { Button { Task { await self.store.startWhatsAppLogin(force: false) } } label: { if self.store.whatsappBusy { ProgressView().controlSize(.small) } else { Text("Show QR") } } .buttonStyle(.borderedProminent) .disabled(self.store.whatsappBusy) Button("Relink") { Task { await self.store.startWhatsAppLogin(force: true) } } .buttonStyle(.bordered) .disabled(self.store.whatsappBusy) } .font(.caption) } self.configEditorSection(channelId: "whatsapp") } } @ViewBuilder func genericChannelSection(_ channel: ChannelItem) -> some View { VStack(alignment: .leading, spacing: 16) { self.configEditorSection(channelId: channel.id) } } @ViewBuilder private func configEditorSection(channelId: String) -> some View { self.formSection("Configuration") { ChannelConfigForm(store: self.store, channelId: channelId) } self.configStatusMessage HStack(spacing: 12) { Button { Task { await self.store.saveConfigDraft() } } label: { if self.store.isSavingConfig { ProgressView().controlSize(.small) } else { Text("Save") } } .buttonStyle(.borderedProminent) .disabled(self.store.isSavingConfig || !self.store.configDirty) Button("Reload") { Task { await self.store.reloadConfigDraft() } } .buttonStyle(.bordered) .disabled(self.store.isSavingConfig) Spacer() } .font(.caption) } @ViewBuilder var configStatusMessage: some View { if let status = self.store.configStatus { Text(status) .font(.caption) .foregroundStyle(.secondary) .fixedSize(horizontal: false, vertical: true) } } }