Skip to content

Instantly share code, notes, and snippets.

@MainActor
struct ChatView: View {
@Bindable private var viewModel: ChatViewModel = ChatViewModel()
var body: some View {
NavigationStack {
VStack {
ChatMessagesList(viewModel: viewModel)
SendMessageButton {
Task {
await viewModel.sendMessage()
}
}
.disabled(!viewModel.canSendMessage)
@MainActor
@Observable
class ChatViewModel {
// Private
private let client: GeminiClient = GeminiClient()
// Public
var error: Error?
var waitingForResponse: Bool = false
struct ChatMessagesList: View {
@Bindable var viewModel: ChatViewModel
@State private var loadingViewId: UUID? = UUID()
var body: some View {
ScrollView {
ForEach(viewModel.messages) { message in
MessageCell(message: message)
.padding(message.role.padding)
@MainActor
@Observable
class ChatViewModel {
// ...
var scrollPosition: UUID? = nil
func sendMessage() {
guard canSendMessage else { return }
// In a real chat app this would make a server call to send the message
@MainActor
struct ChatView: View {
@Bindable private var viewModel: ChatViewModel = ChatViewModel()
var body: some View {
NavigationStack {
VStack {
ChatMessagesList(viewModel: viewModel)
HStack {
import Foundation
import Observation
@MainActor
@Observable
class ChatViewModel {
var draftMessage: String = ""
private(set) var messages: [Message] = [
Message(
import SwiftUI
struct ErrorView: View {
var body: some View {
Text("Something went wrong, please try sending your message again.")
.foregroundStyle(Color.red)
}
}
import SwiftUI
struct LoadingView: View {
var body: some View {
Image(systemName: "ellipsis.rectangle.fill")
.symbolRenderingMode(.hierarchical)
.foregroundStyle(Color.gray)
.font(.largeTitle)
.symbolEffect(.variableColor, options: .repeating, isActive: true)
@MainActor
@Observable
class ChatViewModel {
// Private
private let client: GeminiClient = GeminiClient()
// Public
var error: Error?
var waitingForResponse: Bool = false