aboutsummaryrefslogtreecommitdiff
path: root/Hotline
diff options
context:
space:
mode:
authorDustin Mierau <dustin@mierau.me>2025-10-24 23:02:12 -0700
committerDustin Mierau <dustin@mierau.me>2025-10-24 23:02:12 -0700
commitfefede829c12d9f69db72d70231291d973b0c1a2 (patch)
treee51caa817df6fb00063c5179ff0a8a77753a21ae /Hotline
parentcf113ea053334175b93770b025c1f7d22eda6eab (diff)
Further polish on chat. Try not to persist back to back disconnect messages.
Diffstat (limited to 'Hotline')
-rw-r--r--Hotline/Models/ChatMessage.swift5
-rw-r--r--Hotline/Models/Hotline.swift14
-rw-r--r--Hotline/iOS/ChatView.swift11
-rw-r--r--Hotline/macOS/ChatView.swift97
4 files changed, 47 insertions, 80 deletions
diff --git a/Hotline/Models/ChatMessage.swift b/Hotline/Models/ChatMessage.swift
index 365f91f..744a5d2 100644
--- a/Hotline/Models/ChatMessage.swift
+++ b/Hotline/Models/ChatMessage.swift
@@ -2,7 +2,6 @@ import SwiftUI
enum ChatMessageType {
case agreement
- case status
case joined
case left
case message
@@ -15,8 +14,6 @@ extension ChatMessageType {
switch self {
case .agreement:
return "agreement"
- case .status:
- return "status"
case .joined:
return "joined"
case .left:
@@ -34,8 +31,6 @@ extension ChatMessageType {
switch storageKey {
case "agreement":
self = .agreement
- case "status":
- self = .status
case "joined":
self = .joined
case "left":
diff --git a/Hotline/Models/Hotline.swift b/Hotline/Models/Hotline.swift
index 8cdeccd..08b79a1 100644
--- a/Hotline/Models/Hotline.swift
+++ b/Hotline/Models/Hotline.swift
@@ -196,6 +196,7 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileDownloadClientDelega
@ObservationIgnored private var chatSessionKey: ChatStore.SessionKey?
@ObservationIgnored private var restoredChatSessionKey: ChatStore.SessionKey?
@ObservationIgnored private var chatHistoryObserver: NSObjectProtocol?
+ @ObservationIgnored private var lastPersistedMessageType: ChatMessageType?
#if os(macOS)
var bannerImage: NSImage? = nil
#elseif os(iOS)
@@ -244,6 +245,7 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileDownloadClientDelega
let key = sessionKey(for: server)
self.chatSessionKey = key
self.restoredChatSessionKey = nil
+ self.lastPersistedMessageType = nil
self.chat = []
self.restoreChatHistory(for: key)
@@ -1132,6 +1134,7 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileDownloadClientDelega
self.chatSessionKey = nil
self.restoredChatSessionKey = nil
+ self.lastPersistedMessageType = nil
}
else if status == .loggedIn {
if Prefs.shared.playSounds && Prefs.shared.playLoggedInSound {
@@ -1395,12 +1398,19 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileDownloadClientDelega
}
private func recordChatMessage(_ message: ChatMessage, persist: Bool = true, display: Bool = true) {
+ let shouldPersist = persist && message.type != .agreement
+ if shouldPersist,
+ message.type == .signOut,
+ lastPersistedMessageType == .signOut {
+ return
+ }
+
if display {
self.chat.append(message)
}
- let shouldPersist = persist && message.type != .agreement
guard shouldPersist, let key = chatSessionKey else { return }
+ self.lastPersistedMessageType = message.type
let entry = ChatStore.Entry(
id: message.id,
body: message.text,
@@ -1438,6 +1448,7 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileDownloadClientDelega
return ChatMessage(text: renderedText, type: chatType, date: entry.date)
}
self.chat = historyMessages + currentMessages
+ self.lastPersistedMessageType = historyMessages.last?.type
self.unreadPublicChat = false
self.restoredChatSessionKey = key
}
@@ -1448,6 +1459,7 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileDownloadClientDelega
self.chat = []
self.unreadPublicChat = false
self.restoredChatSessionKey = nil
+ self.lastPersistedMessageType = nil
}
func updateServerTitle() {
diff --git a/Hotline/iOS/ChatView.swift b/Hotline/iOS/ChatView.swift
index 0ad41e0..e320dbf 100644
--- a/Hotline/iOS/ChatView.swift
+++ b/Hotline/iOS/ChatView.swift
@@ -52,17 +52,6 @@ struct ChatView: View {
.frame(maxWidth: .infinity)
.padding()
}
- else if msg.type == .status {
- HStack {
- Spacer()
- Text(msg.text)
- .lineLimit(1)
- .truncationMode(.middle)
- .opacity(0.3)
- Spacer()
- }
- .padding()
- }
else if msg.type == .signOut {
HStack {
Spacer()
diff --git a/Hotline/macOS/ChatView.swift b/Hotline/macOS/ChatView.swift
index 12e6c94..a45e7ed 100644
--- a/Hotline/macOS/ChatView.swift
+++ b/Hotline/macOS/ChatView.swift
@@ -4,35 +4,11 @@ enum FocusedField: Int, Hashable {
case chatInput
}
-struct ChatStatusMessageView: View {
- let message: ChatMessage
-
- var body: some View {
- HStack(alignment: .center, spacing: 8) {
- Image(systemName: "arrow.right")
- .resizable()
- .scaledToFit()
- .fontWeight(.semibold)
- .foregroundStyle(.primary)
- .frame(width: 14, height: 14)
-
- Text(message.text)
- .lineLimit(1)
- .truncationMode(.middle)
- .textSelection(.disabled)
-
- Spacer()
- }
- .opacity(0.3)
- }
-}
-
-
struct ChatJoinedMessageView: View {
let message: ChatMessage
var body: some View {
- HStack(alignment: .center, spacing: 8) {
+ HStack(alignment: .center, spacing: 4) {
Image(systemName: "arrow.right")
.resizable()
.scaledToFit()
@@ -56,7 +32,7 @@ struct ChatLeftMessageView: View {
let message: ChatMessage
var body: some View {
- HStack(alignment: .center, spacing: 8) {
+ HStack(alignment: .center, spacing: 4) {
Image(systemName: "arrow.left")
.resizable()
.scaledToFit()
@@ -206,14 +182,9 @@ struct ChatView: View {
}
.padding(.vertical, 24)
}
- // MARK: Server Message
else if msg.type == .server {
ServerMessageView(message: msg.text)
}
- // MARK: Status
- else if msg.type == .status {
- ChatStatusMessageView(message: msg)
- }
else if msg.type == .joined {
ChatJoinedMessageView(message: msg)
}
@@ -313,38 +284,38 @@ struct ChatView: View {
}
}
- 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
- }
+// 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
+// }
}
#Preview {