Public Access
feat(picker): add the speedrun mood and the speedrun.com link
"What to play next" gets a Speedrun mood. The game detail links the game's speedrun.com page when Core found one with verified runs; only https://www.speedrun.com/ links are shown.
This commit is contained in:
1 parent
b0c78d8dca
commit
23ab5a91e7
7 files changed
+82
-12
No files matched your search
@@ -1,7 +1,7 @@
|
||||
import {useEffect, useMemo, useState} from 'react';
|
||||
import {Link, useNavigate, useParams} from 'react-router-dom';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {ArrowLeft, Clock, ExternalLink, Gamepad2, Image as ImageIcon, ImageOff, PanelTop, RotateCcw, ShieldOff, Trophy} from 'lucide-react';
|
||||
import {ArrowLeft, Clock, ExternalLink, Gamepad2, Image as ImageIcon, ImageOff, PanelTop, RotateCcw, ShieldOff, Timer, Trophy} from 'lucide-react';
|
||||
|
||||
import {Badge} from '@/components/ui/badge';
|
||||
import {Button} from '@/components/ui/button';
|
||||
@@ -24,6 +24,8 @@ import {apiFetch} from '../utils/api.js';
|
||||
import {hasSession} from '../utils/auth.js';
|
||||
import {isSteamKey} from '../utils/manualGames.js';
|
||||
|
||||
const SPEEDRUN_PREFIX = 'https://www.speedrun.com/';
|
||||
|
||||
const formatUnlockedAt = (instant, locale) => {
|
||||
if (!instant) return '';
|
||||
try {
|
||||
@@ -103,6 +105,9 @@ export default function GameDetail() {
|
||||
|
||||
const manual = data?.source === 'MANUAL';
|
||||
const onSteam = !!data && isSteamKey(data.appid);
|
||||
// Core checks the link too; a link from the API must never run script.
|
||||
const speedrunUrl = typeof data?.speedrunUrl === 'string' && data.speedrunUrl.startsWith(SPEEDRUN_PREFIX)
|
||||
? data.speedrunUrl : null;
|
||||
const isBackground = !!data && appearance.backgroundAppid === data.appid;
|
||||
const isBanner = !!data && appearance.showBanner && appearance.bannerAppid === data.appid;
|
||||
|
||||
@@ -154,6 +159,13 @@ export default function GameDetail() {
|
||||
<div className="mt-3">
|
||||
<TimeToBeat time={data.timeToBeat}/>
|
||||
</div>
|
||||
{speedrunUrl && (
|
||||
<Button asChild variant="outline" size="sm" className="mt-3">
|
||||
<a href={speedrunUrl} target="_blank" rel="noopener noreferrer">
|
||||
<Timer/>{t('GAME_DETAIL.OPEN_IN_SPEEDRUN')}<ExternalLink/>
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{/* Store page, background and banner need Steam art, so a game off Steam has none of them. */}
|
||||
{onSteam && <div className="flex flex-wrap gap-2">
|
||||
|
||||
Reference in new issue
Block a user