UNPKG

@owdproject/core

Version:

Nuxt Desktop module for browser desktop experiences (windows, shell, apps)

177 lines (143 loc) 4.82 kB
import type { IWindowController } from '@owdproject/core' import { computed, ref } from 'vue' import { useDesktopWorkspaceStore } from '../stores/storeDesktopWorkspace' import { WORKSPACE_EDGE_DROP_PX } from '../constants/shellLayout' const edgeHint = ref<'left' | 'right' | null>(null) const isWindowDragActive = ref(false) let draggingWindowId: string | null = null function adjacentWorkspaceId(side: 'left' | 'right'): string | null { const desktopWorkspaceStore = useDesktopWorkspaceStore() if (desktopWorkspaceStore.overview) return null const list = desktopWorkspaceStore.list if (list.length < 2) return null const index = desktopWorkspaceStore.workspaceActiveIndex if (index < 0) return null if (side === 'left' && index > 0) { return list[index - 1] ?? null } if (side === 'right' && index < list.length - 1) { return list[index + 1] ?? null } return null } function updateEdgeHintFromClientX(clientX: number) { const desktopWorkspaceStore = useDesktopWorkspaceStore() if (!isWindowDragActive.value || desktopWorkspaceStore.overview) { edgeHint.value = null return } const viewportWidth = typeof globalThis !== 'undefined' ? globalThis.innerWidth : 0 if (clientX <= WORKSPACE_EDGE_DROP_PX && adjacentWorkspaceId('left')) { edgeHint.value = 'left' return } if ( clientX >= viewportWidth - WORKSPACE_EDGE_DROP_PX && adjacentWorkspaceId('right') ) { edgeHint.value = 'right' return } edgeHint.value = null } function onDocumentPointerMove(e: PointerEvent) { updateEdgeHintFromClientX(e.clientX) } function stopPointerTracking() { document.removeEventListener('pointermove', onDocumentPointerMove) } /** * While dragging a window (normal desktop, not overview), highlight left/right * screen edges when an adjacent workspace exists so the user can drop there. */ export function useWorkspaceEdgeDrop() { const desktopWorkspaceStore = useDesktopWorkspaceStore() function beginWindowDrag(windowId: string) { if (desktopWorkspaceStore.overview) return if (desktopWorkspaceStore.list.length < 2) return draggingWindowId = windowId isWindowDragActive.value = true edgeHint.value = null document.addEventListener('pointermove', onDocumentPointerMove, { passive: true, }) } function commitEdgeDrop(win: IWindowController) { const side = edgeHint.value if (!side || !draggingWindowId) return false const targetWorkspaceId = adjacentWorkspaceId(side) if (!targetWorkspaceId) return false win.actions.setWorkspace(targetWorkspaceId) desktopWorkspaceStore.setWorkspace(targetWorkspaceId) const inset = WORKSPACE_EDGE_DROP_PX + 24 const pos = win.position if (pos && typeof pos.y === 'number') { const viewportWidth = typeof globalThis !== 'undefined' ? globalThis.innerWidth : 1920 const rawWidth = win.size?.width ?? 400 const width = typeof rawWidth === 'number' ? rawWidth : Number.parseFloat(String(rawWidth)) || 400 const x = side === 'left' ? inset : Math.max(inset, viewportWidth - width - inset) win.actions.setPosition({ x, y: pos.y }) } return true } function endWindowDrag(win?: IWindowController): boolean { stopPointerTracking() let moved = false if (win && edgeHint.value) { moved = commitEdgeDrop(win) } isWindowDragActive.value = false draggingWindowId = null edgeHint.value = null return moved } const edgeTargetDesktopIndex = computed(() => { const side = edgeHint.value if (!side) return null const targetId = adjacentWorkspaceId(side) if (!targetId) return null const index = desktopWorkspaceStore.list.indexOf(targetId) return index >= 0 ? index + 1 : null }) return { edgeHint, edgeTargetDesktopIndex, isWindowDragActive, beginWindowDrag, endWindowDrag, adjacentWorkspaceId, } } /** * Wire {@link useWorkspaceEdgeDrop} to DesktopWindow drag events (theme Window wrapper). */ export function useWorkspaceEdgeDropWindowHandlers( getWindow: () => IWindowController | undefined, ) { const desktopWorkspaceStore = useDesktopWorkspaceStore() const { beginWindowDrag, endWindowDrag } = useWorkspaceEdgeDrop() function onDragStart() { const win = getWindow() if (!win?.state?.id || desktopWorkspaceStore.overview) return beginWindowDrag(win.state.id) } function onDragEnd(data: { left: number; top: number }) { const win = getWindow() const moved = Boolean(win) && !desktopWorkspaceStore.overview && endWindowDrag(win) if (!moved && win) { win.actions.setPosition({ x: data.left, y: data.top }) } } return { onDragStart, onDragEnd } }