@lobehub/lobehub 2.0.0-next.179 → 2.0.0-next.180
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.
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
name: Desktop Manual Build
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
channel:
|
|
7
|
+
description: 'Release channel for desktop build (affects version suffix and workflow:set-desktop-version)'
|
|
8
|
+
required: true
|
|
9
|
+
default: nightly
|
|
10
|
+
type: choice
|
|
11
|
+
options:
|
|
12
|
+
- nightly
|
|
13
|
+
- beta
|
|
14
|
+
- stable
|
|
15
|
+
build_macos:
|
|
16
|
+
description: 'Build macOS artifacts'
|
|
17
|
+
required: true
|
|
18
|
+
default: true
|
|
19
|
+
type: boolean
|
|
20
|
+
build_windows:
|
|
21
|
+
description: 'Build Windows artifacts'
|
|
22
|
+
required: true
|
|
23
|
+
default: true
|
|
24
|
+
type: boolean
|
|
25
|
+
build_linux:
|
|
26
|
+
description: 'Build Linux artifacts'
|
|
27
|
+
required: true
|
|
28
|
+
default: true
|
|
29
|
+
type: boolean
|
|
30
|
+
version:
|
|
31
|
+
description: 'Override desktop version (e.g. 1.2.3). Leave empty to auto-generate.'
|
|
32
|
+
required: false
|
|
33
|
+
default: ''
|
|
34
|
+
|
|
35
|
+
concurrency:
|
|
36
|
+
group: manual-${{ github.ref }}-${{ github.workflow }}
|
|
37
|
+
cancel-in-progress: true
|
|
38
|
+
|
|
39
|
+
permissions:
|
|
40
|
+
contents: read
|
|
41
|
+
|
|
42
|
+
env:
|
|
43
|
+
NODE_VERSION: 24.11.1
|
|
44
|
+
BUN_VERSION: 1.2.23
|
|
45
|
+
|
|
46
|
+
jobs:
|
|
47
|
+
test:
|
|
48
|
+
name: Code quality check
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
steps:
|
|
51
|
+
- name: Checkout base
|
|
52
|
+
uses: actions/checkout@v5
|
|
53
|
+
with:
|
|
54
|
+
fetch-depth: 0
|
|
55
|
+
|
|
56
|
+
- name: Setup Node & Bun
|
|
57
|
+
uses: ./.github/actions/setup-node-bun
|
|
58
|
+
with:
|
|
59
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
60
|
+
bun-version: ${{ env.BUN_VERSION }}
|
|
61
|
+
package-manager-cache: 'false'
|
|
62
|
+
|
|
63
|
+
- name: Install deps
|
|
64
|
+
run: bun i
|
|
65
|
+
env:
|
|
66
|
+
NODE_OPTIONS: --max-old-space-size=6144
|
|
67
|
+
|
|
68
|
+
- name: Lint
|
|
69
|
+
run: bun run lint
|
|
70
|
+
env:
|
|
71
|
+
NODE_OPTIONS: --max-old-space-size=6144
|
|
72
|
+
|
|
73
|
+
version:
|
|
74
|
+
name: Determine version
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
outputs:
|
|
77
|
+
version: ${{ steps.set_version.outputs.version }}
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v5
|
|
80
|
+
with:
|
|
81
|
+
fetch-depth: 0
|
|
82
|
+
|
|
83
|
+
- name: Setup Node.js
|
|
84
|
+
uses: actions/setup-node@v6
|
|
85
|
+
with:
|
|
86
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
87
|
+
package-manager-cache: false
|
|
88
|
+
|
|
89
|
+
- name: Set version
|
|
90
|
+
id: set_version
|
|
91
|
+
env:
|
|
92
|
+
INPUT_VERSION: ${{ inputs.version }}
|
|
93
|
+
CHANNEL: ${{ inputs.channel }}
|
|
94
|
+
run: |
|
|
95
|
+
base_version=$(node -p "require('./apps/desktop/package.json').version")
|
|
96
|
+
|
|
97
|
+
if [ -n "$INPUT_VERSION" ]; then
|
|
98
|
+
version="$INPUT_VERSION"
|
|
99
|
+
echo "📦 Using provided version: ${version} (base: ${base_version})"
|
|
100
|
+
else
|
|
101
|
+
ci_build_number="${{ github.run_number }}"
|
|
102
|
+
version="0.0.0-${CHANNEL}.manual.${ci_build_number}"
|
|
103
|
+
echo "📦 Generated version: ${version} (base: ${base_version})"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
echo "version=${version}" >> $GITHUB_OUTPUT
|
|
107
|
+
|
|
108
|
+
- name: Version Summary
|
|
109
|
+
run: |
|
|
110
|
+
echo "🚦 Release Version: ${{ steps.set_version.outputs.version }}"
|
|
111
|
+
|
|
112
|
+
build-macos:
|
|
113
|
+
needs: [version, test]
|
|
114
|
+
name: Build Desktop App (macOS)
|
|
115
|
+
if: inputs.build_macos
|
|
116
|
+
runs-on: ${{ matrix.os }}
|
|
117
|
+
strategy:
|
|
118
|
+
matrix:
|
|
119
|
+
os: [macos-latest, macos-15-intel]
|
|
120
|
+
steps:
|
|
121
|
+
- uses: actions/checkout@v5
|
|
122
|
+
with:
|
|
123
|
+
fetch-depth: 0
|
|
124
|
+
|
|
125
|
+
- name: Setup Node & pnpm
|
|
126
|
+
uses: ./.github/actions/setup-node-pnpm
|
|
127
|
+
with:
|
|
128
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
129
|
+
package-manager-cache: 'false'
|
|
130
|
+
|
|
131
|
+
# node-linker=hoisted 模式将可以确保 asar 压缩可用
|
|
132
|
+
- name: Install dependencies
|
|
133
|
+
run: pnpm install --node-linker=hoisted
|
|
134
|
+
|
|
135
|
+
- name: Install deps on Desktop
|
|
136
|
+
run: npm run install-isolated --prefix=./apps/desktop
|
|
137
|
+
|
|
138
|
+
- name: Set package version
|
|
139
|
+
run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
|
|
140
|
+
|
|
141
|
+
- name: Build artifact on macOS
|
|
142
|
+
run: npm run desktop:build
|
|
143
|
+
env:
|
|
144
|
+
UPDATE_CHANNEL: ${{ inputs.channel }}
|
|
145
|
+
APP_URL: http://localhost:3015
|
|
146
|
+
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
|
|
147
|
+
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
|
|
148
|
+
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
|
|
149
|
+
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
150
|
+
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
|
|
151
|
+
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
|
|
152
|
+
CSC_FOR_PULL_REQUEST: true
|
|
153
|
+
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
154
|
+
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
|
155
|
+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
156
|
+
|
|
157
|
+
- name: Rename macOS latest-mac.yml for multi-architecture support
|
|
158
|
+
if: runner.os == 'macOS'
|
|
159
|
+
run: |
|
|
160
|
+
cd apps/desktop/release
|
|
161
|
+
if [ -f "latest-mac.yml" ]; then
|
|
162
|
+
SYSTEM_ARCH=$(uname -m)
|
|
163
|
+
if [[ "$SYSTEM_ARCH" == "arm64" ]]; then
|
|
164
|
+
ARCH_SUFFIX="arm64"
|
|
165
|
+
else
|
|
166
|
+
ARCH_SUFFIX="x64"
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
mv latest-mac.yml "latest-mac-${ARCH_SUFFIX}.yml"
|
|
170
|
+
echo "✅ Renamed latest-mac.yml to latest-mac-${ARCH_SUFFIX}.yml (detected: $SYSTEM_ARCH)"
|
|
171
|
+
ls -la latest-mac-*.yml
|
|
172
|
+
else
|
|
173
|
+
echo "⚠️ latest-mac.yml not found, skipping rename"
|
|
174
|
+
ls -la latest*.yml || echo "No latest*.yml files found"
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
- name: Upload artifact
|
|
178
|
+
uses: actions/upload-artifact@v5
|
|
179
|
+
with:
|
|
180
|
+
name: release-${{ matrix.os }}
|
|
181
|
+
path: |
|
|
182
|
+
apps/desktop/release/latest*
|
|
183
|
+
apps/desktop/release/*.dmg*
|
|
184
|
+
apps/desktop/release/*.zip*
|
|
185
|
+
apps/desktop/release/*.exe*
|
|
186
|
+
apps/desktop/release/*.AppImage
|
|
187
|
+
apps/desktop/release/*.deb*
|
|
188
|
+
apps/desktop/release/*.snap*
|
|
189
|
+
apps/desktop/release/*.rpm*
|
|
190
|
+
apps/desktop/release/*.tar.gz*
|
|
191
|
+
retention-days: 5
|
|
192
|
+
|
|
193
|
+
build-windows:
|
|
194
|
+
needs: [version, test]
|
|
195
|
+
name: Build Desktop App (Windows)
|
|
196
|
+
if: inputs.build_windows
|
|
197
|
+
runs-on: windows-2025
|
|
198
|
+
steps:
|
|
199
|
+
- uses: actions/checkout@v5
|
|
200
|
+
with:
|
|
201
|
+
fetch-depth: 0
|
|
202
|
+
|
|
203
|
+
- name: Setup Node & pnpm
|
|
204
|
+
uses: ./.github/actions/setup-node-pnpm
|
|
205
|
+
with:
|
|
206
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
207
|
+
package-manager-cache: 'false'
|
|
208
|
+
|
|
209
|
+
- name: Install dependencies
|
|
210
|
+
run: pnpm install --node-linker=hoisted
|
|
211
|
+
|
|
212
|
+
- name: Install deps on Desktop
|
|
213
|
+
run: npm run install-isolated --prefix=./apps/desktop
|
|
214
|
+
|
|
215
|
+
- name: Set package version
|
|
216
|
+
run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
|
|
217
|
+
|
|
218
|
+
- name: Build artifact on Windows
|
|
219
|
+
run: npm run desktop:build
|
|
220
|
+
env:
|
|
221
|
+
UPDATE_CHANNEL: ${{ inputs.channel }}
|
|
222
|
+
APP_URL: http://localhost:3015
|
|
223
|
+
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
|
|
224
|
+
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
|
|
225
|
+
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
|
|
226
|
+
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
|
|
227
|
+
TEMP: C:\temp
|
|
228
|
+
TMP: C:\temp
|
|
229
|
+
|
|
230
|
+
- name: Upload artifact
|
|
231
|
+
uses: actions/upload-artifact@v5
|
|
232
|
+
with:
|
|
233
|
+
name: release-windows-2025
|
|
234
|
+
path: |
|
|
235
|
+
apps/desktop/release/latest*
|
|
236
|
+
apps/desktop/release/*.dmg*
|
|
237
|
+
apps/desktop/release/*.zip*
|
|
238
|
+
apps/desktop/release/*.exe*
|
|
239
|
+
apps/desktop/release/*.AppImage
|
|
240
|
+
apps/desktop/release/*.deb*
|
|
241
|
+
apps/desktop/release/*.snap*
|
|
242
|
+
apps/desktop/release/*.rpm*
|
|
243
|
+
apps/desktop/release/*.tar.gz*
|
|
244
|
+
retention-days: 5
|
|
245
|
+
|
|
246
|
+
build-linux:
|
|
247
|
+
needs: [version, test]
|
|
248
|
+
name: Build Desktop App (Linux)
|
|
249
|
+
if: inputs.build_linux
|
|
250
|
+
runs-on: ubuntu-latest
|
|
251
|
+
steps:
|
|
252
|
+
- uses: actions/checkout@v5
|
|
253
|
+
with:
|
|
254
|
+
fetch-depth: 0
|
|
255
|
+
|
|
256
|
+
- name: Setup Node & pnpm
|
|
257
|
+
uses: ./.github/actions/setup-node-pnpm
|
|
258
|
+
with:
|
|
259
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
260
|
+
package-manager-cache: 'false'
|
|
261
|
+
|
|
262
|
+
- name: Install dependencies
|
|
263
|
+
run: pnpm install --node-linker=hoisted
|
|
264
|
+
|
|
265
|
+
- name: Install deps on Desktop
|
|
266
|
+
run: npm run install-isolated --prefix=./apps/desktop
|
|
267
|
+
|
|
268
|
+
- name: Set package version
|
|
269
|
+
run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
|
|
270
|
+
|
|
271
|
+
- name: Build artifact on Linux
|
|
272
|
+
run: npm run desktop:build
|
|
273
|
+
env:
|
|
274
|
+
UPDATE_CHANNEL: ${{ inputs.channel }}
|
|
275
|
+
APP_URL: http://localhost:3015
|
|
276
|
+
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
|
|
277
|
+
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
|
|
278
|
+
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
|
|
279
|
+
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
|
|
280
|
+
|
|
281
|
+
- name: Upload artifact
|
|
282
|
+
uses: actions/upload-artifact@v5
|
|
283
|
+
with:
|
|
284
|
+
name: release-ubuntu-latest
|
|
285
|
+
path: |
|
|
286
|
+
apps/desktop/release/latest*
|
|
287
|
+
apps/desktop/release/*.dmg*
|
|
288
|
+
apps/desktop/release/*.zip*
|
|
289
|
+
apps/desktop/release/*.exe*
|
|
290
|
+
apps/desktop/release/*.AppImage
|
|
291
|
+
apps/desktop/release/*.deb*
|
|
292
|
+
apps/desktop/release/*.snap*
|
|
293
|
+
apps/desktop/release/*.rpm*
|
|
294
|
+
apps/desktop/release/*.tar.gz*
|
|
295
|
+
retention-days: 5
|
|
296
|
+
|
|
297
|
+
merge-mac-files:
|
|
298
|
+
needs: [build-macos, version]
|
|
299
|
+
name: Merge macOS Release Files
|
|
300
|
+
runs-on: ubuntu-latest
|
|
301
|
+
permissions:
|
|
302
|
+
contents: read
|
|
303
|
+
if: inputs.build_macos
|
|
304
|
+
steps:
|
|
305
|
+
- name: Checkout repository
|
|
306
|
+
uses: actions/checkout@v5
|
|
307
|
+
|
|
308
|
+
- name: Setup Node & Bun
|
|
309
|
+
uses: ./.github/actions/setup-node-bun
|
|
310
|
+
with:
|
|
311
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
312
|
+
bun-version: ${{ env.BUN_VERSION }}
|
|
313
|
+
package-manager-cache: 'false'
|
|
314
|
+
|
|
315
|
+
- name: Download artifacts
|
|
316
|
+
uses: actions/download-artifact@v6
|
|
317
|
+
with:
|
|
318
|
+
path: release
|
|
319
|
+
pattern: release-*
|
|
320
|
+
merge-multiple: true
|
|
321
|
+
|
|
322
|
+
- name: List downloaded artifacts
|
|
323
|
+
run: ls -R release
|
|
324
|
+
|
|
325
|
+
- name: Install yaml only for merge step
|
|
326
|
+
run: |
|
|
327
|
+
cd scripts/electronWorkflow
|
|
328
|
+
if [ ! -f package.json ]; then
|
|
329
|
+
echo '{"name":"merge-mac-release","private":true}' > package.json
|
|
330
|
+
fi
|
|
331
|
+
bun add --no-save yaml@2.8.1
|
|
332
|
+
|
|
333
|
+
- name: Merge latest-mac.yml files
|
|
334
|
+
run: bun run scripts/electronWorkflow/mergeMacReleaseFiles.js
|
|
335
|
+
|
|
336
|
+
- name: Upload artifacts with merged macOS files
|
|
337
|
+
uses: actions/upload-artifact@v5
|
|
338
|
+
with:
|
|
339
|
+
name: merged-release-manual
|
|
340
|
+
path: release/
|
|
341
|
+
retention-days: 1
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.180](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.179...v2.0.0-next.180)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-12-26**</sup>
|
|
8
|
+
|
|
9
|
+
<br/>
|
|
10
|
+
|
|
11
|
+
<details>
|
|
12
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
13
|
+
|
|
14
|
+
</details>
|
|
15
|
+
|
|
16
|
+
<div align="right">
|
|
17
|
+
|
|
18
|
+
[](#readme-top)
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
5
22
|
## [Version 2.0.0-next.179](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.178...v2.0.0-next.179)
|
|
6
23
|
|
|
7
24
|
<sup>Released on **2025-12-25**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.180",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -17,16 +17,6 @@
|
|
|
17
17
|
"@lobechat/const": "workspace:*",
|
|
18
18
|
"@lobechat/types": "workspace:*",
|
|
19
19
|
"@lobechat/utils": "workspace:*",
|
|
20
|
-
"@lobehub/charts": "^2.1.2",
|
|
21
|
-
"@lobehub/chat-plugin-sdk": "^1.32.4",
|
|
22
|
-
"@neondatabase/serverless": "^1.0.2",
|
|
23
|
-
"@trpc/server": "^11.7.1",
|
|
24
|
-
"debug": "^4.4.3",
|
|
25
|
-
"drizzle-zod": "^0.5.1",
|
|
26
|
-
"lodash-es": "^4.17.21",
|
|
27
|
-
"model-bank": "workspace:*",
|
|
28
|
-
"next-auth": "5.0.0-beta.30",
|
|
29
|
-
"p-map": "^7.0.4",
|
|
30
20
|
"random-words": "^2.0.1",
|
|
31
21
|
"ts-md5": "^2.0.1",
|
|
32
22
|
"type-fest": "^5.2.0",
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { isCommandPressed } from './keyboard';
|
|
4
|
+
import * as platform from './platform';
|
|
5
|
+
|
|
6
|
+
describe('keyboard', () => {
|
|
7
|
+
describe('isCommandPressed', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
vi.restoreAllMocks();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should return true when metaKey is pressed on macOS', () => {
|
|
13
|
+
vi.spyOn(platform, 'isMacOS').mockReturnValue(true);
|
|
14
|
+
|
|
15
|
+
const event = {
|
|
16
|
+
metaKey: true,
|
|
17
|
+
ctrlKey: false,
|
|
18
|
+
} as KeyboardEvent;
|
|
19
|
+
|
|
20
|
+
expect(isCommandPressed(event)).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should return false when metaKey is not pressed on macOS', () => {
|
|
24
|
+
vi.spyOn(platform, 'isMacOS').mockReturnValue(true);
|
|
25
|
+
|
|
26
|
+
const event = {
|
|
27
|
+
metaKey: false,
|
|
28
|
+
ctrlKey: false,
|
|
29
|
+
} as KeyboardEvent;
|
|
30
|
+
|
|
31
|
+
expect(isCommandPressed(event)).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should return true when ctrlKey is pressed on Windows/Linux', () => {
|
|
35
|
+
vi.spyOn(platform, 'isMacOS').mockReturnValue(false);
|
|
36
|
+
|
|
37
|
+
const event = {
|
|
38
|
+
metaKey: false,
|
|
39
|
+
ctrlKey: true,
|
|
40
|
+
} as KeyboardEvent;
|
|
41
|
+
|
|
42
|
+
expect(isCommandPressed(event)).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should return false when ctrlKey is not pressed on Windows/Linux', () => {
|
|
46
|
+
vi.spyOn(platform, 'isMacOS').mockReturnValue(false);
|
|
47
|
+
|
|
48
|
+
const event = {
|
|
49
|
+
metaKey: false,
|
|
50
|
+
ctrlKey: false,
|
|
51
|
+
} as KeyboardEvent;
|
|
52
|
+
|
|
53
|
+
expect(isCommandPressed(event)).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should ignore ctrlKey on macOS and only check metaKey', () => {
|
|
57
|
+
vi.spyOn(platform, 'isMacOS').mockReturnValue(true);
|
|
58
|
+
|
|
59
|
+
const event = {
|
|
60
|
+
metaKey: false,
|
|
61
|
+
ctrlKey: true, // ctrlKey should be ignored on macOS
|
|
62
|
+
} as KeyboardEvent;
|
|
63
|
+
|
|
64
|
+
expect(isCommandPressed(event)).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should ignore metaKey on Windows/Linux and only check ctrlKey', () => {
|
|
68
|
+
vi.spyOn(platform, 'isMacOS').mockReturnValue(false);
|
|
69
|
+
|
|
70
|
+
const event = {
|
|
71
|
+
metaKey: true, // metaKey should be ignored on Windows/Linux
|
|
72
|
+
ctrlKey: false,
|
|
73
|
+
} as KeyboardEvent;
|
|
74
|
+
|
|
75
|
+
expect(isCommandPressed(event)).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should handle both keys pressed on macOS correctly', () => {
|
|
79
|
+
vi.spyOn(platform, 'isMacOS').mockReturnValue(true);
|
|
80
|
+
|
|
81
|
+
const event = {
|
|
82
|
+
metaKey: true,
|
|
83
|
+
ctrlKey: true, // both pressed, but only metaKey matters on macOS
|
|
84
|
+
} as KeyboardEvent;
|
|
85
|
+
|
|
86
|
+
expect(isCommandPressed(event)).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should handle both keys pressed on Windows/Linux correctly', () => {
|
|
90
|
+
vi.spyOn(platform, 'isMacOS').mockReturnValue(false);
|
|
91
|
+
|
|
92
|
+
const event = {
|
|
93
|
+
metaKey: true, // both pressed, but only ctrlKey matters on Windows/Linux
|
|
94
|
+
ctrlKey: true,
|
|
95
|
+
} as KeyboardEvent;
|
|
96
|
+
|
|
97
|
+
expect(isCommandPressed(event)).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|