Add workspace background customization and fix launcher drawer drag

- Add workspace background image support with file-based storage
  - Store background images in $APPLOCALDATA/files directory
  - Save file paths in database (text column in haex_workspaces)
  - Use convertFileSrc for secure asset:// URL conversion
  - Add context menu to workspaces with "Hintergrund ändern" option

- Implement background management in settings
  - File selection dialog for PNG, JPG, JPEG, WebP images
  - Copy selected images to app data directory
  - Remove background with file cleanup
  - Multilingual UI (German/English)

- Fix launcher drawer drag interference
  - Add :handle-only="true" to UDrawer to restrict drag to handle
  - Simplify drag handlers (removed complex state tracking)
  - Items can now be dragged to desktop without drawer interference

- Extend Tauri asset protocol scope to include $APPLOCALDATA/**
  for background image loading
This commit is contained in:
2025-11-03 01:29:08 +01:00
parent 931d51a1e1
commit f38cecc84b
6 changed files with 376 additions and 184 deletions

View File

@ -4,6 +4,7 @@ import {
type SelectHaexWorkspaces,
} from '~/database/schemas'
import type { Swiper } from 'swiper/types'
import { convertFileSrc } from '@tauri-apps/api/core'
export type IWorkspace = SelectHaexWorkspaces
@ -203,12 +204,86 @@ export const useWorkspaceStore = defineStore('workspaceStore', () => {
isOverviewMode.value = false
}
const updateWorkspaceBackgroundAsync = async (
workspaceId: string,
base64Image: string | null,
) => {
if (!currentVault.value?.drizzle) {
throw new Error('Kein Vault geöffnet')
}
try {
const result = await currentVault.value.drizzle
.update(haexWorkspaces)
.set({ background: base64Image })
.where(eq(haexWorkspaces.id, workspaceId))
.returning()
if (result.length > 0 && result[0]) {
const index = workspaces.value.findIndex((ws) => ws.id === workspaceId)
if (index !== -1) {
workspaces.value[index] = result[0]
}
}
} catch (error) {
console.error('Fehler beim Aktualisieren des Workspace-Hintergrunds:', error)
throw error
}
}
const getWorkspaceBackgroundStyle = (workspace: IWorkspace) => {
if (!workspace.background) return {}
// The background field contains the absolute file path
// Convert it to an asset URL
const assetUrl = convertFileSrc(workspace.background)
return {
backgroundImage: `url(${assetUrl})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}
}
const getWorkspaceContextMenuItems = (workspaceId: string) => {
const windowManager = useWindowManagerStore()
return [[
{
label: 'Hintergrund ändern',
icon: 'i-mdi-image',
onSelect: async () => {
// Store the workspace ID for settings to use
currentWorkspaceIndex.value = workspaces.value.findIndex(
(ws) => ws.id === workspaceId,
)
// Get settings window info
const settingsWindow = windowManager.getAllSystemWindows()
.find((win) => win.id === 'settings')
if (settingsWindow) {
await windowManager.openWindowAsync({
type: 'system',
sourceId: settingsWindow.id,
title: settingsWindow.name,
icon: settingsWindow.icon || undefined,
workspaceId,
})
}
},
},
]]
}
return {
addWorkspaceAsync,
allowSwipe,
closeWorkspaceAsync,
currentWorkspace,
currentWorkspaceIndex,
getWorkspaceBackgroundStyle,
getWorkspaceContextMenuItems,
isOverviewMode,
slideToWorkspace,
loadWorkspacesAsync,
@ -218,6 +293,7 @@ export const useWorkspaceStore = defineStore('workspaceStore', () => {
switchToNext,
switchToPrevious,
switchToWorkspace,
updateWorkspaceBackgroundAsync,
workspaces,
}
})