Skip to content

Commit f04080f

Browse files
authored
[Feat] Add icons to a few select menus (#4546)
* Don't make `buttonWithIcon` center its contents * Add icons to all items in the GameSubMenu * Extract Wine Item in selector into its own component * Add icon to WineVersionListItem * Also use WineVersionListItem in the install modal Wine selector * Remove "Wine - " / "Proton - " prefix from wine version names This won't require any migration, since the Frontend will already find versions by binary path (which hasn't changed) * Add "Autorenew" icon to top-right of `-latest` Wine versions * Add icons to the install modal platform selector * Use "current" color for Proton logo * Add GE logo * Prefer `marginInlineEnd` to `marginRight` * Add icons to context menu entries
1 parent a4aa2bd commit f04080f

File tree

15 files changed

+919
-55
lines changed

15 files changed

+919
-55
lines changed

src/backend/utils/__tests__/compatibility_layers.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe('getDefaultWine', () => {
3737

3838
const result = getDefaultWine()
3939
expect(result.bin).toBe('/usr/bin/wine')
40-
expect(result.name).toBe('Wine Default - wine-6.0 (Staging)')
40+
expect(result.name).toBe('wine-6.0 (Staging)')
4141
expect(result.type).toBe('wine')
4242
})
4343
})

src/backend/utils/compatibility_layers.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ export function getDefaultWine(): WineInstallation {
3737
defaultWine.bin = wineBin
3838

3939
stdout = execSync(`wine --version`).toString()
40-
const version = stdout.split('\n')[0]
41-
defaultWine.name = `Wine Default - ${version}`
40+
defaultWine.name = stdout.split('\n')[0]
4241

4342
return {
4443
...defaultWine,
@@ -127,7 +126,7 @@ export async function getLinuxWineSet(
127126
const wineBin = join(toolsPath, 'wine', version, 'bin', 'wine')
128127
altWine.add({
129128
bin: wineBin,
130-
name: `Wine - ${version}`,
129+
name: version,
131130
type: 'wine',
132131
...getWineLibs(wineBin),
133132
...getWineExecs(wineBin)
@@ -142,7 +141,7 @@ export async function getLinuxWineSet(
142141
const wineBin = join(lutrisCompatPath, version, 'bin', 'wine')
143142
altWine.add({
144143
bin: wineBin,
145-
name: `Wine - ${version}`,
144+
name: version,
146145
type: 'wine',
147146
...getWineLibs(wineBin),
148147
...getWineExecs(wineBin)
@@ -180,7 +179,7 @@ export async function getLinuxWineSet(
180179
if (existsSync(protonBin)) {
181180
proton.add({
182181
bin: protonBin,
183-
name: `Proton - ${version}`,
182+
name: version,
184183
type: 'proton'
185184
// No need to run this.getWineExecs here since Proton ships neither Wineboot nor Wineserver
186185
})

src/frontend/assets/codeweavers_icon.svg

Lines changed: 346 additions & 0 deletions
Loading

src/frontend/assets/ge-logo.svg

Lines changed: 363 additions & 0 deletions
Loading

src/frontend/assets/proton_logo.svg

Lines changed: 6 additions & 0 deletions
Loading

src/frontend/screens/Game/GamePage/index.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@
307307
& .mainBtn {
308308
min-width: 200px;
309309
font-size: var(--text-md);
310+
display: flex;
311+
justify-content: center;
310312
white-space: nowrap;
311313

312314
span {

src/frontend/screens/Game/GameSubMenu/index.tsx

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,32 @@ import { useTranslation } from 'react-i18next'
99
import ContextProvider from 'frontend/state/ContextProvider'
1010
import { NavLink } from 'react-router-dom'
1111

12-
import { CircularProgress } from '@mui/material'
12+
import { CircularProgress, SvgIcon } from '@mui/material'
1313
import UninstallModal from 'frontend/components/UI/UninstallModal'
1414
import GameContext from '../GameContext'
1515
import { openInstallGameModal } from 'frontend/state/InstallGameModal'
1616
import useGlobalState from 'frontend/state/GlobalStateV2'
1717

18+
import {
19+
ArrowUpward as ArrowUpwardIcon,
20+
CheckCircle as CheckCircleIcon,
21+
Delete as DeleteIcon,
22+
DesktopAccessDisabled as DesktopAccessDisabledIcon,
23+
DriveFileMove as DriveFileMoveIcon,
24+
Edit as EditIcon,
25+
FindInPage as FindInPageIcon,
26+
Folder as FolderIcon,
27+
FormatListBulleted as FormatListBulletedIcon,
28+
Info as InfoIcon,
29+
PictureInPicture as PictureInPictureIcon,
30+
Repartition as RepartitionIcon,
31+
Shortcut as ShortcutIcon,
32+
ShoppingCart as ShoppingCartIcon
33+
} from '@mui/icons-material'
34+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
35+
import { faLinux, faSteam } from '@fortawesome/free-brands-svg-icons'
36+
import { faWineGlass } from '@fortawesome/free-solid-svg-icons'
37+
1838
interface Props {
1939
appName: string
2040
isInstalled: boolean
@@ -267,56 +287,63 @@ export default function GamesSubmenu({
267287
{isSideloaded && (
268288
<button
269289
onClick={async () => handleEdit()}
270-
className="link button is-text is-link"
290+
className="link button is-text is-link buttonWithIcon"
271291
>
292+
<EditIcon />
272293
{t('button.sideload.edit', 'Edit App/Game')}
273294
</button>
274295
)}{' '}
275296
<button
276297
onClick={() => handleShortcuts()}
277-
className="link button is-text is-link"
298+
className="link button is-text is-link buttonWithIcon"
278299
>
300+
<ShortcutIcon />
279301
{hasShortcuts
280302
? t('submenu.removeShortcut', 'Remove shortcuts')
281303
: t('submenu.addShortcut', 'Add shortcut')}
282304
</button>
283305
<button
284306
onClick={async () => setShowUninstallModal(true)}
285-
className="link button is-text is-link"
307+
className="link button is-text is-link buttonWithIcon"
286308
disabled={is.playing}
287309
>
310+
<DeleteIcon />
288311
{t('button.uninstall', 'Uninstall')}
289312
</button>{' '}
290313
{!isSideloaded && !isThirdPartyManaged && (
291314
<button
292315
onClick={async () => handleUpdate()}
293-
className="link button is-text is-link"
316+
className="link button is-text is-link buttonWithIcon"
294317
disabled={disableUpdate}
295318
>
319+
<ArrowUpwardIcon />
296320
{t('button.force_update', 'Force Update if Available')}
297321
</button>
298322
)}{' '}
299323
{!isSideloaded && !isThirdPartyManaged && (
300324
<button
301325
onClick={async () => handleMoveInstall()}
302-
className="link button is-text is-link"
326+
className="link button is-text is-link buttonWithIcon"
303327
>
328+
<DriveFileMoveIcon />
304329
{t('submenu.move', 'Move Game')}
305330
</button>
306331
)}{' '}
307332
{!isSideloaded && !isThirdPartyManaged && (
308333
<button
309334
onClick={async () => handleChangeInstall()}
310-
className="link button is-text is-link"
335+
className="link button is-text is-link buttonWithIcon"
311336
>
337+
<FindInPageIcon />
312338
{t('submenu.change', 'Change Install Location')}
313339
</button>
314340
)}{' '}
315341
{!isSideloaded && !isThirdPartyManaged && (
316342
<button
317343
onClick={async () => handleRepair(appName)}
318-
className="link button is-text is-link"
344+
className="link button is-text is-link buttonWithIcon"
319345
>
346+
<CheckCircleIcon />
320347
{t('submenu.verify', 'Verify and Repair')}
321348
</button>
322349
)}{' '}
@@ -326,9 +353,10 @@ export default function GamesSubmenu({
326353
refreshCircle()
327354
) : (
328355
<button
329-
className="link button is-text is-link"
356+
className="link button is-text is-link buttonWithIcon"
330357
onClick={handleEosOverlay}
331358
>
359+
<PictureInPictureIcon />
332360
{eosOverlayEnabled
333361
? t('submenu.disableEosOverlay', 'Disable EOS Overlay')
334362
: t('submenu.enableEosOverlay', 'Enable EOS Overlay')}
@@ -341,72 +369,87 @@ export default function GamesSubmenu({
341369
) : (
342370
<button
343371
onClick={async () => handleAddToSteam()}
344-
className="link button is-text is-link"
372+
className="link button is-text is-link buttonWithIcon"
345373
>
374+
<SvgIcon>
375+
<FontAwesomeIcon icon={faSteam} />
376+
</SvgIcon>
346377
{addedToSteam
347378
? t('submenu.removeFromSteam', 'Remove from Steam')
348379
: t('submenu.addToSteam', 'Add to Steam')}
349380
</button>
350381
)}
351382
<button
352383
onClick={() => openGameCategoriesModal(gameInfo)}
353-
className="link button is-text is-link"
384+
className="link button is-text is-link buttonWithIcon"
354385
>
386+
<FormatListBulletedIcon />
355387
{t('submenu.categories', 'Categories')}
356388
</button>
357389
{!isSideloaded && storeUrl && (
358390
<NavLink
359-
className="link button is-text is-link"
391+
className="link button is-text is-link buttonWithIcon"
360392
to={`/store-page?store-url=${storeUrl}`}
361393
>
394+
<ShoppingCartIcon />
362395
{t('submenu.store')}
363396
</NavLink>
364397
)}
365398
{!isSideloaded && !!changelog?.length && (
366399
<button
367400
onClick={() => handleChangeLog()}
368-
className="link button is-text is-link"
401+
className="link button is-text is-link buttonWithIcon"
369402
>
403+
<InfoIcon />
370404
{t('button.changelog', 'Show Changelog')}
371405
</button>
372406
)}{' '}
373407
{!isSideloaded && isLinux && (
374408
<button
375409
onClick={() => createNewWindow(protonDBurl)}
376-
className="link button is-text is-link"
410+
className="link button is-text is-link buttonWithIcon"
377411
>
412+
<SvgIcon>
413+
<FontAwesomeIcon icon={faLinux} />
414+
</SvgIcon>
378415
{t('submenu.protondb', 'Check Compatibility')}
379416
</button>
380417
)}
381418
{onShowRequirements && (
382419
<button
383420
onClick={async () => onShowRequirements()}
384-
className="link button is-text is-link"
421+
className="link button is-text is-link buttonWithIcon"
385422
>
423+
<DesktopAccessDisabledIcon />
386424
{t('game.requirements', 'Requirements')}
387425
</button>
388426
)}
389427
{showModifyItem && (
390428
<button
391429
onClick={async () => onShowModifyInstall()}
392-
className="link button is-text is-link"
430+
className="link button is-text is-link buttonWithIcon"
393431
>
432+
<RepartitionIcon />
394433
{t('game.modify', 'Modify Installation')}
395434
</button>
396435
)}
397436
{isInstalled && (
398437
<button
399438
onClick={async () => onBrowseFiles()}
400-
className="link button is-text is-link"
439+
className="link button is-text is-link buttonWithIcon"
401440
>
441+
<FolderIcon />
402442
{t('button.browse_files', 'Browse Files')}
403443
</button>
404444
)}
405445
{hasWine && (
406446
<button
407447
onClick={async () => onBrowsePrefix()}
408-
className="link button is-text is-link"
448+
className="link button is-text is-link buttonWithIcon"
409449
>
450+
<SvgIcon>
451+
<FontAwesomeIcon icon={faWineGlass} />
452+
</SvgIcon>
410453
{t('button.browse_wine_prefix', 'Browse Wine Prefix')}
411454
</button>
412455
)}

src/frontend/screens/Library/components/ContextMenu/index.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@
1212
text-decoration: none;
1313
background-color: var(--navbar-active-background);
1414
}
15+
16+
.contextMenu .MuiSvgIcon-root {
17+
color: var(--text-default);
18+
}

src/frontend/screens/Library/components/ContextMenu/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import React from 'react'
1+
import React, { type ReactElement } from 'react'
22
import Menu from '@mui/material/Menu'
33
import MenuItem from '@mui/material/MenuItem'
44
import './index.css'
5+
import { ListItemIcon } from '@mui/material'
56

67
export interface Item {
8+
icon: ReactElement
79
label: string
810
onclick: () => void
911
show: boolean
@@ -56,9 +58,10 @@ function ContextMenu({ children, items }: Props) {
5658
}
5759
>
5860
{items.map(
59-
({ label, onclick, show }, i) =>
61+
({ label, onclick, show, icon }, i) =>
6062
show && (
6163
<MenuItem key={i} onClick={() => handleClick(onclick)}>
64+
<ListItemIcon>{icon}</ListItemIcon>
6265
{label}
6366
</MenuItem>
6467
)

0 commit comments

Comments
 (0)