I’ve added the Gemini ChatBot extension to a Firebase venture.
I’ve added the profile!.uid
to the doc by way of ship message operate in order that I can solely retrieve the customers ChatDocuments
.
func sendMessage(_ message: String) {
guard let profileId = profile?.uid else {
print("Profile ID not discovered")
return
}
let knowledge: [String: Any] = [
"prompt": message,
"userID": profileId,
]
db.assortment(collectionPath).addDocument(knowledge: knowledge) { error in
if let error = error {
print("Error including doc: (error)")
} else {
print("Doc added for userID: (profileId)")
}
}
}
At this level, the app efficiently provides a doc to the FireStore and the extension provides a response.
The response is the present within the UI utilizing the next operate.
func fetchMessages() {
print("Fetch messages referred to as for userID: (profile!.uid)")
db.assortment(collectionPath)
.whereField("userID", isEqualTo: profile!.uid)
.order(by: "createTime", descending: false)
.addSnapshotListener { [weak self] querySnapshot, error in
guard let self else { return }
guard let paperwork = querySnapshot?.paperwork else {
print("No paperwork discovered")
return
}
self.messages = paperwork.compactMap { queryDocumentSnapshot -> [ChatMessage]? in
do {
let doc = attempt queryDocumentSnapshot.knowledge(as: ChatDocument.self)
let immediate = ChatMessage(textual content: doc.immediate, isUser: true, state: .COMPLETED)
let response = ChatMessage(textual content: doc.response ?? "", isUser: false, state: doc.standing.chatState)
print("RESPONSE FROM DOCUMENTS")
print("fetched (response)")
return [prompt, response]
} catch {
print(error.localizedDescription)
return nil
}
}.flatMap { $0 }
}
}
Nonetheless when including the next line, the paperwork should not fetched.
.whereField("userID", isEqualTo: profile!.uid)
Chat Doc
struct ChatDocument: Codable {
let createTime: Timestamp
let immediate: String
let response: String?
let standing: Standing
let userID: String
struct Standing: Codable {
let startTime: Timestamp?
let completeTime: Timestamp?
let updateTime: Timestamp
let state: String
let error: String?
var chatState: ChatState {
return ChatState(rawValue: state) ?? .PROCESSING
}
}
}
struct ChatMessage: Hashable {
@ServerTimestamp var createdTime: Timestamp?
@DocumentID var uid: String?
non-public(set) var id: UUID = .init()
var textual content: String?
var isUser: Bool
var state: ChatState = .PROCESSING
var message: String {
change state {
case .COMPLETED:
return textual content ?? ""
case .ERROR:
return "One thing went mistaken. Please attempt once more."
case .PROCESSING:
return "..."
}
}
}
enum ChatState: String, Codable {
case COMPLETED
case ERROR
case PROCESSING
}
FireStore:
Curiously the next removes all paperwork for the profile.uid
and makes use of the identical .whereField("userID", isEqualTo: profile!.uid)
func removeAllMessages() async {
do {
let querySnapshot = attempt await db.assortment(collectionPath)
.whereField("userID", isEqualTo: profile!.uid)
.getDocuments()
for doc in querySnapshot.paperwork {
do {
attempt await db.assortment(collectionPath).doc(doc.documentID).delete()
self.messages.removeAll()
print("Doc with ID (doc.documentID) efficiently eliminated!")
} catch {
print("Error eradicating doc with ID (doc.documentID): (error)")
}
}
} catch {
print("Error querying paperwork for profileId (profile!.uid): (error)")
}
}