UNPKG

feeds-fun

Version:

Frontend for the Feeds Fun — web-based news reader

122 lines (96 loc) 3.38 kB
import {ref, watch, computed} from "vue"; import {useRouter, useRoute} from "vue-router"; import {defineStore} from "pinia"; import {computedAsync, useBroadcastChannel} from "@vueuse/core"; import {Timer} from "@/logic/timer"; import * as settings from "@/logic/settings"; import * as api from "@/logic/api"; import * as e from "@/logic/enums"; const GLOBAL_BROADCAST_CHANNEL_ID = "ffun-global-event-channel"; const GLOBAL_BROADCAST_EVENT_LOGOUT_COMPLETED = "logoutCompleted"; const LOGGED_OUT_QUERY_MARKER = "logged-out"; export const useGlobalState = defineStore("globalState", () => { const router = useRouter(); const route = useRoute(); const infoRefreshMarker = ref(0); function refreshAuthState() { infoRefreshMarker.value++; } //////////////////////////////// // sync login state between tabs //////////////////////////////// const globalChannel = useBroadcastChannel<any, any>({name: GLOBAL_BROADCAST_CHANNEL_ID}); watch(globalChannel.data, (event) => { if (event.type === GLOBAL_BROADCAST_EVENT_LOGOUT_COMPLETED) { refreshAuthState(); } }); // check if the marker is in the URL (means that user has just redirected after logout) watch(route, (r) => { if (!(LOGGED_OUT_QUERY_MARKER in r.query)) { return; } globalChannel.post({type: GLOBAL_BROADCAST_EVENT_LOGOUT_COMPLETED}); // remove the marker from the URL const query = {...r.query}; delete query[LOGGED_OUT_QUERY_MARKER]; router.replace({query}); }); //////////////////////////////// // Periodic check auth state by timer const authStateRefresher = new Timer(refreshAuthState, settings.authRefreshInterval); // Check auth state on the particular events // do not check "focus" and "visibilitychange" — they are too noisy window.addEventListener("online", refreshAuthState); window.addEventListener("pageshow", (event) => { if (event.persisted) { // BFCache restore (the user goes Back/Forward and the browser instantly revives a frozen snapshot). refreshAuthState(); } }); const info = computedAsync(async () => { infoRefreshMarker.value; return await api.getInfo(); }, null); const userId = computedAsync(async () => { infoRefreshMarker.value; let userData = await api.getUser(); return userData ? userData.userId : null; }, "unknown"); const isSingleUserMode = computed(() => { return info.value ? info.value.singleUserMode : false; }); const loginState = computed(() => { if (userId.value === "unknown") { return e.LoginState.Unknown; } return userId.value ? e.LoginState.LoggedIn : e.LoginState.LoggedOut; }); const loginUnknown = computed(() => { return loginState.value === e.LoginState.Unknown; }); const loginConfirmed = computed(() => { return loginState.value === e.LoginState.LoggedIn; }); const logoutConfirmed = computed(() => { return loginState.value === e.LoginState.LoggedOut; }); function logout() { if (isSingleUserMode.value) { // In single user mode the user is always "logged in" return; } api.logoutRedirect(); // TODO: we may want to notify other tabs about logout event } return { userId, isSingleUserMode, loginState, loginUnknown, loginConfirmed, logoutConfirmed, refreshAuthState, logout }; });