@opensumi/ide-electron-basic 2.21.8-rc-1670567192.0 → 2.21.8
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/package.json +10 -11
- package/src/browser/clipboard/index.ts +0 -62
- package/src/browser/dialog/index.ts +0 -17
- package/src/browser/header/header.module.less +0 -61
- package/src/browser/header/header.service.ts +0 -145
- package/src/browser/header/header.view.tsx +0 -263
- package/src/browser/index.ts +0 -391
- package/src/browser/welcome/common.ts +0 -4
- package/src/browser/welcome/contribution.ts +0 -64
- package/src/browser/welcome/welcome.module.less +0 -13
- package/src/browser/welcome/welcome.tsx +0 -57
- package/src/common/header.ts +0 -40
package/package.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensumi/ide-electron-basic",
|
|
3
|
-
"version": "2.21.8
|
|
3
|
+
"version": "2.21.8",
|
|
4
4
|
"files": [
|
|
5
|
-
"lib"
|
|
6
|
-
"src"
|
|
5
|
+
"lib"
|
|
7
6
|
],
|
|
8
7
|
"license": "MIT",
|
|
9
8
|
"main": "lib/index.js",
|
|
@@ -17,16 +16,16 @@
|
|
|
17
16
|
"url": "git@github.com:opensumi/core.git"
|
|
18
17
|
},
|
|
19
18
|
"dependencies": {
|
|
20
|
-
"@opensumi/ide-core-common": "2.21.8
|
|
21
|
-
"@opensumi/ide-core-node": "2.21.8
|
|
22
|
-
"@opensumi/ide-utils": "2.21.8
|
|
19
|
+
"@opensumi/ide-core-common": "2.21.8",
|
|
20
|
+
"@opensumi/ide-core-node": "2.21.8",
|
|
21
|
+
"@opensumi/ide-utils": "2.21.8"
|
|
23
22
|
},
|
|
24
23
|
"devDependencies": {
|
|
25
|
-
"@opensumi/ide-core-browser": "2.21.8
|
|
24
|
+
"@opensumi/ide-core-browser": "2.21.8",
|
|
26
25
|
"@opensumi/ide-dev-tool": "^1.3.1",
|
|
27
|
-
"@opensumi/ide-editor": "2.21.8
|
|
28
|
-
"@opensumi/ide-overlay": "2.21.8
|
|
29
|
-
"@opensumi/ide-workspace": "2.21.8
|
|
26
|
+
"@opensumi/ide-editor": "2.21.8",
|
|
27
|
+
"@opensumi/ide-overlay": "2.21.8",
|
|
28
|
+
"@opensumi/ide-workspace": "2.21.8"
|
|
30
29
|
},
|
|
31
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "603eaa81756ee0e8a58871fb67cfb01c8499593a"
|
|
32
31
|
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Injectable, Autowired } from '@opensumi/di';
|
|
2
|
-
import { IClipboardService, CLIPBOARD_FILE_TOKEN } from '@opensumi/ide-core-common';
|
|
3
|
-
import { URI } from '@opensumi/ide-core-common';
|
|
4
|
-
import { IElectronMainUIService } from '@opensumi/ide-core-common/lib/electron';
|
|
5
|
-
|
|
6
|
-
export { CLIPBOARD_FILE_TOKEN };
|
|
7
|
-
|
|
8
|
-
export const INativeClipboardService = Symbol('INativeClipboardService');
|
|
9
|
-
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
11
|
-
export interface INativeClipboardService extends IClipboardService {}
|
|
12
|
-
|
|
13
|
-
@Injectable()
|
|
14
|
-
export class ElectronClipboardService implements INativeClipboardService {
|
|
15
|
-
@Autowired(IElectronMainUIService)
|
|
16
|
-
private electronMainUIService: IElectronMainUIService;
|
|
17
|
-
|
|
18
|
-
async writeText(text: string): Promise<void> {
|
|
19
|
-
return await this.electronMainUIService.writeClipboardText(text);
|
|
20
|
-
}
|
|
21
|
-
async readText(): Promise<string> {
|
|
22
|
-
return await this.electronMainUIService.readClipboardText();
|
|
23
|
-
}
|
|
24
|
-
async writeResources(resources: URI[], field = CLIPBOARD_FILE_TOKEN): Promise<void> {
|
|
25
|
-
try {
|
|
26
|
-
const buffer = Buffer.from(JSON.stringify(resources.map((uri) => uri.toString())), 'utf8');
|
|
27
|
-
return await this.electronMainUIService.writeClipboardBuffer(field, buffer);
|
|
28
|
-
} catch {}
|
|
29
|
-
}
|
|
30
|
-
async readResources(field = CLIPBOARD_FILE_TOKEN): Promise<URI[]> {
|
|
31
|
-
try {
|
|
32
|
-
const buffer = await this.electronMainUIService.readClipboardBuffer(field);
|
|
33
|
-
const list = JSON.parse(Buffer.from(buffer).toString('utf8'));
|
|
34
|
-
if (
|
|
35
|
-
!Array.isArray(list) ||
|
|
36
|
-
!list.length ||
|
|
37
|
-
!list.every((str) => typeof str === 'string' && URI.isUriString(str))
|
|
38
|
-
) {
|
|
39
|
-
return [];
|
|
40
|
-
}
|
|
41
|
-
return list.map((str) => URI.parse(str));
|
|
42
|
-
} catch {
|
|
43
|
-
return [];
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
async hasResources(field?: string | undefined): Promise<boolean> {
|
|
47
|
-
try {
|
|
48
|
-
const buffer = await this.electronMainUIService.readClipboardBuffer(field ?? CLIPBOARD_FILE_TOKEN);
|
|
49
|
-
const list = JSON.parse(Buffer.from(buffer).toString('utf8'));
|
|
50
|
-
if (
|
|
51
|
-
!Array.isArray(list) ||
|
|
52
|
-
!list.length ||
|
|
53
|
-
!list.every((str) => typeof str === 'string' && URI.isUriString(str))
|
|
54
|
-
) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
return true;
|
|
58
|
-
} catch {
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Injectable, Autowired } from '@opensumi/di';
|
|
2
|
-
import { IElectronNativeDialogService, electronEnv } from '@opensumi/ide-core-browser';
|
|
3
|
-
import { IElectronMainUIService } from '@opensumi/ide-core-common/lib/electron';
|
|
4
|
-
|
|
5
|
-
@Injectable()
|
|
6
|
-
export class ElectronNativeDialogService implements IElectronNativeDialogService {
|
|
7
|
-
@Autowired(IElectronMainUIService)
|
|
8
|
-
electronMainUIService: IElectronMainUIService;
|
|
9
|
-
|
|
10
|
-
async showOpenDialog(options: Electron.OpenDialogOptions): Promise<string[] | undefined> {
|
|
11
|
-
return this.electronMainUIService.showOpenDialog(electronEnv.currentWindowId, options);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
showSaveDialog(options: Electron.SaveDialogOptions): Promise<string | undefined> {
|
|
15
|
-
return this.electronMainUIService.showSaveDialog(electronEnv.currentWindowId, options);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
.header {
|
|
2
|
-
background: var(--menu-background);
|
|
3
|
-
color: var(--titlebar-activeForeground);
|
|
4
|
-
display: flex;
|
|
5
|
-
align-items: center;
|
|
6
|
-
text-align: center;
|
|
7
|
-
line-height: 100%;
|
|
8
|
-
font-size: 12px;
|
|
9
|
-
user-select: none;
|
|
10
|
-
|
|
11
|
-
.title_info {
|
|
12
|
-
height: 100%;
|
|
13
|
-
display: flex;
|
|
14
|
-
align-items: center;
|
|
15
|
-
-webkit-app-region: drag;
|
|
16
|
-
flex-grow: 1;
|
|
17
|
-
text-align: left;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
:global .menu-bar {
|
|
21
|
-
flex-shrink: 0;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
:global .menubarWrapper {
|
|
25
|
-
background-color: var(--kt-menubar-background);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.windowActions {
|
|
30
|
-
display: flex;
|
|
31
|
-
align-items: center;
|
|
32
|
-
-webkit-app-region: no-drag;
|
|
33
|
-
user-select: none;
|
|
34
|
-
|
|
35
|
-
> div {
|
|
36
|
-
font-size: 16px;
|
|
37
|
-
padding: 0 15px;
|
|
38
|
-
height: 100%;
|
|
39
|
-
width: 100%;
|
|
40
|
-
display: flex;
|
|
41
|
-
align-items: center;
|
|
42
|
-
|
|
43
|
-
&:hover {
|
|
44
|
-
background-color: hsla(0, 0%, 100%, 0.1);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
&:hover:last-child {
|
|
48
|
-
background-color: rgba(232, 17, 35, 0.9);
|
|
49
|
-
color: white;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
:global(.vs) {
|
|
55
|
-
.windowActions {
|
|
56
|
-
> div:not(:last-child):hover {
|
|
57
|
-
background-color: rgba(0, 0, 0, 0.1);
|
|
58
|
-
color: #696767;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { Injectable, Autowired, INJECTOR_TOKEN, Injector } from '@opensumi/di';
|
|
2
|
-
import {
|
|
3
|
-
AppConfig,
|
|
4
|
-
localize,
|
|
5
|
-
replaceLocalizePlaceholder,
|
|
6
|
-
Emitter,
|
|
7
|
-
DisposableCollection,
|
|
8
|
-
isMacintosh,
|
|
9
|
-
} from '@opensumi/ide-core-browser';
|
|
10
|
-
import { WorkbenchEditorService } from '@opensumi/ide-editor/lib/browser';
|
|
11
|
-
import { basename, dirname, relative } from '@opensumi/ide-utils/lib/path';
|
|
12
|
-
import { template } from '@opensumi/ide-utils/lib/strings';
|
|
13
|
-
|
|
14
|
-
import { IElectronHeaderService } from '../../common/header';
|
|
15
|
-
|
|
16
|
-
// "● "
|
|
17
|
-
export const TITLE_DIRTY = '\u25cf ';
|
|
18
|
-
export const SEPARATOR = ' - ';
|
|
19
|
-
|
|
20
|
-
export let DEFAULT_TEMPLATE = '${dirty}${activeEditorShort}${separator}${rootName}';
|
|
21
|
-
|
|
22
|
-
if (isMacintosh) {
|
|
23
|
-
DEFAULT_TEMPLATE = '${activeEditorShort}${separator}${rootName}';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
@Injectable()
|
|
27
|
-
export class ElectronHeaderService implements IElectronHeaderService {
|
|
28
|
-
disposableCollection = new DisposableCollection();
|
|
29
|
-
|
|
30
|
-
@Autowired(WorkbenchEditorService)
|
|
31
|
-
editorService: WorkbenchEditorService;
|
|
32
|
-
|
|
33
|
-
@Autowired(INJECTOR_TOKEN)
|
|
34
|
-
injector: Injector;
|
|
35
|
-
|
|
36
|
-
@Autowired(AppConfig)
|
|
37
|
-
appConfig: AppConfig;
|
|
38
|
-
|
|
39
|
-
private _onTitleChanged = new Emitter<string>();
|
|
40
|
-
onTitleChanged = this._onTitleChanged.event;
|
|
41
|
-
|
|
42
|
-
private _appTitle: string;
|
|
43
|
-
|
|
44
|
-
separator = SEPARATOR;
|
|
45
|
-
|
|
46
|
-
private _titleTemplate = DEFAULT_TEMPLATE;
|
|
47
|
-
get titleTemplate() {
|
|
48
|
-
return this._titleTemplate;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
set titleTemplate(value: string) {
|
|
52
|
-
this._titleTemplate = value;
|
|
53
|
-
this.updateAppTitle();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private _templateVariables = {} as Record<string, string | undefined>;
|
|
57
|
-
setTemplateVariables(key: string, value: string | undefined) {
|
|
58
|
-
this._templateVariables[key] = value;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
constructor() {
|
|
62
|
-
this.disposableCollection.push(
|
|
63
|
-
this.editorService.onActiveResourceChange(() => {
|
|
64
|
-
this.updateAppTitle();
|
|
65
|
-
}),
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
updateAppTitle() {
|
|
70
|
-
this._onTitleChanged.fire(this.appTitle);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
get appTitle() {
|
|
74
|
-
const formatted = this.formatAppTitle();
|
|
75
|
-
|
|
76
|
-
let result = formatted;
|
|
77
|
-
|
|
78
|
-
if (this.appConfig.extensionDevelopmentHost) {
|
|
79
|
-
result = `[${localize('workspace.development.title')}] ${result}`;
|
|
80
|
-
}
|
|
81
|
-
if (this.appConfig.isRemote) {
|
|
82
|
-
result = `[${localize('common.remoteMode')}] ${result}`;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
this._appTitle = result;
|
|
86
|
-
return this._appTitle;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
formatAppTitle() {
|
|
90
|
-
const { appConfig } = this;
|
|
91
|
-
const currentResource = this.editorService.currentResource;
|
|
92
|
-
const currentEditor = this.editorService.currentEditor;
|
|
93
|
-
|
|
94
|
-
const workspaceDir = appConfig.workspaceDir ? appConfig.workspaceDir : '';
|
|
95
|
-
const workspaceBasename = basename(workspaceDir);
|
|
96
|
-
const activeEditorFull = currentResource?.name ?? '';
|
|
97
|
-
const activeEditorRelative = activeEditorFull && workspaceDir ? relative(workspaceDir, activeEditorFull) : '';
|
|
98
|
-
const activeFolderFull = activeEditorFull ? dirname(activeEditorFull) : '';
|
|
99
|
-
const activeFolderRelative = activeFolderFull && workspaceDir ? relative(workspaceDir, activeFolderFull) : '';
|
|
100
|
-
|
|
101
|
-
const activeEditorShort = basename(activeEditorFull);
|
|
102
|
-
const activeEditorMedium = activeEditorRelative;
|
|
103
|
-
const activeEditorLong = activeEditorFull;
|
|
104
|
-
const activeFolderShort = basename(activeFolderFull);
|
|
105
|
-
const activeFolderMedium = activeFolderRelative;
|
|
106
|
-
const activeFolderLong = activeFolderFull;
|
|
107
|
-
const folderName = workspaceBasename;
|
|
108
|
-
const folderPath = workspaceDir;
|
|
109
|
-
const rootName = workspaceBasename;
|
|
110
|
-
const rootPath = workspaceDir;
|
|
111
|
-
const appName = replaceLocalizePlaceholder(appConfig.appName) ?? '';
|
|
112
|
-
// TODO: 当前 OpenSumi 还不支持 Remote 名字
|
|
113
|
-
const remoteName = '';
|
|
114
|
-
const dirty = currentEditor?.currentDocumentModel?.dirty ? TITLE_DIRTY : '';
|
|
115
|
-
|
|
116
|
-
const result = template(
|
|
117
|
-
this.titleTemplate,
|
|
118
|
-
{
|
|
119
|
-
activeEditorShort,
|
|
120
|
-
activeEditorMedium,
|
|
121
|
-
activeEditorLong,
|
|
122
|
-
activeFolderShort,
|
|
123
|
-
activeFolderMedium,
|
|
124
|
-
activeFolderLong,
|
|
125
|
-
folderName,
|
|
126
|
-
folderPath,
|
|
127
|
-
rootName,
|
|
128
|
-
rootPath,
|
|
129
|
-
appName,
|
|
130
|
-
remoteName,
|
|
131
|
-
dirty,
|
|
132
|
-
...this._templateVariables,
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
separator: this.separator,
|
|
136
|
-
},
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
return result;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
dispose() {
|
|
143
|
-
this.disposableCollection.dispose();
|
|
144
|
-
}
|
|
145
|
-
}
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { observer } from 'mobx-react-lite';
|
|
2
|
-
import React, { useState, useEffect, useRef } from 'react';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
useInjectable,
|
|
6
|
-
ComponentRenderer,
|
|
7
|
-
ComponentRegistry,
|
|
8
|
-
DomListener,
|
|
9
|
-
electronEnv,
|
|
10
|
-
IWindowService,
|
|
11
|
-
useEventEffect,
|
|
12
|
-
} from '@opensumi/ide-core-browser';
|
|
13
|
-
import { getIcon } from '@opensumi/ide-core-browser';
|
|
14
|
-
import { isMacintosh, Disposable } from '@opensumi/ide-core-browser';
|
|
15
|
-
import { LAYOUT_VIEW_SIZE } from '@opensumi/ide-core-browser/lib/layout/constants';
|
|
16
|
-
import { IElectronMainUIService } from '@opensumi/ide-core-common/lib/electron';
|
|
17
|
-
|
|
18
|
-
import { IElectronHeaderService } from '../../common/header';
|
|
19
|
-
|
|
20
|
-
import styles from './header.module.less';
|
|
21
|
-
|
|
22
|
-
const useFullScreen = () => {
|
|
23
|
-
const uiService: IElectronMainUIService = useInjectable(IElectronMainUIService);
|
|
24
|
-
const [isFullScreen, setFullScreen] = useState<boolean>(false);
|
|
25
|
-
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
uiService.isFullScreen(electronEnv.currentWindowId).then((fullScreen) => {
|
|
28
|
-
setFullScreen(fullScreen);
|
|
29
|
-
});
|
|
30
|
-
const listener = uiService.on('fullScreenStatusChange', (windowId, fullScreen) => {
|
|
31
|
-
if (windowId === electronEnv.currentWindowId) {
|
|
32
|
-
setFullScreen(fullScreen);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
return () => {
|
|
36
|
-
listener.dispose();
|
|
37
|
-
};
|
|
38
|
-
}, []);
|
|
39
|
-
return {
|
|
40
|
-
isFullScreen,
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const useMaximize = () => {
|
|
45
|
-
const uiService: IElectronMainUIService = useInjectable(IElectronMainUIService);
|
|
46
|
-
const [maximized, setMaximized] = useState(false);
|
|
47
|
-
|
|
48
|
-
const getMaximized = async () => uiService.isMaximized(electronEnv.currentWindowId);
|
|
49
|
-
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
const maximizeListener = uiService.on('maximizeStatusChange', (windowId, isMaximized) => {
|
|
52
|
-
if (windowId === electronEnv.currentWindowId) {
|
|
53
|
-
setMaximized(isMaximized);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
getMaximized().then((maximized) => {
|
|
57
|
-
setMaximized(maximized);
|
|
58
|
-
});
|
|
59
|
-
return () => {
|
|
60
|
-
maximizeListener.dispose();
|
|
61
|
-
};
|
|
62
|
-
}, []);
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
maximized,
|
|
66
|
-
getMaximized,
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// Big Sur increases title bar height
|
|
71
|
-
const isNewMacHeaderBar = () => isMacintosh && parseFloat(electronEnv.osRelease) >= 20;
|
|
72
|
-
|
|
73
|
-
export const HeaderBarLeftComponent = () => {
|
|
74
|
-
const componentRegistry: ComponentRegistry = useInjectable(ComponentRegistry);
|
|
75
|
-
|
|
76
|
-
if (isMacintosh) {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const initialProps = {
|
|
81
|
-
className: 'menubarWrapper',
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<>
|
|
86
|
-
<ComponentRenderer
|
|
87
|
-
Component={componentRegistry.getComponentRegistryInfo('@opensumi/ide-menu-bar')!.views[0].component!}
|
|
88
|
-
initialProps={initialProps}
|
|
89
|
-
/>
|
|
90
|
-
</>
|
|
91
|
-
);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export const HeaderBarRightComponent = () => {
|
|
95
|
-
const { maximized } = useMaximize();
|
|
96
|
-
const windowService: IWindowService = useInjectable(IWindowService);
|
|
97
|
-
|
|
98
|
-
if (isMacintosh) {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<div
|
|
104
|
-
className={styles.windowActions}
|
|
105
|
-
style={{
|
|
106
|
-
height: isNewMacHeaderBar() ? LAYOUT_VIEW_SIZE.BIG_SUR_TITLEBAR_HEIGHT : LAYOUT_VIEW_SIZE.TITLEBAR_HEIGHT,
|
|
107
|
-
}}
|
|
108
|
-
>
|
|
109
|
-
<div className={getIcon('min')} onClick={() => windowService.minimize()} />
|
|
110
|
-
{maximized ? (
|
|
111
|
-
<div className={getIcon('max')} onClick={() => windowService.unmaximize()} />
|
|
112
|
-
) : (
|
|
113
|
-
<div className={getIcon('unmax')} onClick={() => windowService.maximize()} />
|
|
114
|
-
)}
|
|
115
|
-
<div className={getIcon('close1')} onClick={() => windowService.close()} />
|
|
116
|
-
</div>
|
|
117
|
-
);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
interface ElectronHeaderBarPorps {
|
|
121
|
-
LeftComponent?: React.FunctionComponent;
|
|
122
|
-
RightComponent?: React.FunctionComponent;
|
|
123
|
-
TitleComponent?: React.FunctionComponent<TitleBarProps>;
|
|
124
|
-
Icon?: React.FunctionComponent;
|
|
125
|
-
autoHide?: boolean;
|
|
126
|
-
height?: number;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* autoHide: Hide the HeaderBar when the macOS full screen
|
|
131
|
-
*/
|
|
132
|
-
export const ElectronHeaderBar = observer(
|
|
133
|
-
({
|
|
134
|
-
LeftComponent,
|
|
135
|
-
RightComponent,
|
|
136
|
-
TitleComponent,
|
|
137
|
-
autoHide = true,
|
|
138
|
-
height = isNewMacHeaderBar() ? LAYOUT_VIEW_SIZE.BIG_SUR_TITLEBAR_HEIGHT : LAYOUT_VIEW_SIZE.TITLEBAR_HEIGHT,
|
|
139
|
-
}: React.PropsWithChildren<ElectronHeaderBarPorps>) => {
|
|
140
|
-
const windowService: IWindowService = useInjectable(IWindowService);
|
|
141
|
-
|
|
142
|
-
const { isFullScreen } = useFullScreen();
|
|
143
|
-
const { getMaximized } = useMaximize();
|
|
144
|
-
if (!LeftComponent) {
|
|
145
|
-
LeftComponent = HeaderBarLeftComponent;
|
|
146
|
-
}
|
|
147
|
-
if (!RightComponent) {
|
|
148
|
-
RightComponent = HeaderBarRightComponent;
|
|
149
|
-
}
|
|
150
|
-
if (!TitleComponent) {
|
|
151
|
-
TitleComponent = HeaderBarTitleComponent;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// in Mac, hide the header bar if it is in full screen mode
|
|
155
|
-
if (isMacintosh && isFullScreen && autoHide) {
|
|
156
|
-
return (
|
|
157
|
-
<div>
|
|
158
|
-
<TitleComponent hidden={true} />
|
|
159
|
-
</div>
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return (
|
|
164
|
-
<div
|
|
165
|
-
className={styles.header}
|
|
166
|
-
style={{ height }}
|
|
167
|
-
onDoubleClick={async () => {
|
|
168
|
-
if (await getMaximized()) {
|
|
169
|
-
windowService.unmaximize();
|
|
170
|
-
} else {
|
|
171
|
-
windowService.maximize();
|
|
172
|
-
}
|
|
173
|
-
}}
|
|
174
|
-
>
|
|
175
|
-
<LeftComponent />
|
|
176
|
-
<TitleComponent />
|
|
177
|
-
<RightComponent />
|
|
178
|
-
</div>
|
|
179
|
-
);
|
|
180
|
-
},
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
declare const ResizeObserver: any;
|
|
184
|
-
|
|
185
|
-
export interface TitleInfo {
|
|
186
|
-
currentResourceName?: string;
|
|
187
|
-
workspaceName?: string;
|
|
188
|
-
appName?: string;
|
|
189
|
-
remoteMode?: boolean;
|
|
190
|
-
extensionDevelopmentHost?: boolean;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export interface TitleBarProps {
|
|
194
|
-
hidden?: boolean;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export const HeaderBarTitleComponent = observer(({ hidden }: TitleBarProps) => {
|
|
198
|
-
const headerService = useInjectable(IElectronHeaderService) as IElectronHeaderService;
|
|
199
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
200
|
-
const spanRef = useRef<HTMLSpanElement>(null);
|
|
201
|
-
const [appTitle, setAppTitle] = useState(headerService.appTitle);
|
|
202
|
-
|
|
203
|
-
useEventEffect(
|
|
204
|
-
headerService.onTitleChanged,
|
|
205
|
-
(v) => {
|
|
206
|
-
setAppTitle(v);
|
|
207
|
-
},
|
|
208
|
-
[],
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
useEffect(() => {
|
|
212
|
-
setPosition();
|
|
213
|
-
const disposer = new Disposable();
|
|
214
|
-
|
|
215
|
-
disposer.addDispose(
|
|
216
|
-
new DomListener(window, 'resize', () => {
|
|
217
|
-
setPosition();
|
|
218
|
-
}),
|
|
219
|
-
);
|
|
220
|
-
if (ref.current && ref.current.previousElementSibling) {
|
|
221
|
-
const resizeObserver = new ResizeObserver(setPosition);
|
|
222
|
-
resizeObserver.observe(ref.current.previousElementSibling);
|
|
223
|
-
disposer.addDispose({
|
|
224
|
-
dispose: () => {
|
|
225
|
-
resizeObserver.disconnect();
|
|
226
|
-
},
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
return disposer.dispose.bind(disposer);
|
|
230
|
-
}, []);
|
|
231
|
-
|
|
232
|
-
function setPosition() {
|
|
233
|
-
// 在下一个 animationFrame 执行,此时 spanRef.current!.offsetWidth 的宽度才是正确的
|
|
234
|
-
window.requestAnimationFrame(() => {
|
|
235
|
-
if (ref.current && spanRef.current) {
|
|
236
|
-
const windowWidth = window.innerWidth;
|
|
237
|
-
let prevWidth = 0;
|
|
238
|
-
let node = ref.current.previousElementSibling;
|
|
239
|
-
while (node) {
|
|
240
|
-
prevWidth += (node as HTMLElement).offsetWidth;
|
|
241
|
-
node = node.previousElementSibling;
|
|
242
|
-
}
|
|
243
|
-
const left = Math.max(0, windowWidth * 0.5 - prevWidth - spanRef.current.offsetWidth * 0.5);
|
|
244
|
-
ref.current.style.paddingLeft = left + 'px';
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// 同时更新 document Title
|
|
250
|
-
useEffect(() => {
|
|
251
|
-
document.title = appTitle;
|
|
252
|
-
}, [appTitle]);
|
|
253
|
-
|
|
254
|
-
if (hidden) {
|
|
255
|
-
return null;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return (
|
|
259
|
-
<div className={styles.title_info} ref={ref}>
|
|
260
|
-
<span ref={spanRef}>{appTitle}</span>
|
|
261
|
-
</div>
|
|
262
|
-
);
|
|
263
|
-
});
|
package/src/browser/index.ts
DELETED
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
import { Provider, Injectable, Autowired, INJECTOR_TOKEN, Injector } from '@opensumi/di';
|
|
2
|
-
import {
|
|
3
|
-
BrowserModule,
|
|
4
|
-
Domain,
|
|
5
|
-
AppConfig,
|
|
6
|
-
isOSX,
|
|
7
|
-
ClientAppContribution,
|
|
8
|
-
IElectronMainMenuService,
|
|
9
|
-
localize,
|
|
10
|
-
SlotLocation,
|
|
11
|
-
IElectronNativeDialogService,
|
|
12
|
-
CommandContribution,
|
|
13
|
-
CommandRegistry,
|
|
14
|
-
KeybindingContribution,
|
|
15
|
-
KeybindingRegistry,
|
|
16
|
-
isWindows,
|
|
17
|
-
electronEnv,
|
|
18
|
-
replaceLocalizePlaceholder,
|
|
19
|
-
URI,
|
|
20
|
-
ILogger,
|
|
21
|
-
formatLocalize,
|
|
22
|
-
IEventBus,
|
|
23
|
-
Schemes,
|
|
24
|
-
IClipboardService,
|
|
25
|
-
} from '@opensumi/ide-core-browser';
|
|
26
|
-
import { ComponentContribution, ComponentRegistry } from '@opensumi/ide-core-browser/lib/layout';
|
|
27
|
-
import { IMenuRegistry, MenuContribution, MenuId } from '@opensumi/ide-core-browser/lib/menu/next';
|
|
28
|
-
import { IElectronMenuBarService } from '@opensumi/ide-core-browser/lib/menu/next/renderer/ctxmenu/electron';
|
|
29
|
-
import { IElectronMainLifeCycleService, IElectronMainUIService } from '@opensumi/ide-core-common/lib/electron';
|
|
30
|
-
import { IResourceOpenOptions } from '@opensumi/ide-editor';
|
|
31
|
-
import {
|
|
32
|
-
EditorGroupFileDropEvent,
|
|
33
|
-
DragOverPosition,
|
|
34
|
-
getSplitActionFromDragDrop,
|
|
35
|
-
} from '@opensumi/ide-editor/lib/browser';
|
|
36
|
-
import { IMessageService } from '@opensumi/ide-overlay/lib/common';
|
|
37
|
-
|
|
38
|
-
import { IElectronHeaderService } from '../common/header';
|
|
39
|
-
|
|
40
|
-
import { ElectronClipboardService } from './clipboard';
|
|
41
|
-
import { ElectronNativeDialogService } from './dialog';
|
|
42
|
-
import { ElectronHeaderService } from './header/header.service';
|
|
43
|
-
import { ElectronHeaderBar } from './header/header.view';
|
|
44
|
-
import { WelcomeContribution } from './welcome/contribution';
|
|
45
|
-
|
|
46
|
-
@Injectable()
|
|
47
|
-
export class ElectronBasicModule extends BrowserModule {
|
|
48
|
-
providers: Provider[] = [
|
|
49
|
-
{
|
|
50
|
-
token: IElectronNativeDialogService,
|
|
51
|
-
useClass: ElectronNativeDialogService,
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
token: IElectronHeaderService,
|
|
55
|
-
useClass: ElectronHeaderService,
|
|
56
|
-
},
|
|
57
|
-
ElectronBasicContribution,
|
|
58
|
-
WelcomeContribution,
|
|
59
|
-
];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const nativeRoles = [
|
|
63
|
-
{
|
|
64
|
-
name: 'undo',
|
|
65
|
-
key: 'ctrlcmd+z',
|
|
66
|
-
when: '!editorFocus',
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
name: 'redo',
|
|
70
|
-
key: 'ctrlcmd+shift+z',
|
|
71
|
-
when: '!editorFocus',
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
name: 'copy',
|
|
75
|
-
key: 'ctrlcmd+c',
|
|
76
|
-
when: '!editorFocus',
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
name: 'paste',
|
|
80
|
-
key: 'ctrlcmd+v',
|
|
81
|
-
when: '!editorFocus',
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
name: 'selectAll',
|
|
85
|
-
key: 'ctrlcmd+a',
|
|
86
|
-
when: '!editorFocus',
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: 'cut',
|
|
90
|
-
key: 'ctrlcmd+x',
|
|
91
|
-
when: '!editorFocus',
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
name: 'toggleDevTools',
|
|
95
|
-
key: 'alt+ctrlcmd+i',
|
|
96
|
-
label: '%window.toggleDevTools%',
|
|
97
|
-
alias: 'Toggle Developer Tools',
|
|
98
|
-
},
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
@Domain(ComponentContribution, ClientAppContribution, MenuContribution, CommandContribution, KeybindingContribution)
|
|
102
|
-
export class ElectronBasicContribution
|
|
103
|
-
implements
|
|
104
|
-
KeybindingContribution,
|
|
105
|
-
CommandContribution,
|
|
106
|
-
ComponentContribution,
|
|
107
|
-
ClientAppContribution,
|
|
108
|
-
MenuContribution
|
|
109
|
-
{
|
|
110
|
-
@Autowired(AppConfig)
|
|
111
|
-
config: AppConfig;
|
|
112
|
-
|
|
113
|
-
@Autowired(INJECTOR_TOKEN)
|
|
114
|
-
injector: Injector;
|
|
115
|
-
|
|
116
|
-
@Autowired(IEventBus)
|
|
117
|
-
eventBus: IEventBus;
|
|
118
|
-
|
|
119
|
-
@Autowired(IElectronMenuBarService)
|
|
120
|
-
private electronMenuBarService: IElectronMenuBarService;
|
|
121
|
-
|
|
122
|
-
@Autowired(IElectronMainMenuService)
|
|
123
|
-
private electronMainMenuService: IElectronMainMenuService;
|
|
124
|
-
|
|
125
|
-
@Autowired(IElectronMainLifeCycleService)
|
|
126
|
-
private electronMainLifeCycleService: IElectronMainLifeCycleService;
|
|
127
|
-
|
|
128
|
-
@Autowired(IElectronMainUIService)
|
|
129
|
-
private electronMainUIService: IElectronMainUIService;
|
|
130
|
-
|
|
131
|
-
@Autowired(IMessageService)
|
|
132
|
-
private messageService: IMessageService;
|
|
133
|
-
|
|
134
|
-
@Autowired(ILogger)
|
|
135
|
-
logger: ILogger;
|
|
136
|
-
|
|
137
|
-
registerComponent(registry: ComponentRegistry) {
|
|
138
|
-
const top = this.config.layoutConfig[SlotLocation.top];
|
|
139
|
-
if (top && top.modules) {
|
|
140
|
-
const index = top.modules.indexOf('@opensumi/ide-menu-bar');
|
|
141
|
-
if (index !== -1) {
|
|
142
|
-
top.modules.splice(index, 1, 'electron-header');
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
registry.register(
|
|
146
|
-
'electron-header',
|
|
147
|
-
{
|
|
148
|
-
id: 'electron-header',
|
|
149
|
-
component: ElectronHeaderBar,
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
size: 27,
|
|
153
|
-
containerId: 'electron-header',
|
|
154
|
-
},
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
registerMenus(menuRegistry: IMenuRegistry) {
|
|
159
|
-
menuRegistry.registerMenuItem(MenuId.MenubarAppMenu, {
|
|
160
|
-
command: {
|
|
161
|
-
id: 'electron.about',
|
|
162
|
-
label: localize('common.about'),
|
|
163
|
-
},
|
|
164
|
-
group: '0_about',
|
|
165
|
-
nativeRole: 'about',
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
menuRegistry.registerMenuItem(MenuId.MenubarHelpMenu, {
|
|
169
|
-
command: {
|
|
170
|
-
id: 'electron.toggleDevTools',
|
|
171
|
-
label: localize('window.toggleDevTools'),
|
|
172
|
-
},
|
|
173
|
-
nativeRole: 'toggledevtools',
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
menuRegistry.registerMenuItem(MenuId.MenubarHelpMenu, {
|
|
177
|
-
command: {
|
|
178
|
-
id: 'electron.reload',
|
|
179
|
-
label: localize('window.reload'),
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
menuRegistry.registerMenuItem(MenuId.ExplorerContext, {
|
|
184
|
-
command: 'electron.revealInFinder',
|
|
185
|
-
group: '12_electron',
|
|
186
|
-
order: 3,
|
|
187
|
-
});
|
|
188
|
-
menuRegistry.registerMenuItem(MenuId.EditorTitleContext, {
|
|
189
|
-
command: 'electron.revealInFinderTab',
|
|
190
|
-
group: '2_open',
|
|
191
|
-
order: 3,
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
registerCommands(commands: CommandRegistry): void {
|
|
196
|
-
nativeRoles.forEach((role) => {
|
|
197
|
-
commands.registerCommand(
|
|
198
|
-
{
|
|
199
|
-
id: 'electron.' + role.name,
|
|
200
|
-
label: replaceLocalizePlaceholder(role.label),
|
|
201
|
-
alias: role.alias,
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
execute: () => {
|
|
205
|
-
this.electronMainMenuService.runNativeRoleAction(role.name);
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
);
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
commands.registerCommand(
|
|
212
|
-
{
|
|
213
|
-
id: 'electron.zoomIn',
|
|
214
|
-
label: localize('view.zoomIn'),
|
|
215
|
-
alias: 'View: Zoom In',
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
execute: () => {
|
|
219
|
-
this.electronMainUIService.setZoomFactor(electronEnv.currentWebContentsId, {
|
|
220
|
-
delta: 0.1,
|
|
221
|
-
});
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
commands.registerCommand(
|
|
227
|
-
{
|
|
228
|
-
id: 'electron.zoomOut',
|
|
229
|
-
label: localize('view.zoomOut'),
|
|
230
|
-
alias: 'View: Zoom Out',
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
execute: () => {
|
|
234
|
-
this.electronMainUIService.setZoomFactor(electronEnv.currentWebContentsId, {
|
|
235
|
-
delta: -0.1,
|
|
236
|
-
});
|
|
237
|
-
},
|
|
238
|
-
},
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
commands.registerCommand(
|
|
242
|
-
{
|
|
243
|
-
id: 'electron.zoomReset',
|
|
244
|
-
label: localize('view.zoomReset'),
|
|
245
|
-
alias: 'View: Zoom Reset',
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
execute: () => {
|
|
249
|
-
this.electronMainUIService.setZoomFactor(electronEnv.currentWebContentsId, {
|
|
250
|
-
value: 1,
|
|
251
|
-
});
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
commands.registerCommand(
|
|
257
|
-
{
|
|
258
|
-
id: 'electron.reload',
|
|
259
|
-
label: localize('window.reload'),
|
|
260
|
-
alias: 'Reload Window',
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
execute: () => {
|
|
264
|
-
this.electronMainLifeCycleService.reloadWindow(electronEnv.currentWindowId);
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
commands.registerCommand(
|
|
270
|
-
{
|
|
271
|
-
id: 'electron.revealInFinder',
|
|
272
|
-
label: localize('explorer.electron.revealInFinder'),
|
|
273
|
-
},
|
|
274
|
-
{
|
|
275
|
-
execute: (uri: URI) => {
|
|
276
|
-
if (uri && uri.scheme === Schemes.file) {
|
|
277
|
-
this.electronMainUIService.revealInFinder(uri.codeUri.fsPath);
|
|
278
|
-
}
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
);
|
|
282
|
-
|
|
283
|
-
commands.registerCommand(
|
|
284
|
-
{
|
|
285
|
-
id: 'electron.revealInFinderTab',
|
|
286
|
-
label: localize('explorer.electron.revealInFinder'),
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
execute: ({ uri }: { uri?: URI } = {}) => {
|
|
290
|
-
if (uri && uri.scheme === Schemes.file) {
|
|
291
|
-
this.electronMainUIService.revealInFinder(uri.codeUri.fsPath);
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
},
|
|
295
|
-
);
|
|
296
|
-
|
|
297
|
-
commands.registerCommand(
|
|
298
|
-
{
|
|
299
|
-
id: 'electron.openInSystemTerminal',
|
|
300
|
-
label: localize('explorer.electron.openInSystemTerminal'),
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
execute: (uri: URI) => {
|
|
304
|
-
if (uri && uri.scheme === Schemes.file) {
|
|
305
|
-
try {
|
|
306
|
-
this.electronMainUIService.revealInSystemTerminal(uri.codeUri.fsPath);
|
|
307
|
-
} catch (e) {
|
|
308
|
-
this.logger.error(e);
|
|
309
|
-
this.messageService.error(
|
|
310
|
-
formatLocalize('explorer.electron.openInSystemTerminal.error', uri.displayName, e.message),
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
},
|
|
315
|
-
},
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
registerKeybindings(keybindings: KeybindingRegistry) {
|
|
320
|
-
nativeRoles.forEach((role) => {
|
|
321
|
-
if (role.key) {
|
|
322
|
-
keybindings.registerKeybinding({
|
|
323
|
-
command: 'electron.' + role.name,
|
|
324
|
-
keybinding: role.key,
|
|
325
|
-
when: role.when,
|
|
326
|
-
priority: Number.MIN_SAFE_INTEGER, // 永远在最后被命中
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
keybindings.registerKeybinding({
|
|
332
|
-
command: 'electron.reload',
|
|
333
|
-
keybinding: 'shift+ctrlcmd+r',
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
keybindings.registerKeybinding({
|
|
337
|
-
command: 'electron.zoomIn',
|
|
338
|
-
keybinding: isWindows ? 'alt+=' : 'ctrlcmd+=',
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
keybindings.registerKeybinding({
|
|
342
|
-
command: 'electron.zoomOut',
|
|
343
|
-
keybinding: isWindows ? 'alt+-' : 'ctrlcmd+-',
|
|
344
|
-
});
|
|
345
|
-
keybindings.registerKeybinding({
|
|
346
|
-
command: 'electron.zoomReset',
|
|
347
|
-
keybinding: isWindows ? 'alt+numpad0' : 'ctrlcmd+numpad0',
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
onStart() {
|
|
352
|
-
if (isOSX) {
|
|
353
|
-
this.electronMenuBarService.start();
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// 注册drag drop file的行为
|
|
357
|
-
this.eventBus.on(EditorGroupFileDropEvent, async (event) => {
|
|
358
|
-
const payload = event.payload;
|
|
359
|
-
// fileList 只能这样遍历
|
|
360
|
-
for (let i = 0; i < payload.files.length; i++) {
|
|
361
|
-
const file = payload.files[i];
|
|
362
|
-
let group = event.payload.group;
|
|
363
|
-
if (file.path) {
|
|
364
|
-
const fileURI = URI.file(file.path);
|
|
365
|
-
const options: IResourceOpenOptions = {
|
|
366
|
-
index: event.payload.tabIndex !== -1 ? event.payload.tabIndex : undefined,
|
|
367
|
-
};
|
|
368
|
-
// 只有第一个才split
|
|
369
|
-
if (i === 0 && event.payload.position && event.payload.position !== DragOverPosition.CENTER) {
|
|
370
|
-
options.split = getSplitActionFromDragDrop(event.payload.position);
|
|
371
|
-
}
|
|
372
|
-
// 只有最后一个才可能为 preview
|
|
373
|
-
if (i < payload.files.length - 1) {
|
|
374
|
-
options.preview = false;
|
|
375
|
-
}
|
|
376
|
-
const res = await group.open(fileURI, options);
|
|
377
|
-
if (res) {
|
|
378
|
-
// split后当前group会变动
|
|
379
|
-
group = res.group;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
// override broswer modules
|
|
386
|
-
this.injector.overrideProviders({
|
|
387
|
-
token: IClipboardService,
|
|
388
|
-
useClass: ElectronClipboardService,
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { Autowired } from '@opensumi/di';
|
|
2
|
-
import { Domain, URI, localize, ClientAppContribution, RecentFilesManager } from '@opensumi/ide-core-browser';
|
|
3
|
-
import { ResourceService, IResource, WorkbenchEditorService } from '@opensumi/ide-editor';
|
|
4
|
-
import {
|
|
5
|
-
BrowserEditorContribution,
|
|
6
|
-
EditorComponentRegistry,
|
|
7
|
-
EditorComponentRenderMode,
|
|
8
|
-
} from '@opensumi/ide-editor/lib/browser';
|
|
9
|
-
import { IWorkspaceService } from '@opensumi/ide-workspace';
|
|
10
|
-
|
|
11
|
-
import { IWelcomeMetaData } from './common';
|
|
12
|
-
import { EditorWelcomeComponent } from './welcome';
|
|
13
|
-
|
|
14
|
-
@Domain(BrowserEditorContribution, ClientAppContribution)
|
|
15
|
-
export class WelcomeContribution implements BrowserEditorContribution, ClientAppContribution {
|
|
16
|
-
@Autowired(IWorkspaceService)
|
|
17
|
-
private readonly workspaceService: IWorkspaceService;
|
|
18
|
-
|
|
19
|
-
@Autowired(WorkbenchEditorService)
|
|
20
|
-
private readonly editorService: WorkbenchEditorService;
|
|
21
|
-
|
|
22
|
-
@Autowired(RecentFilesManager)
|
|
23
|
-
private readonly recentFilesManager: RecentFilesManager;
|
|
24
|
-
|
|
25
|
-
registerEditorComponent(registry: EditorComponentRegistry) {
|
|
26
|
-
registry.registerEditorComponent({
|
|
27
|
-
uid: 'welcome',
|
|
28
|
-
scheme: 'welcome',
|
|
29
|
-
component: EditorWelcomeComponent,
|
|
30
|
-
renderMode: EditorComponentRenderMode.ONE_PER_WORKBENCH,
|
|
31
|
-
});
|
|
32
|
-
registry.registerEditorComponentResolver('welcome', (resource, results) => {
|
|
33
|
-
results.push({
|
|
34
|
-
type: 'component',
|
|
35
|
-
componentId: 'welcome',
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
registerResource(service: ResourceService) {
|
|
41
|
-
service.registerResourceProvider({
|
|
42
|
-
scheme: 'welcome',
|
|
43
|
-
provideResource: async (uri: URI): Promise<IResource<IWelcomeMetaData>> =>
|
|
44
|
-
Promise.all([
|
|
45
|
-
this.workspaceService.getMostRecentlyUsedWorkspaces(),
|
|
46
|
-
this.recentFilesManager.getMostRecentlyOpenedFiles(),
|
|
47
|
-
]).then(([workspaces, files]) => ({
|
|
48
|
-
uri,
|
|
49
|
-
name: localize('welcome.title'),
|
|
50
|
-
icon: '',
|
|
51
|
-
metadata: {
|
|
52
|
-
recentWorkspaces: workspaces || [],
|
|
53
|
-
recentFiles: files || [],
|
|
54
|
-
},
|
|
55
|
-
})),
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
onDidStart() {
|
|
60
|
-
if (!this.workspaceService.workspace) {
|
|
61
|
-
this.editorService.open(new URI('welcome://'));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
useInjectable,
|
|
5
|
-
localize,
|
|
6
|
-
FileUri,
|
|
7
|
-
URI,
|
|
8
|
-
CommandService,
|
|
9
|
-
FILE_COMMANDS,
|
|
10
|
-
IWindowService,
|
|
11
|
-
} from '@opensumi/ide-core-browser';
|
|
12
|
-
import { ReactEditorComponent } from '@opensumi/ide-editor/lib/browser';
|
|
13
|
-
|
|
14
|
-
import { IWelcomeMetaData } from './common';
|
|
15
|
-
import styles from './welcome.module.less';
|
|
16
|
-
|
|
17
|
-
export const EditorWelcomeComponent: ReactEditorComponent<IWelcomeMetaData> = ({ resource }) => {
|
|
18
|
-
const commandService: CommandService = useInjectable(CommandService);
|
|
19
|
-
const windowService: IWindowService = useInjectable(IWindowService);
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<div className={styles.welcome}>
|
|
23
|
-
<div>
|
|
24
|
-
<h1>{localize('welcome.quickStart')}</h1>
|
|
25
|
-
<div>
|
|
26
|
-
<a
|
|
27
|
-
onClick={() => {
|
|
28
|
-
commandService.executeCommand(FILE_COMMANDS.OPEN_FOLDER.id, { newWindow: false });
|
|
29
|
-
}}
|
|
30
|
-
>
|
|
31
|
-
{localize('file.open.folder')}
|
|
32
|
-
</a>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
<div>
|
|
36
|
-
<h1>{localize('welcome.recent.workspace')}</h1>
|
|
37
|
-
{resource.metadata!.recentWorkspaces.map((workspace) => {
|
|
38
|
-
let workspacePath = workspace;
|
|
39
|
-
if (workspace.startsWith('file://')) {
|
|
40
|
-
workspacePath = FileUri.fsPath(workspace);
|
|
41
|
-
}
|
|
42
|
-
return (
|
|
43
|
-
<div key={workspace} className={styles.recentRow}>
|
|
44
|
-
<a
|
|
45
|
-
onClick={() => {
|
|
46
|
-
windowService.openWorkspace(new URI(workspace), { newWindow: false });
|
|
47
|
-
}}
|
|
48
|
-
>
|
|
49
|
-
{workspacePath}
|
|
50
|
-
</a>
|
|
51
|
-
</div>
|
|
52
|
-
);
|
|
53
|
-
})}
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
};
|
package/src/common/header.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Event } from '@opensumi/ide-core-browser';
|
|
2
|
-
export const IElectronHeaderService = Symbol('IElectronHeaderService');
|
|
3
|
-
|
|
4
|
-
export interface IElectronHeaderService {
|
|
5
|
-
/**
|
|
6
|
-
* 如果你的 template 中包含自定义变量,请先通过 setTemplateVariables 注入变量后,再调用该函数。
|
|
7
|
-
*/
|
|
8
|
-
titleTemplate: string;
|
|
9
|
-
/**
|
|
10
|
-
* 占位符 ${separator} 的值
|
|
11
|
-
*/
|
|
12
|
-
separator: string;
|
|
13
|
-
appTitle: string;
|
|
14
|
-
onTitleChanged: Event<string>;
|
|
15
|
-
/**
|
|
16
|
-
* 可以让集成方定义可替换的 variables。
|
|
17
|
-
* 如小程序开发者工具注入了一个 ${projectName},含义为用户当前项目的名字。
|
|
18
|
-
*/
|
|
19
|
-
setTemplateVariables(key: string, value: string | undefined): void;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* 默认支持的变量有下面这些,也支持集成方通过 setTemplateVariables 自己注入
|
|
23
|
-
* Controls the window title based on the active editor. Variables are substituted based on the context:
|
|
24
|
-
* - `${activeEditorShort}`: the file name (e.g. myFile.txt).
|
|
25
|
-
* - `${activeEditorMedium}`: the path of the file relative to the workspace folder (e.g. myFolder/myFileFolder/myFile.txt).
|
|
26
|
-
* - `${activeEditorLong}`: the full path of the file (e.g. /Users/Development/myFolder/myFileFolder/myFile.txt).
|
|
27
|
-
* - `${activeFolderShort}`: the name of the folder the file is contained in (e.g. myFileFolder).
|
|
28
|
-
* - `${activeFolderMedium}`: the path of the folder the file is contained in, relative to the workspace folder (e.g. myFolder/myFileFolder).
|
|
29
|
-
* - `${activeFolderLong}`: the full path of the folder the file is contained in (e.g. /Users/Development/myFolder/myFileFolder).
|
|
30
|
-
* - `${folderName}`: name of the workspace folder the file is contained in (e.g. myFolder).
|
|
31
|
-
* - `${folderPath}`: file path of the workspace folder the file is contained in (e.g. /Users/Development/myFolder).
|
|
32
|
-
* - `${rootName}`: name of the opened workspace or folder (e.g. myFolder or myWorkspace).
|
|
33
|
-
* - `${rootPath}`: file path of the opened workspace or folder (e.g. /Users/Development/myWorkspace).
|
|
34
|
-
* - `${appName}`: e.g. VS Code.
|
|
35
|
-
* - `${remoteName}`: e.g. SSH
|
|
36
|
-
* - `${dirty}`: an indicator for when the active editor has unsaved changes.
|
|
37
|
-
* - `${separator}`: a conditional separator (" - ") that only shows when surrounded by variables with values or static text.
|
|
38
|
-
*/
|
|
39
|
-
formatAppTitle(): string;
|
|
40
|
-
}
|