diff options
| author | Dustin Mierau <dustin@mierau.me> | 2023-12-22 23:29:20 -0800 |
|---|---|---|
| committer | Dustin Mierau <dustin@mierau.me> | 2023-12-22 23:29:20 -0800 |
| commit | 8a2a78d62f1cb9a75fe3fc5254f76cc4ffdd26f7 (patch) | |
| tree | 3501ad6fdef17c1823055a7186509eac5dfc76b2 /Hotline | |
| parent | 141ba771eddd2e504a0f29bafd7b9f7c032b72c0 (diff) | |
Added Save Chat button to Chat toolbar.
Diffstat (limited to 'Hotline')
| -rw-r--r-- | Hotline/Application.swift | 12 | ||||
| -rw-r--r-- | Hotline/Utility/TextDocument.swift | 29 | ||||
| -rw-r--r-- | Hotline/macOS/ChatView.swift | 85 | ||||
| -rw-r--r-- | Hotline/macOS/ServerView.swift | 42 |
4 files changed, 111 insertions, 57 deletions
diff --git a/Hotline/Application.swift b/Hotline/Application.swift index 2e35e3c..65833f1 100644 --- a/Hotline/Application.swift +++ b/Hotline/Application.swift @@ -36,6 +36,18 @@ struct Application: App { ServerView(server: s) .frame(minWidth: 400, minHeight: 300) .environment(Hotline(trackerClient: HotlineTrackerClient(), client: HotlineClient())) + .toolbar { + ToolbarItem(placement: .navigation) { + Image(systemName: "globe.americas.fill") + .resizable() + .scaledToFit() +// .foregroundColor(.secondary) + .frame(width: 22) +// .fontWeight(.light) +// Text("") +// .font(.system(size: 22, weight: .ultraLight)) + } + } } } .defaultSize(width: 700, height: 800) diff --git a/Hotline/Utility/TextDocument.swift b/Hotline/Utility/TextDocument.swift new file mode 100644 index 0000000..3904a21 --- /dev/null +++ b/Hotline/Utility/TextDocument.swift @@ -0,0 +1,29 @@ +import Foundation +import UniformTypeIdentifiers +import SwiftUI + +struct TextFile: FileDocument { + // tell the system we support only plain text + static var readableContentTypes = [UTType.plainText, UTType.utf8PlainText] + + // by default our document is empty + var text = "" + + // a simple initializer that creates new, empty documents + init(initialText: String = "") { + text = initialText + } + + // this initializer loads data that has been saved previously + init(configuration: ReadConfiguration) throws { + if let data = configuration.file.regularFileContents { + text = String(decoding: data, as: UTF8.self) + } + } + + // this will be called when the system wants to write our data to disk + func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper { + let data = Data(text.utf8) + return FileWrapper(regularFileWithContents: data) + } +} diff --git a/Hotline/macOS/ChatView.swift b/Hotline/macOS/ChatView.swift index 2b6d10b..618fd12 100644 --- a/Hotline/macOS/ChatView.swift +++ b/Hotline/macOS/ChatView.swift @@ -16,6 +16,10 @@ struct ChatView: View { @FocusState private var focusedField: FocusedField? @Namespace var bottomID + + @State private var showingExporter: Bool = false + + @State private var chatDocument: TextFile = TextFile() var body: some View { NavigationStack { @@ -32,13 +36,13 @@ struct ChatView: View { // MARK: Agreement if msg.type == .agreement { - VStack(alignment: .center) { + VStack(alignment: .center, spacing: 16) { FileImageView() .environment(self.model) .frame(maxWidth: 468.0) - .clipShape(RoundedRectangle(cornerRadius: 8)) - + .clipShape(RoundedRectangle(cornerRadius: 3)) + VStack(spacing: 0) { ScrollView(.vertical) { HStack { @@ -52,28 +56,10 @@ struct ChatView: View { } .scrollBounceBehavior(.basedOnSize) .frame(maxHeight: 375) - -// Divider() -// -// HStack { -// Button("Disagree") { -// dismiss() -// } -// .controlSize(.large) -// -// Spacer() -// -// Button("Agree") { -// model.sendAgree() -// } -// .controlSize(.large) -// .keyboardShortcut(.defaultAction) -// } -// .padding(16) } .background(Color(white: colorScheme == .light ? 0.0 : 1.0).opacity(0.05)) .frame(maxWidth: 468.0) - .clipShape(RoundedRectangle(cornerRadius: 8)) + .clipShape(RoundedRectangle(cornerRadius: 3)) } .frame(maxWidth: .infinity) .padding() @@ -177,6 +163,61 @@ struct ChatView: View { .navigationTitle(self.model.serverTitle) .navigationSubtitle(self.model.users.count > 0 ? "^[\(self.model.users.count) user](inflect: true) online" : "") .background(Color(nsColor: .textBackgroundColor)) + .toolbar { + ToolbarItem(placement: .primaryAction) { + Button { + if prepareChatDocument() { + showingExporter = true + } + } label: { + Image(systemName: "square.and.arrow.up") + }.help("Save Chat") + } + } + .fileExporter(isPresented: $showingExporter, document: chatDocument, contentType: .utf8PlainText, defaultFilename: "\(model.serverTitle) Chat") { result in +// switch result { +// case .success(let url): +// print("Saved to \(url)") +// +// case .failure(let error): +// print(error.localizedDescription) +// } + self.chatDocument.text = "" + } + } + + private func prepareChatDocument() -> Bool { + var text: String = String() + + self.chatDocument.text = "" + + for msg in model.chat { + if msg.type == .agreement { + text.append(msg.text) + text.append("\n\n") + } + else if msg.type == .message { + if let username = msg.username { + text.append("\(username): \(msg.text)") + } + else { + text.append(msg.text) + } + text.append("\n") + } + else if msg.type == .status { + text.append(msg.text) + text.append("\n") + } + } + + if text.isEmpty { + return false + } + + self.chatDocument.text = text + + return true } } diff --git a/Hotline/macOS/ServerView.swift b/Hotline/macOS/ServerView.swift index 7476b3c..7ad344e 100644 --- a/Hotline/macOS/ServerView.swift +++ b/Hotline/macOS/ServerView.swift @@ -131,32 +131,6 @@ struct ServerView: View { var body: some View { NavigationSplitView { List(selection: $selection) { - -// VStack(spacing: 0) { -// bannerImage -// .resizable() -// .aspectRatio(contentMode: .fit) -// .frame(maxWidth: .infinity, minHeight: 60, alignment: .topLeading) -// .clipped() -// } -// .frame(maxWidth: .infinity) -// } -// else { -// HStack { -// Text(server.name ?? "") -// .fontWeight(.medium) -// .lineLimit(2) -// .font(.title3) -// .multilineTextAlignment(.center) -// .padding() -// } -// .selectionDisabled() -// .frame(maxWidth: .infinity, minHeight: 60) -// .background(VisualEffectView(material: .titlebar, blendingMode: .withinWindow).cornerRadius(16)) -// .cornerRadius(10) -// .tag(MenuItem(name: "title", image: "", type: .banner)) -// .padding(.bottom, 16) -// } if model.status != .loggedIn { HStack { @@ -169,19 +143,17 @@ struct ServerView: View { } if model.status == .loggedIn { - Section(model.serverTitle) { - ForEach(ServerView.menuItems) { menuItem in - if let minServerVersion = menuItem.serverVersion { - if let v = model.serverVersion, v >= minServerVersion { - ListItemView(icon: menuItem.image, title: menuItem.name) - .tag(menuItem) - } - } - else { + ForEach(ServerView.menuItems) { menuItem in + if let minServerVersion = menuItem.serverVersion { + if let v = model.serverVersion, v >= minServerVersion { ListItemView(icon: menuItem.image, title: menuItem.name) .tag(menuItem) } } + else { + ListItemView(icon: menuItem.image, title: menuItem.name) + .tag(menuItem) + } } if model.users.count > 0 { |