Created
December 24, 2021 14:57
-
-
Save Jimeux/845010dbb23e231edb244a094dda0892 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {ref} from "vue" | |
import {Leave, Message, User, UserList, usernames} from "../data/data" | |
import {eventBus} from "./eventBus" | |
import {defineStore} from "pinia" | |
export const usePiniaStore = defineStore("main", () => { | |
const connectionId = ref<string | null>() | |
const currentRecipient = ref<User | null>() | |
const userList = ref(new Map<string, User>()) | |
const messages = ref(new Map<string, Message[]>()) | |
const unread = ref(new Set<string>()) | |
eventBus.subscribe("ws:open", (event: Event) => { | |
eventBus.send("user:joined", { | |
username: usernames[Math.floor(Math.random() * usernames.length)], | |
}) | |
}) | |
eventBus.subscribe("user:left", (l: Leave) => { | |
userList.value.delete(l.connectionId) | |
if (currentRecipient.value?.connectionId === l.connectionId) | |
currentRecipient.value = null | |
}) | |
eventBus.subscribe("user:joined", (list: UserList) => { | |
connectionId.value = list.connectionId | |
for (const u of list.userList) { | |
if ( | |
u.connectionId !== list.connectionId && | |
!userList.value.has(u.connectionId) | |
) | |
userList.value.set(u.connectionId, u) | |
} | |
}) | |
eventBus.subscribe("user:message", (m: Message) => { | |
const key = | |
m.receiverId === connectionId.value ? m.senderId : m.receiverId | |
const mm = messages.value.get(key) | |
if (!mm) messages.value.set(key, [m]) | |
else mm.push(m) | |
if (currentRecipient.value?.connectionId !== key) { | |
unread.value.add(key) | |
} else { | |
unread.value.delete(key) | |
} | |
} | |
) | |
function setRecipient(u: User) { | |
currentRecipient.value = u | |
unread.value.delete(u.connectionId) | |
} | |
function sendMessage(text: string) { | |
if (currentRecipient.value == null || text.length === 0) return | |
eventBus.send("user:message", { | |
message: text, | |
senderId: connectionId.value, | |
receiverId: currentRecipient.value.connectionId, | |
}) | |
} | |
return { | |
connectionId, | |
currentRecipient, | |
userList, | |
messages, | |
unread, | |
setRecipient, | |
sendMessage, | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {App, inject, reactive, readonly} from "vue" | |
import {Leave, Message, User, UserList, usernames} from "../data/data" | |
import {eventBus, EventBus} from "./eventBus" | |
interface State { | |
connectionId: string | null | |
userList: Map<string, User> | |
messages: Map<string, Message[]> | |
currentRecipient: User | null | |
unread: Set<string> | |
} | |
export class Store { | |
readonly #bus: EventBus | |
readonly #state: State | |
constructor(bus: EventBus, initial: State) { | |
this.#bus = bus | |
this.#state = reactive(initial) | |
bus.subscribe("ws:open", this.onOpen.bind(this)) | |
bus.subscribe("user:left", this.eventUserLeft.bind(this)) | |
bus.subscribe("user:joined", this.eventUserJoined.bind(this)) | |
bus.subscribe("user:message", this.eventUserMessage.bind(this)) | |
} | |
public install(app: App) { | |
app.provide(storeKey, this) | |
} | |
public get state() { | |
return readonly(this.#state) | |
} | |
public setRecipient(u: User) { | |
this.#state.currentRecipient = u | |
this.#state.unread.delete(u.connectionId) | |
} | |
public sendMessage(text: string) { | |
const {connectionId, currentRecipient} = this.#state | |
if (currentRecipient == null || text.length === 0) return | |
this.#bus.send("user:message", { | |
message: text, | |
senderId: connectionId, | |
receiverId: currentRecipient.connectionId, | |
}) | |
} | |
private onOpen(event: Event) { | |
this.#bus.send("user:joined", { | |
username: usernames[Math.floor(Math.random() * usernames.length)], | |
}) | |
} | |
private eventUserLeft(l: Leave) { | |
this.#state.userList.delete(l.connectionId) | |
if (this.#state.currentRecipient?.connectionId === l.connectionId) | |
this.#state.currentRecipient = null | |
} | |
private eventUserMessage(m: Message) { | |
const key = | |
m.receiverId === this.#state.connectionId ? m.senderId : m.receiverId | |
const mm = this.#state.messages.get(key) | |
if (!mm) this.#state.messages.set(key, [m]) | |
else mm.push(m) | |
if (this.#state?.currentRecipient?.connectionId !== key) { | |
this.#state.unread.add(key) | |
} else { | |
this.#state.unread.delete(key) | |
} | |
} | |
private eventUserJoined(list: UserList) { | |
this.#state.connectionId = list.connectionId | |
for (const u of list.userList) { | |
if ( | |
u.connectionId !== list.connectionId && | |
!this.#state.userList.has(u.connectionId) | |
) | |
this.#state.userList.set(u.connectionId, u) | |
} | |
} | |
} | |
export const store = new Store(eventBus, { | |
connectionId: null, | |
currentRecipient: null, | |
userList: new Map<string, User>(), | |
messages: new Map<string, Message[]>(), | |
unread: new Set<string>(), | |
}) | |
export const storeKey = Symbol("store") | |
export function useStore() { | |
const store = inject<Store>(storeKey) | |
if (!store) throw new Error("Store was not provided") | |
return store | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment