Files
speckle-server/packages/frontend-2/lib/common/composables/toast.ts
T
Kristaps Fabians Geikins ee5ae8af62 fix(fe2): accept invite before onboarding after sign up (#2491)
* explicitly ordering global middlewares

* various subscription fixes & WIP project invite middleware

* SSR invite accept & toast notifs seem to work

* backend support for mixpanel

* mixpanel be logic -> shared

* minor fix

* finissh

* lint fix

* minor comment adjustments

* better adblock handling
2024-07-11 11:45:11 +03:00

83 lines
2.2 KiB
TypeScript

import { useTimeoutFn } from '@vueuse/core'
import type { Optional } from '@speckle/shared'
import type { ToastNotification } from '@speckle/ui-components'
import { ToastNotificationType } from '@speckle/ui-components'
import { useSynchronizedCookie } from '~/lib/common/composables/reactiveCookie'
/**
* Persisting toast state between reqs and between CSR & SSR loads so that we can trigger
* toasts anywhere and anytime
*/
const useGlobalToastState = () =>
useSynchronizedCookie<Optional<ToastNotification>>('global-toast-state')
/**
* Set up a new global toast manager/renderer (don't use this in multiple components that live at the same time)
*/
export function useGlobalToastManager() {
const stateNotification = useGlobalToastState()
const currentNotification = ref(stateNotification.value)
const readOnlyNotification = computed(() => currentNotification.value)
const dismiss = () => {
currentNotification.value = undefined
stateNotification.value = undefined
}
const { start, stop } = useTimeoutFn(() => {
dismiss()
}, 4000)
watch(
stateNotification,
(newVal) => {
if (!newVal) return
if (import.meta.server) {
currentNotification.value = newVal
return
}
// First dismiss old notification, then set a new one on next tick
// this is so that the old one actually disappears from the screen for the user,
// instead of just having its contents replaced
dismiss()
nextTick(() => {
currentNotification.value = newVal
// (re-)init timeout
stop()
if (newVal.autoClose !== false) start()
})
},
{ deep: true, immediate: true }
)
return { currentNotification: readOnlyNotification, dismiss }
}
/**
* Trigger global toast notifications
*/
export function useGlobalToast() {
const stateNotification = useGlobalToastState()
const logger = useLogger()
/**
* Trigger a new toast notification
*/
const triggerNotification = (notification: ToastNotification) => {
stateNotification.value = notification
if (import.meta.server) {
logger.info('Queued SSR toast notification', notification)
}
}
return { triggerNotification }
}
export { ToastNotificationType }
export type { ToastNotification }