Skip to content

[FEAT] Show Genres and Release date on Game Page #3330

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

Merged
merged 19 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from 18 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
3 changes: 2 additions & 1 deletion public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,8 @@
}
},
"label": {
"loading": "Loading"
"loading": "Loading",
"releaseDate": "Release Date: "
},
"library": {
"refresh": "Refresh",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@ const testPCGamingWikiInfo = {
score: '10',
urlid: 'the-witcher-3-wild-hunt'
},
genres: [''],
opencritic: {
score: '22',
urlid: '463/the-witcher-3-wild-hunt'
},
releaseDate: [],
igdb: {
score: '40',
urlid: 'the-witcher-3-wild-hunt'
Expand Down
2 changes: 2 additions & 0 deletions src/backend/wiki_game_info/pcgamingwiki/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export const idgbRegEx = /game\/row\/reception\|IGDB\|(\S+)\|([0-9]+)/m
export const steamIDRegEx = /steam appid {2}= ([0-9]+)/m
export const howLongToBeatIDRegEx = /hltb {9}= ([0-9]+)/m
export const direct3DVersionsRegEx = /direct3d versions {6}= (.+)/m
export const genresRegEx = /game\/row\/taxonomy\/genres\s*\|\s*(.*?)\s*}}/
export const releaseDateRegEx = /game\/row\/date\|([^|]+)\|([^}]*)/g
18 changes: 17 additions & 1 deletion src/backend/wiki_game_info/pcgamingwiki/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {
direct3DVersionsRegEx,
genresRegEx,
howLongToBeatIDRegEx,
idgbRegEx,
metacriticRegEx,
opencriticRegEx,
releaseDateRegEx,
steamIDRegEx
} from './constants'
import { logError, logInfo, LogPrefix } from '../../logger/logger'
Expand Down Expand Up @@ -37,14 +39,19 @@ export async function getInfoFromPCGamingWiki(
const steamID = wikitext.match(steamIDRegEx)?.[1] ?? ''
const howLongToBeatID = wikitext.match(howLongToBeatIDRegEx)?.[1] ?? ''
const direct3DVersions = wikitext.match(direct3DVersionsRegEx)?.[1] ?? ''
const genres = wikitext.match(genresRegEx)?.[1] ?? ''

const releaseDates = getReleaseDates(wikitext)

return {
steamID,
howLongToBeatID,
metacritic,
opencritic,
igdb,
direct3DVersions: direct3DVersions.replaceAll(' ', '').split(',')
direct3DVersions: direct3DVersions.replaceAll(' ', '').split(','),
genres: genres.replaceAll(' ', '').split(','),
releaseDate: releaseDates
}
} catch (error) {
logError(
Expand All @@ -55,6 +62,15 @@ export async function getInfoFromPCGamingWiki(
}
}

function getReleaseDates(wikitext: string) {
const releaseDates = []
const matches = wikitext.matchAll(releaseDateRegEx)
for (const match of matches) {
releaseDates.push(`${match[1]}: ${match[2]}`)
}
return releaseDates
}

async function getPageID(title: string, id?: string): Promise<string | null> {
if (id) {
const { data } = await axios.get(
Expand Down
2 changes: 2 additions & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,8 @@ export interface PCGamingWikiInfo {
opencritic: GameScoreInfo
igdb: GameScoreInfo
direct3DVersions: string[]
genres: string[]
releaseDate: string[]
}

export interface AppleGamingWikiInfo {
Expand Down
23 changes: 23 additions & 0 deletions src/frontend/screens/Game/GamePage/components/Genres.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react'

type GenresProps = {
genres: string[]
}

const Genres: React.FC<GenresProps> = ({ genres }) => {
if (genres[0] === '' || genres.length === 0) {
return null
}

return (
<span className="genres">
{genres.map((genre) => (
<span key={genre} className="genre">
{genre}
</span>
))}
</span>
)
}

export default Genres
74 changes: 74 additions & 0 deletions src/frontend/screens/Game/GamePage/components/ReleaseDate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import GameContext from '../../GameContext'

type ReleaseDateProps = {
date: string[] | undefined
}

// convert date to current locale using Intl module
function convertDate(date: string) {
// Extract only the date part if the string contains extra information
const match = date.match(/(\w+ \d{1,2}, \d{4})/)
if (match) {
date = match[1]
}

const options: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'long',
day: 'numeric'
}

const dateObj = new Date(date)

// Check if dateObj is a valid date
if (isNaN(dateObj.getTime())) {
return null
}

return dateObj.toLocaleDateString(undefined, options)
}

const ReleaseDate: React.FC<ReleaseDateProps> = ({ date }) => {
const { is } = useContext(GameContext)

const { t } = useTranslation()

if (!date || date[0] === '' || date.length === 0) {
return null
}

const getReleaseDate = () => {
let windowsReleaseDate = ''

for (let i = 0; i < date.length; i++) {
const [platformName, releaseDate] = date[i].split(': ')

if (platformName === 'Windows') {
windowsReleaseDate = releaseDate
}

if (
(platformName === 'Linux' && is.linuxNative && is.linux) ||
(platformName === 'OS X' && is.macNative && is.mac)
) {
return convertDate(releaseDate)
}
}

return convertDate(windowsReleaseDate)
}

if (!getReleaseDate()) {
return null
}

return (
<div className="releaseDate">
{t('label.releaseDate', 'Release Date')}: {getReleaseDate()}
</div>
)
}

export default ReleaseDate
33 changes: 32 additions & 1 deletion src/frontend/screens/Game/GamePage/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,23 @@
align-self: flex-start;
}

.genres {
display: flex;
flex-wrap: wrap;
gap: var(--space-xs);
margin-bottom: 0.5rem;

.genre {
background: var(--accent-overlay);
color: var(--text-tertiary);
padding: 1px 6px;
border-radius: 6px;
font-size: var(--text-sm);
}
}

.developer {
padding: var(--space-md-fixed) 0;
padding: var(--space-md-fixed) 0 0 0;
color: var(--text-default);
}

Expand All @@ -275,6 +290,7 @@
overflow: auto;
height: 150px;
line-height: 1.5;
padding-top: var(--space-md-fixed);
b {
font-weight: 700;
}
Expand Down Expand Up @@ -561,6 +577,21 @@
flex-grow: 1;
}

.genres {
display: flex;
flex-wrap: wrap;
gap: var(--space-xs);
margin-bottom: 0.5rem;

.genre {
background: var(--accent-overlay);
color: var(--text-tertiary);
padding: 1px 6px;
border-radius: 6px;
font-size: var(--text-sm);
}
}

.gameStatus {
text-align: left;
}
Expand Down
6 changes: 6 additions & 0 deletions src/frontend/screens/Game/GamePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ import {
SettingsButton
} from './components'
import { hasAnticheatInfo } from 'frontend/hooks/hasAnticheatInfo'
import Genres from './components/Genres'
import ReleaseDate from './components/ReleaseDate'

export default React.memo(function GamePage(): JSX.Element | null {
const { appName, runner } = useParams() as { appName: string; runner: Runner }
Expand Down Expand Up @@ -355,7 +357,9 @@ export default React.memo(function GamePage(): JSX.Element | null {
<DotsMenu gameInfo={gameInfo} handleUpdate={handleUpdate} />
</div>
<div className="infoWrapper">
<Genres genres={wikiInfo?.pcgamingwiki?.genres || []} />
<Developer gameInfo={gameInfo} />
<ReleaseDate date={wikiInfo?.pcgamingwiki?.releaseDate} />
<Description />
<CloudSavesSync gameInfo={gameInfo} />
<DownloadSizeInfo gameInfo={gameInfo} />
Expand Down Expand Up @@ -415,7 +419,9 @@ export default React.memo(function GamePage(): JSX.Element | null {
<StoreLogos runner={runner} />
</div>
<h1>{title}</h1>
<Genres genres={wikiInfo?.pcgamingwiki?.genres || []} />
<Developer gameInfo={gameInfo} />
<ReleaseDate date={wikiInfo?.pcgamingwiki?.releaseDate} />
<Description />
{!notInstallable && (
<TimeContainer runner={runner} game={appName} />
Expand Down