From a59be8afa60b46f2d237f1dc89d64da369298002 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Wed, 20 May 2026 18:29:48 -0400 Subject: [PATCH 1/3] chore: adjust game screenshot limits --- .../Actions/AddGameScreenshotAction.php | 16 ++++++------- .../Actions/ApproveGameScreenshotAction.php | 5 ++-- app/Platform/Enums/ScreenshotType.php | 8 +++++++ .../Actions/AddGameScreenshotActionTest.php | 24 +++++++++++++++---- .../ApproveGameScreenshotActionTest.php | 4 ++-- 5 files changed, 40 insertions(+), 17 deletions(-) diff --git a/app/Platform/Actions/AddGameScreenshotAction.php b/app/Platform/Actions/AddGameScreenshotAction.php index 36539a9684..e08bc41f5a 100644 --- a/app/Platform/Actions/AddGameScreenshotAction.php +++ b/app/Platform/Actions/AddGameScreenshotAction.php @@ -75,14 +75,15 @@ public function execute( if ($shouldBePrimary) { $legacyPath = (new CreateLegacyScreenshotPngAction())->execute($imageContents); - // Demote existing approved screenshots of this type to pending. This - // prevents the 20-screenshot cap from being hit by normal editor - // uploads and keeps demoted screenshots available for future gallery - // management (Set as Primary, Delete, etc). + $demotedStatus = match ($type) { + ScreenshotType::Title, ScreenshotType::Completion => GameScreenshotStatus::Replaced, + ScreenshotType::Ingame => GameScreenshotStatus::Pending, + }; + $game->gameScreenshots() ->ofType($type) ->approved() - ->update(['is_primary' => false, 'status' => GameScreenshotStatus::Pending]); + ->update(['is_primary' => false, 'status' => $demotedStatus]); } $customProperties = ['sha1' => $hash]; @@ -146,10 +147,7 @@ private function validateCap(Game $game, ScreenshotType $type, bool $isPrimary = return; } - $cap = match ($type) { - ScreenshotType::Ingame => 20, - ScreenshotType::Title, ScreenshotType::Completion => 1, - }; + $cap = $type->approvedCap(); $approvedCount = $game->gameScreenshots() ->ofType($type) diff --git a/app/Platform/Actions/ApproveGameScreenshotAction.php b/app/Platform/Actions/ApproveGameScreenshotAction.php index d2bba4b58b..1991a72720 100644 --- a/app/Platform/Actions/ApproveGameScreenshotAction.php +++ b/app/Platform/Actions/ApproveGameScreenshotAction.php @@ -52,9 +52,10 @@ public function execute(GameScreenshot $screenshot, User $reviewer): void ->approved() ->count(); - if ($approvedCount >= 20) { + $cap = ScreenshotType::Ingame->approvedCap(); + if ($approvedCount >= $cap) { throw ValidationException::withMessages([ - 'screenshot' => 'This game has reached the maximum of 20 approved in-game screenshots.', + 'screenshot' => "This game has reached the maximum of {$cap} approved in-game screenshots.", ]); } diff --git a/app/Platform/Enums/ScreenshotType.php b/app/Platform/Enums/ScreenshotType.php index 6db6e05316..5bf54e08f9 100644 --- a/app/Platform/Enums/ScreenshotType.php +++ b/app/Platform/Enums/ScreenshotType.php @@ -18,4 +18,12 @@ public function label(): string self::Completion => 'Completion', }; } + + public function approvedCap(): int + { + return match ($this) { + self::Title, self::Completion => 1, + self::Ingame => 10, + }; + } } diff --git a/tests/Feature/Platform/Actions/AddGameScreenshotActionTest.php b/tests/Feature/Platform/Actions/AddGameScreenshotActionTest.php index ad6f05b23f..fab3491603 100644 --- a/tests/Feature/Platform/Actions/AddGameScreenshotActionTest.php +++ b/tests/Feature/Platform/Actions/AddGameScreenshotActionTest.php @@ -71,6 +71,22 @@ expect($first->fresh()->status)->toEqual(GameScreenshotStatus::Pending); }); +it('archives the prior completion image as replaced when a new completion is uploaded', function () { + // ARRANGE + $game = Game::factory()->create(['system_id' => System::factory()]); + $action = new AddGameScreenshotAction(); + $first = $action->execute($game, UploadedFile::fake()->image('completion-1.png', 256, 224), ScreenshotType::Completion); + + // ACT + $second = $action->execute($game, UploadedFile::fake()->image('completion-2.png', 320, 240), ScreenshotType::Completion, isPrimary: true); + + // ASSERT + expect($second->is_primary)->toBeTrue(); + expect($second->status)->toEqual(GameScreenshotStatus::Approved); + expect($first->fresh()->is_primary)->toBeFalse(); + expect($first->fresh()->status)->toEqual(GameScreenshotStatus::Replaced); +}); + it('rejects duplicate images for the same game', function () { // ARRANGE $game = Game::factory()->create(['system_id' => System::factory()]); @@ -110,10 +126,10 @@ $action->execute($game->fresh(), $duplicate, ScreenshotType::Ingame); })->throws(ValidationException::class); -it('enforces a cap of 20 approved ingame screenshots', function () { +it('enforces a cap of 10 approved ingame screenshots', function () { // ARRANGE $game = Game::factory()->create(['system_id' => System::factory()]); - GameScreenshot::factory()->count(20)->for($game)->ingame()->create(); + GameScreenshot::factory()->count(10)->for($game)->ingame()->create(); $file = UploadedFile::fake()->image('screenshot.png', 256, 224); // ASSERT @@ -123,7 +139,7 @@ it('does not enforce the ingame cap for title screenshots', function () { // ARRANGE $game = Game::factory()->create(['system_id' => System::factory()]); - GameScreenshot::factory()->count(20)->for($game)->ingame()->create(); + GameScreenshot::factory()->count(10)->for($game)->ingame()->create(); $file = UploadedFile::fake()->image('title.png', 256, 224); // ACT @@ -159,7 +175,7 @@ expect($second->is_primary)->toBeTrue(); expect($second->status)->toEqual(GameScreenshotStatus::Approved); expect($first->fresh()->is_primary)->toBeFalse(); - expect($first->fresh()->status)->toEqual(GameScreenshotStatus::Pending); + expect($first->fresh()->status)->toEqual(GameScreenshotStatus::Replaced); }); it('rejects a file smaller than 64x64', function () { diff --git a/tests/Feature/Platform/Actions/ApproveGameScreenshotActionTest.php b/tests/Feature/Platform/Actions/ApproveGameScreenshotActionTest.php index 6d6bbccf84..31a88f54e8 100644 --- a/tests/Feature/Platform/Actions/ApproveGameScreenshotActionTest.php +++ b/tests/Feature/Platform/Actions/ApproveGameScreenshotActionTest.php @@ -243,13 +243,13 @@ function createPendingScreenshotForApprovalTest( expect($fileManipulator->createdDerivedFilesFor)->toHaveCount(1); }); -it('enforces the 20 approved ingame screenshot cap during approval', function () { +it('enforces the 10 approved ingame screenshot cap during approval', function () { // ARRANGE $game = Game::factory()->create(['system_id' => System::factory()]); $submitter = User::factory()->create(); $reviewer = User::factory()->create(); - GameScreenshot::factory()->count(20)->for($game)->ingame()->create(); + GameScreenshot::factory()->count(10)->for($game)->ingame()->create(); $pending = createPendingScreenshotForApprovalTest($game, $submitter, ScreenshotType::Ingame); From 9f1b5e9bdd0c22a6518645c618f5bc7c6db938de Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Wed, 20 May 2026 18:36:59 -0400 Subject: [PATCH 2/3] fix: remove magic numbers --- .../Resources/GameScreenshotModerationResource.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/Filament/Resources/GameScreenshotModerationResource.php b/app/Filament/Resources/GameScreenshotModerationResource.php index 25c5d807ae..40b1e923da 100644 --- a/app/Filament/Resources/GameScreenshotModerationResource.php +++ b/app/Filament/Resources/GameScreenshotModerationResource.php @@ -239,7 +239,7 @@ public static function table(Table $table): Table ->modalSubmitAction(function (Action $action, GameScreenshot $record) { if ( $record->type === ScreenshotType::Ingame - && $record->game->gameScreenshots()->ofType(ScreenshotType::Ingame)->approved()->count() >= 20 + && $record->game->gameScreenshots()->ofType(ScreenshotType::Ingame)->approved()->count() >= ScreenshotType::Ingame->approvedCap() ) { return $action->hidden(); } @@ -395,11 +395,12 @@ private static function buildApproveIngameDescription( $countLabel = $approvedCount === 1 ? 'screenshot' : 'screenshots'; $mediaPageUrl = GameResource::getUrl('media', ['record' => $record->game]); + $cap = ScreenshotType::Ingame->approvedCap(); - if ($approvedCount >= 20) { + if ($approvedCount >= $cap) { return new HtmlString( $subjectLine - . self::buildApproveExplanation('This game already has 20 in-game screenshots approved. (20 max)') + . self::buildApproveExplanation("This game already has {$cap} in-game screenshots approved. ({$cap} max)") . self::buildApproveExplanation("To approve this submission, first remove a screenshot from the game's media page.") . self::buildCenteredPreview(self::buildApproveImageTag($submissionUrl, $submissionResolution, '')) ); @@ -419,7 +420,7 @@ private static function buildApproveIngameDescription( return new HtmlString( $subjectLine . self::buildApproveExplanation('This will replace the current primary in-game screenshot (invalid resolution) and add it to the gallery.') - . self::buildApproveExplanation("{$approvedCount} in-game {$countLabel} currently approved. (20 max)") + . self::buildApproveExplanation("{$approvedCount} in-game {$countLabel} currently approved. ({$cap} max)") . $mixedResolutionWarning . self::buildComparisonPreview( currentLabel: 'Current Primary (' . $currentResolutionLabel . ')', @@ -433,7 +434,7 @@ private static function buildApproveIngameDescription( return new HtmlString( $subjectLine . self::buildApproveExplanation("This will add the screenshot to the game's gallery.") - . self::buildApproveExplanation("{$approvedCount} in-game {$countLabel} currently approved. (20 max)") + . self::buildApproveExplanation("{$approvedCount} in-game {$countLabel} currently approved. ({$cap} max)") . self::buildCenteredPreview(self::buildApproveImageTag($submissionUrl, $submissionResolution, '')) ); } From d9c1cbaa68444d32a1e7ef1723c64e4ec9f0b6c2 Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Thu, 21 May 2026 17:55:53 -0400 Subject: [PATCH 3/3] fix: address feedback --- app/Filament/Resources/GameScreenshotModerationResource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Filament/Resources/GameScreenshotModerationResource.php b/app/Filament/Resources/GameScreenshotModerationResource.php index 40b1e923da..4ac93dcd90 100644 --- a/app/Filament/Resources/GameScreenshotModerationResource.php +++ b/app/Filament/Resources/GameScreenshotModerationResource.php @@ -400,7 +400,7 @@ private static function buildApproveIngameDescription( if ($approvedCount >= $cap) { return new HtmlString( $subjectLine - . self::buildApproveExplanation("This game already has {$cap} in-game screenshots approved. ({$cap} max)") + . self::buildApproveExplanation("This game already has {$approvedCount} in-game screenshots approved. ({$cap} max)") . self::buildApproveExplanation("To approve this submission, first remove a screenshot from the game's media page.") . self::buildCenteredPreview(self::buildApproveImageTag($submissionUrl, $submissionResolution, '')) );