owltide/stores/users.ts

83 lines
2.1 KiB
TypeScript
Raw Normal View History

/*
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { Info } from "~/shared/utils/luxon";
import { defineStore } from 'pinia'
interface SyncOperation {
controller: AbortController,
promise: Promise<Ref<ClientMap<ClientUser>>>,
}
export const useUsersStore = defineStore("users", () => {
const accountStore = useAccountStore();
const state = {
fetched: ref<boolean>(false),
pendingSync: ref<SyncOperation>(),
users: ref<ClientMap<ClientUser>>(new ClientMap(ClientUser, new Map(), new Map())),
}
const getters = {
}
const actions = {
async fetch() {
if (!accountStore.isCrew || state.fetched.value) {
return state.users;
}
const pending = state.pendingSync.value;
if (pending) {
return pending.promise;
}
const requestFetch = useRequestFetch();
const controller = new AbortController();
const zone = Info.normalizeZone(accountStore.activeTimezone);
const locale = accountStore.activeLocale;
const promise = (async () => {
try {
const apiUsers = await requestFetch("/api/users", { signal: controller.signal });
state.users.value.apiUpdate(apiUsers, { zone, locale });
state.pendingSync.value = undefined;
state.fetched.value = true;
return state.users;
} catch (err: any) {
if (err.name !== "AbortError")
state.pendingSync.value = undefined;
throw err;
}
})();
state.pendingSync.value = {
controller,
promise,
};
return promise;
},
async resync(id: number) {
const pending = state.pendingSync.value;
if (pending) {
pending.controller.abort();
}
state.pendingSync.value = undefined;
state.fetched.value = false;
await actions.fetch();
},
}
appEventSource?.addEventListener("update", (event) => {
if (event.data.type !== "user-update") {
return;
}
console.log("appyling", event.data)
const zone = Info.normalizeZone(accountStore.activeTimezone);
const locale = accountStore.activeLocale;
state.users.value.apiUpdate([event.data.data], { zone, locale });
});
return {
...state,
...getters,
...actions,
};
})