mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-16 14:10:52 +01:00
fix window overview
This commit is contained in:
@ -90,7 +90,8 @@
|
||||
<!-- Window with dynamic teleport -->
|
||||
<Teleport
|
||||
:to="
|
||||
windowManager.showWindowOverview
|
||||
windowManager.showWindowOverview &&
|
||||
overviewWindowState.has(window.id)
|
||||
? `#window-preview-${window.id}`
|
||||
: `#desktop-container-${window.id}`
|
||||
"
|
||||
@ -98,15 +99,15 @@
|
||||
<template
|
||||
v-if="
|
||||
windowManager.showWindowOverview &&
|
||||
overviewWindowState[window.id]
|
||||
overviewWindowState.has(window.id)
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="absolute origin-top-left"
|
||||
:style="{
|
||||
transform: `scale(${overviewWindowState[window.id]!.scale})`,
|
||||
width: `${overviewWindowState[window.id]!.width}px`,
|
||||
height: `${overviewWindowState[window.id]!.height}px`,
|
||||
transform: `scale(${overviewWindowState.get(window.id)!.scale})`,
|
||||
width: `${overviewWindowState.get(window.id)!.width}px`,
|
||||
height: `${overviewWindowState.get(window.id)!.height}px`,
|
||||
}"
|
||||
>
|
||||
<HaexWindow
|
||||
@ -116,10 +117,10 @@
|
||||
:id="window.id"
|
||||
:title="window.title"
|
||||
:icon="window.icon"
|
||||
v-model:x="overviewWindowState[window.id]!.x"
|
||||
v-model:y="overviewWindowState[window.id]!.y"
|
||||
v-model:width="overviewWindowState[window.id]!.width"
|
||||
v-model:height="overviewWindowState[window.id]!.height"
|
||||
v-model:x="overviewWindowState.get(window.id)!.x"
|
||||
v-model:y="overviewWindowState.get(window.id)!.y"
|
||||
v-model:width="overviewWindowState.get(window.id)!.width"
|
||||
v-model:height="overviewWindowState.get(window.id)!.height"
|
||||
:is-active="windowManager.isWindowActive(window.id)"
|
||||
:source-x="window.sourceX"
|
||||
:source-y="window.sourceY"
|
||||
@ -567,47 +568,48 @@ const MIN_PREVIEW_HEIGHT = 225 // 50% increase from 150
|
||||
const MAX_PREVIEW_HEIGHT = 450 // 50% increase from 300
|
||||
|
||||
// Store window state for overview (position only, size stays original)
|
||||
const overviewWindowState = reactive<
|
||||
Record<
|
||||
string,
|
||||
{ x: number; y: number; width: number; height: number; scale: number }
|
||||
>
|
||||
>({})
|
||||
const overviewWindowState = ref(
|
||||
new Map<string, { x: number; y: number; width: number; height: number; scale: number }>(),
|
||||
)
|
||||
|
||||
// Calculate scale and card dimensions for each window
|
||||
watch(
|
||||
() => windowManager.showWindowOverview,
|
||||
(isOpen) => {
|
||||
if (isOpen) {
|
||||
// Calculate scale for each window
|
||||
windowManager.windows.forEach((window) => {
|
||||
const scaleX = MAX_PREVIEW_WIDTH / window.width
|
||||
const scaleY = MAX_PREVIEW_HEIGHT / window.height
|
||||
const scale = Math.min(scaleX, scaleY, 1) // Never scale up, only down
|
||||
// Wait for the Overview modal to mount and create the teleport targets
|
||||
nextTick(() => {
|
||||
windowManager.windows.forEach((window) => {
|
||||
const scaleX = MAX_PREVIEW_WIDTH / window.width
|
||||
const scaleY = MAX_PREVIEW_HEIGHT / window.height
|
||||
const scale = Math.min(scaleX, scaleY, 1)
|
||||
|
||||
// Ensure minimum card size
|
||||
const scaledWidth = window.width * scale
|
||||
const scaledHeight = window.height * scale
|
||||
// Ensure minimum card size
|
||||
const scaledWidth = window.width * scale
|
||||
const scaledHeight = window.height * scale
|
||||
|
||||
let finalScale = scale
|
||||
if (scaledWidth < MIN_PREVIEW_WIDTH) {
|
||||
finalScale = MIN_PREVIEW_WIDTH / window.width
|
||||
}
|
||||
if (scaledHeight < MIN_PREVIEW_HEIGHT) {
|
||||
finalScale = Math.max(finalScale, MIN_PREVIEW_HEIGHT / window.height)
|
||||
}
|
||||
let finalScale = scale
|
||||
if (scaledWidth < MIN_PREVIEW_WIDTH) {
|
||||
finalScale = MIN_PREVIEW_WIDTH / window.width
|
||||
}
|
||||
if (scaledHeight < MIN_PREVIEW_HEIGHT) {
|
||||
finalScale = Math.max(finalScale, MIN_PREVIEW_HEIGHT / window.height)
|
||||
}
|
||||
|
||||
overviewWindowState[window.id] = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: window.width, // Keep original width
|
||||
height: window.height, // Keep original height
|
||||
scale: finalScale, // Store the scale factor
|
||||
}
|
||||
overviewWindowState.value.set(window.id, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: window.width,
|
||||
height: window.height,
|
||||
scale: finalScale,
|
||||
})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
// Clear state when overview is closed
|
||||
overviewWindowState.value.clear()
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
// Disable Swiper in overview mode
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
ref="windowEl"
|
||||
:style="windowStyle"
|
||||
:class="[
|
||||
'absolute bg-default/80 backdrop-blur-xl rounded-xl shadow-2xl overflow-hidden isolate',
|
||||
'absolute bg-default/80 backdrop-blur-xl rounded-lg shadow-xl overflow-hidden isolate',
|
||||
'border border-gray-200 dark:border-gray-700 transition-all ease-out duration-600 ',
|
||||
'flex flex-col @container',
|
||||
{ 'select-none': isResizingOrDragging },
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
<template>
|
||||
<UModal
|
||||
v-model:open="localShowWindowOverview"
|
||||
title=""
|
||||
:title="t('modal.title')"
|
||||
:description="t('modal.description')"
|
||||
fullscreen
|
||||
>
|
||||
<template #content>
|
||||
<div class="flex flex-col h-full">
|
||||
<!-- Header -->
|
||||
<div
|
||||
class="flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700"
|
||||
class="flex items-center justify-end border-b p-2 border-gray-200 dark:border-gray-700"
|
||||
>
|
||||
<h3 class="text-2xl font-bold">Window Overview</h3>
|
||||
<UButton
|
||||
icon="i-heroicons-x-mark"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
color="error"
|
||||
variant="soft"
|
||||
@click="localShowWindowOverview = false"
|
||||
/>
|
||||
</div>
|
||||
@ -48,15 +48,15 @@
|
||||
v-if="window.isMinimized"
|
||||
color="info"
|
||||
size="xs"
|
||||
:title="t('minimized')"
|
||||
>
|
||||
Minimized
|
||||
</UBadge>
|
||||
</div>
|
||||
|
||||
<!-- Scaled Window Preview Container / Teleport Target -->
|
||||
<div
|
||||
:id="`window-preview-${window.id}`"
|
||||
class="relative bg-gray-100 dark:bg-gray-900 rounded-lg overflow-hidden border-2 border-gray-200 dark:border-gray-700 group-hover:border-primary-500 transition-all shadow-lg"
|
||||
class="relative bg-gray-100 dark:bg-gray-900 rounded-xl overflow-hidden border-2 border-gray-200 dark:border-gray-700 group-hover:border-primary-500 transition-all shadow-lg"
|
||||
:style="getCardStyle(window)"
|
||||
@click="handleRestoreAndActivateWindow(window.id)"
|
||||
>
|
||||
@ -75,7 +75,7 @@
|
||||
>
|
||||
<UIcon
|
||||
name="i-heroicons-window"
|
||||
class="size-16 mb-4"
|
||||
class="size-16 mb-4 shrink-0"
|
||||
/>
|
||||
<p class="text-lg font-medium">No windows open</p>
|
||||
<p class="text-sm">
|
||||
@ -89,6 +89,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { t } = useI18n()
|
||||
|
||||
const windowManager = useWindowManagerStore()
|
||||
const workspaceStore = useWorkspaceStore()
|
||||
|
||||
@ -217,3 +219,19 @@ watch(
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<i18n lang="yaml">
|
||||
de:
|
||||
modal:
|
||||
title: Fensterübersicht
|
||||
description: Übersicht aller offenen Fenster auf allen Workspaces
|
||||
|
||||
minimized: Minimiert
|
||||
|
||||
en:
|
||||
modal:
|
||||
title: Window Overview
|
||||
description: Overview of all open windows on all workspaces
|
||||
|
||||
minimized: Minimized
|
||||
</i18n>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<UCard
|
||||
ref="cardEl"
|
||||
class="cursor-pointer transition-all h-32 w-72 shrink-0 group duration-500"
|
||||
class="cursor-pointer transition-all h-32 w-72 shrink-0 group duration-500 rounded-lg"
|
||||
:class="[
|
||||
workspace.id === currentWorkspace?.id
|
||||
? 'ring-2 ring-secondary bg-secondary/10'
|
||||
|
||||
@ -178,11 +178,10 @@ const drizzleCallback = (async (
|
||||
}
|
||||
|
||||
console.log('drizzleCallback', method, sql, params)
|
||||
console.log('drizzleCallback rows', rows)
|
||||
console.log('drizzleCallback rows', rows, rows.slice(0, 1))
|
||||
|
||||
if (method === 'get') {
|
||||
return { rows: rows.slice(0, 1) }
|
||||
//return rows.length > 0 ? { rows: rows[0] } : { rows }
|
||||
return rows.length > 0 ? { rows: rows.at(0) } : { rows }
|
||||
}
|
||||
return { rows }
|
||||
}) satisfies AsyncRemoteCallback
|
||||
|
||||
Reference in New Issue
Block a user