Handle force closing logic on mobile
This commit is contained in:
@@ -144,17 +144,25 @@ import {
|
||||
useInjectedViewerState
|
||||
} from '~~/lib/viewer/composables/setup'
|
||||
import { useThreadUtilities, useFilterUtilities } from '~~/lib/viewer/composables/ui'
|
||||
import { TailwindBreakpoints } from '~~/lib/common/helpers/tailwind'
|
||||
import { useBreakpoints } from '@vueuse/core'
|
||||
|
||||
const emit = defineEmits<{
|
||||
forceClosePanels: []
|
||||
}>()
|
||||
|
||||
const parentEl = ref(null as Nullable<HTMLElement>)
|
||||
const { isLoggedIn } = useActiveUser()
|
||||
const viewerState = useInjectedViewerState()
|
||||
const { sessionId } = viewerState
|
||||
const { users } = useViewerUserActivityTracking({ parentEl })
|
||||
const { isOpenThread, open } = useThreadUtilities()
|
||||
const { isOpenThread, open, closeAllThreads } = useThreadUtilities()
|
||||
const {
|
||||
filters: { hasAnyFiltersApplied }
|
||||
} = useFilterUtilities({ state: viewerState })
|
||||
const canPostComment = useCheckViewerCommentingAccess()
|
||||
const breakpoints = useBreakpoints(TailwindBreakpoints)
|
||||
const isMobile = breakpoints.smaller('sm')
|
||||
|
||||
const { isEnabled: isEmbedEnabled } = useEmbed()
|
||||
|
||||
@@ -275,4 +283,23 @@ function setUserSpotlight(sessionId: string) {
|
||||
source: 'navbar'
|
||||
})
|
||||
}
|
||||
|
||||
const forceCloseThreads = async () => {
|
||||
await closeAllThreads()
|
||||
}
|
||||
|
||||
// Watch for thread opening on mobile and emit event
|
||||
watch(
|
||||
() => openThread.value,
|
||||
(newThread, oldThread) => {
|
||||
// If a thread opened (wasn't open before) on mobile, emit event
|
||||
if (newThread && !oldThread && isMobile.value) {
|
||||
emit('forceClosePanels')
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
defineExpose({
|
||||
forceCloseThreads
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -41,7 +41,10 @@
|
||||
enter-from-class="opacity-0"
|
||||
enter-active-class="transition duration-1000"
|
||||
>
|
||||
<ViewerAnchoredPoints />
|
||||
<ViewerAnchoredPoints
|
||||
ref="anchoredPoints"
|
||||
@force-close-panels="() => closeAllPanels('threads')"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
@@ -54,8 +57,14 @@
|
||||
<!-- Controls -->
|
||||
<!-- <ViewerControls v-if="showControls" class="relative z-20" /> -->
|
||||
<template v-if="showControls">
|
||||
<ViewerControlsLeft />
|
||||
<ViewerControlsBottom />
|
||||
<ViewerControlsLeft
|
||||
ref="leftControls"
|
||||
@force-close-panels="() => closeAllPanels('left')"
|
||||
/>
|
||||
<ViewerControlsBottom
|
||||
ref="bottomControls"
|
||||
@force-close-panels="() => closeAllPanels('bottom')"
|
||||
/>
|
||||
<ViewerControlsRight v-if="isMobile" />
|
||||
</template>
|
||||
|
||||
@@ -73,7 +82,11 @@
|
||||
enter-from-class="opacity-0"
|
||||
enter-active-class="transition duration-1000"
|
||||
>
|
||||
<ViewerSelectionSidebar class="z-20" />
|
||||
<ViewerSelectionSidebar
|
||||
ref="selectionSidebar"
|
||||
class="z-20"
|
||||
@force-close-panels="() => closeAllPanels('selection')"
|
||||
/>
|
||||
</Transition>
|
||||
<div
|
||||
class="absolute z-10 w-screen px-8 grid grid-cols-1 sm:grid-cols-3 gap-2 top-[3.75rem]"
|
||||
@@ -156,6 +169,11 @@ const isWorkspacesEnabled = useIsWorkspacesEnabled()
|
||||
const breakpoints = useBreakpoints(TailwindBreakpoints)
|
||||
const isMobile = breakpoints.smaller('sm')
|
||||
|
||||
const leftControls = ref()
|
||||
const bottomControls = ref()
|
||||
const selectionSidebar = ref()
|
||||
const anchoredPoints = ref()
|
||||
|
||||
const resourceIdString = computed(() => route.params.modelId as string)
|
||||
const projectId = writableAsyncComputed({
|
||||
get: () => route.params.id as string,
|
||||
@@ -294,4 +312,19 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const closeAllPanels = (except?: 'left' | 'bottom' | 'selection' | 'threads') => {
|
||||
if (except !== 'left' && leftControls.value?.forceClosePanels) {
|
||||
leftControls.value.forceClosePanels()
|
||||
}
|
||||
if (except !== 'bottom' && bottomControls.value?.forceClosePanels) {
|
||||
bottomControls.value.forceClosePanels()
|
||||
}
|
||||
if (except !== 'selection' && selectionSidebar.value?.forceClose) {
|
||||
selectionSidebar.value.forceClose()
|
||||
}
|
||||
if (except !== 'threads' && anchoredPoints.value?.forceCloseThreads) {
|
||||
anchoredPoints.value.forceCloseThreads()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -51,8 +51,9 @@ import {
|
||||
useViewerShortcuts,
|
||||
useFilterUtilities
|
||||
} from '~~/lib/viewer/composables/ui'
|
||||
import { onKeyStroke } from '@vueuse/core'
|
||||
import { onKeyStroke, useBreakpoints } from '@vueuse/core'
|
||||
import { useEmbed } from '~/lib/viewer/composables/setup/embed'
|
||||
import { TailwindBreakpoints } from '~~/lib/common/helpers/tailwind'
|
||||
|
||||
enum ActivePanel {
|
||||
none = 'none',
|
||||
@@ -63,6 +64,10 @@ enum ActivePanel {
|
||||
lightControls = 'lightControls'
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
forceClosePanels: []
|
||||
}>()
|
||||
|
||||
const { getShortcutDisplayText, shortcuts, registerShortcuts } = useViewerShortcuts()
|
||||
const { toggleSectionBox, resetSectionBox, closeSectionBox } = useSectionBoxUtilities()
|
||||
const { getActiveMeasurement, removeMeasurement, enableMeasurements } =
|
||||
@@ -70,8 +75,11 @@ const { getActiveMeasurement, removeMeasurement, enableMeasurements } =
|
||||
const { resetExplode } = useFilterUtilities()
|
||||
const { getTooltipProps } = useSmartTooltipDelay()
|
||||
const { isEnabled: isEmbedEnabled } = useEmbed()
|
||||
const breakpoints = useBreakpoints(TailwindBreakpoints)
|
||||
const isMobile = breakpoints.smaller('sm')
|
||||
|
||||
const activePanel = ref<ActivePanel>(ActivePanel.none)
|
||||
|
||||
const panels = shallowRef({
|
||||
[ActivePanel.measurements]: {
|
||||
id: ActivePanel.measurements,
|
||||
@@ -122,6 +130,10 @@ const showResetButton = computed(() => {
|
||||
const toggleActivePanel = (panel: ActivePanel) => {
|
||||
activePanel.value = activePanel.value === panel ? ActivePanel.none : panel
|
||||
|
||||
if (activePanel.value !== ActivePanel.none && isMobile.value) {
|
||||
emit('forceClosePanels')
|
||||
}
|
||||
|
||||
if (panel === ActivePanel.sectionBox) {
|
||||
toggleSectionBox()
|
||||
}
|
||||
@@ -161,6 +173,10 @@ registerShortcuts({
|
||||
ToggleSectionBox: () => toggleSectionBox()
|
||||
})
|
||||
|
||||
const forceClosePanels = () => {
|
||||
activePanel.value = ActivePanel.none
|
||||
}
|
||||
|
||||
onKeyStroke('Escape', () => {
|
||||
const isActiveMeasurement = getActiveMeasurement()
|
||||
|
||||
@@ -175,4 +191,8 @@ onKeyStroke('Escape', () => {
|
||||
activePanel.value = ActivePanel.none
|
||||
}
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
forceClosePanels
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -156,6 +156,10 @@ type ActivePanel =
|
||||
| 'filters'
|
||||
| 'devMode'
|
||||
|
||||
const emit = defineEmits<{
|
||||
forceClosePanels: []
|
||||
}>()
|
||||
|
||||
const width = ref(264)
|
||||
const scrollableControlsContainer = ref(null as Nullable<HTMLDivElement>)
|
||||
const height = ref(scrollableControlsContainer.value?.clientHeight)
|
||||
@@ -246,7 +250,17 @@ registerShortcuts({
|
||||
})
|
||||
|
||||
const toggleActivePanel = (panel: ActivePanel) => {
|
||||
const wasNone = activePanel.value === 'none'
|
||||
activePanel.value = activePanel.value === panel ? 'none' : panel
|
||||
|
||||
// If a panel is being opened (not closed) on mobile, emit event to parent
|
||||
if (wasNone && activePanel.value !== 'none' && isMobile.value) {
|
||||
emit('forceClosePanels')
|
||||
}
|
||||
}
|
||||
|
||||
const forceClosePanel = () => {
|
||||
activePanel.value = 'none'
|
||||
}
|
||||
|
||||
const openDocs = () => {
|
||||
@@ -261,4 +275,9 @@ onMounted(() => {
|
||||
watch(isSmallerOrEqualSm, (newVal) => {
|
||||
activePanel.value = newVal ? 'none' : 'models'
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
forceClosePanel,
|
||||
forceClosePanels: forceClosePanel
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -100,6 +100,10 @@ import { TailwindBreakpoints } from '~~/lib/common/helpers/tailwind'
|
||||
import type { ConcreteComponent } from 'vue'
|
||||
import type { LayoutMenuItem } from '~~/lib/layout/helpers/components'
|
||||
|
||||
const emit = defineEmits<{
|
||||
forceClosePanels: []
|
||||
}>()
|
||||
|
||||
enum ActionTypes {
|
||||
OpenInNewTab = 'open-in-new-tab'
|
||||
}
|
||||
@@ -119,6 +123,7 @@ const { hideObjects, showObjects, isolateObjects, unIsolateObjects } =
|
||||
const { isSmallerOrEqualSm } = useIsSmallerOrEqualThanBreakpoint()
|
||||
const breakpoints = useBreakpoints(TailwindBreakpoints)
|
||||
const isGreaterThanSm = breakpoints.greater('sm')
|
||||
const isMobile = breakpoints.smaller('sm')
|
||||
const menuId = useId()
|
||||
const mp = useMixpanel()
|
||||
const { getTooltipProps } = useSmartTooltipDelay()
|
||||
@@ -248,6 +253,10 @@ const onClose = () => {
|
||||
trackAndClearSelection()
|
||||
}
|
||||
|
||||
const forceClose = () => {
|
||||
sidebarOpen.value = false
|
||||
}
|
||||
|
||||
onKeyStroke('Escape', () => {
|
||||
// Cleareance of any vis/iso state coming from here should happen in clearSelection()
|
||||
// Note: we're not using the trackAndClearSelection method beacuse
|
||||
@@ -267,6 +276,10 @@ watch(
|
||||
// Dont open sidebar if a comment is open
|
||||
if (newLength !== 0 && !focusedThreadId.value) {
|
||||
sidebarOpen.value = true
|
||||
// Emit event when sidebar opens on mobile
|
||||
if (isMobile.value) {
|
||||
emit('forceClosePanels')
|
||||
}
|
||||
} else if (newLength === 0) {
|
||||
sidebarOpen.value = false
|
||||
}
|
||||
@@ -295,4 +308,8 @@ watch(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
defineExpose({
|
||||
forceClose
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user