diff --git a/app/Platform/Data/GameHashData.php b/app/Platform/Data/GameHashData.php index cb71d763bf..969b512865 100644 --- a/app/Platform/Data/GameHashData.php +++ b/app/Platform/Data/GameHashData.php @@ -20,6 +20,8 @@ public function __construct( #[TypeScriptType('App\\Platform\\Data\\GameHashLabelData[]')] public array $labels, public ?string $patchUrl, + /** "Resource Page URL" */ + public ?string $source, ) { } @@ -31,6 +33,7 @@ public static function fromGameHash(GameHash $gameHash): self name: $gameHash->name, labels: GameHashLabelData::fromLabelsString($gameHash->labels), patchUrl: $gameHash->patch_url, + source: $gameHash->source, ); } diff --git a/lang/en_US.json b/lang/en_US.json index a13bafb2cb..24e4dcb110 100644 --- a/lang/en_US.json +++ b/lang/en_US.json @@ -520,5 +520,7 @@ "This page may contain content that is not appropriate for all ages.": "This page may contain content that is not appropriate for all ages.", "Are you sure you want to view this page?": "Are you sure you want to view this page?", "Yes, and don't ask again": "Yes, and don't ask again", - "Yes, I'm an adult": "Yes, I'm an adult" + "Yes, I'm an adult": "Yes, I'm an adult", + "Download from Original Source (Recommended)": "Download from Original Source (Recommended)", + "Mirror": "Mirror" } \ No newline at end of file diff --git a/resources/js/features/games/components/HashesMainRoot/HashesList/HashesList.test.tsx b/resources/js/features/games/components/HashesMainRoot/HashesList/HashesList.test.tsx index 7f67fd33d5..1c67d7b6c8 100644 --- a/resources/js/features/games/components/HashesMainRoot/HashesList/HashesList.test.tsx +++ b/resources/js/features/games/components/HashesMainRoot/HashesList/HashesList.test.tsx @@ -68,20 +68,6 @@ describe('Component: HashesList', () => { expect(screen.getByText(hash.md5)).toBeVisible(); }); - it('given the hash has a patch URL, adds a link to it', () => { - // ARRANGE - const hash = createGameHash({ patchUrl: faker.internet.url() }); - - render(, { - pageProps: { hashes: [hash] }, - }); - - // ASSERT - const linkEl = screen.getByRole('link', { name: /download patch file/i }); - expect(linkEl).toBeVisible(); - expect(linkEl).toHaveAttribute('href', hash.patchUrl); - }); - it('given the hash has no patch URL, does not display a download link', () => { // ARRANGE const hash = createGameHash({ patchUrl: null }); @@ -186,4 +172,79 @@ describe('Component: HashesList', () => { expect(renderedMd5s[1]).toContain('77057d9d14b99e465ea9e29783af0ae3'); expect(renderedMd5s[2]).toContain('a78d58b97eddb7c70647d939e20bef4f'); }); + + it('given the hash has both source and patch URLs, displays links to both', () => { + // ARRANGE + const hash = createGameHash({ + source: faker.internet.url(), + patchUrl: faker.internet.url(), + }); + + render(, { + pageProps: { hashes: [hash] }, + }); + + // ASSERT + const links = screen.getAllByRole('link'); + expect(links[0]).toHaveAttribute('href', hash.source); + expect(links[1]).toHaveAttribute('href', hash.patchUrl); + + expect(screen.getByText(/download from original source/i)).toBeVisible(); + expect(screen.getByText(/mirror/i)).toBeVisible(); + }); + + it('given the hash only has a patch URL, displays a single download link', () => { + // ARRANGE + const hash = createGameHash({ + source: null, + patchUrl: faker.internet.url(), + }); + + render(, { + pageProps: { hashes: [hash] }, + }); + + // ASSERT + const link = screen.getByRole('link'); + expect(link).toHaveAttribute('href', hash.patchUrl); + expect(screen.getByText(/download patch file/i)).toBeVisible(); + + expect(screen.queryByText(/mirror/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/download from original source/i)).not.toBeInTheDocument(); + }); + + it('given the hash only has a source URL, does not display any links', () => { + // ARRANGE + const hash = createGameHash({ + source: faker.internet.url(), + patchUrl: null, + }); + + render(, { + pageProps: { hashes: [hash] }, + }); + + // ASSERT + expect(screen.queryByRole('link')).not.toBeInTheDocument(); + }); + + it('given the hash only has a patch URL, displays a single download link', () => { + // ARRANGE + const hash = createGameHash({ + source: null, + patchUrl: faker.internet.url(), + }); + + render(, { + pageProps: { hashes: [hash] }, + }); + + // ASSERT + const link = screen.getByRole('link'); + expect(link).toHaveAttribute('href', hash.patchUrl); + expect(screen.getByText(/download patch file/i)).toBeVisible(); + + expect(screen.queryByText(/mirror/i)).not.toBeInTheDocument(); + expect(screen.queryByText(/download from original source/i)).not.toBeInTheDocument(); + }); }); diff --git a/resources/js/features/games/components/HashesMainRoot/HashesList/HashesListItem.tsx b/resources/js/features/games/components/HashesMainRoot/HashesList/HashesListItem.tsx index af9e2bf9c7..0f6f6f186a 100644 --- a/resources/js/features/games/components/HashesMainRoot/HashesList/HashesListItem.tsx +++ b/resources/js/features/games/components/HashesMainRoot/HashesList/HashesListItem.tsx @@ -2,6 +2,7 @@ import type { FC } from 'react'; import { useTranslation } from 'react-i18next'; import { buildTrackingClassNames } from '@/common/utils/buildTrackingClassNames'; +import { cn } from '@/common/utils/cn'; interface HashListingProps { hash: App.Platform.Data.GameHash; @@ -27,7 +28,27 @@ export const HashesListItem: FC = ({ hash }) => {

{hash.md5}

- {hash.patchUrl ? ( + {/* Can show RAPatches as the mirror */} + {hash.source && hash.patchUrl ? ( + + ) : null} + + {/* Show RAPatches as the direct download link */} + {!hash.source && hash.patchUrl ? ( ((faker) md5: faker.string.alphanumeric(32), name: faker.word.words(3), patchUrl: faker.internet.url(), + source: null, }; }); diff --git a/resources/js/types/generated.d.ts b/resources/js/types/generated.d.ts index 3677defe7f..15aba62a28 100644 --- a/resources/js/types/generated.d.ts +++ b/resources/js/types/generated.d.ts @@ -225,7 +225,7 @@ declare namespace App.Data { }; } declare namespace App.Enums { - export type ClientSupportLevel = 0 | 1 | 2 | 3; + export type ClientSupportLevel = 0 | 1 | 2 | 3 | 4; export type UserPreference = | 0 | 1 @@ -353,6 +353,7 @@ declare namespace App.Platform.Data { name: string | null; labels: Array; patchUrl: string | null; + source: string | null; }; export type GameHashLabel = { label: string;