Add device management and database-backed desktop settings

This update migrates desktop grid settings from localStorage to the database
and introduces a comprehensive device management system.

Features:
- New haex_devices table for device identification and naming
- Device-specific settings with foreign key relationships
- Preset-based icon sizes (Small, Medium, Large, Extra Large)
- Grid positioning improvements to prevent dragging behind PageHeader
- Dynamic icon sizing based on database settings

Database Changes:
- Created haex_devices table with deviceId (UUID) and name columns
- Modified haex_settings to include device_id FK and updated unique constraint
- Migration 0002_loose_quasimodo.sql for schema changes

Technical Improvements:
- Replaced arbitrary icon size slider (60-200px) with preset system
- Icons use actual measured dimensions for proper grid centering
- Settings sync on vault mount for cross-device consistency
- Proper bounds checking during icon drag operations

Bump version to 0.1.7
This commit is contained in:
2025-11-04 16:04:38 +01:00
parent cffb129e4f
commit 279468eddc
19 changed files with 1421 additions and 128 deletions

View File

@ -1,9 +1,13 @@
import { eq } from 'drizzle-orm'
import { haexDesktopItems } from '~/database/schemas'
import { haexDesktopItems, haexDevices } from '~/database/schemas'
import type {
InsertHaexDesktopItems,
SelectHaexDesktopItems,
} from '~/database/schemas'
import {
DesktopIconSizePreset,
iconSizePresetValues,
} from '~/stores/vault/settings'
import de from './de.json'
import en from './en.json'
@ -20,6 +24,10 @@ 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,
@ -29,6 +37,86 @@ export const useDesktopStore = defineStore('desktopStore', () => {
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)
// 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),
})
return device?.id ? device.id : undefined
}
// Sync icon size from DB
const syncDesktopIconSizeAsync = async () => {
const deviceInternalId = await getDeviceInternalIdAsync()
if (!deviceInternalId) return
const preset = await settingsStore.syncDesktopIconSizeAsync(deviceInternalId)
iconSizePreset.value = preset
}
// Update icon size in DB
const updateDesktopIconSizeAsync = async (preset: DesktopIconSizePreset) => {
const deviceInternalId = await getDeviceInternalIdAsync()
if (!deviceInternalId) return
await settingsStore.updateDesktopIconSizeAsync(deviceInternalId, preset)
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]
})
// Calculate grid cell size based on icon size
const gridCellSize = computed(() => {
// Add padding around icon (20px extra for spacing)
return effectiveIconSize.value + 20
})
// 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 cellSize = gridCellSize.value
// Calculate which grid cell the position falls into
const col = Math.floor(x / cellSize)
const row = Math.floor(y / cellSize)
// Use provided dimensions or fall back to cell size
const actualIconWidth = iconWidth || cellSize
const actualIconHeight = iconHeight || cellSize
// Center the icon in the cell(s) it occupies
const cellsWide = Math.max(1, Math.ceil(actualIconWidth / cellSize))
const cellsHigh = Math.max(1, Math.ceil(actualIconHeight / cellSize))
const totalWidth = cellsWide * cellSize
const totalHeight = cellsHigh * cellSize
const paddingX = (totalWidth - actualIconWidth) / 2
const paddingY = (totalHeight - actualIconHeight) / 2
return {
x: col * cellSize + paddingX,
y: row * cellSize + paddingY,
}
}
const loadDesktopItemsAsync = async () => {
if (!currentVault.value?.drizzle) {
console.error('Kein Vault geöffnet')
@ -347,5 +435,14 @@ export const useDesktopStore = defineStore('desktopStore', () => {
toggleSelection,
clearSelection,
isItemSelected,
// Grid settings
iconSizePreset,
syncDesktopIconSizeAsync,
updateDesktopIconSizeAsync,
effectiveGridColumns,
effectiveGridRows,
effectiveIconSize,
gridCellSize,
snapToGrid,
}
})