| 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) |
| } |
| } |
|
|
| 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") |
| } |
| } |
|
|
| 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) |
| } |
| } |
| } |
|
|