Files
speckle-server/packages/frontend-2/lib/viewer/composables/setup/embed.ts
T
andrewwallacespeckle ff6433128a FE2 - Embedding (#1979)
* Add Dialog

* Add options to embed dialog

* Min Height of Clipboard Input multiline to 3 lines

* Check for visibility

* Link to change access of project

* Rename to guided mode

* Change icon when user clicks copy button

* Update Menu styles based on agi feedback

* Update graphql.ts

* Embed Options as hashState

* Auto grow Clipboard Input

* embed state and more options

* Tidyups

* Footer only shows when !embedOptions.isTransparent

* Add auto/manual Load

* Add Pre setup component

* WIP Button Group mobile

* Updates around manual load

* Viewer Share nav

* Add embed dialog to project page

* Minor fixes

* Check for federated

* Responsive Tidyups

* Responsive Fixes. Fix console issues

* Add Alert to Version Embed

* Disable Zoom

* GQL updates

* Comment Slideshow

* GraphQl changes

* Fix visibility

* Build fix

* Revert "Build fix"

This reverts commit 0e706cbd9fde78204032bb1ec4421b1742d023ac.

* remove unneeded change, revert yarn.lock

* Test Commit

* Remove commit test

* Fix build

* Update Tailwind. Add base url env

* fix for portal scope issue

* useLogger

* useLogger

* chore(fe2): include NUXT_PUBLIC_BASE_URL in deployment manifests

* lazy load optimization

* lint fixes

* Updates

* Re-add guided open Dialog sections

* Prevent login popup on embed

* Tidy up mobile combined button group

* Tidy up embed Dialogs

* Small styling issues

* Update scrolling in embed dialog

* Move selection info when embed

* Testing fixes

* Discuss in Speckle

* Responsive Dialog Changes

* Fix bug

* WIP Manual Load

* Fix nuxt errors

* Fix nuxt logger issue

* Fix embed dialog overflows

* New Dialog layout

* Responsive Breakpoint change

* Preview Image

* Fix bug with dialogSection

* Hide selection info on mobile when thread is open

* Footer Model Name

* Overflow on ClipboardInput

* Style fixes

* Tidy ups

* Responsive updates

* Responsive fixes

* Update button

* Changes from testing

* Fix embed height with footer

* Fix Dialog Section

* Fixes from testing

* Move "reset filters" on embed

* Small fixes

* Updates from CR 1

* CR Comments 2

* Updates from CR

* Add deserializeEmbedOptions helper

* DialogSection changes

* Revert changes in TextArea

* Updates from CR

* Only check for noscroll in watch

* Update useRoute

* Comment Slideshow mode

* Changes from testing

* Fix mobile share button

* onMounted warn fixes

* Updates from testing

* Remove nesting of ManualLoad

* Keep Speckle text on mobile

* minor cleanup & bugfixes

* Add target prop to Logo

* navbar flash fix + more cleanup

* Fix urls

* Footer Logo changes

* Remove viewer-transparent from layout

* Add Reply in Speckle

* Remove Anchored Points from embed

* Final changes pre CR

* Fix Anchored Points

* Update packages/frontend-2/components/project/model-page/dialog/embed/Embed.vue

Co-authored-by: Kristaps Fabians Geikins <fabians@speckle.systems>

* Fixes from CR

* Updates from cr

* Changes WIP

* Fix for dialog opening

* Changes from PR

* Updates to check embed in activity

* fix(fe2): project settings dialog error

* Make Team open section on click of "Manage"

* Fixes from merge

* Changes from cr

* Compare old to new in watch

* Fix logo in footer of embed

* Fixes from merge

* Fix build. Fix lazy load

* Updates from Benjamin

* Fix transparent bg

---------

Co-authored-by: Kristaps Fabians Geikins <fabis94@live.com>
Co-authored-by: Iain Sproat <68657+iainsproat@users.noreply.github.com>
Co-authored-by: Kristaps Fabians Geikins <fabians@speckle.systems>
2024-02-06 10:38:22 +00:00

130 lines
3.6 KiB
TypeScript

import { writableAsyncComputed } from '~/lib/common/composables/async'
import { useScopedState } from '~/lib/common/composables/scopedState'
import { ViewerHashStateKeys } from '~/lib/viewer/composables/setup/urlHashState'
import { useConditionalViewerRendering } from '~/lib/viewer/composables/ui'
import { useRouteHashState } from '~~/lib/common/composables/url'
export type EmbedOptions = {
isEnabled?: boolean
isTransparent?: boolean
hideControls?: boolean
hideSelectionInfo?: boolean
noScroll?: boolean
manualLoad?: boolean
}
export function isEmbedOptions(obj: unknown): obj is EmbedOptions {
if (typeof obj === 'object' && obj !== null) {
const possibleOptions = obj as Partial<EmbedOptions>
return Object.keys(possibleOptions).every(
(key) =>
[
'isEnabled',
'isTransparent',
'hideControls',
'hideSelectionInfo',
'noScroll',
'manualLoad'
].includes(key) &&
typeof possibleOptions[key as keyof EmbedOptions] === 'boolean'
)
}
return false
}
export function deserializeEmbedOptions(embedString: string | null): EmbedOptions {
const logger = useLogger()
if (!embedString) {
return { isEnabled: false }
}
try {
const parsed: unknown = JSON.parse(embedString)
if (isEmbedOptions(parsed)) {
return { ...parsed, isEnabled: true }
}
logger.error('Parsed object is not of type EmbedOptions')
} catch (error) {
logger.error(error)
}
return { isEnabled: false }
}
export function useEmbedState() {
const { hashState } = useRouteHashState()
const embedOptions = writableAsyncComputed({
get: () => {
const embedString = hashState.value[ViewerHashStateKeys.EmbedOptions]
return deserializeEmbedOptions(embedString)
},
set: async (newOptions) => {
const embedString = newOptions ? JSON.stringify(newOptions) : null
await hashState.update({
...hashState.value,
[ViewerHashStateKeys.EmbedOptions]: embedString
})
},
initialState: null,
asyncRead: false
})
return { embedOptions }
}
const embedStateScopedKey = Symbol('EmbedStateScopedKey')
export function useEmbed() {
const { embedOptions } = useEmbedState()
const { showControls } = useConditionalViewerRendering()
// useScopedState so that we don't keep creating new computeds
return useScopedState(embedStateScopedKey, () => {
const createComputed = <K extends keyof EmbedOptions>(key: K) =>
writableAsyncComputed({
get: () => embedOptions.value?.[key],
set: async (newVal) => {
await embedOptions.update({
...(embedOptions.value ?? {}),
...{
[key]: newVal
}
})
},
initialState: null,
asyncRead: false
})
const isEnabled = createComputed('isEnabled')
const isTransparent = createComputed('isTransparent')
const hideSelectionInfo = createComputed('hideSelectionInfo')
const noScroll = createComputed('noScroll')
const manualLoad = createComputed('manualLoad')
const showControlsNew = writableAsyncComputed({
get: () => showControls.value,
set: async (newVal) =>
await embedOptions.update({
...(embedOptions.value ?? {}),
...{
hideControls: !(newVal || undefined)
}
}),
initialState: null,
asyncRead: false
})
return {
isEnabled,
isEmbedEnabled: isEnabled,
isTransparent,
showControls: showControlsNew,
hideSelectionInfo,
noScroll,
manualLoad
}
})
}