UNPKG

esoftplay-chatting

Version:

chat module on esoftplay framework

463 lines (416 loc) 16.4 kB
// useLibs // noPage import { doc, serverTimestamp, writeBatch } from "@react-native-firebase/firestore" import { LibUtils } from "esoftplay/cache/lib/utils/import" import { UserClass } from "esoftplay/cache/user/class/import" import esp from "esoftplay/esp" import FastStorage from "esoftplay/mmkv" import { Alert } from "react-native" export interface ChattingLibReturn { chatSendNew: (chat_to: string, message: string, attach: any, withHistory?: boolean, callback?: (message: any, chat_id: string) => void) => void, chatSend: (chat_id: string, chat_to: string, message: string, attach: any, callback: (message: any) => void) => void, chatAll: (chat_id: string, callback: (messages: any[]) => void, lastIndex?: string) => void, chatGet: (chat_id: string, key: string, callback: (chat: any) => void) => void, chatDelete: (chat_id: string, key: string) => void, historyDelete: (chat_id: string, deleted_user_id: string, callback?: () => void) => void, chatGetAll: (chat_id: string, callback: (allmsg: any, end?: boolean) => void, page?: number, limit?: number) => void, // chatListenChange: (chat_id: string, callback: (removedChild: any) => void) => void, chatUpdate: (key: string, chat_id: string, value: any) => void, listenUser: (user_id: string, callback: (user: any) => void) => void, setUser: (username?: string, image?: string, deleted?: boolean) => void, getChatId: (chat_to: string, group_id: string, callback: (chat_id: string) => void) => void, makeId: (length: number) => void, pathChat: any, pathHistory: any, pathUsers: any, } export default function m(): ChattingLibReturn { const group_id = esp.config('group_id') || '4' const perPage = 20 const rootPath: string = esp?.appjson?.()?.expo?.name const pathChat = [rootPath, 'chat', 'chat'] const pathHistory = [rootPath, 'chat', 'history'] const pathUsers = [rootPath, 'chat', 'users'] function makeid(length: number) { var result = ''; var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } function chatSendNew(chat_to: string, message: string, attach: any, withHistory?: boolean, callback?: (message: any, chat_id: string) => void): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!user) return if (user?.id == chat_to) { Alert.alert(esp.lang("chatting/lib", "alert_title"), esp.lang("chatting/lib", "alert_msg")) return } const chat_id = (new Date().getTime() / 1000).toFixed(0) + "-" + makeid(4) const time = (new Date().getTime() / 1000).toFixed(0) let msg: any = { msg: message, read: '0', time: time, timestamp: serverTimestamp(), user_id: user?.id, } if (attach) { msg['attach'] = attach } /* buat chat member default */ let memberMe = { user_id: user?.id, is_typing: false, draf: '' } let memberNotMe = { user_id: chat_to, is_typing: false, draf: '' } /* me */ esp.mod("firestore/index")().addCollection(app, [...pathChat, chat_id, 'member'], memberMe, () => { }, console.warn) /* notMe */ esp.mod("firestore/index")().addCollection(app, [...pathChat, chat_id, 'member'], memberNotMe, () => { }, console.warn) esp.mod("firestore/index")().addCollection(app, [...pathChat, chat_id, 'conversation'], msg, (data) => { msg['key'] = data?.id if (callback) callback(msg, chat_id) if (withHistory) historyNew(chat_id, chat_to, message) }, console.warn) } function historyNew(chat_id: string, chat_to: string, last_message: string, createHistory: "me" | "not-me" | "all" = "all"): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!user) return const _time = (new Date().getTime() / 1000).toFixed(0) let me = { chat_id: chat_id, time: _time, chat_to: chat_to, last_message, read: "0", sender_id: user?.id, group_id, user_id: user?.id } let notMe = { chat_id: chat_id, time: _time, chat_to: user?.id, last_message, read: "0", sender_id: user?.id, group_id, user_id: chat_to } let historyMe: any = {} const historyNotMe = { chat_to_username: user?.name, chat_to_image: user?.image } esp.mod("firestore/index")().getCollectionWhere(app, [...pathUsers], [["user_id", "==", chat_to]], (arr) => { if (arr.length > 0) { historyMe["chat_to_username"] = arr?.[0]?.data?.username historyMe["chat_to_image"] = arr?.[0]?.data?.image } switch (createHistory) { case "all": esp.mod("firestore/index")().addCollection(app, [...pathHistory], { ...me, ...historyMe }, () => { }); esp.mod("firestore/index")().addCollection(app, [...pathHistory], { ...notMe, ...historyNotMe }, () => { }); break; case "me": esp.mod("firestore/index")().addCollection(app, [...pathHistory], { ...me, ...historyMe }, () => { }); break; case "not-me": esp.mod("firestore/index")().addCollection(app, [...pathHistory], { ...notMe, ...historyNotMe }, () => { }); break; } }) } function chatSend(chat_id: string, chat_to: string, message: string, attach: any, callback: (message: any) => void): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!user) return const _time = (new Date().getTime() / 1000).toFixed(0) let msg: any = { msg: message, read: '0', time: _time, timestamp: serverTimestamp(), user_id: user?.id, } if (attach) { msg['attach'] = attach } /* simpan pesan */ esp.mod("firestore/index")().addCollection(app, [...pathChat, chat_id, 'conversation'], msg, (data) => { msg['key'] = data?.id if (callback) { callback(msg) } if (!chat_id) return esp.mod("firestore/index")().getCollectionWhere(app, [...pathHistory], [['chat_id', '==', chat_id]], (datas) => { if (datas.length > 0) { //data isinya {data} id const keys = datas.map((x: any) => x.id) const firstData = { ...datas[0].data, id: datas[0].data.id } esp.mod("firestore/index")().updateBatchDocument(app, [...pathHistory], keys, [ { key: "time", value: _time }, { key: "last_message", value: message }, { key: "read", value: "0" }, { key: "sender_id", value: user?.id }, ] ) if (datas?.length == 1) { const isMe = firstData?.user_id == UserClass?.state?.()?.get?.()?.id if (isMe) historyNew(chat_id, chat_to, message, "not-me") else historyNew(chat_id, chat_to, message, "me") } } else { historyNew(chat_id, chat_to, message) } }, console.warn) }, console.warn) } function chatAll(chat_id: string, callback: (messages: any[]) => void, lastIndex?: string): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!user) return esp.mod("firestore/index")().getCollectionWhereOrderBy(app, [...pathChat, chat_id, 'conversation'], [], [], (arr) => { if (arr) { const snapshoot: any = arr; let a: any = {} snapshoot.map((key: any) => { let item = snapshoot[key]; item.key = key a[key] = item }) callback(a); } else { //@ts-ignore callback(null) } }) } function chatGet(chat_id: string, key: string, callback: (chat: any) => void): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!user) return esp.mod("firestore/index")().getDocument(app, [...pathChat, chat_id, 'conversation', key], (dt) => { if (dt) { callback({ key: dt.id, ...dt.data }); } else { callback(null) } }) } function chatDelete(chat_id: string, key: string): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() const persistKey = 'chatting_chat_message02' + chat_id if (!user) return esp.mod("firestore/index")().deleteDocument(app, [...pathChat, chat_id, 'conversation', key], () => { const storedValue: any = FastStorage.getItemSync(persistKey); const data = JSON.parse(storedValue) const index = data.findIndex((x: any) => x?.key == key) if (index > -1) { const newData = esp.mod("lib/object").splice(data, index, 1)() FastStorage.setItem(persistKey, JSON.stringify(newData)); } }) } function historyDelete(chat_id: string, deleted_user_id: string, callback?: () => void) { const user = UserClass?.state?.()?.get?.() const firestore = esp.mod("firestore/index")() const app: any = firestore.instance() if (!user) return firestore.getCollectionIds(app, [...pathHistory], [["chat_id", "==", chat_id], ["user_id", "==", deleted_user_id]], [], (ids) => { if (ids.length > 0) { const path = [...pathChat, chat_id, "conversation"] //deleting collection history esp.mod("firestore/index")().deleteDocument(app, [...pathHistory, ids[0]], () => { //deleting cache deleteCacheData(ids[0]) // delete cache chat history const persistKey = 'chatting_chat_message02' + chat_id FastStorage.removeItem(persistKey) firestore.getCollectionLimit(app, path, [], [["time", "desc"]], 1, (data: any) => { if (data?.length > 0) { const id = data?.[0]?.id const lastBlocked: any[] = data?.[0]?.data?.hidden_history_user_ids let values: any = [] if (lastBlocked) { if (lastBlocked.includes(deleted_user_id)) { values = lastBlocked?.filter?.(x => x != deleted_user_id) } else { values = lastBlocked } } const updatedValue = [...values, deleted_user_id] firestore.updateDocument(app, [...path, id], [{ //@ts-ignore key: "hidden_history_user_ids", value: updatedValue }], () => { }) } }) }) } }) } const deleteCacheData = (deletedKey: string) => { const oldHistory = esp.modProp("chatting/history").state().get() const updatedHistory = oldHistory.filter((x: any) => x.id != deletedKey) esp.modProp("chatting/history").state().set(updatedHistory) } function chatGetAll(chat_id: string, callback: (allmsg: any, end?: boolean) => void, isStartPage?: number, limit?: number): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!user) return esp.mod("firestore/index")().paginate(app, isStartPage == 1 ? true : false, [...pathChat, chat_id, 'conversation'], [], [["time", "desc"]], limit || perPage, (dt, endR) => { if (dt) { callback(dt, endR); } else { callback(null) } }) } // function chatListenChange(chat_id: string, callback: (removedChild: any) => void) { // const user = UserClass?.state?.()?.get?.() // const app: any = esp.mod("firestore/index")().instance() // if (!user) return // esp.mod("firestore/index")().listenCollection(app, [...pathChat, chat_id, 'conversation'], [], [["time", "desc"]], (dt) => { // callback(dt); // }) // } function chatUpdate(key: string, chat_id: string, values: { key: string, value: any }[]): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!key) return if (!user) return esp.mod("firestore/index")().updateDocument(app, [...pathChat, chat_id, 'conversation', key], values, () => { }) } function listenUser(user_id: string, callback: (user: any) => void) { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!user) return esp.mod("firestore/index")().listenDocument(app, [...pathUsers, user_id], (dt) => { if (dt) { callback(dt) } else { callback(null) } }) } async function updateBatch(db: any, key: any[], rootPath: string[], data: any[]) { if (key.length > 0) { const batch = writeBatch(db); const value = data.map((x) => { return { [x.key]: x.value } }) const newValue = Object.assign({}, ...value) key.forEach((id) => { const laRef = doc(db, ...rootPath, id); //@ts-ignore batch.update(laRef, newValue); }) await batch.commit() } } function setUser(username?: string, image?: string, deleted?: boolean): void { const app: any = esp.mod("firestore/index")().instance() const firestoreUser = esp.mod("firestore/index")().getUserData(app.name) const user = UserClass.state().get() if (!user) return if (!firestoreUser) return esp.mod("firestore/index")().getCollectionIds(app, [...pathUsers], [["user_id", "==", String(user?.id)]], [], (arr) => { if (arr.length > 0) { esp.mod("firestore/index")().deleteBatchDocument(app, [...pathUsers], arr, (re) => { addUser() }) } else { addUser() } }) function addUser() { esp.mod("firestore/index")().addDocument(app, [...pathUsers, firestoreUser?.uid], { uid: firestoreUser?.uid, user_id: user?.id || '0', username: LibUtils.ucwords(username || user?.name), image: image || user?.image, deleted: deleted ? "1" : "0" }, () => { updateHistoryUser() }) } function updateHistoryUser() { esp.mod("firestore/index")().getCollectionIds(app, [...pathHistory], [["chat_to", "==", String(user?.id)]], [], (ids) => { if (ids.length > 0) { esp.mod("firestore/index")().updateBatchDocument(app, [...pathHistory], ids, [ { key: "chat_to_username", value: LibUtils.ucwords(username || user?.name) }, { key: "chat_to_image", value: image || user?.image } ] ) } }) } } function getChatId(chat_to: string, group_id: string, callback: (chat_id: string) => void): void { const user = UserClass?.state?.()?.get?.() const app: any = esp.mod("firestore/index")().instance() if (!user) return let chattochecks: string[] = []; const check = (id: string, opposite_id: string, callback: (chat_id: string) => void) => { if (!opposite_id) return if (!group_id) return chattochecks.push(id + '+' + opposite_id) esp.mod("firestore/index")().getCollectionWhere(app, [...pathHistory], [["user_id", "==", user?.id], ["chat_to", "==", opposite_id], ["group_id", "==", group_id]], (dt) => { if (dt) { let s: any[] = dt if (s.length > 0) { callback(s[0]?.data?.chat_id) } else { callback("") } } else { callback("") } }) } /* check my node */ check(user?.id, chat_to, chat_id => { if (chat_id) { callback(chat_id) } else { /* check opposite node */ check(chat_to, user?.id, chat_id => { callback(chat_id) }) } }) } return { pathChat: pathChat, pathUsers: pathUsers, pathHistory: pathHistory, chatSendNew: chatSendNew, chatSend: chatSend, chatAll: chatAll, chatGet: chatGet, chatDelete: chatDelete, historyDelete: historyDelete, chatGetAll: chatGetAll, // chatListenChange: chatListenChange, chatUpdate: chatUpdate, listenUser: listenUser, setUser: setUser, getChatId: getChatId, makeId: makeid } }