diff options
| author | Dustin Mierau <dustin@mierau.me> | 2025-11-07 10:19:42 -0800 |
|---|---|---|
| committer | Dustin Mierau <dustin@mierau.me> | 2025-11-07 10:19:42 -0800 |
| commit | 87f08cf60a5d7c1cf618463916cbac4dab88e0f8 (patch) | |
| tree | c15a94443801beff5fcb8ac5d5dbc8276726ee39 /Hotline/macOS/Chat | |
| parent | bcf36ef614aa46ae3d8e714add470f749fdf3714 (diff) | |
Massive refactor of transfer cients (new folder upload implementation), brand new async version of NetSocket, and a rewritten Hotline view model. New cross-server transfers UI.
Diffstat (limited to 'Hotline/macOS/Chat')
| -rw-r--r-- | Hotline/macOS/Chat/ChatView.swift | 77 |
1 files changed, 50 insertions, 27 deletions
diff --git a/Hotline/macOS/Chat/ChatView.swift b/Hotline/macOS/Chat/ChatView.swift index 0795856..e1ec73a 100644 --- a/Hotline/macOS/Chat/ChatView.swift +++ b/Hotline/macOS/Chat/ChatView.swift @@ -88,7 +88,7 @@ struct ChatMessageView: View { } struct ChatView: View { - @Environment(Hotline.self) private var model: Hotline + @Environment(HotlineState.self) private var model: HotlineState @Environment(\.colorScheme) var colorScheme @Environment(\.dismiss) var dismiss @@ -98,12 +98,14 @@ struct ChatView: View { @State private var searchQuery: String = "" @State private var searchResults: [ChatMessage] = [] @State private var isSearching: Bool = false + + @State private var stableBannerImage: Image? @FocusState private var focusedField: FocusedField? @Namespace var bottomID - private var bindableModel: Bindable<Hotline> { + private var bindableModel: Bindable<HotlineState> { Bindable(model) } @@ -114,7 +116,36 @@ struct ChatView: View { var displayedMessages: [ChatMessage] { searchQuery.isEmpty ? model.chat : searchResults } - + +// private var blurredBannerImage: some View { +// self.stableBannerImage? +// .resizable() +// .scaledToFit() +// .frame(maxWidth: 468.0) +// .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) +// .offset(y: 1.5) +// .blur(radius: 4) +// .opacity(0.2) +// } + + private var bannerView: some View { + ZStack { + self.stableBannerImage? + .resizable() + .scaledToFit() + .frame(maxWidth: 468.0) + .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) + .offset(y: 1.5) + .blur(radius: 4) + .opacity(0.2) + self.stableBannerImage? + .resizable() + .scaledToFit() + .frame(maxWidth: 468.0) + .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) + } + } + var body: some View { @Bindable var bindModel = model @@ -129,28 +160,10 @@ struct ChatView: View { ForEach(displayedMessages) { msg in if msg.type == .agreement { VStack(alignment: .center, spacing: 16) { - if let bannerImage = self.model.bannerImage { - HStack(spacing: 0) { - Spacer(minLength: 0) - ZStack { - Image(nsImage: bannerImage) - .resizable() - .scaledToFit() - .frame(maxWidth: 468.0) - .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) - .offset(y: 1.5) - .blur(radius: 4) - .opacity(0.2) - - Image(nsImage: bannerImage) - .resizable() - .scaledToFit() - .frame(maxWidth: 468.0) - .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) - } - - Spacer(minLength: 0) - } + HStack(spacing: 0) { + Spacer(minLength: 0) + self.bannerView + Spacer(minLength: 0) } ServerAgreementView(text: msg.text) @@ -218,7 +231,11 @@ struct ChatView: View { .multilineTextAlignment(.leading) .onSubmit { if !model.chatInput.isEmpty { - model.sendChat(model.chatInput, announce: NSEvent.modifierFlags.contains(.shift)) + let message = model.chatInput + let announce = NSEvent.modifierFlags.contains(.shift) + Task { + try? await model.sendChat(message, announce: announce) + } } model.chatInput = "" } @@ -252,6 +269,12 @@ struct ChatView: View { .onChange(of: searchQuery) { performSearch() } + .onChange(of: model.bannerImage) { oldValue, newValue in + stableBannerImage = newValue + } + .onAppear { + stableBannerImage = model.bannerImage + } // .toolbar { // ToolbarItem(placement: .primaryAction) { // Button { @@ -318,5 +341,5 @@ struct ChatView: View { #Preview { ChatView() - .environment(Hotline(trackerClient: HotlineTrackerClient(), client: HotlineClient())) + .environment(HotlineState()) } |