Skip to content

Commit b0692b8

Browse files
authored
Merge pull request #143 from jumpserver/pr@dev@perf_windows_display
Pr@dev@perf windows display
2 parents 6718de0 + e8d7bbf commit b0692b8

File tree

9 files changed

+89
-91
lines changed

9 files changed

+89
-91
lines changed

go-client/config.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
"en": "Microsoft Remote Desktop is a powerful Microsoft remote connection tool that can connect to remote PCs and your work resources from almost anywhere."
109109
},
110110
"download_url": "",
111-
"type": "windows",
111+
"type": "remotedesktop",
112112
"path": "mstsc.exe",
113113
"arg_format": "{file}",
114114
"match_first": [
@@ -484,7 +484,7 @@
484484
"en": "Microsoft Remote Desktop is a powerful Microsoft remote connection tool that can connect to remote PCs and your work resources from almost anywhere.\n\n!!!Manually download and install, click Save to activate!!!"
485485
},
486486
"download_url": "",
487-
"type": "windows",
487+
"type": "remotedesktop",
488488
"path": "/Applications/Microsoft Remote Desktop.app",
489489
"arg_format": "{file}",
490490
"match_first": [
@@ -651,7 +651,7 @@
651651
"en": "Remmina is a remote desktop client developed using GTK+, providing support for remote connection protocols such as RDP, VNC, XDMCP, and SSH."
652652
},
653653
"download_url": "https://remmina.org/how-to-install-remmina/",
654-
"type": "windows",
654+
"type": "remotedesktop",
655655
"path": "remmina",
656656
"arg_format": "{file}",
657657
"match_first": [],
@@ -670,7 +670,7 @@
670670
"en": "FreeRDP is a free implementation of the Remote Desktop Protocol (RDP), released under the Apache License.\nInstallation command\nsudo apt-get install freerdp\nsudo yum install freerdp"
671671
},
672672
"download_url": "https://github.com/FreeRDP/FreeRDP",
673-
"type": "windows",
673+
"type": "remotedesktop",
674674
"path": "xfreerdp",
675675
"arg_format": "{file} /cert-ignore /d: /p:",
676676
"match_first": [],

go-client/pkg/awaken/awaken_linux.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,29 @@ func awakenSSHCommand(r *Rouse, cfg *config.AppConfig) *exec.Cmd {
7070
currentPath := filepath.Dir(os.Args[0])
7171
commands := getCommandFromArgs(connectMap, appItem.ArgFormat)
7272
clientPath := filepath.Join(currentPath, "client")
73-
out, _ := exec.Command("bash", "-c", "echo $XDG_CURRENT_DESKTOP").CombinedOutput()
74-
currentDesktop := strings.ToLower(strings.Trim(string(out), "\n"))
73+
out, err := exec.Command("bash", "-c", "echo $XDG_CURRENT_DESKTOP").CombinedOutput()
74+
if err != nil {
75+
global.LOG.Error(fmt.Sprintf("Failed to detect desktop environment: %v", err))
76+
return nil
77+
}
78+
79+
currentDesktop := strings.ToLower(strings.TrimSpace(string(out)))
7580

7681
switch currentDesktop {
77-
case "gnome", "ubuntu:gnome", "ukui":
78-
cmd = exec.Command(
79-
"gnome-terminal", "--", "bash", "-c",
82+
case "gnome", "ubuntu:gnome", "ukui", "cinnamon":
83+
cmd = exec.Command("gnome-terminal", "--", "bash", "-c",
8084
fmt.Sprintf("%s %s; exec bash -i", clientPath, commands),
8185
)
86+
case "unity":
87+
cmd = exec.Command("x-terminal-emulator", "-e", fmt.Sprintf("%s %s", clientPath, commands))
8288
case "deepin":
8389
cmd = exec.Command("deepin-terminal", "--keep-open", "-C", fmt.Sprintf("%s %s", clientPath, commands))
90+
case "kde":
91+
cmd = exec.Command("konsole", "--noclose", "-e", "bash", "-c", fmt.Sprintf("%s %s", clientPath, commands))
92+
case "xfce":
93+
cmd = exec.Command("xfce4-terminal", "--hold", "-e", fmt.Sprintf("%s %s", clientPath, commands))
94+
case "lxde":
95+
cmd = exec.Command("lxterminal", "-e", fmt.Sprintf("%s %s", clientPath, commands))
8496
default:
8597
msg := fmt.Sprintf("Not yet supported %s desktop system", currentDesktop)
8698
global.LOG.Info(msg)

ui/electron-builder.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ linux:
5050
arch:
5151
- x64
5252
- arm64
53+
- target: AppImage
54+
arch:
55+
- x64
56+
- arm64
5357
maintainer: electronjs.org
5458
category: Utility
5559
deb:

ui/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "jumpserver-client",
33
"author": "Fit2Cloud Technology Co., Ltd.; <[email protected]>",
4-
"version": "v3.0.2",
4+
"version": "v3.0.3",
55
"homepage": "https://jumpserver.org",
66
"main": "./out/main/index.js",
77
"scripts": {
@@ -27,6 +27,7 @@
2727
"axios": "^1.7.7",
2828
"clipboard-polyfill": "^4.1.0",
2929
"electron-conf": "^1.2.1",
30+
"electron-log": "^5.3.3",
3031
"electron-store": "^10.0.0",
3132
"electron-updater": "^6.1.7",
3233
"lucide-vue-next": "^0.468.0",

ui/src/main/index.ts

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import path, { join, resolve } from 'path';
22
import { Conf, useConf } from 'electron-conf/main';
3-
3+
import log from 'electron-log';
44
import { app, BrowserWindow, ipcMain, session, shell } from 'electron';
55

66
import { execFile } from 'child_process';
@@ -22,9 +22,13 @@ let defaults = {
2222
language: 'en'
2323
}
2424
};
25+
2526
let mainWindow: BrowserWindow | null = null;
2627

27-
const platform = process.platform === 'win32' ? 'windows' : process.platform === 'darwin' ? 'macos' : 'linux';
28+
let openMainWindow: boolean = true;
29+
30+
const platform =
31+
process.platform === 'win32' ? 'windows' : process.platform === 'darwin' ? 'macos' : 'linux';
2832
const configFilePath = path.join(app.getPath('userData'), 'config.json');
2933

3034
if (!existsSync(configFilePath)) {
@@ -56,21 +60,23 @@ const handleUrl = (url: string) => {
5660

5761
if (token) {
5862
const decodedTokenJson = Buffer.from(token, 'base64').toString('utf-8');
59-
6063
try {
6164
const decodedToken = JSON.parse(decodedTokenJson);
6265
if ('bearer_token' in decodedToken) {
66+
openMainWindow = true;
6367
mainWindow?.webContents.send('set-token', decodedToken.bearer_token);
6468
} else {
69+
openMainWindow = false;
6570
handleClientPullUp(url);
6671
}
72+
log.info('handleUrl:', openMainWindow);
6773
} catch (error) {
68-
console.error('Failed to parse decoded token:', error);
74+
log.error('Failed to parse decoded token:', error);
6975
}
7076
}
7177
};
7278

73-
const handleArgv = (argv: any) => {
79+
const handleArgv = (argv: string[]) => {
7480
const offset = app.isPackaged ? 1 : 2;
7581
const url = argv.find((arg, i) => i >= offset && arg.startsWith('jms'));
7682
if (url) handleUrl(url);
@@ -97,7 +103,7 @@ const handleClientPullUp = (url: string) => {
97103
} else {
98104
subPath += '/windows';
99105
}
100-
let exeFilePath = path.join(subPath, 'JumpServerClient');
106+
const exeFilePath = path.join(subPath, 'JumpServerClient');
101107
execFile(exeFilePath, [url], error => {
102108
if (error) {
103109
console.log(error);
@@ -107,7 +113,8 @@ const handleClientPullUp = (url: string) => {
107113
};
108114

109115
const createWindow = async (): Promise<void> => {
110-
const windowBounds = (conf.get('windowBounds') as { width: number; height: number }) || defaults.windowBounds;
116+
const windowBounds =
117+
(conf.get('windowBounds') as { width: number; height: number }) || defaults.windowBounds;
111118

112119
mainWindow = new BrowserWindow({
113120
width: windowBounds.width,
@@ -132,7 +139,11 @@ const createWindow = async (): Promise<void> => {
132139
});
133140

134141
mainWindow.webContents.setWindowOpenHandler(details => {
135-
shell.openExternal(details.url);
142+
try {
143+
shell.openExternal(details.url);
144+
} catch (err) {
145+
log.error('Failed to open external URL:', err);
146+
}
136147
return { action: 'deny' };
137148
});
138149

@@ -179,6 +190,24 @@ const createWindow = async (): Promise<void> => {
179190
}
180191
};
181192

193+
// @ts-ignore
194+
app.on('second-instance', (_event: Event, argv: string[]) => {
195+
log.info('second-instance');
196+
if (process.platform === 'win32' || process.platform === 'linux') {
197+
handleArgv(argv);
198+
}
199+
if (mainWindow && openMainWindow) {
200+
if (mainWindow.isMinimized()) mainWindow.restore();
201+
mainWindow.focus();
202+
}
203+
});
204+
205+
// @ts-ignore
206+
app.on('open-url', (_event: Event, url: string) => {
207+
log.info('open-url');
208+
handleUrl(url);
209+
});
210+
182211
!app.requestSingleInstanceLock() ? app.quit() : '';
183212

184213
app.whenReady().then(async () => {
@@ -200,21 +229,25 @@ app.whenReady().then(async () => {
200229
conf.registerRendererListener();
201230
useConf();
202231

203-
await createWindow();
204232
setDefaultProtocol();
205233

206-
setTitleBar(conf.get('defaultSetting.theme') as string);
207-
208-
if (process.platform === 'win32') {
234+
if (process.platform === 'win32' || process.platform === 'linux') {
209235
handleArgv(process.argv);
210236
}
237+
log.info('whenReady: ', openMainWindow);
238+
if (openMainWindow) {
239+
await createWindow();
240+
setTitleBar(conf.get('defaultSetting.theme') as string);
241+
} else {
242+
app.quit();
243+
}
211244

212245
app.on('activate', function () {
213-
if (BrowserWindow.getAllWindows().length === 0) createWindow();
246+
if (BrowserWindow.getAllWindows().length === 0 && openMainWindow) createWindow();
214247
});
215248

216249
if (is.dev) {
217-
if (process.platform === 'win32') {
250+
if (process.platform === 'win32' || process.platform === 'linux') {
218251
process.on('message', data => {
219252
if (data === 'graceful-exit') {
220253
app.quit();
@@ -231,26 +264,7 @@ app.whenReady().then(async () => {
231264
// 除外 macOS 外,关闭所有窗口时退出 app
232265
app.on('window-all-closed', () => {
233266
// mainWindow 可能已经被销毁,所以不要再尝试访问它
234-
if (process.platform !== 'darwin') {
235-
app.quit();
236-
}
237-
});
238-
239-
// @ts-ignore
240-
app.on('second-instance', (_event: Event, argv: string) => {
241-
if (process.platform === 'win32') {
242-
handleArgv(argv);
243-
}
244-
if (mainWindow) {
245-
if (mainWindow.isMinimized()) mainWindow.restore();
246-
mainWindow.focus();
247-
}
248-
});
249-
250-
// 从 web 唤起 Client
251-
// @ts-ignore
252-
app.on('open-url', (_event: Event, url: string) => {
253-
handleUrl(url);
267+
app.quit();
254268
});
255269

256270
const setTitleBar = (theme: string) => {

ui/src/renderer/components.d.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ declare module 'vue' {
99
export interface GlobalComponents {
1010
Drawer: typeof import('./src/components/Drawer/index.vue')['default']
1111
ListContainer: typeof import('./src/components/ListContainer/index.vue')['default']
12-
ListItem: typeof import('./src/components/ListItem/index.vue')['default']
1312
LoginModal: typeof import('./src/components/LoginModal/index.vue')['default']
1413
MainSection: typeof import('./src/components/MainSection/index.vue')['default']
1514
NA: typeof import('naive-ui')['NA']
@@ -19,56 +18,39 @@ declare module 'vue' {
1918
NCollapse: typeof import('naive-ui')['NCollapse']
2019
NCollapseItem: typeof import('naive-ui')['NCollapseItem']
2120
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
22-
NDataTable: typeof import('naive-ui')['NDataTable']
23-
NDescriptions: typeof import('naive-ui')['NDescriptions']
24-
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
2521
NDivider: typeof import('naive-ui')['NDivider']
2622
NDrawer: typeof import('naive-ui')['NDrawer']
2723
NDrawerContent: typeof import('naive-ui')['NDrawerContent']
2824
NDropdown: typeof import('naive-ui')['NDropdown']
2925
NEllipsis: typeof import('naive-ui')['NEllipsis']
3026
NEmpty: typeof import('naive-ui')['NEmpty']
31-
NFl: typeof import('naive-ui')['NFl']
3227
NFlex: typeof import('naive-ui')['NFlex']
33-
NFlexl: typeof import('naive-ui')['NFlexl']
34-
NFom: typeof import('naive-ui')['NFom']
3528
NForm: typeof import('naive-ui')['NForm']
3629
NFormItem: typeof import('naive-ui')['NFormItem']
3730
NGi: typeof import('naive-ui')['NGi']
3831
NGrid: typeof import('naive-ui')['NGrid']
39-
NGridForm: typeof import('naive-ui')['NGridForm']
4032
NGridItem: typeof import('naive-ui')['NGridItem']
4133
NH3: typeof import('naive-ui')['NH3']
42-
NHighlight: typeof import('naive-ui')['NHighlight']
4334
NIcon: typeof import('naive-ui')['NIcon']
4435
NInfiniteScroll: typeof import('naive-ui')['NInfiniteScroll']
4536
NInput: typeof import('naive-ui')['NInput']
4637
NInputGroup: typeof import('naive-ui')['NInputGroup']
47-
NIocn: typeof import('naive-ui')['NIocn']
4838
NLayout: typeof import('naive-ui')['NLayout']
4939
NLayoutContent: typeof import('naive-ui')['NLayoutContent']
5040
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
51-
NList: typeof import('naive-ui')['NList']
52-
NListItem: typeof import('naive-ui')['NListItem']
5341
NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
5442
NMenu: typeof import('naive-ui')['NMenu']
5543
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
5644
NModal: typeof import('naive-ui')['NModal']
5745
NModalProvider: typeof import('naive-ui')['NModalProvider']
58-
NPopconfirm: typeof import('naive-ui')['NPopconfirm']
5946
NPopover: typeof import('naive-ui')['NPopover']
6047
NPopselect: typeof import('naive-ui')['NPopselect']
61-
NResult: typeof import('naive-ui')['NResult']
6248
NScrollbar: typeof import('naive-ui')['NScrollbar']
6349
NSelect: typeof import('naive-ui')['NSelect']
6450
NSpin: typeof import('naive-ui')['NSpin']
6551
NSwitch: typeof import('naive-ui')['NSwitch']
66-
NTabPane: typeof import('naive-ui')['NTabPane']
67-
NTabs: typeof import('naive-ui')['NTabs']
6852
NTag: typeof import('naive-ui')['NTag']
69-
NTex: typeof import('naive-ui')['NTex']
7053
NText: typeof import('naive-ui')['NText']
71-
NTooltip: typeof import('naive-ui')['NTooltip']
7254
RenderList: typeof import('./src/components/RenderList/index.vue')['default']
7355
RouterLink: typeof import('vue-router')['RouterLink']
7456
RouterView: typeof import('vue-router')['RouterView']

ui/src/renderer/src/App.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { useElectronConfig } from './hooks/useElectronConfig';
3232
import { getIconImage, getAvatarImage } from './utils/common';
3333
3434
import type { ConfigProviderProps } from 'naive-ui';
35-
35+
import { useRouter } from 'vue-router';
3636
import mittBus from './eventBus';
3737
import LoginModal from './components/LoginModal/index.vue';
3838
@@ -48,6 +48,7 @@ const {
4848
} = useUserAccount();
4949
5050
const userStore = useUserStore();
51+
const router = useRouter();
5152
5253
const defaultLang = ref('');
5354
const defaultTheme = ref('');
@@ -135,6 +136,9 @@ onMounted(async () => {
135136
if (!userStore.token || (userStore.userInfo && userStore.userInfo.length <= 0)) {
136137
handleModalOpacity();
137138
}
139+
if (userStore.userInfo.length > 0) {
140+
router.push({ name: 'Linux' });
141+
}
138142
139143
window.electron.ipcRenderer.on('set-token', (_e, token: string) => handleTokenReceived(token));
140144

ui/src/renderer/src/router/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const routes: RouteRecordRaw[] = [
66
path: '/',
77
name: 'homePage',
88
component: () => import('../layouts/index.vue'),
9+
redirect: '',
910
children: [
1011
{
1112
path: 'linux',

0 commit comments

Comments
 (0)