Files
damus/damus/Features/Live/LiveChat/Views/LiveChatHomeView.swift
T
2026-03-09 21:08:29 -04:00

137 lines
4.0 KiB
Swift

//
// LiveChatHomeView.swift
// damus
//
// Created by eric on 8/7/25.
//
import SwiftUI
struct LiveChatHomeView: View, KeyboardReadable {
let state: DamusState
let event: LiveEvent
@StateObject var model: LiveChatModel
@State private var chat_message = ""
@FocusState private var isTextFieldFocused: Bool
@Environment(\.colorScheme) var colorScheme
func content_filter(_ fstate: FilterState) -> ((NostrEvent) -> Bool) {
var filters = ContentFilters.defaults(damus_state: state)
filters.append(fstate.filter)
return ContentFilters(filters: filters).filter
}
var Footer: some View {
HStack(spacing: 0) {
ChatInput
Button(
role: .none,
action: {
Task { await send_chat() }
}
) {
Label("", image: "send")
.font(.title)
}
.disabled(chat_message.isEmpty)
}
.safeAreaInset(edge: .bottom) {
Color.clear.frame(height: 10)
}
}
func send_chat() async {
guard
let keypair = state.keypair.to_full(),
let liveChat = make_live_chat_event(keypair: keypair, content: chat_message, root: event.event.pubkey.hex(), dtag: event.uuid ?? "", relayURL: nil)
else {
return
}
await state.nostrNetwork.postbox.send(liveChat)
chat_message = ""
end_editing()
}
var ChatInput: some View {
HStack{
TextField(NSLocalizedString("Chat", comment: "Placeholder text to prompt entry of chat message."), text: $chat_message)
.autocorrectionDisabled(true)
.textInputAutocapitalization(.never)
.focused($isTextFieldFocused)
}
.padding(10)
.background(.secondary.opacity(0.2))
.cornerRadius(20)
.padding(.horizontal, 15)
}
func scroll_to_end(_ scroller: ScrollViewProxy, animated: Bool = false) {
if animated {
withAnimation {
scroller.scrollTo("endblock")
}
} else {
scroller.scrollTo("endblock")
}
}
var Chat: some View {
ScrollViewReader { scroller in
ScrollView {
LazyVStack(alignment: .leading, spacing: 0) {
let events = model.events.events
ForEach(Array(zip(events, events.indices).reversed()).filter { should_show_event(state: state, ev: $0.0)}, id: \.0.id) { (ev, ind) in
TextEvent(damus: state, event: ev, pubkey: ev.pubkey, options: .live_chat)
}
EndBlock(height: 1)
}
}
.dismissKeyboardOnTap()
.onAppear {
scroll_to_end(scroller)
}.onChange(of: model.events.events.count) { _ in
scroll_to_end(scroller, animated: true)
}
.padding(.top, 5)
Footer
.onReceive(keyboardPublisher) { visible in
guard visible else {
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
scroll_to_end(scroller, animated: true)
}
}
}
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
HStack {
Text("Live Chat", comment: "Title for the live stream chat.")
.fontWeight(.bold)
.padding(5)
LiveStreamViewers(state: state, currentParticipants: event.currentParticipants ?? 0, preview: false)
}
Divider()
Chat
}
.onReceive(handle_notify(.new_mutes)) { _ in
self.model.filter_muted()
}
.onAppear {
model.subscribe()
}
.onDisappear {
model.unsubscribe()
}
}
}