@owdproject/core 3.4.0 → 4.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -13
- package/dist/dom/index.d.mts +65 -0
- package/dist/dom/index.d.ts +65 -0
- package/dist/dom/index.mjs +224 -0
- package/dist/events/index.d.mts +70 -0
- package/dist/events/index.d.ts +70 -0
- package/dist/events/index.mjs +3 -0
- package/dist/index.d.mts +73 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.mjs +115 -0
- package/dist/layout/index.d.mts +41 -0
- package/dist/layout/index.d.ts +41 -0
- package/dist/layout/index.mjs +64 -0
- package/dist/machines/index.d.mts +31 -0
- package/dist/machines/index.d.ts +31 -0
- package/dist/machines/index.mjs +2 -0
- package/dist/managers/index.d.mts +117 -0
- package/dist/managers/index.d.ts +117 -0
- package/dist/managers/index.mjs +6 -0
- package/dist/session/index.d.mts +57 -0
- package/dist/session/index.d.ts +57 -0
- package/dist/session/index.mjs +65 -0
- package/dist/shared/core.B0B0KfVK.mjs +865 -0
- package/dist/shared/core.B1XxB289.mjs +239 -0
- package/dist/shared/core.B3mp7ztE.mjs +237 -0
- package/dist/shared/core.BOvFdEVQ.d.ts +114 -0
- package/dist/shared/core.CsDFgGnX.mjs +40 -0
- package/dist/shared/core.Di1eFcr_.d.mts +114 -0
- package/dist/shared/core.Pd_Ogt4g.mjs +101 -0
- package/dist/shared/core.b3Xldzyu.mjs +29 -0
- package/dist/types/index.d.mts +266 -0
- package/dist/types/index.d.ts +266 -0
- package/dist/types/index.mjs +1 -0
- package/package.json +56 -112
- package/CHANGELOG.md +0 -98
- package/DESKTOP_KERNEL.md +0 -232
- package/MIGRATION_3.3.2.md +0 -23
- package/MIGRATION_3.4.md +0 -126
- package/PLAYGROUND.md +0 -91
- package/dist/module.d.mts +0 -13
- package/dist/module.json +0 -9
- package/dist/module.mjs +0 -254
- package/dist/types.d.mts +0 -7
- package/index.ts +0 -8
- package/kit/authoring.ts +0 -340
- package/kit/defineDesktopApp.ts +0 -56
- package/module.ts +0 -203
- package/runtime/components/Application/DesktopCoreApplicationRender.vue +0 -20
- package/runtime/components/Application/DesktopCoreApplicationWindowsRender.vue +0 -38
- package/runtime/components/background/DesktopCoreBackground.vue +0 -16
- package/runtime/components/core/DesktopCore.vue +0 -43
- package/runtime/components/time/DesktopCoreTime.vue +0 -56
- package/runtime/components/window/DesktopCoreWindow.vue +0 -215
- package/runtime/components/window/DesktopCoreWindowContent.vue +0 -28
- package/runtime/components/window/DesktopCoreWindowNav.vue +0 -66
- package/runtime/components/window/DesktopCoreWindowSnapHintsBase.vue +0 -74
- package/runtime/components/workspace/DesktopCoreWorkspaceEdgeHintsBase.vue +0 -84
- package/runtime/composables/useApplicationEntries.ts +0 -51
- package/runtime/composables/useApplicationManager.ts +0 -285
- package/runtime/composables/useBlockNonInputContextMenu.ts +0 -30
- package/runtime/composables/useDesktopConfig.ts +0 -8
- package/runtime/composables/useDesktopDialogs.ts +0 -16
- package/runtime/composables/useDesktopExtension.ts +0 -8
- package/runtime/composables/useDesktopManager.ts +0 -51
- package/runtime/composables/useDesktopManifest.ts +0 -17
- package/runtime/composables/useDesktopSession.ts +0 -27
- package/runtime/composables/useDesktopShellIdentity.ts +0 -99
- package/runtime/composables/useDesktopShellOptions.ts +0 -36
- package/runtime/composables/useDesktopShellReady.ts +0 -7
- package/runtime/composables/useDesktopWorkArea.ts +0 -93
- package/runtime/composables/useTerminalManager.ts +0 -159
- package/runtime/composables/useToggleWindowMaximize.ts +0 -35
- package/runtime/composables/useWindowDragHandlers.ts +0 -47
- package/runtime/composables/useWindowSnapDrop.ts +0 -112
- package/runtime/composables/useWorkspaceEdgeDrop.ts +0 -176
- package/runtime/composables/useWorkspaceManager.ts +0 -67
- package/runtime/composables/useWorkspaceOverviewCapture.ts +0 -92
- package/runtime/composables/useWorkspaceOverviewLiveScale.ts +0 -151
- package/runtime/constants/desktopShellKeys.ts +0 -12
- package/runtime/constants/shellLayout.ts +0 -5
- package/runtime/dialogs/desktopDialogProvider.ts +0 -73
- package/runtime/internal/controllers/ApplicationController.ts +0 -351
- package/runtime/internal/controllers/WindowController.ts +0 -547
- package/runtime/plugins/01.desktop-shell-init.client.ts +0 -28
- package/runtime/plugins/02.desktop-register-desktop-apps.client.ts +0 -13
- package/runtime/plugins/resize.client.ts +0 -6
- package/runtime/stores/storeApplicationMeta.ts +0 -60
- package/runtime/stores/storeApplicationWindows.ts +0 -21
- package/runtime/stores/storeDesktop.ts +0 -71
- package/runtime/stores/storeDesktopDefaultApps.ts +0 -54
- package/runtime/stores/storeDesktopVolume.ts +0 -19
- package/runtime/stores/storeDesktopWindow.ts +0 -38
- package/runtime/stores/storeDesktopWorkspace.ts +0 -105
- package/runtime/stores/storeIds.ts +0 -35
- package/runtime/types/desktopMenu.ts +0 -10
- package/runtime/utils/initDesktopShell.ts +0 -80
- package/runtime/utils/migratePersistedStoreIds.ts +0 -57
- package/runtime/utils/utilApp.ts +0 -25
- package/runtime/utils/utilCaptureElementToCanvas.ts +0 -21
- package/runtime/utils/utilCommon.ts +0 -26
- package/runtime/utils/utilDebug.ts +0 -30
- package/runtime/utils/utilDetectSnapZone.ts +0 -57
- package/runtime/utils/utilTerminal.ts +0 -6
- package/runtime/utils/utilWindowControllerAdapter.ts +0 -15
- package/runtime/utils/utilWindowLayout.ts +0 -82
- package/runtime/utils/utilWindowMaximizeLayout.ts +0 -44
- package/runtime/utils/utilWorkspaceWindows.ts +0 -33
- package/types/index.d.ts +0 -531
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import type { IWindowController } from '@owdproject/core'
|
|
2
|
-
import { computed, ref } from 'vue'
|
|
3
|
-
import { useDesktopWorkspaceStore } from '../stores/storeDesktopWorkspace'
|
|
4
|
-
import { WORKSPACE_EDGE_DROP_PX } from '../constants/shellLayout'
|
|
5
|
-
|
|
6
|
-
const edgeHint = ref<'left' | 'right' | null>(null)
|
|
7
|
-
const isWindowDragActive = ref(false)
|
|
8
|
-
let draggingWindowId: string | null = null
|
|
9
|
-
|
|
10
|
-
function adjacentWorkspaceId(side: 'left' | 'right'): string | null {
|
|
11
|
-
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
12
|
-
if (desktopWorkspaceStore.overview) return null
|
|
13
|
-
const list = desktopWorkspaceStore.list
|
|
14
|
-
if (list.length < 2) return null
|
|
15
|
-
|
|
16
|
-
const index = desktopWorkspaceStore.workspaceActiveIndex
|
|
17
|
-
if (index < 0) return null
|
|
18
|
-
|
|
19
|
-
if (side === 'left' && index > 0) {
|
|
20
|
-
return list[index - 1] ?? null
|
|
21
|
-
}
|
|
22
|
-
if (side === 'right' && index < list.length - 1) {
|
|
23
|
-
return list[index + 1] ?? null
|
|
24
|
-
}
|
|
25
|
-
return null
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function updateEdgeHintFromClientX(clientX: number) {
|
|
29
|
-
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
30
|
-
if (!isWindowDragActive.value || desktopWorkspaceStore.overview) {
|
|
31
|
-
edgeHint.value = null
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const viewportWidth =
|
|
36
|
-
typeof globalThis !== 'undefined' ? globalThis.innerWidth : 0
|
|
37
|
-
|
|
38
|
-
if (clientX <= WORKSPACE_EDGE_DROP_PX && adjacentWorkspaceId('left')) {
|
|
39
|
-
edgeHint.value = 'left'
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
clientX >= viewportWidth - WORKSPACE_EDGE_DROP_PX &&
|
|
45
|
-
adjacentWorkspaceId('right')
|
|
46
|
-
) {
|
|
47
|
-
edgeHint.value = 'right'
|
|
48
|
-
return
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
edgeHint.value = null
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function onDocumentPointerMove(e: PointerEvent) {
|
|
55
|
-
updateEdgeHintFromClientX(e.clientX)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function stopPointerTracking() {
|
|
59
|
-
document.removeEventListener('pointermove', onDocumentPointerMove)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* While dragging a window (normal desktop, not overview), highlight left/right
|
|
64
|
-
* screen edges when an adjacent workspace exists so the user can drop there.
|
|
65
|
-
*/
|
|
66
|
-
export function useWorkspaceEdgeDrop() {
|
|
67
|
-
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
68
|
-
|
|
69
|
-
function beginWindowDrag(windowId: string) {
|
|
70
|
-
if (desktopWorkspaceStore.overview) return
|
|
71
|
-
if (desktopWorkspaceStore.list.length < 2) return
|
|
72
|
-
|
|
73
|
-
draggingWindowId = windowId
|
|
74
|
-
isWindowDragActive.value = true
|
|
75
|
-
edgeHint.value = null
|
|
76
|
-
|
|
77
|
-
document.addEventListener('pointermove', onDocumentPointerMove, {
|
|
78
|
-
passive: true,
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function commitEdgeDrop(win: IWindowController) {
|
|
83
|
-
const side = edgeHint.value
|
|
84
|
-
if (!side || !draggingWindowId) return false
|
|
85
|
-
|
|
86
|
-
const targetWorkspaceId = adjacentWorkspaceId(side)
|
|
87
|
-
if (!targetWorkspaceId) return false
|
|
88
|
-
|
|
89
|
-
win.actions.setWorkspace(targetWorkspaceId)
|
|
90
|
-
desktopWorkspaceStore.setWorkspace(targetWorkspaceId)
|
|
91
|
-
|
|
92
|
-
const inset = WORKSPACE_EDGE_DROP_PX + 24
|
|
93
|
-
const pos = win.position
|
|
94
|
-
if (pos && typeof pos.y === 'number') {
|
|
95
|
-
const viewportWidth =
|
|
96
|
-
typeof globalThis !== 'undefined' ? globalThis.innerWidth : 1920
|
|
97
|
-
const rawWidth = win.size?.width ?? 400
|
|
98
|
-
const width =
|
|
99
|
-
typeof rawWidth === 'number'
|
|
100
|
-
? rawWidth
|
|
101
|
-
: Number.parseFloat(String(rawWidth)) || 400
|
|
102
|
-
const x =
|
|
103
|
-
side === 'left'
|
|
104
|
-
? inset
|
|
105
|
-
: Math.max(inset, viewportWidth - width - inset)
|
|
106
|
-
win.actions.setPosition({ x, y: pos.y })
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return true
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function endWindowDrag(win?: IWindowController): boolean {
|
|
113
|
-
stopPointerTracking()
|
|
114
|
-
|
|
115
|
-
let moved = false
|
|
116
|
-
if (win && edgeHint.value) {
|
|
117
|
-
moved = commitEdgeDrop(win)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
isWindowDragActive.value = false
|
|
121
|
-
draggingWindowId = null
|
|
122
|
-
edgeHint.value = null
|
|
123
|
-
|
|
124
|
-
return moved
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const edgeTargetDesktopIndex = computed(() => {
|
|
128
|
-
const side = edgeHint.value
|
|
129
|
-
if (!side) return null
|
|
130
|
-
|
|
131
|
-
const targetId = adjacentWorkspaceId(side)
|
|
132
|
-
if (!targetId) return null
|
|
133
|
-
|
|
134
|
-
const index = desktopWorkspaceStore.list.indexOf(targetId)
|
|
135
|
-
return index >= 0 ? index + 1 : null
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
edgeHint,
|
|
140
|
-
edgeTargetDesktopIndex,
|
|
141
|
-
isWindowDragActive,
|
|
142
|
-
beginWindowDrag,
|
|
143
|
-
endWindowDrag,
|
|
144
|
-
adjacentWorkspaceId,
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Wire {@link useWorkspaceEdgeDrop} to DesktopWindow drag events (theme Window wrapper).
|
|
150
|
-
*/
|
|
151
|
-
export function useWorkspaceEdgeDropWindowHandlers(
|
|
152
|
-
getWindow: () => IWindowController | undefined,
|
|
153
|
-
) {
|
|
154
|
-
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
155
|
-
const { beginWindowDrag, endWindowDrag } = useWorkspaceEdgeDrop()
|
|
156
|
-
|
|
157
|
-
function onDragStart() {
|
|
158
|
-
const win = getWindow()
|
|
159
|
-
if (!win?.state?.id || desktopWorkspaceStore.overview) return
|
|
160
|
-
beginWindowDrag(win.state.id)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function onDragEnd(data: { left: number; top: number }) {
|
|
164
|
-
const win = getWindow()
|
|
165
|
-
const moved =
|
|
166
|
-
Boolean(win) &&
|
|
167
|
-
!desktopWorkspaceStore.overview &&
|
|
168
|
-
endWindowDrag(win)
|
|
169
|
-
|
|
170
|
-
if (!moved && win) {
|
|
171
|
-
win.actions.setPosition({ x: data.left, y: data.top })
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return { onDragStart, onDragEnd }
|
|
176
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { useEventListener } from '@vueuse/core'
|
|
2
|
-
import { useApplicationManager } from './useApplicationManager'
|
|
3
|
-
import { useDesktopWorkspaceStore } from '../stores/storeDesktopWorkspace'
|
|
4
|
-
import { collectWindowsOnWorkspace } from '../utils/utilWorkspaceWindows'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Keyboard + HTML5 drop handlers for workspace management (move windows between desktops).
|
|
8
|
-
*/
|
|
9
|
-
export function useWorkspaceManager() {
|
|
10
|
-
const applicationManager = useApplicationManager()
|
|
11
|
-
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
12
|
-
|
|
13
|
-
useEventListener(window, 'keydown', (e: KeyboardEvent) => {
|
|
14
|
-
if (e.key !== 'Escape') return
|
|
15
|
-
if (!desktopWorkspaceStore.overview) return
|
|
16
|
-
desktopWorkspaceStore.setOverview(false)
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
function onWorkspaceDragOver(e: DragEvent) {
|
|
20
|
-
if (!desktopWorkspaceStore.overview) return
|
|
21
|
-
e.preventDefault()
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function onWorkspaceDrop(e: DragEvent, workspaceId: string) {
|
|
25
|
-
e.preventDefault()
|
|
26
|
-
if (!desktopWorkspaceStore.overview) return
|
|
27
|
-
|
|
28
|
-
const raw =
|
|
29
|
-
e.dataTransfer?.getData('text/plain') ||
|
|
30
|
-
e.dataTransfer?.getData('text') ||
|
|
31
|
-
''
|
|
32
|
-
if (!raw) return
|
|
33
|
-
|
|
34
|
-
const win = applicationManager.getWindowOpenedId(raw)
|
|
35
|
-
win?.actions.setWorkspace(workspaceId)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Remove a virtual desktop: migrate its windows to the last remaining workspace
|
|
40
|
-
* (excluding the removed id), then drop the workspace from the list.
|
|
41
|
-
*/
|
|
42
|
-
function removeWorkspace(workspaceId: string): boolean {
|
|
43
|
-
if (desktopWorkspaceStore.list.length <= 2) return false
|
|
44
|
-
|
|
45
|
-
const fallbackId = desktopWorkspaceStore.resolveWorkspaceFallback(workspaceId)
|
|
46
|
-
if (!fallbackId) return false
|
|
47
|
-
|
|
48
|
-
const activeId = desktopWorkspaceStore.active
|
|
49
|
-
const windows = collectWindowsOnWorkspace(
|
|
50
|
-
applicationManager.apps.values(),
|
|
51
|
-
workspaceId,
|
|
52
|
-
activeId,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
for (const win of windows) {
|
|
56
|
-
win.actions.setWorkspace(fallbackId)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return desktopWorkspaceStore.removeWorkspace(workspaceId)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
onWorkspaceDragOver,
|
|
64
|
-
onWorkspaceDrop,
|
|
65
|
-
removeWorkspace,
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { useDebounceFn } from '@vueuse/core'
|
|
2
|
-
import { nextTick, ref, shallowRef, watch } from 'vue'
|
|
3
|
-
import { useDesktopWorkspaceStore } from '@owdproject/core/runtime/stores/storeDesktopWorkspace'
|
|
4
|
-
import { captureElementToCanvas } from '../utils/utilCaptureElementToCanvas'
|
|
5
|
-
|
|
6
|
-
export type WorkspaceRootResolver = (
|
|
7
|
-
workspaceId: string,
|
|
8
|
-
) => HTMLElement | null | undefined
|
|
9
|
-
|
|
10
|
-
export type UseWorkspaceOverviewCaptureOptions = {
|
|
11
|
-
/** Delay before capturing after overview opens (ms). Default 150. */
|
|
12
|
-
debounceMs?: number
|
|
13
|
-
/** JPEG quality for thumbnail data URLs (0–1). Default 0.7. */
|
|
14
|
-
jpegQuality?: number
|
|
15
|
-
/** Passed through to html2canvas. */
|
|
16
|
-
captureOptions?: Record<string, unknown>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Captures workspace desktop roots as JPEG data URLs while workspace overview is open.
|
|
21
|
-
* Themes supply a resolver that maps each workspace id to its DOM root (e.g. a layer wrapping
|
|
22
|
-
* {@link DesktopApplicationRender} with `workspace-filter`).
|
|
23
|
-
*/
|
|
24
|
-
export function useWorkspaceOverviewCapture(
|
|
25
|
-
resolveWorkspaceRoot: WorkspaceRootResolver,
|
|
26
|
-
options: UseWorkspaceOverviewCaptureOptions = {},
|
|
27
|
-
) {
|
|
28
|
-
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
29
|
-
const thumbnails = shallowRef(new Map<string, string>())
|
|
30
|
-
const isCapturing = ref(false)
|
|
31
|
-
|
|
32
|
-
const debounceMs = options.debounceMs ?? 150
|
|
33
|
-
const jpegQuality = options.jpegQuality ?? 0.7
|
|
34
|
-
|
|
35
|
-
async function captureWorkspace(workspaceId: string): Promise<string | null> {
|
|
36
|
-
const element = resolveWorkspaceRoot(workspaceId)
|
|
37
|
-
const canvas = await captureElementToCanvas(element, options.captureOptions)
|
|
38
|
-
if (!canvas) return null
|
|
39
|
-
return canvas.toDataURL('image/jpeg', jpegQuality)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function refreshThumbnails() {
|
|
43
|
-
if (!desktopWorkspaceStore.overview) return
|
|
44
|
-
|
|
45
|
-
isCapturing.value = true
|
|
46
|
-
const next = new Map<string, string>()
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
await nextTick()
|
|
50
|
-
const ids = [...desktopWorkspaceStore.list]
|
|
51
|
-
await Promise.all(
|
|
52
|
-
ids.map(async (id) => {
|
|
53
|
-
const dataUrl = await captureWorkspace(id)
|
|
54
|
-
if (dataUrl) next.set(id, dataUrl)
|
|
55
|
-
}),
|
|
56
|
-
)
|
|
57
|
-
thumbnails.value = next
|
|
58
|
-
} finally {
|
|
59
|
-
isCapturing.value = false
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const scheduleRefresh = useDebounceFn(() => {
|
|
64
|
-
void refreshThumbnails()
|
|
65
|
-
}, debounceMs)
|
|
66
|
-
|
|
67
|
-
watch(
|
|
68
|
-
() => desktopWorkspaceStore.overview,
|
|
69
|
-
(open) => {
|
|
70
|
-
if (open) scheduleRefresh()
|
|
71
|
-
else thumbnails.value = new Map()
|
|
72
|
-
},
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
watch(
|
|
76
|
-
() => desktopWorkspaceStore.list.join('\0'),
|
|
77
|
-
() => {
|
|
78
|
-
if (desktopWorkspaceStore.overview) scheduleRefresh()
|
|
79
|
-
},
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
function thumbnailFor(workspaceId: string): string | undefined {
|
|
83
|
-
return thumbnails.value.get(workspaceId)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
thumbnails,
|
|
88
|
-
isCapturing,
|
|
89
|
-
refreshThumbnails,
|
|
90
|
-
thumbnailFor,
|
|
91
|
-
}
|
|
92
|
-
}
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties, Ref } from 'vue'
|
|
2
|
-
import {
|
|
3
|
-
nextTick,
|
|
4
|
-
onScopeDispose,
|
|
5
|
-
readonly,
|
|
6
|
-
shallowRef,
|
|
7
|
-
watch,
|
|
8
|
-
} from 'vue'
|
|
9
|
-
import { useDesktopWorkspaceStore } from '@owdproject/core/runtime/stores/storeDesktopWorkspace'
|
|
10
|
-
|
|
11
|
-
export type WorkspaceStageSize = {
|
|
12
|
-
width: number
|
|
13
|
-
height: number
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type WorkspaceOverviewLiveScaleOptions = {
|
|
17
|
-
/** Upper bound for scale (default 1). */
|
|
18
|
-
maxScale?: number
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type WorkspaceOverviewInnerStyleOptions =
|
|
22
|
-
WorkspaceOverviewLiveScaleOptions & {
|
|
23
|
-
transformOrigin?: string
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Fit factor to show a 1:1 shell stage inside a panel viewport without clipping.
|
|
28
|
-
*/
|
|
29
|
-
export function computeScaleToFit(
|
|
30
|
-
panelWidth: number,
|
|
31
|
-
panelHeight: number,
|
|
32
|
-
stageWidth: number,
|
|
33
|
-
stageHeight: number,
|
|
34
|
-
options?: WorkspaceOverviewLiveScaleOptions,
|
|
35
|
-
): number {
|
|
36
|
-
if (
|
|
37
|
-
panelWidth <= 0 ||
|
|
38
|
-
panelHeight <= 0 ||
|
|
39
|
-
stageWidth <= 0 ||
|
|
40
|
-
stageHeight <= 0
|
|
41
|
-
) {
|
|
42
|
-
return 1
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const scale = Math.min(panelWidth / stageWidth, panelHeight / stageHeight)
|
|
46
|
-
const maxScale = options?.maxScale ?? 1
|
|
47
|
-
return Math.min(scale, maxScale)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Live DOM workspace overview: measure shell stage, scale desktop roots to fit cards.
|
|
52
|
-
*/
|
|
53
|
-
export function useWorkspaceOverviewLiveScale(
|
|
54
|
-
shellStageRef: Ref<HTMLElement | null | undefined>,
|
|
55
|
-
) {
|
|
56
|
-
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
57
|
-
const stageSize = shallowRef<WorkspaceStageSize>({ width: 0, height: 0 })
|
|
58
|
-
|
|
59
|
-
let resizeObserver: ResizeObserver | null = null
|
|
60
|
-
|
|
61
|
-
function readStageSize() {
|
|
62
|
-
const el = shellStageRef.value
|
|
63
|
-
if (!el) {
|
|
64
|
-
stageSize.value = { width: 0, height: 0 }
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
stageSize.value = {
|
|
68
|
-
width: el.clientWidth,
|
|
69
|
-
height: el.clientHeight,
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function stopObserving() {
|
|
74
|
-
resizeObserver?.disconnect()
|
|
75
|
-
resizeObserver = null
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function startObserving() {
|
|
79
|
-
stopObserving()
|
|
80
|
-
const el = shellStageRef.value
|
|
81
|
-
if (!el || typeof ResizeObserver === 'undefined') return
|
|
82
|
-
|
|
83
|
-
readStageSize()
|
|
84
|
-
resizeObserver = new ResizeObserver(() => readStageSize())
|
|
85
|
-
resizeObserver.observe(el)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
watch(
|
|
89
|
-
() => desktopWorkspaceStore.overview,
|
|
90
|
-
(open) => {
|
|
91
|
-
if (open) {
|
|
92
|
-
void nextTick(() => startObserving())
|
|
93
|
-
} else {
|
|
94
|
-
stopObserving()
|
|
95
|
-
stageSize.value = { width: 0, height: 0 }
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
watch(shellStageRef, (el) => {
|
|
101
|
-
if (desktopWorkspaceStore.overview && el) {
|
|
102
|
-
void nextTick(() => startObserving())
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
onScopeDispose(stopObserving)
|
|
107
|
-
|
|
108
|
-
function scaleToFit(
|
|
109
|
-
panelEl: HTMLElement | null | undefined,
|
|
110
|
-
options?: WorkspaceOverviewLiveScaleOptions,
|
|
111
|
-
): number {
|
|
112
|
-
if (!panelEl) return 1
|
|
113
|
-
const { width: stageWidth, height: stageHeight } = stageSize.value
|
|
114
|
-
if (stageWidth <= 0 || stageHeight <= 0) return 1
|
|
115
|
-
|
|
116
|
-
return computeScaleToFit(
|
|
117
|
-
panelEl.clientWidth,
|
|
118
|
-
panelEl.clientHeight,
|
|
119
|
-
stageWidth,
|
|
120
|
-
stageHeight,
|
|
121
|
-
options,
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function innerOverviewStyle(
|
|
126
|
-
panelEl: HTMLElement | null | undefined,
|
|
127
|
-
options?: WorkspaceOverviewInnerStyleOptions,
|
|
128
|
-
): CSSProperties | undefined {
|
|
129
|
-
if (!desktopWorkspaceStore.overview) return undefined
|
|
130
|
-
|
|
131
|
-
const { width: stageWidth, height: stageHeight } = stageSize.value
|
|
132
|
-
if (stageWidth <= 0 || stageHeight <= 0) return undefined
|
|
133
|
-
|
|
134
|
-
const scale = scaleToFit(panelEl, options)
|
|
135
|
-
const transformOrigin = options?.transformOrigin ?? 'top left'
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
width: `${stageWidth}px`,
|
|
139
|
-
height: `${stageHeight}px`,
|
|
140
|
-
transform: `scale(${scale})`,
|
|
141
|
-
transformOrigin,
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return {
|
|
146
|
-
stageSize: readonly(stageSize),
|
|
147
|
-
scaleToFit,
|
|
148
|
-
innerOverviewStyle,
|
|
149
|
-
refreshStageSize: readStageSize,
|
|
150
|
-
}
|
|
151
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { InjectionKey } from 'vue'
|
|
2
|
-
import type { DesktopDialogProvider } from '../dialogs/desktopDialogProvider'
|
|
3
|
-
|
|
4
|
-
export type DesktopToggleWindowMaximizeFn = (
|
|
5
|
-
win: IWindowController | undefined,
|
|
6
|
-
) => boolean
|
|
7
|
-
|
|
8
|
-
export const DESKTOP_DIALOG_PROVIDER_KEY: InjectionKey<DesktopDialogProvider> =
|
|
9
|
-
Symbol('desktop-dialog-provider')
|
|
10
|
-
|
|
11
|
-
export const DESKTOP_TOGGLE_WINDOW_MAXIMIZE_KEY: InjectionKey<DesktopToggleWindowMaximizeFn> =
|
|
12
|
-
Symbol('desktop-toggle-window-maximize')
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/** Options for a yes/no confirmation (theme renders labels and chrome). */
|
|
2
|
-
export interface DesktopConfirmDialogOptions {
|
|
3
|
-
title?: string
|
|
4
|
-
message: string
|
|
5
|
-
danger?: boolean
|
|
6
|
-
acceptLabel?: string
|
|
7
|
-
rejectLabel?: string
|
|
8
|
-
/**
|
|
9
|
-
* Theme-specific payload (e.g. delete dialog passes `toTrash` for slot templates).
|
|
10
|
-
*/
|
|
11
|
-
extras?: Record<string, unknown>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Cross-theme dialog API. Themes implement with PrimeVue, native dialogs, etc.
|
|
16
|
-
* Callers pass user-facing strings (usually from i18n); implementations only render.
|
|
17
|
-
*/
|
|
18
|
-
export interface DesktopDialogProvider {
|
|
19
|
-
confirm(options: DesktopConfirmDialogOptions): Promise<boolean>
|
|
20
|
-
alert(message: string, options?: { title?: string }): Promise<void>
|
|
21
|
-
prompt(message: string, defaultValue?: string): Promise<string | null>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function browserGlobals(): {
|
|
25
|
-
confirm: (message?: string) => boolean
|
|
26
|
-
alert: (message?: string) => void
|
|
27
|
-
prompt: (message?: string, defaultText?: string) => string | null
|
|
28
|
-
} | null {
|
|
29
|
-
const g = globalThis as typeof globalThis & {
|
|
30
|
-
confirm?: (message?: string) => boolean
|
|
31
|
-
alert?: (message?: string) => void
|
|
32
|
-
prompt?: (message?: string, defaultText?: string) => string | null
|
|
33
|
-
}
|
|
34
|
-
if (typeof g.confirm !== 'function') return null
|
|
35
|
-
return {
|
|
36
|
-
confirm: g.confirm.bind(g),
|
|
37
|
-
alert:
|
|
38
|
-
typeof g.alert === 'function'
|
|
39
|
-
? g.alert.bind(g)
|
|
40
|
-
: (m?: string) => {
|
|
41
|
-
void m
|
|
42
|
-
},
|
|
43
|
-
prompt:
|
|
44
|
-
typeof g.prompt === 'function'
|
|
45
|
-
? g.prompt.bind(g)
|
|
46
|
-
: () => null,
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function createBrowserFallbackDialogProvider(): DesktopDialogProvider {
|
|
51
|
-
return {
|
|
52
|
-
async confirm(opts) {
|
|
53
|
-
if (import.meta.server) return false
|
|
54
|
-
const w = browserGlobals()
|
|
55
|
-
if (!w) return false
|
|
56
|
-
const text = [opts.title, opts.message].filter(Boolean).join('\n\n')
|
|
57
|
-
return w.confirm(text)
|
|
58
|
-
},
|
|
59
|
-
async alert(message, opts) {
|
|
60
|
-
if (import.meta.server) return
|
|
61
|
-
const w = browserGlobals()
|
|
62
|
-
if (!w) return
|
|
63
|
-
w.alert([opts?.title, message].filter(Boolean).join('\n\n'))
|
|
64
|
-
},
|
|
65
|
-
async prompt(message, defaultValue = '') {
|
|
66
|
-
if (import.meta.server) return null
|
|
67
|
-
const w = browserGlobals()
|
|
68
|
-
if (!w) return null
|
|
69
|
-
const v = w.prompt(message, defaultValue)
|
|
70
|
-
return v === null ? null : v
|
|
71
|
-
},
|
|
72
|
-
}
|
|
73
|
-
}
|