Skip to content

Commit d32cf27

Browse files
Merge pull request #2547 from RedisInsight/feature/RI-4723-open_RI_from_SM
Feature/ri 4723 open ri from sm
2 parents bdeda3f + e70d745 commit d32cf27

File tree

65 files changed

+1226
-330
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1226
-330
lines changed

redisinsight/desktop/app.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ import {
1616
} from 'desktopSrc/lib'
1717
import { wrapErrorMessageSensitiveData } from 'desktopSrc/utils'
1818
import { configMain as config } from 'desktopSrc/config'
19+
import { deepLinkHandler, deepLinkWindowHandler } from 'desktopSrc/lib/app/deep-link.handlers'
1920

2021
if (!config.isProduction) {
2122
const sourceMapSupport = require('source-map-support')
2223
sourceMapSupport.install()
2324
}
2425

26+
let deepLink: undefined | string
27+
2528
const init = async () => {
2629
await launchApiServer()
2730
initLogging()
@@ -45,23 +48,42 @@ const init = async () => {
4548
try {
4649
await app.whenReady()
4750

48-
// todo: create and move to some on app ready handler
51+
deepLink = process.argv?.[1] || deepLink
52+
4953
// deep linking
5054
// register our application to handle custom protocol
5155
if (process.defaultApp) {
52-
if (process.argv.length >= 2) {
53-
app.setAsDefaultProtocolClient(config.schema, process.execPath, [path.resolve(process.argv[1])])
56+
if (deepLink) {
57+
app.setAsDefaultProtocolClient(config.schema, process.execPath, [path.resolve(deepLink)])
5458
}
5559
} else {
5660
app.setAsDefaultProtocolClient(config.schema)
5761
}
5862

5963
const splashWindow = await windowFactory(WindowType.Splash)
60-
await windowFactory(WindowType.Main, splashWindow)
64+
65+
let parsedDeepLink
66+
67+
if (deepLink) {
68+
parsedDeepLink = await deepLinkHandler(deepLink)
69+
}
70+
71+
await windowFactory(WindowType.Main, splashWindow, { parsedDeepLink })
6172
} catch (_err) {
6273
const error = _err as Error
6374
console.log(wrapErrorMessageSensitiveData(error))
6475
}
6576
}
6677

78+
// deep link open (darwin)
79+
// if app is not ready then we store url and continue in init function
80+
app.on('open-url', async (event, url) => {
81+
event.preventDefault()
82+
83+
deepLink = url
84+
if (app.isReady()) {
85+
await deepLinkWindowHandler(await deepLinkHandler(url))
86+
}
87+
})
88+
6789
export default init

redisinsight/desktop/preload.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ contextBridge.exposeInMainWorld('app', {
2222
cloudOauthCallback: ((connected: any) => {
2323
ipcRenderer.on(IpcOnEvent.cloudOauthCallback, connected)
2424
}),
25+
deepLinkAction: ((parsedDeepLink: any) => {
26+
ipcRenderer.on(IpcOnEvent.deepLinkAction, parsedDeepLink)
27+
}),
2528
ipc: ipcHandler,
2629
config: {
2730
apiPort: config.apiPort

redisinsight/desktop/src/lib/app/app.handlers.ts

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { app } from 'electron'
22
import log from 'electron-log'
3-
import { getBackendGracefulShutdown, WindowType, getWindows, windowFactory, windows } from 'desktopSrc/lib'
4-
import { deepLinkHandler } from 'desktopSrc/lib/app/deep-link.handlers'
3+
import { getBackendGracefulShutdown, WindowType, getWindows, windowFactory } from 'desktopSrc/lib'
4+
import { deepLinkHandler, deepLinkWindowHandler } from 'desktopSrc/lib/app/deep-link.handlers'
55

66
export const initAppHandlers = () => {
77
app.on('activate', () => {
@@ -44,27 +44,8 @@ export const initAppHandlers = () => {
4444
}
4545
})
4646

47-
// deep link open (unix)
48-
app.on('open-url', async (event, url) => {
49-
event.preventDefault()
50-
// todo: implement url handler to map url to a proper function
51-
await deepLinkHandler(url)
52-
53-
if (windows.size) {
54-
const win = windows.values().next().value
55-
if (win.isMinimized()) win.restore()
56-
win.focus()
57-
}
58-
})
59-
60-
// deep link open (win)
47+
// deep link open (win + linux)
6148
app.on('second-instance', async (_event, commandLine) => {
62-
await deepLinkHandler(commandLine?.pop())
63-
// Someone tried to run a second instance, we should focus our window.
64-
if (windows.size) {
65-
const win = windows.values().next().value
66-
if (win.isMinimized()) win.restore()
67-
win.focus()
68-
}
49+
await deepLinkWindowHandler(await deepLinkHandler(commandLine?.pop()))
6950
})
7051
}
Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,54 @@
11
import log from 'electron-log'
22
import { parse } from 'url'
33
import {
4-
cloudDeepLinkHandler
4+
cloudDeepLinkHandler, focusWindow, getWindows, windowFactory, WindowType
55
} from 'desktopSrc/lib'
66
import { wrapErrorMessageSensitiveData } from 'desktopSrc/utils'
7+
import { IpcOnEvent } from 'uiSrc/electron/constants'
78

8-
export const deepLinkHandler = async (from?: string) => {
9-
if (!from) return
10-
try {
11-
const url = parse(from, true)
9+
export interface IParsedDeepLink {
10+
initialPage?: string
11+
target?: string
12+
from?: string
13+
}
14+
15+
export const deepLinkHandler = async (from?: string): Promise<undefined | IParsedDeepLink> => {
16+
if (from) {
17+
try {
18+
const url = parse(from, true)
19+
switch (url?.hostname) {
20+
case 'cloud':
21+
await cloudDeepLinkHandler(url)
22+
break
23+
default:
24+
return {
25+
from: encodeURIComponent(from),
26+
target: url.query?.target || '_self',
27+
initialPage: url.query?.initialPage,
28+
} as IParsedDeepLink
29+
}
30+
} catch (e) {
31+
log.error(wrapErrorMessageSensitiveData(e as Error))
32+
}
33+
}
34+
35+
return undefined
36+
}
37+
38+
export const deepLinkWindowHandler = async (parsedDeepLink?: IParsedDeepLink) => {
39+
// tbd: implement mechanism to find current window
40+
const [currentWindow] = getWindows().values()
1241

13-
switch (url?.hostname) {
14-
case 'cloud':
15-
await cloudDeepLinkHandler(url)
16-
break
17-
default:
18-
log.warn('Unknown deep link hostname', url?.hostname)
42+
if (parsedDeepLink) {
43+
if (parsedDeepLink?.target === '_blank') {
44+
await windowFactory(WindowType.Main, null, { parsedDeepLink })
45+
} else if (currentWindow) {
46+
currentWindow?.webContents.send(IpcOnEvent.deepLinkAction, parsedDeepLink)
47+
focusWindow(currentWindow)
48+
} else {
49+
await windowFactory(WindowType.Main, null, { parsedDeepLink })
1950
}
20-
} catch (e) {
21-
log.error(wrapErrorMessageSensitiveData(e as Error))
51+
} else if (currentWindow) {
52+
focusWindow(currentWindow)
2253
}
2354
}

redisinsight/desktop/src/lib/app/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { initWindowIPCHandlers } from 'desktopSrc/lib/window'
12
import { initAppHandlers } from './app.handlers'
23
import { initDialogHandlers } from './dialog.handlers'
34
import { initIPCHandlers } from './ipc.handlers'
@@ -6,4 +7,6 @@ export const initElectronHandlers = () => {
67
initAppHandlers()
78
initIPCHandlers()
89
initDialogHandlers()
10+
11+
initWindowIPCHandlers()
912
}

redisinsight/desktop/src/lib/window/browserWindow.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@ import contextMenu from 'electron-context-menu'
22
import { BrowserWindow } from 'electron'
33
import { v4 as uuidv4 } from 'uuid'
44

5+
import { IParsedDeepLink } from 'desktopSrc/lib/app/deep-link.handlers'
56
import { configMain as config } from 'desktopSrc/config'
67
import { updateTray } from 'desktopSrc/lib'
78
import { resolveHtmlPath } from 'desktopSrc/utils'
89
import { initWindowHandlers } from './window.handlers'
910

1011
export const windows = new Map<string, BrowserWindow>()
1112
export const getWindows = () => windows
13+
export const focusWindow = (win: BrowserWindow) => {
14+
if (win.isMinimized()) win.restore()
15+
win.focus()
16+
}
1217

1318
export enum WindowType {
1419
Splash = 'splash',
@@ -54,7 +59,7 @@ export const createWindow = async ({
5459
return newWindow
5560
}
5661

57-
newWindow.loadURL(resolveHtmlPath(htmlFileName))
62+
newWindow.loadURL(resolveHtmlPath(htmlFileName, options?.parsedDeepLink))
5863

5964
initWindowHandlers(newWindow, prevWindow, windows, id)
6065

@@ -69,7 +74,8 @@ export const createWindow = async ({
6974

7075
export const windowFactory = async (
7176
windowType: WindowType,
72-
prevWindow: BrowserWindow | null = null
77+
prevWindow: BrowserWindow | null = null,
78+
options?: { parsedDeepLink?: IParsedDeepLink }
7379
): Promise<BrowserWindow> => {
7480
switch (windowType) {
7581
case WindowType.Splash:
@@ -88,6 +94,7 @@ export const windowFactory = async (
8894
htmlFileName: 'index.html',
8995
windowType,
9096
options: {
97+
...options,
9198
...config.mainWindow,
9299
preloadPath: config.preloadPath
93100
}

redisinsight/desktop/src/lib/window/window.handlers.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { BrowserWindow, app, shell } from 'electron'
1+
import { BrowserWindow, app, shell, ipcMain } from 'electron'
22
import {
33
MenuBuilder,
44
getDisplayAppInTrayValue,
55
getIsQuiting,
66
getTray,
77
getTrayInstance,
8-
electronStore
8+
electronStore,
9+
windowFactory,
10+
WindowType,
911
} from 'desktopSrc/lib'
10-
import { ElectronStorageItem, IpcOnEvent } from 'uiSrc/electron/constants'
12+
import { IpcInvokeEvent, ElectronStorageItem, IpcOnEvent } from 'uiSrc/electron/constants'
13+
import { Pages } from 'uiSrc/constants/pages'
1114

1215
export const initWindowHandlers = (
1316
newWindow: BrowserWindow,
@@ -92,3 +95,9 @@ export const initWindowHandlers = (
9295
return { action: 'deny' }
9396
})
9497
}
98+
99+
export const initWindowIPCHandlers = () => {
100+
ipcMain.handle(IpcInvokeEvent.windowOpen, async (_event, { location }) => {
101+
await windowFactory(WindowType.Main, null, { parsedDeepLink: { initialPage: location } })
102+
})
103+
}
Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
/* eslint import/prefer-default-export: off */
2-
import { URL } from 'url'
2+
import { URL, URLSearchParams } from 'url'
33
import path from 'path'
44
import { configMain as config } from 'desktopSrc/config'
5+
import { IParsedDeepLink } from 'desktopSrc/lib/app/deep-link.handlers'
56

6-
export const resolveHtmlPath = (htmlFileName: string) => {
7+
export const resolveHtmlPath = (htmlFileName: string, parsedDeepLink?: IParsedDeepLink) => {
78
if (config.isDevelopment) {
89
const port = process.env.PORT || 1212
910
const url = new URL(`http://localhost:${port}`)
1011
url.pathname = htmlFileName
1112
return url.href
1213
}
13-
return `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}`
14+
15+
let resolved = `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}#/`
16+
17+
if (parsedDeepLink) {
18+
try {
19+
if (parsedDeepLink.initialPage) {
20+
const initialPage = parsedDeepLink.initialPage.slice(+parsedDeepLink.initialPage.startsWith('/'))
21+
resolved += initialPage
22+
}
23+
24+
const queryParameters = new URLSearchParams([
25+
['from', parsedDeepLink.from || ''],
26+
['target', parsedDeepLink.target || ''],
27+
])
28+
29+
resolved += `${resolved.indexOf('?') !== -1 ? '&' : '?'}${queryParameters.toString()}`
30+
} catch (e) {
31+
// todo: log error
32+
}
33+
}
34+
35+
return resolved
1436
}

redisinsight/ui/src/components/config/Config.spec.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ describe('Config', () => {
6969
getWBTutorials(),
7070
getFeatureFlags(),
7171
getUserConfigSettings(),
72+
setSettingsPopupState(false)
7273
]
7374
expect(store.getActions()).toEqual([...afterRenderActions])
7475
})

redisinsight/ui/src/components/config/Config.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,7 @@ const Config = () => {
141141
const specConsents = spec?.agreements
142142
const appliedConsents = config?.agreements
143143

144-
if (isDifferentConsentsExists(specConsents, appliedConsents)) {
145-
dispatch(setSettingsPopupState(true))
146-
}
144+
dispatch(setSettingsPopupState(isDifferentConsentsExists(specConsents, appliedConsents)))
147145
}
148146

149147
return null

0 commit comments

Comments
 (0)