@owdproject/core 3.1.4 → 3.2.0
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 +6 -6
- package/bin/cli.js +395 -0
- package/bin/desktop.js +5 -0
- package/bin/lib/catalog.js +293 -0
- package/bin/lib/config.js +109 -0
- package/bin/lib/desktopConfig.js +56 -0
- package/bin/lib/generateTemplate.js +389 -0
- package/bin/lib/install.js +408 -0
- package/bin/lib/migrateModulePlayground.config.mjs +164 -0
- package/bin/lib/migrateModulePlayground.mjs +313 -0
- package/bin/lib/npmVersions.js +124 -0
- package/bin/lib/playgroundContext.js +188 -0
- package/bin/lib/scaffold.js +197 -0
- package/bin/lib/status.js +289 -0
- package/bin/lib/validateModule.js +683 -0
- package/bin/lib/workspace.js +182 -0
- package/bin/owd.js +2 -25
- package/bin/tui.js +1379 -0
- package/dist/module.d.mts +13 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +219 -0
- package/dist/types.d.mts +7 -0
- package/module.ts +38 -12
- package/package.json +78 -22
- package/runtime/components/Core/Application/CoreApplicationRender.vue +3 -1
- package/runtime/components/Core/Application/CoreApplicationWindowsRender.vue +28 -7
- package/runtime/components/Core/Window/CoreWindow.vue +42 -8
- package/runtime/components/Core/Window/CoreWindowNav.vue +26 -8
- package/runtime/composables/useApplicationManager.ts +18 -13
- package/runtime/composables/useDesktopManager.ts +31 -7
- package/runtime/composables/useOwdDialogs.ts +13 -0
- package/runtime/composables/useWorkspaceOverview.ts +41 -0
- package/runtime/core/controllers/ApplicationController.ts +114 -24
- package/runtime/core/controllers/WindowController.ts +4 -9
- package/runtime/dialogs/owdDialogProvider.ts +81 -0
- package/runtime/plugins/01.owd-dialogs-fallback.ts +15 -0
- package/runtime/stores/storeApplicationMeta.ts +56 -12
- package/runtime/stores/storeDesktop.ts +79 -2
- package/runtime/stores/storeDesktopDefaultApps.ts +2 -2
- package/runtime/stores/storeDesktopExplorer.ts +74 -0
- package/runtime/stores/storeDesktopWorkspace.ts +14 -2
- package/runtime/utils/captureElementToCanvas.ts +21 -0
- package/runtime/utils/explorerEntryPath.ts +10 -0
- package/runtime/utils/resolveDesktopConfigPath.ts +52 -0
- package/runtime/utils/validateOwdUserConfig.ts +44 -0
- package/types/index.d.ts +64 -12
- package/CHANGELOG.md +0 -25
- package/project.json +0 -4
- package/runtime/stores/storeApplication.ts +0 -236
- package/test/basic.test.ts +0 -15
- package/test/fixtures/basic/app.vue +0 -5
- package/test/fixtures/basic/nuxt.config.ts +0 -5
- package/test/fixtures/basic/package.json +0 -5
- package/tsconfig.app.json +0 -31
- package/tsconfig.json +0 -12
- package/tsconfig.spec.json +0 -37
- package/vitest.config.ts +0 -24
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
declare const _default: _nuxt_schema.NuxtModule<{
|
|
4
|
+
theme: string;
|
|
5
|
+
apps: never[];
|
|
6
|
+
modules: never[];
|
|
7
|
+
}, {
|
|
8
|
+
theme: string;
|
|
9
|
+
apps: never[];
|
|
10
|
+
modules: never[];
|
|
11
|
+
}, false>;
|
|
12
|
+
|
|
13
|
+
export { _default as default };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, installModule, addComponentsDir, addPlugin, addImportsDir } from '@nuxt/kit';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
function deepMerge(target, source) {
|
|
6
|
+
function isObject(value) {
|
|
7
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof RegExp);
|
|
8
|
+
}
|
|
9
|
+
if (isObject(target) && isObject(source)) {
|
|
10
|
+
const result = { ...target };
|
|
11
|
+
for (const key in source) {
|
|
12
|
+
const targetValue = target[key];
|
|
13
|
+
const sourceValue = source[key];
|
|
14
|
+
if (isObject(sourceValue) && isObject(targetValue)) {
|
|
15
|
+
result[key] = deepMerge(targetValue, sourceValue);
|
|
16
|
+
} else {
|
|
17
|
+
result[key] = sourceValue;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
return source;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function assertValidOwdUserConfig(config, configFile = "desktop.config.ts") {
|
|
26
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`[@owdproject/core] ${configFile} must default-export a non-array object from defineDesktopConfig({ ... }).`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
const c = config;
|
|
32
|
+
if (c.theme != null && typeof c.theme !== "string") {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`[@owdproject/core] ${configFile}: \`theme\` must be a string (npm package name of the theme module).`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
if (c.apps !== void 0) {
|
|
38
|
+
if (!Array.isArray(c.apps) || !c.apps.every((item) => typeof item === "string")) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`[@owdproject/core] ${configFile}: \`apps\` must be an array of strings (Nuxt module package names).`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (c.modules !== void 0) {
|
|
45
|
+
if (!Array.isArray(c.modules) || !c.modules.every((item) => typeof item === "string")) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`[@owdproject/core] ${configFile}: \`modules\` must be an array of strings (Nuxt module package names).`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const DESKTOP_CONFIG_FILENAME = "desktop.config.ts";
|
|
54
|
+
const LEGACY_DESKTOP_CONFIG_FILENAME = "owd.config.ts";
|
|
55
|
+
const LEGACY_CONFIG_DEPRECATION = "[@owdproject/core] owd.config.ts is deprecated and kept only for backward compatibility; rename to desktop.config.ts (required from @owdproject/core 3.2).";
|
|
56
|
+
function resolveDesktopConfigPath(rootDir) {
|
|
57
|
+
const desktopPath = join(rootDir, DESKTOP_CONFIG_FILENAME);
|
|
58
|
+
const legacyPath = join(rootDir, LEGACY_DESKTOP_CONFIG_FILENAME);
|
|
59
|
+
const hasDesktop = existsSync(desktopPath);
|
|
60
|
+
const hasLegacy = existsSync(legacyPath);
|
|
61
|
+
if (hasDesktop && hasLegacy) {
|
|
62
|
+
console.warn(
|
|
63
|
+
"[@owdproject/core] Both desktop.config.ts and owd.config.ts exist; using desktop.config.ts. Remove owd.config.ts."
|
|
64
|
+
);
|
|
65
|
+
return { path: desktopPath, file: DESKTOP_CONFIG_FILENAME, legacy: false };
|
|
66
|
+
}
|
|
67
|
+
if (hasDesktop) {
|
|
68
|
+
return { path: desktopPath, file: DESKTOP_CONFIG_FILENAME, legacy: false };
|
|
69
|
+
}
|
|
70
|
+
if (hasLegacy) {
|
|
71
|
+
return {
|
|
72
|
+
path: legacyPath,
|
|
73
|
+
file: LEGACY_DESKTOP_CONFIG_FILENAME,
|
|
74
|
+
legacy: true
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
function warnLegacyDesktopConfig(resolved) {
|
|
80
|
+
if (resolved?.legacy) {
|
|
81
|
+
console.warn(LEGACY_CONFIG_DEPRECATION);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const version = "3.2.0";
|
|
86
|
+
const pkg = {
|
|
87
|
+
version: version};
|
|
88
|
+
|
|
89
|
+
const module$1 = defineNuxtModule({
|
|
90
|
+
meta: {
|
|
91
|
+
name: "desktop",
|
|
92
|
+
configKey: "owd"
|
|
93
|
+
},
|
|
94
|
+
defaults: {
|
|
95
|
+
theme: "@owdproject/theme-nova",
|
|
96
|
+
apps: [],
|
|
97
|
+
modules: []
|
|
98
|
+
},
|
|
99
|
+
async setup(_options, _nuxt) {
|
|
100
|
+
const { resolve } = createResolver(import.meta.url);
|
|
101
|
+
_nuxt.options.experimental = {
|
|
102
|
+
..._nuxt.options.experimental,
|
|
103
|
+
viteEnvironmentApi: _nuxt.options.experimental?.viteEnvironmentApi ?? true
|
|
104
|
+
};
|
|
105
|
+
_nuxt.options.runtimeConfig.public.desktop = {};
|
|
106
|
+
let clientConfig;
|
|
107
|
+
const resolvedConfig = resolveDesktopConfigPath(_nuxt.options.rootDir);
|
|
108
|
+
if (!resolvedConfig) {
|
|
109
|
+
const hint = "Create desktop.config.ts next to your Nuxt root (e.g. desktop/desktop.config.ts), export default defineDesktopConfig({ theme, apps, modules }).";
|
|
110
|
+
throw new Error(`[@owdproject/core] Cannot find desktop.config.ts in ${_nuxt.options.rootDir}. ${hint}`);
|
|
111
|
+
}
|
|
112
|
+
warnLegacyDesktopConfig(resolvedConfig);
|
|
113
|
+
try {
|
|
114
|
+
clientConfig = (await import(resolvedConfig.path)).default;
|
|
115
|
+
} catch (e) {
|
|
116
|
+
const hint = "Export default defineDesktopConfig({ theme, apps, modules }) from desktop.config.ts.";
|
|
117
|
+
throw new Error(
|
|
118
|
+
`[@owdproject/core] Cannot load ${resolvedConfig.file}. ${hint}`,
|
|
119
|
+
{ cause: e }
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
assertValidOwdUserConfig(clientConfig, resolvedConfig.file);
|
|
123
|
+
if (!clientConfig.theme) {
|
|
124
|
+
clientConfig.theme = "@owdproject/theme-nova";
|
|
125
|
+
}
|
|
126
|
+
_nuxt.options = {
|
|
127
|
+
..._nuxt.options,
|
|
128
|
+
...clientConfig
|
|
129
|
+
};
|
|
130
|
+
_nuxt.options.runtimeConfig.public.desktop = {
|
|
131
|
+
coreVersion: pkg.version
|
|
132
|
+
};
|
|
133
|
+
_nuxt.options.runtimeConfig.public.desktop = deepMerge(
|
|
134
|
+
_nuxt.options.runtimeConfig.public.desktop,
|
|
135
|
+
clientConfig
|
|
136
|
+
);
|
|
137
|
+
{
|
|
138
|
+
if (clientConfig.theme) {
|
|
139
|
+
await installModule(clientConfig.theme);
|
|
140
|
+
}
|
|
141
|
+
if (clientConfig.modules && Array.isArray(clientConfig.modules)) {
|
|
142
|
+
for (const modulePath of clientConfig.modules) {
|
|
143
|
+
await installModule(modulePath);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (clientConfig.apps && Array.isArray(clientConfig.apps)) {
|
|
147
|
+
for (const appPath of clientConfig.apps) {
|
|
148
|
+
await installModule(appPath);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
_nuxt.options.appConfig.desktop = _nuxt.options.runtimeConfig.public.desktop;
|
|
153
|
+
{
|
|
154
|
+
_nuxt.options.primevue = _nuxt.options.primevue || {};
|
|
155
|
+
_nuxt.options.primevue.options = _nuxt.options.primevue.options || {};
|
|
156
|
+
_nuxt.options.primevue.options.theme = _nuxt.options.primevue.options.theme || {};
|
|
157
|
+
await installModule("@primevue/nuxt-module");
|
|
158
|
+
}
|
|
159
|
+
{
|
|
160
|
+
const tailwindPaths = _nuxt.options.runtimeConfig.app.owd?.tailwindPaths || [];
|
|
161
|
+
tailwindPaths.push("./runtime/components/**/*.{vue,mjs,ts}");
|
|
162
|
+
_nuxt.options.tailwindcss = _nuxt.options.tailwindcss || {};
|
|
163
|
+
_nuxt.options.tailwindcss.config = _nuxt.options.tailwindcss.config || {};
|
|
164
|
+
_nuxt.options.tailwindcss.config.content = tailwindPaths;
|
|
165
|
+
await installModule("@nuxtjs/tailwindcss", {
|
|
166
|
+
viewer: false
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
{
|
|
170
|
+
await installModule("@pinia/nuxt");
|
|
171
|
+
}
|
|
172
|
+
{
|
|
173
|
+
await installModule("@nuxt/fonts");
|
|
174
|
+
}
|
|
175
|
+
{
|
|
176
|
+
await installModule("@nuxt/icon", {
|
|
177
|
+
clientBundle: {
|
|
178
|
+
scan: true,
|
|
179
|
+
sizeLimitKb: 256
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
{
|
|
184
|
+
await installModule("@vueuse/nuxt");
|
|
185
|
+
}
|
|
186
|
+
{
|
|
187
|
+
await installModule("@nuxtjs/i18n");
|
|
188
|
+
}
|
|
189
|
+
{
|
|
190
|
+
_nuxt.hook("vite:extendConfig", (viteConfig) => {
|
|
191
|
+
viteConfig.css = viteConfig.css || {};
|
|
192
|
+
viteConfig.css.preprocessorOptions = viteConfig.css.preprocessorOptions || {};
|
|
193
|
+
viteConfig.css.preprocessorOptions.scss = {
|
|
194
|
+
api: "modern-compiler"
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
{
|
|
199
|
+
_nuxt.options.css.push("sanitize.css");
|
|
200
|
+
}
|
|
201
|
+
{
|
|
202
|
+
addComponentsDir({
|
|
203
|
+
path: resolve("./runtime/components"),
|
|
204
|
+
prefix: "",
|
|
205
|
+
global: true
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
{
|
|
209
|
+
addPlugin(resolve("./runtime/plugins/resize.client.ts"));
|
|
210
|
+
addPlugin(resolve("./runtime/plugins/01.owd-dialogs-fallback.ts"));
|
|
211
|
+
addImportsDir(resolve("./runtime/composables"));
|
|
212
|
+
addImportsDir(resolve("./runtime/core"));
|
|
213
|
+
addImportsDir(resolve("./runtime/stores"));
|
|
214
|
+
addImportsDir(resolve("./runtime/utils"));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
export { module$1 as default };
|
package/dist/types.d.mts
ADDED
package/module.ts
CHANGED
|
@@ -7,43 +7,68 @@ import {
|
|
|
7
7
|
addPlugin
|
|
8
8
|
} from '@nuxt/kit'
|
|
9
9
|
import { deepMerge } from './runtime/utils/utilCommon'
|
|
10
|
+
import { assertValidOwdUserConfig } from './runtime/utils/validateOwdUserConfig'
|
|
11
|
+
import {
|
|
12
|
+
resolveDesktopConfigPath,
|
|
13
|
+
warnLegacyDesktopConfig,
|
|
14
|
+
} from './runtime/utils/resolveDesktopConfigPath'
|
|
10
15
|
import pkg from './package.json'
|
|
11
16
|
|
|
12
17
|
export default defineNuxtModule({
|
|
13
18
|
meta: {
|
|
14
|
-
name: '
|
|
15
|
-
configKey: 'owd'
|
|
19
|
+
name: 'desktop',
|
|
20
|
+
configKey: 'owd',
|
|
16
21
|
},
|
|
17
22
|
defaults: {
|
|
18
|
-
theme: '@owdproject/theme-
|
|
23
|
+
theme: '@owdproject/theme-nova',
|
|
19
24
|
apps: [],
|
|
20
25
|
modules: [],
|
|
21
26
|
},
|
|
22
27
|
async setup(_options, _nuxt) {
|
|
23
28
|
const { resolve } = createResolver(import.meta.url)
|
|
24
29
|
|
|
30
|
+
// Required for Nuxt 4 dev (playgrounds, module graphs): avoids
|
|
31
|
+
// "Vite Node IPC socket path not configured" when using @nuxt/kit pipelines.
|
|
32
|
+
_nuxt.options.experimental = {
|
|
33
|
+
..._nuxt.options.experimental,
|
|
34
|
+
viteEnvironmentApi:
|
|
35
|
+
_nuxt.options.experimental?.viteEnvironmentApi ?? true,
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
_nuxt.options.runtimeConfig.public.desktop = {}
|
|
26
39
|
|
|
27
|
-
// get open web desktop config
|
|
40
|
+
// get open web desktop config (desktop.config.ts; owd.config.ts legacy)
|
|
28
41
|
|
|
29
42
|
let clientConfig
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
const resolvedConfig = resolveDesktopConfigPath(_nuxt.options.rootDir)
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
if (!resolvedConfig) {
|
|
47
|
+
const hint =
|
|
48
|
+
'Create desktop.config.ts next to your Nuxt root (e.g. desktop/desktop.config.ts), export default defineDesktopConfig({ theme, apps, modules }).'
|
|
49
|
+
throw new Error(`[@owdproject/core] Cannot find desktop.config.ts in ${_nuxt.options.rootDir}. ${hint}`)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
warnLegacyDesktopConfig(resolvedConfig)
|
|
36
53
|
|
|
54
|
+
try {
|
|
55
|
+
clientConfig = (await import(resolvedConfig.path)).default
|
|
37
56
|
} catch (e) {
|
|
38
|
-
|
|
39
|
-
|
|
57
|
+
const hint =
|
|
58
|
+
'Export default defineDesktopConfig({ theme, apps, modules }) from desktop.config.ts.'
|
|
59
|
+
throw new Error(
|
|
60
|
+
`[@owdproject/core] Cannot load ${resolvedConfig.file}. ${hint}`,
|
|
61
|
+
{ cause: e },
|
|
62
|
+
)
|
|
40
63
|
}
|
|
41
64
|
|
|
65
|
+
assertValidOwdUserConfig(clientConfig, resolvedConfig.file)
|
|
66
|
+
|
|
42
67
|
if (!clientConfig.theme) {
|
|
43
|
-
clientConfig.theme = '@owdproject/theme-
|
|
68
|
+
clientConfig.theme = '@owdproject/theme-nova'
|
|
44
69
|
}
|
|
45
70
|
|
|
46
|
-
// extend nuxt.config.ts with
|
|
71
|
+
// extend nuxt.config.ts with desktop.config.ts
|
|
47
72
|
|
|
48
73
|
_nuxt.options = {
|
|
49
74
|
..._nuxt.options,
|
|
@@ -186,6 +211,7 @@ export default defineNuxtModule({
|
|
|
186
211
|
|
|
187
212
|
{
|
|
188
213
|
addPlugin(resolve('./runtime/plugins/resize.client.ts'))
|
|
214
|
+
addPlugin(resolve('./runtime/plugins/01.owd-dialogs-fallback.ts'))
|
|
189
215
|
|
|
190
216
|
// add other files
|
|
191
217
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owdproject/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
|
+
"description": "Nuxt Desktop module for browser desktop experiences (windows, shell, apps)",
|
|
4
5
|
"keywords": [
|
|
5
|
-
"web",
|
|
6
|
-
"desktop",
|
|
7
|
-
"vue",
|
|
8
6
|
"nuxt",
|
|
7
|
+
"nuxt-module",
|
|
8
|
+
"nuxt-desktop",
|
|
9
|
+
"desktop",
|
|
9
10
|
"web-desktop",
|
|
10
|
-
"
|
|
11
|
+
"vue",
|
|
12
|
+
"owd",
|
|
13
|
+
"open-web-desktop"
|
|
11
14
|
],
|
|
12
15
|
"homepage": "https://github.com/owdproject/client#readme",
|
|
13
16
|
"bugs": {
|
|
@@ -24,30 +27,83 @@
|
|
|
24
27
|
},
|
|
25
28
|
"type": "module",
|
|
26
29
|
"types": "types/index.d.ts",
|
|
30
|
+
"files": [
|
|
31
|
+
"bin",
|
|
32
|
+
"dist",
|
|
33
|
+
"runtime",
|
|
34
|
+
"types",
|
|
35
|
+
"index.ts",
|
|
36
|
+
"module.ts",
|
|
37
|
+
"package.json",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"dev": "pnpm run dev:prepare",
|
|
42
|
+
"dev:prepare": "nuxt-module-build build --stub",
|
|
43
|
+
"build:module": "nuxt-module-build build",
|
|
44
|
+
"prepack": "nuxt-module-build build"
|
|
45
|
+
},
|
|
46
|
+
"exports": {
|
|
47
|
+
".": {
|
|
48
|
+
"types": "./types/index.d.ts",
|
|
49
|
+
"default": "./index.ts"
|
|
50
|
+
},
|
|
51
|
+
"./module": {
|
|
52
|
+
"types": "./dist/types.d.mts",
|
|
53
|
+
"development": "./module.ts",
|
|
54
|
+
"import": "./module.ts",
|
|
55
|
+
"default": "./module.ts"
|
|
56
|
+
},
|
|
57
|
+
"./nuxt": {
|
|
58
|
+
"types": "./dist/types.d.mts",
|
|
59
|
+
"development": "./module.ts",
|
|
60
|
+
"import": "./module.ts",
|
|
61
|
+
"default": "./module.ts"
|
|
62
|
+
},
|
|
63
|
+
"./package.json": "./package.json",
|
|
64
|
+
"./runtime/*": {
|
|
65
|
+
"types": "./runtime/*",
|
|
66
|
+
"development": "./runtime/*",
|
|
67
|
+
"import": "./runtime/*",
|
|
68
|
+
"default": "./runtime/*"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
27
71
|
"bin": {
|
|
72
|
+
"desktop": "bin/desktop.js",
|
|
28
73
|
"owd": "bin/owd.js"
|
|
29
74
|
},
|
|
30
75
|
"dependencies": {
|
|
31
|
-
"@nuxt/fonts": "^0.
|
|
32
|
-
"@nuxt/icon": "^
|
|
33
|
-
"@nuxt/kit": "^
|
|
34
|
-
"@nuxtjs/i18n": "^
|
|
76
|
+
"@nuxt/fonts": "^0.14.0",
|
|
77
|
+
"@nuxt/icon": "^2.2.1",
|
|
78
|
+
"@nuxt/kit": "^4.4.4",
|
|
79
|
+
"@nuxtjs/i18n": "^10.3.0",
|
|
35
80
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
|
36
|
-
"@pinia/nuxt": "^0.11.
|
|
37
|
-
"@primeuix/themes": "^
|
|
38
|
-
"@primevue/forms": "^4.
|
|
39
|
-
"@primevue/nuxt-module": "^4.
|
|
40
|
-
"@vueuse/components": "^
|
|
41
|
-
"@vueuse/core": "^
|
|
42
|
-
"@vueuse/nuxt": "^
|
|
81
|
+
"@pinia/nuxt": "^0.11.3",
|
|
82
|
+
"@primeuix/themes": "^2.0.3",
|
|
83
|
+
"@primevue/forms": "^4.5.5",
|
|
84
|
+
"@primevue/nuxt-module": "^4.5.5",
|
|
85
|
+
"@vueuse/components": "^14.3.0",
|
|
86
|
+
"@vueuse/core": "^14.3.0",
|
|
87
|
+
"@vueuse/nuxt": "^14.3.0",
|
|
43
88
|
"mitt": "^3.0.1",
|
|
44
|
-
"nanoid": "^5.1.
|
|
45
|
-
"nuxt": "^
|
|
46
|
-
"pinia": "^3.0.
|
|
89
|
+
"nanoid": "^5.1.11",
|
|
90
|
+
"nuxt": "^4.4.4",
|
|
91
|
+
"pinia": "^3.0.4",
|
|
47
92
|
"sanitize.css": "^13.0.0",
|
|
48
|
-
"sass": "^1.
|
|
49
|
-
"shellwords": "^1.
|
|
93
|
+
"sass": "^1.99.0",
|
|
94
|
+
"shellwords": "^1.1.1",
|
|
50
95
|
"vue-resizable": "^2.1.7",
|
|
51
|
-
"getopts": "^2.3.0"
|
|
96
|
+
"getopts": "^2.3.0",
|
|
97
|
+
"neo-blessed": "^0.2.0"
|
|
98
|
+
},
|
|
99
|
+
"optionalDependencies": {
|
|
100
|
+
"html2canvas": "^1.4.1"
|
|
101
|
+
},
|
|
102
|
+
"devDependencies": {
|
|
103
|
+
"@nuxt/devtools": "^3.2.4",
|
|
104
|
+
"@nuxt/module-builder": "^1.0.2",
|
|
105
|
+
"@nuxt/schema": "^4.4.4",
|
|
106
|
+
"typescript": "~5.8.3",
|
|
107
|
+
"vue-tsc": "^2.2.10"
|
|
52
108
|
}
|
|
53
109
|
}
|
|
@@ -6,13 +6,15 @@ defineProps<{
|
|
|
6
6
|
}>()
|
|
7
7
|
|
|
8
8
|
const applicationManager = useApplicationManager()
|
|
9
|
+
const runningApps = applicationManager.appsRunning
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
12
|
<template>
|
|
12
13
|
<CoreApplicationWindowsRender
|
|
13
|
-
v-for="app of
|
|
14
|
+
v-for="app of runningApps"
|
|
14
15
|
:key="app.id"
|
|
15
16
|
:workspace-filter="workspaceFilter"
|
|
16
17
|
:windows="app.windowsOpened"
|
|
18
|
+
:window-revision="app.openWindowCount.value"
|
|
17
19
|
/>
|
|
18
20
|
</template>
|
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useDesktopWorkspaceStore } from '../../../stores/storeDesktopWorkspace'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
3
6
|
workspaceFilter?: string
|
|
4
|
-
windows: Map<string,
|
|
7
|
+
windows: Map<string, IWindowController>
|
|
8
|
+
/** Tracks ApplicationController.openWindowCount so Vue re-renders when the map is replaced. */
|
|
9
|
+
windowRevision?: number
|
|
5
10
|
}>()
|
|
11
|
+
|
|
12
|
+
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
13
|
+
|
|
14
|
+
const windowEntries = computed(() => {
|
|
15
|
+
void props.windowRevision
|
|
16
|
+
return Array.from(props.windows.entries())
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
function matchesWorkspace(window: IWindowController): boolean {
|
|
20
|
+
const filter = props.workspaceFilter
|
|
21
|
+
if (!filter) return true
|
|
22
|
+
|
|
23
|
+
const ws = window.state.workspace
|
|
24
|
+
if (!ws) {
|
|
25
|
+
return filter === desktopWorkspaceStore.active
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return ws === filter
|
|
29
|
+
}
|
|
6
30
|
</script>
|
|
7
31
|
|
|
8
32
|
<template>
|
|
9
|
-
<template v-for="[windowId, window] in
|
|
33
|
+
<template v-for="[windowId, window] in windowEntries" :key="windowId">
|
|
10
34
|
<component
|
|
11
|
-
v-if="
|
|
12
|
-
!workspaceFilter ||
|
|
13
|
-
(workspaceFilter && window.state.workspace === workspaceFilter)
|
|
14
|
-
"
|
|
35
|
+
v-if="matchesWorkspace(window)"
|
|
15
36
|
:window="window"
|
|
16
37
|
:is="window.config.component"
|
|
17
38
|
/>
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
import { ref, provide } from 'vue'
|
|
3
3
|
import { computed } from '@vue/reactivity'
|
|
4
4
|
import { useAppConfig } from 'nuxt/app'
|
|
5
|
-
import { useDesktopManager } from '@owdproject/core/runtime/composables/useDesktopManager'
|
|
6
5
|
import { handleWindowControllerProps } from '@owdproject/core/runtime/utils/utilWindow'
|
|
6
|
+
import { useDesktopWorkspaceStore } from '../../../stores/storeDesktopWorkspace'
|
|
7
7
|
|
|
8
8
|
const props = defineProps<{
|
|
9
9
|
window?: IWindowController
|
|
10
10
|
content?: WindowContent
|
|
11
11
|
}>()
|
|
12
12
|
|
|
13
|
+
const desktopWorkspaceStore = useDesktopWorkspaceStore()
|
|
14
|
+
|
|
13
15
|
const emit = defineEmits([
|
|
14
16
|
'resize:start',
|
|
15
17
|
'resize:move',
|
|
@@ -29,7 +31,6 @@ const emit = defineEmits([
|
|
|
29
31
|
])
|
|
30
32
|
|
|
31
33
|
const appConfig = useAppConfig()
|
|
32
|
-
const desktopManager = useDesktopManager() // used in <style v-bind>
|
|
33
34
|
const windowController: IWindowController = handleWindowControllerProps(
|
|
34
35
|
props.window,
|
|
35
36
|
)
|
|
@@ -117,6 +118,36 @@ const classes = computed(() => {
|
|
|
117
118
|
|
|
118
119
|
return list
|
|
119
120
|
})
|
|
121
|
+
|
|
122
|
+
/** While workspace overview is open, disable vue-resizable chrome drag and use native HTML5 drag to move windows between desktops. */
|
|
123
|
+
const workspaceChromeDragSelector = computed(() => {
|
|
124
|
+
if (desktopWorkspaceStore.overview) {
|
|
125
|
+
return '.owd-window-overview-drag-none'
|
|
126
|
+
}
|
|
127
|
+
return windowController?.isDraggable
|
|
128
|
+
? '.owd-window-nav__draggable'
|
|
129
|
+
: '.owd-window-nav__draggable-none'
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
function onOverviewNativeDragStart(e: DragEvent) {
|
|
133
|
+
if (!desktopWorkspaceStore.overview || !windowController) return
|
|
134
|
+
e.stopPropagation()
|
|
135
|
+
e.dataTransfer?.setData('text/plain', windowController.state.id)
|
|
136
|
+
e.dataTransfer!.effectAllowed = 'move'
|
|
137
|
+
try {
|
|
138
|
+
const img = new Image()
|
|
139
|
+
img.src =
|
|
140
|
+
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
|
|
141
|
+
e.dataTransfer?.setDragImage(img, 0, 0)
|
|
142
|
+
} catch {
|
|
143
|
+
/* noop */
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** `fit-parent` clamps drag/resize to the parent box — wrong for viewport-fixed shells (Win11, GNOME). */
|
|
148
|
+
const shouldFitParent = computed(
|
|
149
|
+
() => appConfig.desktop.windows.position !== 'fixed',
|
|
150
|
+
)
|
|
120
151
|
</script>
|
|
121
152
|
|
|
122
153
|
<template>
|
|
@@ -132,7 +163,7 @@ const classes = computed(() => {
|
|
|
132
163
|
:left="windowController?.position?.x"
|
|
133
164
|
:top="windowController?.position?.y"
|
|
134
165
|
:active="windowController?.isResizable ? undefined : []"
|
|
135
|
-
fit-parent
|
|
166
|
+
:fit-parent="shouldFitParent"
|
|
136
167
|
@drag:start="onWindowDragStart"
|
|
137
168
|
@drag:move="onWindowDragMove"
|
|
138
169
|
@drag:end="onWindowDragEnd"
|
|
@@ -140,18 +171,21 @@ const classes = computed(() => {
|
|
|
140
171
|
@resize:move="onWindowResizeMove"
|
|
141
172
|
@resize:end="onWindowResizeEnd"
|
|
142
173
|
:style="{ zIndex: windowController?.position?.z }"
|
|
143
|
-
:drag-selector="
|
|
144
|
-
|
|
145
|
-
? '.owd-window-nav__draggable'
|
|
146
|
-
: '.owd-window-nav__draggable-none'
|
|
147
|
-
"
|
|
174
|
+
:drag-selector="workspaceChromeDragSelector"
|
|
175
|
+
:draggable="desktopWorkspaceStore.overview"
|
|
148
176
|
@pointerdown="onWindowPointerDown"
|
|
177
|
+
@dragstart="onOverviewNativeDragStart"
|
|
149
178
|
>
|
|
150
179
|
<slot />
|
|
151
180
|
</vue-resizable>
|
|
152
181
|
</template>
|
|
153
182
|
|
|
154
183
|
<style scoped lang="scss">
|
|
184
|
+
/* vue-resizable sets `.resizable-component { position: relative }` — override so desktop geometry stays consistent */
|
|
185
|
+
.owd-window.resizable-component {
|
|
186
|
+
position: v-bind('appConfig.desktop.windows.position') !important;
|
|
187
|
+
}
|
|
188
|
+
|
|
155
189
|
.owd-window {
|
|
156
190
|
position: v-bind('appConfig.desktop.windows.position');
|
|
157
191
|
|
|
@@ -14,10 +14,7 @@ const classes = computed(() => {
|
|
|
14
14
|
list.push('owd-window-nav--active')
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (
|
|
18
|
-
typeof windowController?.state.focused === 'undefined' ||
|
|
19
|
-
!!windowController?.state.focused
|
|
20
|
-
) {
|
|
17
|
+
if (windowController?.state.focused) {
|
|
21
18
|
list.push('owd-window-nav--focused')
|
|
22
19
|
}
|
|
23
20
|
|
|
@@ -34,15 +31,36 @@ const classes = computed(() => {
|
|
|
34
31
|
</template>
|
|
35
32
|
|
|
36
33
|
<style lang="scss">
|
|
34
|
+
/**
|
|
35
|
+
* Title/icon sit above the drag layer in DOM order; use pointer-events so
|
|
36
|
+
* mousedown reaches `.owd-window-nav__draggable` for vue-resizable. Window
|
|
37
|
+
* controls stay clickable.
|
|
38
|
+
*/
|
|
37
39
|
.owd-window-nav {
|
|
38
40
|
position: relative;
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: stretch;
|
|
43
|
+
width: 100%;
|
|
44
|
+
min-height: 0;
|
|
39
45
|
|
|
40
46
|
&__draggable {
|
|
41
47
|
position: absolute;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
inset: 0;
|
|
49
|
+
z-index: 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
> :not(.owd-window-nav__draggable) {
|
|
53
|
+
position: relative;
|
|
54
|
+
z-index: 2;
|
|
55
|
+
pointer-events: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
> .owd-window-nav__btn-group {
|
|
59
|
+
pointer-events: auto;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
> .owd-window-nav__interactive {
|
|
63
|
+
pointer-events: auto;
|
|
46
64
|
}
|
|
47
65
|
}
|
|
48
66
|
</style>
|