From a66a2f5645a38f93ee6a88a7a1d7899622f46168 Mon Sep 17 00:00:00 2001 From: Akash K <57758277+amk-dev@users.noreply.github.com> Date: Wed, 29 Mar 2023 23:59:28 +0530 Subject: [PATCH] chore: move settings firebase things to platform (#2953) --- .../hoppscotch-common/src/helpers/fb/index.ts | 3 +- .../hoppscotch-common/src/platform/index.ts | 2 + .../src/platform/settings.ts | 3 + packages/hoppscotch-web/src/main.ts | 2 + packages/hoppscotch-web/src/settings.ts | 108 ++++++++++++++++++ 5 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 packages/hoppscotch-common/src/platform/settings.ts create mode 100644 packages/hoppscotch-web/src/settings.ts diff --git a/packages/hoppscotch-common/src/helpers/fb/index.ts b/packages/hoppscotch-common/src/helpers/fb/index.ts index 9b82c20f5..a944c0a27 100644 --- a/packages/hoppscotch-common/src/helpers/fb/index.ts +++ b/packages/hoppscotch-common/src/helpers/fb/index.ts @@ -2,7 +2,6 @@ import { initializeApp } from "firebase/app" import { platform } from "~/platform" import { initAnalytics } from "./analytics" import { initHistory } from "./history" -import { initSettings } from "./settings" const firebaseConfig = { apiKey: import.meta.env.VITE_API_KEY, @@ -23,7 +22,7 @@ export function initializeFirebase() { initializeApp(firebaseConfig) platform.auth.performAuthInit() - initSettings() + platform.sync.settings.initSettingsSync() platform.sync.collections.initCollectionsSync() initHistory() platform.sync.environments.initEnvironmentsSync() diff --git a/packages/hoppscotch-common/src/platform/index.ts b/packages/hoppscotch-common/src/platform/index.ts index 5845f4065..cd8d39499 100644 --- a/packages/hoppscotch-common/src/platform/index.ts +++ b/packages/hoppscotch-common/src/platform/index.ts @@ -2,6 +2,7 @@ import { AuthPlatformDef } from "./auth" import { UIPlatformDef } from "./ui" import { EnvironmentsPlatformDef } from "./environments" import { CollectionsPlatformDef } from "./collections" +import { SettingsPlatformDef } from "./settings" export type PlatformDef = { ui?: UIPlatformDef @@ -9,6 +10,7 @@ export type PlatformDef = { sync: { environments: EnvironmentsPlatformDef collections: CollectionsPlatformDef + settings: SettingsPlatformDef } } diff --git a/packages/hoppscotch-common/src/platform/settings.ts b/packages/hoppscotch-common/src/platform/settings.ts new file mode 100644 index 000000000..fb79b2a29 --- /dev/null +++ b/packages/hoppscotch-common/src/platform/settings.ts @@ -0,0 +1,3 @@ +export type SettingsPlatformDef = { + initSettingsSync: () => void +} diff --git a/packages/hoppscotch-web/src/main.ts b/packages/hoppscotch-web/src/main.ts index e223e6493..80201251b 100644 --- a/packages/hoppscotch-web/src/main.ts +++ b/packages/hoppscotch-web/src/main.ts @@ -2,11 +2,13 @@ import { createHoppApp } from "@hoppscotch/common" import { def as authDef } from "./firebase/auth" import { def as envDef } from "./environments" import { def as collectionsDef } from "./collections" +import { def as settingsDef } from "./settings" createHoppApp("#app", { auth: authDef, sync: { environments: envDef, collections: collectionsDef, + settings: settingsDef, }, }) diff --git a/packages/hoppscotch-web/src/settings.ts b/packages/hoppscotch-web/src/settings.ts new file mode 100644 index 000000000..5331a0081 --- /dev/null +++ b/packages/hoppscotch-web/src/settings.ts @@ -0,0 +1,108 @@ +import { + collection, + doc, + getFirestore, + onSnapshot, + setDoc, +} from "firebase/firestore" +import { def as platformAuth } from "./firebase/auth" +import { + applySetting, + settingsStore, + SettingsDef, +} from "@hoppscotch/common/newstore/settings" +import { SettingsPlatformDef } from "@hoppscotch/common/platform/settings" + +/** + * Used locally to prevent infinite loop when settings sync update + * is applied to the store which then fires the store sync listener. + * When you want to update settings and not want to fire the update listener, + * set this to true and then set it back to false once it is done + */ +let loadedSettings = false + +/** + * Write Transform + */ +async function writeSettings(setting: string, value: any) { + const currentUser = platformAuth.getCurrentUser() + + if (currentUser === null) + throw new Error("Cannot write setting, user not signed in") + + const st = { + updatedOn: new Date(), + author: currentUser.uid, + author_name: currentUser.displayName, + author_image: currentUser.photoURL, + name: setting, + value, + } + + try { + await setDoc( + doc(getFirestore(), "users", currentUser.uid, "settings", setting), + st + ) + } catch (e) { + console.error("error updating", st, e) + throw e + } +} + +export function initSettingsSync() { + const currentUser$ = platformAuth.getCurrentUserStream() + + settingsStore.dispatches$.subscribe((dispatch) => { + const currentUser = platformAuth.getCurrentUser() + + if (currentUser && loadedSettings) { + if (dispatch.dispatcher === "bulkApplySettings") { + Object.keys(dispatch.payload).forEach((key) => { + writeSettings(key, dispatch.payload[key]) + }) + } else { + writeSettings( + dispatch.payload.settingKey, + settingsStore.value[dispatch.payload.settingKey as keyof SettingsDef] + ) + } + } + }) + + let snapshotStop: (() => void) | null = null + + // Subscribe and unsubscribe event listeners + currentUser$.subscribe((user) => { + if (!user && snapshotStop) { + // User logged out + snapshotStop() + snapshotStop = null + } else if (user) { + snapshotStop = onSnapshot( + collection(getFirestore(), "users", user.uid, "settings"), + (settingsRef) => { + const settings: any[] = [] + + settingsRef.forEach((doc) => { + const setting = doc.data() + setting.id = doc.id + settings.push(setting) + }) + + loadedSettings = false + settings.forEach((e) => { + if (e && e.name && e.value != null) { + applySetting(e.name, e.value) + } + }) + loadedSettings = true + } + ) + } + }) +} + +export const def: SettingsPlatformDef = { + initSettingsSync, +}