Skip to content

Commit

Permalink
[UI/UX] Replace native dialogs (#1891)
Browse files Browse the repository at this point in the history
* replaced native uninstall dialog box with uninstall modal

* refactoring into dialog handler to reduce boilerplate

* refactor and rm showErrorBox and openMessageBox

* refactor showMessageBox in backend into frontend modals, improved dialog handler

* ButtonOptions interface, DialotType enum, generic showDialogBoxModalAuto fxn, refactor error dialog into message box modal, uninstall modal closes immediately on input

* rename showErrorBoxModalAuto to showDialog, close messageBoxModal on button click, optimization for linux uninstall modal

* updating arguments for showDialogBoxModalAuto backend and button options interface frontend

* C:/Program Files/Git/src/ absolute import alias refactor

* fix import

* removing enum from common types so imports work

* backend now can use absolute imports

* updating tests

* tests again

* replace @@ with src folder names

* max width on dialog modal

* add back removed stuff

* rename to showDialogBoxModalAuto
  • Loading branch information
BrettCleary committed Oct 20, 2022
1 parent bc79812 commit a03347e
Show file tree
Hide file tree
Showing 48 changed files with 847 additions and 600 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@
"typescript": "^4.6.3",
"vite": "^3.0.3",
"vite-plugin-electron": "^0.8.3",
"vite-plugin-svgr": "^2.2.1",
"vite-tsconfig-paths": "^3.5.0"
"vite-plugin-svgr": "^2.2.1"
}
}
2 changes: 1 addition & 1 deletion src/backend/api/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
InstallPlatform,
ConnectivityChangedCallback,
ConnectivityStatus
} from '../../common/types'
} from 'common/types'

export const notify = (notification: string[]) =>
ipcRenderer.send('Notify', notification)
Expand Down
4 changes: 1 addition & 3 deletions src/backend/api/library.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ipcRenderer } from 'electron'
import { Runner, InstallParams, LaunchParams } from '../../common/types'
import { Runner, InstallParams, LaunchParams } from 'common/types'

export const removeFolder = (args: [path: string, folderName: string]) =>
ipcRenderer.send('removeFolder', args)
Expand All @@ -9,8 +9,6 @@ export const openDialog = async (args: Electron.OpenDialogOptions) =>

export const install = async (args: InstallParams) =>
ipcRenderer.invoke('install', args)
export const openMessageBox = async (args: Electron.MessageBoxOptions) =>
ipcRenderer.invoke('openMessageBox', args)
export const uninstall = async (
args: [appName: string, shouldRemovePrefix: boolean, runner: Runner]
) => ipcRenderer.invoke('uninstall', args)
Expand Down
2 changes: 1 addition & 1 deletion src/backend/api/menu.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ipcRenderer } from 'electron'
import { Runner } from '../../common/types'
import { Runner } from 'common/types'

export const removeShortcut = (appName: string, runner: Runner) =>
ipcRenderer.send('removeShortcut', appName, runner)
Expand Down
16 changes: 11 additions & 5 deletions src/backend/api/misc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GOGCloudSavesLocation } from 'common/types/gog'
import { ipcRenderer } from 'electron'
import { Runner, Tools } from '../../common/types'
import { Runner, Tools, ButtonOptions, DialogType } from 'common/types'

export const clearCache = () => ipcRenderer.send('clearCache')
export const resetHeroic = () => ipcRenderer.send('resetHeroic')
Expand Down Expand Up @@ -83,12 +83,18 @@ export const clipboardReadText = async () =>
export const clipboardWriteText = async (text: string) =>
ipcRenderer.send('clipboardWriteText', text)

export const handleShowErrorDialog = (
onError: (e: Electron.IpcRendererEvent, title: string, error: string) => void
export const handleShowDialog = (
onMessage: (
e: Electron.IpcRendererEvent,
title: string,
message: string,
type: DialogType,
buttons?: Array<ButtonOptions>
) => void
) => {
ipcRenderer.on('showErrorDialog', onError)
ipcRenderer.on('showDialog', onMessage)
return () => {
ipcRenderer.removeListener('showErrorDialog', onError)
ipcRenderer.removeListener('showDialog', onMessage)
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/backend/api/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ export const showUpdateSetting = async () =>
ipcRenderer.invoke('showUpdateSetting')
export const egsSync = async (args: string) =>
ipcRenderer.invoke('egsSync', args)
export const showErrorBox = async (args: [title: string, message: string]) =>
ipcRenderer.invoke('showErrorBox', args)

export const showLogFileInFolder = (args: {
appName: string
Expand Down
2 changes: 1 addition & 1 deletion src/backend/api/wine.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ipcRenderer } from 'electron'
import { RuntimeName, WineVersionInfo } from '../../common/types'
import { RuntimeName, WineVersionInfo } from 'common/types'
import { ProgressInfo, State } from 'heroic-wine-downloader'

export const toggleDXVK = (
Expand Down
2 changes: 1 addition & 1 deletion src/backend/dialog/__mocks__/dialog.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const dialog = jest.requireActual('../dialog')

dialog.showErrorBoxModalAuto = jest.fn()
dialog.showDialogBoxModalAuto = jest.fn()

module.exports = dialog
export {}
41 changes: 33 additions & 8 deletions src/backend/dialog/dialog.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,55 @@
import { LogPrefix, logWarning } from '../logger/logger'
import { BrowserWindow, dialog } from 'electron'
import { ButtonOptions, DialogType } from 'common/types'

const { showErrorBox } = dialog
const { showErrorBox, showMessageBox } = dialog

function showErrorBoxModalAuto(props: {
function showDialogBoxModalAuto(props: {
event?: Electron.IpcMainInvokeEvent
title: string
error: string
message: string
type: DialogType
buttons?: Array<ButtonOptions>
}) {
if (props.event) {
props.event.sender.send('showErrorDialog', props.title, props.error)
props.event.sender.send(
'showDialog',
props.title,
props.message,
props.type,
props.buttons
)
} else {
let window: BrowserWindow | null
try {
window = BrowserWindow.getFocusedWindow()
if (!window) {
window = BrowserWindow.getAllWindows()[0]
}
window.webContents.send('showErrorDialog', props.title, props.error)
window.webContents.send(
'showDialog',
props.title,
props.message,
props.type,
props.buttons
)
} catch (error) {
logWarning(['showErrorBoxModalAuto:', error], {
logWarning(['showDialogBoxModalAuto:', error], {
prefix: LogPrefix.Backend
})
showErrorBox(props.title, props.error)
switch (props.type) {
case 'ERROR':
showErrorBox(props.title, props.message)
break
default:
showMessageBox(BrowserWindow.getAllWindows()[0], {
title: props.title,
message: props.message
})
break
}
}
}
}

export { showErrorBoxModalAuto }
export { showDialogBoxModalAuto }
10 changes: 0 additions & 10 deletions src/backend/dialog/ipc_handler.ts

This file was deleted.

12 changes: 7 additions & 5 deletions src/backend/gog/games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import {
GogInstallPlatform
} from 'common/types/gog'
import { t } from 'i18next'
import { showErrorBoxModalAuto } from '../dialog/dialog'
import { showDialogBoxModalAuto } from '../dialog/dialog'

class GOGGame extends Game {
public appName: string
Expand Down Expand Up @@ -337,9 +337,10 @@ class GOGGame extends Game {
this.logFileLocation,
`Launch aborted: ${launchPrepFailReason}`
)
showErrorBoxModalAuto({
showDialogBoxModalAuto({
title: t('box.error.launchAborted', 'Launch aborted'),
error: launchPrepFailReason!
message: launchPrepFailReason!,
type: 'ERROR'
})
return false
}
Expand All @@ -365,9 +366,10 @@ class GOGGame extends Game {
`Launch aborted: ${wineLaunchPrepFailReason}`
)
if (wineLaunchPrepFailReason) {
showErrorBoxModalAuto({
showDialogBoxModalAuto({
title: t('box.error.launchAborted', 'Launch aborted'),
error: wineLaunchPrepFailReason
message: wineLaunchPrepFailReason!,
type: 'ERROR'
})
}
return false
Expand Down
23 changes: 13 additions & 10 deletions src/backend/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import { spawn } from 'child_process'
import shlex from 'shlex'
import { Game } from './games'
import { isOnline } from './online_monitor'
import { showErrorBoxModalAuto } from './dialog/dialog'
import { showDialogBoxModalAuto } from './dialog/dialog'

async function prepareLaunch(
game: LegendaryGame | GOGGame,
Expand Down Expand Up @@ -172,16 +172,17 @@ async function prepareWineLaunch(game: LegendaryGame | GOGGame): Promise<{
)
)
if (!bottleExists) {
showErrorBoxModalAuto({
showDialogBoxModalAuto({
title: i18next.t(
'box.error.cx-bottle-not-found.title',
'CrossOver bottle not found'
),
error: i18next.t(
message: i18next.t(
'box.error.cx-bottle-not-found.message',
`The CrossOver bottle "{{bottle_name}}" does not exist, can't launch!`,
{ bottle_name: gameSettings.wineCrossoverBottle }
)
),
type: 'ERROR'
})
return { success: false }
}
Expand Down Expand Up @@ -394,27 +395,29 @@ export async function validWine(
const wineBin = wineVersion.bin

if (!wineBin) {
showErrorBoxModalAuto({
showDialogBoxModalAuto({
title: i18next.t('box.error.wine-not-found.title', 'Wine Not Found'),
error: i18next.t(
message: i18next.t(
'box.error.wine-not-found.message',
'No Wine Version Selected. Check Game Settings!'
)
),
type: 'ERROR'
})
return false
}

if (!existsSync(wineBin)) {
showErrorBoxModalAuto({
showDialogBoxModalAuto({
title: i18next.t('box.error.wine-not-found.title', 'Wine Not Found'),
error: i18next.t('box.error.wine-not-found.invalid', {
message: i18next.t('box.error.wine-not-found.invalid', {
defaultValue:
"The selected wine version was not found. Install it or select a different version in the game's settings{{newline}}Version: {{version}}{{newline}}Path: {{path}}",
version: wineVersion.name,
path: wineBin,
newline: '\n',
interpolation: { escapeValue: false }
})
}),
type: 'ERROR'
})
return false
}
Expand Down
12 changes: 7 additions & 5 deletions src/backend/legendary/games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { removeNonSteamGame } from '../shortcuts/nonesteamgame/nonesteamgame'
import shlex from 'shlex'
import { t } from 'i18next'
import { isOnline } from '../online_monitor'
import { showErrorBoxModalAuto } from '../dialog/dialog'
import { showDialogBoxModalAuto } from '../dialog/dialog'

class LegendaryGame extends Game {
public appName: string
Expand Down Expand Up @@ -578,9 +578,10 @@ class LegendaryGame extends Game {
this.logFileLocation,
`Launch aborted: ${launchPrepFailReason}`
)
showErrorBoxModalAuto({
showDialogBoxModalAuto({
title: t('box.error.launchAborted', 'Launch aborted'),
error: launchPrepFailReason!
message: launchPrepFailReason!,
type: 'ERROR'
})
return false
}
Expand Down Expand Up @@ -611,9 +612,10 @@ class LegendaryGame extends Game {
`Launch aborted: ${wineLaunchPrepFailReason}`
)
if (wineLaunchPrepFailReason) {
showErrorBoxModalAuto({
showDialogBoxModalAuto({
title: t('box.error.launchAborted', 'Launch aborted'),
error: wineLaunchPrepFailReason
message: wineLaunchPrepFailReason!,
type: 'ERROR'
})
}
return false
Expand Down
9 changes: 5 additions & 4 deletions src/backend/logger/__tests__/logger.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as logger from '../logger'
import { appendMessageToLogFile } from '../logfile'
import { showErrorBoxModalAuto } from '../../dialog/dialog'
import { showDialogBoxModalAuto } from '../../dialog/dialog'

jest.mock('../logfile')
jest.mock('../../dialog/dialog')
Expand All @@ -12,7 +12,7 @@ const testData = [
'normalString',
['string1', 'string2'],
{ key1: 100, key2: 'value', key3: { subKey: ['hello', 'world'] } },
new Error('FAILED')
'Error: FAILED'
]

type logLevel = 'WARNING' | 'ERROR' | 'INFO' | 'DEBUG'
Expand Down Expand Up @@ -122,9 +122,10 @@ describe('logger/logger.ts', () => {
showDialog: true
})

expect(showErrorBoxModalAuto).toBeCalledWith({
expect(showDialogBoxModalAuto).toBeCalledWith({
title: 'Backend',
error: expect.stringContaining(getStringPassedToLogFile(level, true))
message: getStringPassedToLogFile(level, true),
type: 'ERROR'
})
})
})
Expand Down
7 changes: 4 additions & 3 deletions src/backend/logger/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Note that with console.log and console.warn everything will be saved too.
* error equals console.error
*/
import { showErrorBoxModalAuto } from '../dialog/dialog'
import { showDialogBoxModalAuto } from '../dialog/dialog'
import { appendMessageToLogFile, getLongestPrefix } from './logfile'

export enum LogPrefix {
Expand Down Expand Up @@ -119,9 +119,10 @@ function logBase(
}

if (options?.showDialog) {
showErrorBoxModalAuto({
showDialogBoxModalAuto({
title: options?.prefix ?? LogPrefix.Backend,
error: text
message: text,
type: 'ERROR'
})
}

Expand Down

0 comments on commit a03347e

Please sign in to comment.