Skip to content

Commit 30b6737

Browse files
authored
[Tech] Refactor overlay (#923)
* refactor overlay * fixes * update overlay
1 parent ba87152 commit 30b6737

File tree

19 files changed

+237
-76
lines changed

19 files changed

+237
-76
lines changed

.github/workflows/submodules-are-merged.yml

-25
This file was deleted.

.gitmodules

-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
[submodule "src/backend/hyperplay-overlay"]
2-
path = src/backend/hyperplay-overlay
3-
url = https://github.com/HyperPlay-Gaming/hyperplay-overlay.git

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
"@fortawesome/react-fontawesome": "^0.1.18",
170170
"@hyperplay/check-disk-space": "^3.5.2",
171171
"@hyperplay/ui": "^1.5.9",
172-
"@hyperplay/utils": "^0.0.12",
172+
"@hyperplay/utils": "^0.0.14",
173173
"@mantine/carousel": "^7.5.1",
174174
"@mantine/core": "^7.5.1",
175175
"@mantine/dropzone": "^7.5.1",
@@ -364,6 +364,7 @@
364364
"@hyperplay/extension-importer": "^0.0.4",
365365
"@hyperplay/extension-provider": "^0.0.6",
366366
"@hyperplay/mock-backend": "^0.0.1",
367+
"@hyperplay/overlay": "^0.0.6",
367368
"@hyperplay/providers": "^0.0.5",
368369
"@hyperplay/proxy-server": "^0.0.11"
369370
},

src/backend/api/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as Proxy from './proxy'
99
import * as DownloadManager from './downloadmanager'
1010
import * as Extensions from './extensionImporter'
1111
import * as Metrics from './metrics'
12-
import * as Overlay from 'backend/hyperplay-overlay/api'
12+
import * as Overlay from 'backend/overlay/api'
1313
import * as Achievements from './questsAchievements'
1414

1515
export default {

src/backend/extension/importer/index.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@ import store from './store'
33
import { HyperPlayAPI } from '@hyperplay/utils'
44
import './backendEventHandlers'
55
import './ipcHandler'
6+
import { LogPrefix, logError } from 'backend/logger/logger'
67

78
export const initExtension = async function (api: HyperPlayAPI) {
8-
const extensionImporter = await import('@hyperplay/extension-importer')
9-
const isInitialized = store.get('isInitialized', false)
10-
extensionImporter.initExtension(api, session.defaultSession, isInitialized)
9+
try {
10+
const extensionImporter = await import('@hyperplay/extension-importer')
11+
const isInitialized = store.get('isInitialized', false)
12+
extensionImporter.initExtension(api, session.defaultSession, isInitialized)
13+
} catch (err) {
14+
logError(`Error initializing extension ${err}`, LogPrefix.HyperPlay)
15+
}
1116
}

src/backend/hyperplay-overlay

-1
This file was deleted.

src/backend/launcher.ts

+17-8
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ import { isOnline } from './online_monitor'
5858
import { showDialogBoxModalAuto } from './dialog/dialog'
5959
import { legendarySetup } from './storeManagers/legendary/setup'
6060
import { gameManagerMap } from 'backend/storeManagers'
61-
import { closeOverlay, openOverlay } from 'backend/hyperplay-overlay'
6261
import * as VDF from '@node-steam/vdf'
6362
import { readFileSync } from 'fs'
6463
import { LegendaryCommand } from './storeManagers/legendary/commands'
6564
import { commandToArgsArray } from './storeManagers/legendary/library'
6665
import { searchForExecutableOnPath } from './utils/os/path'
66+
import { getHpOverlay } from './overlay'
6767

6868
async function prepareLaunch(
6969
gameSettings: GameSettings,
@@ -652,6 +652,7 @@ async function runWineCommand({
652652
const wineBin = wineVersion.bin.replaceAll("'", '')
653653

654654
logDebug(['Running Wine command:', commandParts.join(' ')], LogPrefix.Backend)
655+
const hpOverlay = await getHpOverlay()
655656

656657
return new Promise<{ stderr: string; stdout: string }>((res) => {
657658
const wrappers = options?.wrappers || []
@@ -672,7 +673,7 @@ async function runWineCommand({
672673

673674
if (overlayInfo) {
674675
const { showOverlay, appName, runner } = overlayInfo
675-
if (showOverlay) openOverlay(appName, runner)
676+
if (showOverlay) hpOverlay?.openOverlay(appName, runner)
676677
}
677678

678679
if (!logsDisabled) {
@@ -735,18 +736,24 @@ async function runWineCommand({
735736

736737
if (overlayInfo) {
737738
const { showOverlay } = overlayInfo
738-
if (showOverlay) closeOverlay()
739+
if (showOverlay) {
740+
const hpOverlay = await getHpOverlay()
741+
hpOverlay?.closeOverlay()
742+
}
739743
}
740744

741745
res(response)
742746
})
743747

744-
child.on('error', (error) => {
748+
child.on('error', async (error) => {
745749
console.log(error)
746750

747751
if (overlayInfo) {
748752
const { showOverlay } = overlayInfo
749-
if (showOverlay) closeOverlay()
753+
if (showOverlay) {
754+
const hpOverlay = await getHpOverlay()
755+
hpOverlay?.closeOverlay()
756+
}
750757
}
751758
})
752759
})
@@ -813,6 +820,7 @@ async function callRunner(
813820
if (currentPromise) {
814821
return currentPromise
815822
}
823+
const hpOverlay = await getHpOverlay()
816824

817825
let promise = new Promise<ExecResult>((res, rej) => {
818826
const child = spawn(bin, commandParts, {
@@ -826,7 +834,8 @@ async function callRunner(
826834
(gameInfo.runner === 'hyperplay' ||
827835
(gameInfo.runner === 'sideload' && gameInfo.web3?.supported))
828836

829-
if (shouldOpenOverlay) openOverlay(gameInfo?.app_name, gameInfo.runner)
837+
if (shouldOpenOverlay)
838+
hpOverlay?.openOverlay(gameInfo?.app_name, gameInfo.runner)
830839

831840
const stdout: string[] = []
832841
const stderr: string[] = []
@@ -879,7 +888,7 @@ async function callRunner(
879888
})
880889

881890
child.on('close', (code, signal) => {
882-
if (shouldOpenOverlay) closeOverlay()
891+
if (shouldOpenOverlay) hpOverlay?.closeOverlay()
883892
errorHandler({
884893
error: `${stdout.join().concat(stderr.join())}`,
885894
logPath: options?.logFile,
@@ -898,7 +907,7 @@ async function callRunner(
898907
})
899908

900909
child.on('error', (error) => {
901-
if (shouldOpenOverlay) closeOverlay()
910+
if (shouldOpenOverlay) hpOverlay?.closeOverlay()
902911
rej(error)
903912
})
904913
})

src/backend/main.ts

+23-15
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ import { legendarySetup } from 'backend/storeManagers/legendary/setup'
150150

151151
import * as Sentry from '@sentry/electron'
152152
import { DEV_PORTAL_URL, devSentryDsn, prodSentryDsn } from 'common/constants'
153+
import { getHpOverlay, initOverlay } from './overlay'
153154

154155
/*
155156
* INSERT OTHER IPC HANDLERS HERE
@@ -175,11 +176,6 @@ import { metricsAreEnabled, trackEvent } from './metrics/metrics'
175176
import { hpLibraryStore } from './storeManagers/hyperplay/electronStore'
176177
import { libraryStore as sideloadLibraryStore } from 'backend/storeManagers/sideload/electronStores'
177178
import { backendEvents } from 'backend/backend_events'
178-
import {
179-
closeOverlay,
180-
overlayIsRunning,
181-
toggleOverlay
182-
} from 'backend/hyperplay-overlay'
183179
import { PROVIDERS } from 'common/types/proxy-types'
184180
import 'backend/ipcHandlers/quests'
185181
import 'backend/ipcHandlers/achievements'
@@ -304,7 +300,7 @@ async function completeHyperPlayQuest() {
304300
async function initializeWindow(): Promise<BrowserWindow> {
305301
createNecessaryFolders()
306302
configStore.set('userHome', userHome)
307-
mainWindow = createMainWindow()
303+
mainWindow = await createMainWindow()
308304

309305
mainWindow.webContents.on('input-event', (ev, inputEv) => {
310306
if (eventsToCloseMetaMaskPopupOn.includes(inputEv.type)) {
@@ -415,10 +411,11 @@ if (!gotTheLock) {
415411
logInfo('HyperPlay is already running, quitting this instance')
416412
app.quit()
417413
} else {
418-
app.on('second-instance', (event, argv) => {
414+
app.on('second-instance', async (event, argv) => {
419415
// Someone tried to run a second instance, we should focus the overlay or the main window if no overlay is running.
420-
if (overlayIsRunning()) {
421-
toggleOverlay({ action: 'ON' })
416+
const hpOverlay = await getHpOverlay()
417+
if (hpOverlay?.overlayIsRunning()) {
418+
hpOverlay.toggleOverlay({ action: 'ON' })
422419
} else {
423420
const mainWindow = getMainWindow()
424421
mainWindow?.show()
@@ -457,12 +454,21 @@ if (!gotTheLock) {
457454
])
458455

459456
// keyboards with alt and no option key can be used with mac so register both
457+
const hpOverlay = await getHpOverlay()
458+
const toggle =
459+
hpOverlay?.toggleOverlay ??
460+
(() =>
461+
logInfo(
462+
'Cannot toggle overlay without @hyperplay/overlay package',
463+
LogPrefix.HyperPlay
464+
))
460465
const openOverlayAccelerator = 'Alt+X'
461-
globalShortcut.register(openOverlayAccelerator, toggleOverlay)
466+
globalShortcut.register(openOverlayAccelerator, toggle)
462467
const openOverlayAcceleratorMac = 'Option+X'
463-
globalShortcut.register(openOverlayAcceleratorMac, toggleOverlay)
468+
globalShortcut.register(openOverlayAcceleratorMac, toggle)
464469

465470
initExtension(hpApi)
471+
initOverlay(hpApi)
466472

467473
initOnlineMonitor()
468474

@@ -2011,12 +2017,14 @@ ipcMain.on('openAuthModalIfAppReloads', () => {
20112017
onboardLocalStore.set('openAuthModalIfAppReloads', true)
20122018
})
20132019

2014-
ipcMain.on('killOverlay', () => {
2015-
closeOverlay()
2020+
ipcMain.on('killOverlay', async () => {
2021+
const hpOverlay = await getHpOverlay()
2022+
hpOverlay?.closeOverlay()
20162023
})
20172024

2018-
ipcMain.on('toggleOverlay', () => {
2019-
toggleOverlay()
2025+
ipcMain.on('toggleOverlay', async () => {
2026+
const hpOverlay = await getHpOverlay()
2027+
hpOverlay?.toggleOverlay()
20202028
})
20212029

20222030
ipcMain.handle('getHyperPlayListings', async () => {

src/backend/main_window.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { BrowserWindow, screen, app } from 'electron'
22
import path from 'path'
33
import { configStore } from './constants'
4-
import { controlWindow } from './hyperplay-overlay/model'
4+
import { getHpOverlay } from './overlay'
55

66
let mainWindow: BrowserWindow | null = null
77

@@ -41,7 +41,7 @@ const hiddenPhrase = 'superhyper123'
4141
let hiddenPhraseCurrentIndex = 0
4242

4343
// creates the mainWindow based on the configuration
44-
export const createMainWindow = () => {
44+
export const createMainWindow = async () => {
4545
let windowProps: Electron.Rectangle = {
4646
height: minSupportedResolution.height,
4747
width: minSupportedResolution.width,
@@ -92,7 +92,8 @@ export const createMainWindow = () => {
9292
}
9393
})
9494

95-
controlWindow(mainWindow.webContents.id, 'mainWindow')
95+
const hpOverlay = await getHpOverlay()
96+
hpOverlay?.controlWindow(mainWindow.webContents.id, 'mainWindow')
9697

9798
mainWindow.webContents?.on('before-input-event', (ev, input) => {
9899
if (

src/backend/overlay/api.ts

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import {
2+
PROVIDERS,
3+
OverlayRenderState,
4+
OverlayMode,
5+
ToastKey
6+
} from '@hyperplay/utils'
7+
import { Toast } from './types'
8+
import { ipcRenderer } from 'electron'
9+
10+
// TODO share with desktop client
11+
type WrapRendererCallback<
12+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13+
TFunction extends (...args: any) => any
14+
> = (
15+
e: Electron.IpcRendererEvent,
16+
...args: [...Parameters<TFunction>]
17+
) => ReturnType<TFunction>
18+
19+
function getHandleFunction<
20+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
21+
Handler extends WrapRendererCallback<(...args: any[]) => void>
22+
>(topic: string) {
23+
return (cb: Handler) => {
24+
ipcRenderer.on(topic, cb)
25+
return () => {
26+
ipcRenderer.removeListener(topic, cb)
27+
}
28+
}
29+
}
30+
31+
export const getExtensionId = async () => ipcRenderer.invoke('getExtensionId')
32+
33+
export const handleStateUpdate = {
34+
overlay: {
35+
renderState: getHandleFunction<
36+
WrapRendererCallback<(renderState: OverlayRenderState) => void>
37+
>('overlay_state_update_renderState'),
38+
isFullscreenOverlay: getHandleFunction<
39+
WrapRendererCallback<(isFullscreenOverlay: boolean) => void>
40+
>('overlay_state_update_isFullscreenOverlay'),
41+
showOverlay: getHandleFunction<
42+
WrapRendererCallback<(showOverlay: boolean) => void>
43+
>('overlay_state_update_showOverlay'),
44+
title: getHandleFunction<
45+
WrapRendererCallback<(title: OverlayMode) => void>
46+
>('overlay_state_update_title')
47+
},
48+
extension: {
49+
isPopupOpen: getHandleFunction<
50+
WrapRendererCallback<(isPopupOpen: boolean) => void>
51+
>('extension_state_update_isPopupOpen'),
52+
isNotificationOpen: getHandleFunction<
53+
WrapRendererCallback<(isNotificationOpen: boolean) => void>
54+
>('extension_state_update_isNotificationOpen')
55+
},
56+
transaction: {
57+
isInitialToastShown: getHandleFunction<
58+
WrapRendererCallback<(isInitialToastShown: boolean) => void>
59+
>('transaction_state_update_isInitialToastShown'),
60+
latestToast: getHandleFunction<
61+
WrapRendererCallback<(latestToast: Toast) => void>
62+
>('transaction_state_update_latestToast')
63+
},
64+
walletState: {
65+
address: getHandleFunction<WrapRendererCallback<(address: string) => void>>(
66+
'wallet_state_update_address'
67+
),
68+
isConnected: getHandleFunction<
69+
WrapRendererCallback<(isConnected: boolean) => void>
70+
>('wallet_state_update_isConnected'),
71+
provider: getHandleFunction<
72+
WrapRendererCallback<(provider: PROVIDERS) => void>
73+
>('wallet_state_update_provider'),
74+
otp: getHandleFunction<WrapRendererCallback<(otp: string) => void>>(
75+
'wallet_state_update_otp'
76+
)
77+
}
78+
}
79+
80+
export const initialState = {
81+
walletState: {
82+
address: async () => ipcRenderer.invoke('get_wallet_state_address'),
83+
isConnected: async () => ipcRenderer.invoke('get_wallet_state_isConnected'),
84+
provider: async () => ipcRenderer.invoke('get_wallet_state_provider'),
85+
otp: async () => ipcRenderer.invoke('get_wallet_state_otp')
86+
},
87+
extensionState: {
88+
isPopupOpen: async () =>
89+
ipcRenderer.invoke('get_extension_state_isPopupOpen')
90+
}
91+
}
92+
export const toggleIsPopupOpen = () => ipcRenderer.send('toggleIsPopupOpen')
93+
94+
export const showPopup = () => ipcRenderer.send('showPopup')
95+
96+
export const overlayReady = () => ipcRenderer.send('overlayReady')
97+
98+
export const toastCloseOnClick = (key: ToastKey) =>
99+
ipcRenderer.send('toastCloseOnClick', key)
100+
101+
export const lockPopup = (lock: boolean) => ipcRenderer.send('lockPopup', lock)
102+
103+
export const killOverlay = () => ipcRenderer.send('killOverlay')
104+
105+
export const toggleOverlay = () => ipcRenderer.send('toggleOverlay')

0 commit comments

Comments
 (0)