Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more options for DiscordRPC #4014

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@
"custom_themes_wiki": "Check the Wiki for more details on adding custom themes. Click here.",
"disable_logs": "Toggle this checkbox ON to disable most of the writes to log files (critical information is always logged). Make sure to turn OFF this setting before reporting any issue.",
"disablePlaytimeSync": "Disables playtime synchronization with given store's servers (currently only GOG is supported)",
"discordRPC": "Provide a Discord Application ID to show your status as \"Playing <app_name>\" on Discord. Title and State are optional and accept {game} and {platform} variables for game name and device platform respectively.",
"dxvk": "DXVK is a Vulkan-based translational layer for DirectX 9, 10 and 11 games. Enabling may improve compatibility. Might cause issues especially for older DirectX games.",
"dxvkfpslimit": "Sets a frame rate cap for DXVK games",
"dxvknvapi": "DXVK-NVAPI is an implementation of NVAPI built on top of DXVK and the linux native NVAPI, it allows for the usage of DLSS on Nvidia GPUs.",
Expand Down Expand Up @@ -606,6 +607,9 @@
"disable_logs": "Disable Logs",
"disablePlaytimeSync": "Disable playtime synchronization",
"discordRPC": "Enable Discord Rich Presence",
"discordRPCAppID": "Application ID",
"discordRPCDetails": "Details",
"discordRPCState": "State",
"download-no-https": "Download games without HTTPS (useful for CDNs e.g. LanCache)",
"dxvkfpslimit": "Limit FPS (DX9, 10 and 11)",
"egs-sync": "Sync with Installed Epic Games",
Expand Down
6 changes: 5 additions & 1 deletion src/backend/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ async function prepareLaunch(
// Update Discord RPC if enabled
let rpcClient = undefined
if (globalSettings.discordRPC) {
rpcClient = constructAndUpdateRPC(gameInfo)
rpcClient = constructAndUpdateRPC(gameInfo, {
appId: globalSettings.discordRPCAppId,
details: globalSettings.discordRPCDetails,
state: globalSettings.discordRPCState
})
}

// If we're not on Linux, we can return here
Expand Down
27 changes: 22 additions & 5 deletions src/backend/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ import {
deviceNameCache,
vendorNameCache
} from './utils/systeminfo/gpu/pci_ids'
import type { WineManagerStatus } from 'common/types'
import type { discordRPCOptions, WineManagerStatus } from 'common/types'
import { isUmuSupported } from './utils/compatibility_layers'

const execAsync = promisify(exec)
Expand Down Expand Up @@ -571,12 +571,29 @@ async function getSteamRuntime(
return allAvailableRuntimes.pop()!
}

function constructAndUpdateRPC(gameInfo: GameInfo): RpcClient {
const client = makeClient('852942976564723722')
function constructAndUpdateRPC(
gameInfo: GameInfo,
userSettings: discordRPCOptions
): RpcClient {
const appId = userSettings.appId || '852942976564723722'

const client = makeClient(appId)
const versionText = `Heroic ${app.getVersion()}`

const replaceVariables = (str: string) =>
str
.replace(/{game}/gi, gameInfo.title)
.replace(/{platform}/gi, getFormattedOsName())

const image = gameInfo.art_icon || gameInfo.art_square
const title = gameInfo.title
const title = replaceVariables(
typeof userSettings.details === 'string' ? userSettings.details : '{game}'
)
const state = replaceVariables(
typeof userSettings.state === 'string'
? userSettings.state
: 'via Heroic on {platform}'
)

const overrides = image.startsWith('http')
? {
Expand All @@ -595,7 +612,7 @@ function constructAndUpdateRPC(gameInfo: GameInfo): RpcClient {
instance: true,
large_text: title,
startTimestamp: Date.now(),
state: 'via Heroic on ' + getFormattedOsName(),
state: state,
...overrides
})
logInfo('Started Discord Rich Presence', LogPrefix.Backend)
Expand Down
9 changes: 9 additions & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export type Release = {
body?: string
}

export interface discordRPCOptions {
appId?: string
details?: string
state?: string
}

export type ExperimentalFeatures = {
enableNewDesign: boolean
enableHelp: boolean
Expand Down Expand Up @@ -90,6 +96,9 @@ export interface AppSettings extends GameSettings {
disablePlaytimeSync: boolean
disableLogs: boolean
discordRPC: boolean
discordRPCAppId: string
discordRPCDetails: string
discordRPCState: string
downloadNoHttps: boolean
egsLinkedPath: string
enableUpdates: boolean
Expand Down
61 changes: 54 additions & 7 deletions src/frontend/screens/Settings/components/DiscordRPC.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,72 @@
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { ToggleSwitch } from 'frontend/components/UI'
import { InfoBox, TextInputField, ToggleSwitch } from 'frontend/components/UI'
import useSetting from 'frontend/hooks/useSetting'
import SettingsContext from '../SettingsContext'

const DiscordRPC = () => {
const { t } = useTranslation()
const { isDefault } = useContext(SettingsContext)
const [discordRPC, setDiscordRPC] = useSetting('discordRPC', false)
const [RPCAppId, setRPCAppId] = useSetting(
'discordRPCAppId',
'852942976564723722'
)
const [RPCDetails, setRPCDetails] = useSetting('discordRPCDetails', '{game}')
const [RPCState, setRPCState] = useSetting(
'discordRPCState',
'via Heroic on {platform}'
)

if (!isDefault) {
return <></>
}

return (
<ToggleSwitch
htmlId="discordRPC"
value={discordRPC}
handleChange={() => setDiscordRPC(!discordRPC)}
title={t('setting.discordRPC', 'Enable Discord Rich Presence')}
/>
<>
<ToggleSwitch
htmlId="discordRPC"
value={discordRPC}
handleChange={() => setDiscordRPC(!discordRPC)}
title={t('setting.discordRPC', 'Enable Discord Rich Presence')}
/>
{discordRPC && (
<div
style={{
marginLeft: 'var(--space-md)'
}}
>
<InfoBox text="infobox.help">
{t(
'help.discordRPC',
'Provide a Discord Application ID to show your status as "Playing <app_name>" on Discord. Both Details (line 1) and State (line 2) are optional and accept {game} and {platform} variables for game name and device platform respectively.'
)}
</InfoBox>
<TextInputField
htmlId="discordRPCAppID"
label={t('setting.discordRPCAppID', 'Application ID')}
value={RPCAppId}
onChange={(event) => setRPCAppId(event.target.value)}
/>
<TextInputField
htmlId="discordRPCDetails"
label={t('setting.discordRPCDetails', 'Details')}
value={RPCDetails}
onChange={(event) => setRPCDetails(event.target.value)}
/>
<TextInputField
htmlId="discordRPCState"
label={t('setting.discordRPCState', 'State')}
value={
typeof RPCState === 'string'
? RPCState
: 'via Heroic on {platform}'
}
onChange={(event) => setRPCState(event.target.value)}
/>
</div>
)}
</>
)
}

Expand Down
Loading