mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-16 22:20:51 +01:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b465c117b0 | |||
| 731ae7cc47 | |||
| 26ec4e2a89 |
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "haex-hub",
|
||||
"private": true,
|
||||
"version": "0.1.7",
|
||||
"version": "0.1.10",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
@pointerdown.left="handlePointerDown"
|
||||
@pointermove="handlePointerMove"
|
||||
@pointerup="handlePointerUp"
|
||||
@dragstart.prevent
|
||||
@click.left="handleClick"
|
||||
@dblclick="handleDoubleClick"
|
||||
>
|
||||
@ -176,6 +177,9 @@ const style = computed(() => ({
|
||||
const handlePointerDown = (e: PointerEvent) => {
|
||||
if (!draggableEl.value || !draggableEl.value.parentElement) return
|
||||
|
||||
// Prevent any text selection during drag
|
||||
e.preventDefault()
|
||||
|
||||
isDragging.value = true
|
||||
emit('dragStart', props.id, props.itemType, props.referenceId, iconWidth.value, iconHeight.value, x.value, y.value)
|
||||
|
||||
@ -196,9 +200,12 @@ const handlePointerMove = (e: PointerEvent) => {
|
||||
const newX = e.clientX - parentRect.left - offsetX.value
|
||||
const newY = e.clientY - parentRect.top - offsetY.value
|
||||
|
||||
// Clamp y position to minimum 0 (parent is already below header)
|
||||
x.value = newX
|
||||
y.value = Math.max(0, newY)
|
||||
// Clamp position to viewport bounds during drag
|
||||
const maxX = viewportSize ? Math.max(0, viewportSize.width.value - iconWidth.value) : Number.MAX_SAFE_INTEGER
|
||||
const maxY = viewportSize ? Math.max(0, viewportSize.height.value - iconHeight.value) : Number.MAX_SAFE_INTEGER
|
||||
|
||||
x.value = Math.max(0, Math.min(maxX, newX))
|
||||
y.value = Math.max(0, Math.min(maxY, newY))
|
||||
|
||||
// Emit current position during drag
|
||||
emit('dragging', props.id, x.value, y.value)
|
||||
|
||||
@ -25,12 +25,13 @@
|
||||
>
|
||||
<UContextMenu :items="getWorkspaceContextMenuItems(workspace.id)">
|
||||
<div
|
||||
class="w-full h-full relative"
|
||||
class="w-full h-full relative select-none"
|
||||
:style="getWorkspaceBackgroundStyle(workspace)"
|
||||
@click.self.stop="handleDesktopClick"
|
||||
@mousedown.left.self="handleAreaSelectStart"
|
||||
@dragover.prevent="handleDragOver"
|
||||
@drop.prevent="handleDrop($event, workspace.id)"
|
||||
@selectstart.prevent
|
||||
>
|
||||
<!-- Drop Target Zone (visible during drag) -->
|
||||
<div
|
||||
@ -301,7 +302,7 @@ const { x: mouseX, y: mouseY } = useMouse()
|
||||
const dropTargetZone = computed(() => {
|
||||
if (!isDragging.value) return null
|
||||
|
||||
// Use the actual icon position during drag, not the mouse position
|
||||
// Use the actual icon position during drag
|
||||
const iconX = currentDraggedItem.x
|
||||
const iconY = currentDraggedItem.y
|
||||
|
||||
@ -313,11 +314,14 @@ const dropTargetZone = computed(() => {
|
||||
currentDraggedItem.height || undefined,
|
||||
)
|
||||
|
||||
// Show dropzone at snapped position with grid cell size
|
||||
const cellSize = desktopStore.gridCellSize
|
||||
|
||||
return {
|
||||
x: snapped.x,
|
||||
y: snapped.y,
|
||||
width: currentDraggedItem.width || desktopStore.gridCellSize,
|
||||
height: currentDraggedItem.height || desktopStore.gridCellSize,
|
||||
width: currentDraggedItem.width || cellSize,
|
||||
height: currentDraggedItem.height || cellSize,
|
||||
}
|
||||
})
|
||||
|
||||
@ -732,6 +736,21 @@ watch(currentWorkspace, async () => {
|
||||
}
|
||||
})
|
||||
|
||||
// Reset drag state when mouse leaves the document (fixes stuck dropzone)
|
||||
useEventListener(document, 'mouseleave', () => {
|
||||
if (isDragging.value) {
|
||||
isDragging.value = false
|
||||
currentDraggedItem.id = ''
|
||||
currentDraggedItem.itemType = ''
|
||||
currentDraggedItem.referenceId = ''
|
||||
currentDraggedItem.width = 0
|
||||
currentDraggedItem.height = 0
|
||||
currentDraggedItem.x = 0
|
||||
currentDraggedItem.y = 0
|
||||
allowSwipe.value = true
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
// Load workspaces first
|
||||
await workspaceStore.loadWorkspacesAsync()
|
||||
|
||||
@ -24,29 +24,29 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
const workspaceStore = useWorkspaceStore()
|
||||
const { currentWorkspace } = storeToRefs(workspaceStore)
|
||||
const { $i18n } = useNuxtApp()
|
||||
const uiStore = useUiStore()
|
||||
const { isSmallScreen } = storeToRefs(uiStore)
|
||||
const deviceStore = useDeviceStore()
|
||||
const settingsStore = useVaultSettingsStore()
|
||||
|
||||
$i18n.setLocaleMessage('de', {
|
||||
desktop: de,
|
||||
})
|
||||
$i18n.setLocaleMessage('de', { desktop: de })
|
||||
$i18n.setLocaleMessage('en', { desktop: en })
|
||||
|
||||
const desktopItems = ref<IDesktopItem[]>([])
|
||||
const selectedItemIds = ref<Set<string>>(new Set())
|
||||
|
||||
// Desktop Grid Settings (stored in DB per device)
|
||||
const iconSizePreset = ref<DesktopIconSizePreset>(DesktopIconSizePreset.medium)
|
||||
const iconSizePreset = ref<DesktopIconSizePreset>(
|
||||
DesktopIconSizePreset.medium,
|
||||
)
|
||||
|
||||
// Get device internal ID from DB
|
||||
const getDeviceInternalIdAsync = async () => {
|
||||
if (!deviceStore.deviceId || !currentVault.value?.drizzle) return undefined
|
||||
|
||||
const device = await currentVault.value.drizzle.query.haexDevices.findFirst({
|
||||
where: eq(haexDevices.deviceId, deviceStore.deviceId),
|
||||
})
|
||||
const device = await currentVault.value.drizzle.query.haexDevices.findFirst(
|
||||
{
|
||||
where: eq(haexDevices.deviceId, deviceStore.deviceId),
|
||||
},
|
||||
)
|
||||
|
||||
return device?.id ? device.id : undefined
|
||||
}
|
||||
@ -56,7 +56,8 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
const deviceInternalId = await getDeviceInternalIdAsync()
|
||||
if (!deviceInternalId) return
|
||||
|
||||
const preset = await settingsStore.syncDesktopIconSizeAsync(deviceInternalId)
|
||||
const preset =
|
||||
await settingsStore.syncDesktopIconSizeAsync(deviceInternalId)
|
||||
iconSizePreset.value = preset
|
||||
}
|
||||
|
||||
@ -69,33 +70,34 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
iconSizePreset.value = preset
|
||||
}
|
||||
|
||||
// Reactive grid settings based on screen size
|
||||
const effectiveGridColumns = computed(() => {
|
||||
return isSmallScreen.value ? 4 : 8
|
||||
})
|
||||
|
||||
const effectiveGridRows = computed(() => {
|
||||
return isSmallScreen.value ? 5 : 6
|
||||
})
|
||||
|
||||
const effectiveIconSize = computed(() => {
|
||||
return iconSizePresetValues[iconSizePreset.value]
|
||||
})
|
||||
|
||||
const iconPadding = 30
|
||||
|
||||
// Calculate grid cell size based on icon size
|
||||
const gridCellSize = computed(() => {
|
||||
// Add padding around icon (20px extra for spacing)
|
||||
return effectiveIconSize.value + 20
|
||||
// Add padding around icon (30px extra for spacing)
|
||||
return effectiveIconSize.value + iconPadding
|
||||
})
|
||||
|
||||
// Snap position to grid (centers icon in cell)
|
||||
// iconWidth and iconHeight are optional - if provided, they're used for centering
|
||||
const snapToGrid = (x: number, y: number, iconWidth?: number, iconHeight?: number) => {
|
||||
const snapToGrid = (
|
||||
x: number,
|
||||
y: number,
|
||||
iconWidth?: number,
|
||||
iconHeight?: number,
|
||||
) => {
|
||||
const cellSize = gridCellSize.value
|
||||
|
||||
// Adjust y for grid offset
|
||||
const adjustedY = Math.max(0, y + iconPadding)
|
||||
|
||||
// Calculate which grid cell the position falls into
|
||||
const col = Math.floor(x / cellSize)
|
||||
const row = Math.floor(y / cellSize)
|
||||
const row = Math.floor(adjustedY / cellSize)
|
||||
|
||||
// Use provided dimensions or fall back to cell size
|
||||
const actualIconWidth = iconWidth || cellSize
|
||||
@ -112,8 +114,8 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
const paddingY = (totalHeight - actualIconHeight) / 2
|
||||
|
||||
return {
|
||||
x: col * cellSize + paddingX,
|
||||
y: row * cellSize + paddingY,
|
||||
x: col * cellSize + paddingX - iconPadding,
|
||||
y: row * cellSize + paddingY - iconPadding,
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,9 +136,12 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
.from(haexDesktopItems)
|
||||
.where(eq(haexDesktopItems.workspaceId, currentWorkspace.value.id))
|
||||
|
||||
desktopItems.value = items.map(item => ({
|
||||
desktopItems.value = items.map((item) => ({
|
||||
...item,
|
||||
referenceId: item.itemType === 'extension' ? item.extensionId! : item.systemWindowId!,
|
||||
referenceId:
|
||||
item.itemType === 'extension'
|
||||
? item.extensionId!
|
||||
: item.systemWindowId!,
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Desktop-Items:', error)
|
||||
@ -165,7 +170,10 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
workspaceId: targetWorkspaceId,
|
||||
itemType: itemType,
|
||||
extensionId: itemType === 'extension' ? referenceId : null,
|
||||
systemWindowId: itemType === 'system' || itemType === 'file' || itemType === 'folder' ? referenceId : null,
|
||||
systemWindowId:
|
||||
itemType === 'system' || itemType === 'file' || itemType === 'folder'
|
||||
? referenceId
|
||||
: null,
|
||||
positionX: positionX,
|
||||
positionY: positionY,
|
||||
}
|
||||
@ -178,7 +186,10 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
if (result.length > 0 && result[0]) {
|
||||
const itemWithRef = {
|
||||
...result[0],
|
||||
referenceId: itemType === 'extension' ? result[0].extensionId! : result[0].systemWindowId!,
|
||||
referenceId:
|
||||
itemType === 'extension'
|
||||
? result[0].extensionId!
|
||||
: result[0].systemWindowId!,
|
||||
}
|
||||
desktopItems.value.push(itemWithRef)
|
||||
return itemWithRef
|
||||
@ -189,7 +200,7 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
itemType,
|
||||
referenceId,
|
||||
workspaceId: targetWorkspaceId,
|
||||
position: { x: positionX, y: positionY }
|
||||
position: { x: positionX, y: positionY },
|
||||
})
|
||||
|
||||
// Log full error details
|
||||
@ -226,7 +237,10 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
const item = result[0]
|
||||
desktopItems.value[index] = {
|
||||
...item,
|
||||
referenceId: item.itemType === 'extension' ? item.extensionId! : item.systemWindowId!,
|
||||
referenceId:
|
||||
item.itemType === 'extension'
|
||||
? item.extensionId!
|
||||
: item.systemWindowId!,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -259,16 +273,14 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
itemType: DesktopItemType,
|
||||
referenceId: string,
|
||||
) => {
|
||||
return desktopItems.value.find(
|
||||
(item) => {
|
||||
if (item.itemType !== itemType) return false
|
||||
if (itemType === 'extension') {
|
||||
return item.extensionId === referenceId
|
||||
} else {
|
||||
return item.systemWindowId === referenceId
|
||||
}
|
||||
},
|
||||
)
|
||||
return desktopItems.value.find((item) => {
|
||||
if (item.itemType !== itemType) return false
|
||||
if (itemType === 'extension') {
|
||||
return item.extensionId === referenceId
|
||||
} else {
|
||||
return item.systemWindowId === referenceId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const openDesktopItem = (
|
||||
@ -279,9 +291,9 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
const windowManager = useWindowManagerStore()
|
||||
|
||||
if (itemType === 'system') {
|
||||
const systemWindow = windowManager.getAllSystemWindows().find(
|
||||
(win) => win.id === referenceId,
|
||||
)
|
||||
const systemWindow = windowManager
|
||||
.getAllSystemWindows()
|
||||
.find((win) => win.id === referenceId)
|
||||
|
||||
if (systemWindow) {
|
||||
windowManager.openWindowAsync({
|
||||
@ -439,8 +451,6 @@ export const useDesktopStore = defineStore('desktopStore', () => {
|
||||
iconSizePreset,
|
||||
syncDesktopIconSizeAsync,
|
||||
updateDesktopIconSizeAsync,
|
||||
effectiveGridColumns,
|
||||
effectiveGridRows,
|
||||
effectiveIconSize,
|
||||
gridCellSize,
|
||||
snapToGrid,
|
||||
|
||||
Reference in New Issue
Block a user