Skip to content

Add dynamic background modes with enum config #4144

Merged
ildyria merged 6 commits intomasterfrom
landing-background
Mar 3, 2026
Merged

Add dynamic background modes with enum config #4144
ildyria merged 6 commits intomasterfrom
landing-background

Conversation

@ildyria
Copy link
Member

@ildyria ildyria commented Mar 3, 2026

Fixes #1106

Summary by CodeRabbit

  • New Features
    • Per-orientation landing backgrounds (landscape/portrait) with modes: static URL, photo ID, random public photo, latest album cover, or random from album; backend resolves the final image and falls back to a default when needed.
  • Documentation
    • Added feature plan, spec, tasks, and roadmap entries covering behavior, testing, and acceptance criteria.
  • Localization
    • Added/updated translation keys across many locales for the new mode settings.
  • Chores
    • Migration and config additions to introduce the new mode settings.

ildyria added 2 commits March 3, 2026 20:17
Implements Feature 025 - Dynamic Landing Background Options (#1106).

Adds 5 background modes for landscape and portrait orientations:
- static: URL passthrough (existing behavior, default)
- photo_id: Specific photo by ID (no public access check)
- random: Random public photo
- latest_album_cover: Latest album's cover
- random_from_album: Random photo from album

Changes:
- Add landing_background_landscape_mode and landing_background_portrait_mode enum configs
- Implement resolveBackgroundUrl() with graceful fallback (no exceptions)
- Update English translations

Spec impact: docs/specs/4-architecture/features/025-dynamic-landing-backgrounds/

Resolves: #1106
@ildyria ildyria requested a review from a team as a code owner March 3, 2026 19:19
@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

Adds dynamic landing-page background resolution with five modes (static, photo_id, random, latest_album_cover, random_from_album); introduces a mode enum, migration for two mode configs, backend resolution helpers with fallback and logging, comprehensive feature docs, roadmap update, and many locale string changes.

Changes

Cohort / File(s) Summary
Backend implementation
app/Http/Resources/GalleryConfigs/LandingPageResource.php
Replaces static reads with a private resolver and helpers for each mode, adds FALLBACK_IMAGE, imports Album/Photo and policies, wraps resolution in try/catch with logging and fallback.
Config migration
database/migrations/2026_03_03_120000_add_dynamic_landing_background_modes.php
Adds anonymous BaseConfigMigration adding landing_background_landscape_mode and landing_background_portrait_mode enum configs (default static, allowed modes listed).
Enum
app/Enum/LandingBackgroundModeType.php
Adds string-backed enum LandingBackgroundModeType with cases: static, photo_id, random, latest_album_cover, random_from_album.
Feature documentation
docs/specs/4-architecture/features/025-dynamic-landing-backgrounds/plan.md, .../spec.md, .../tasks.md
Adds full plan, spec, and task list for Feature 025 covering modes, resolution flow, migrations, tests, performance targets, acceptance criteria, fallback behavior, and rollout increments.
Roadmap
docs/specs/4-architecture/roadmap.md
Adds Feature 025 entry to Active Features table and updates last-updated timestamp.
Translations (many locales)
lang/en/all_settings.php, lang/ar/all_settings.php, lang/bg/all_settings.php, lang/cz/all_settings.php, lang/de/all_settings.php, lang/el/all_settings.php, lang/es/all_settings.php, lang/fa/all_settings.php, lang/fr/all_settings.php, lang/hu/all_settings.php, lang/it/all_settings.php, lang/ja/all_settings.php, lang/nl/all_settings.php, lang/no/all_settings.php, lang/pl/all_settings.php, lang/pt/all_settings.php, lang/ru/all_settings.php, lang/sk/all_settings.php, lang/sv/all_settings.php, lang/vi/all_settings.php, lang/zh_CN/all_settings.php, lang/zh_TW/all_settings.php
Adds landing_background_landscape_mode and landing_background_portrait_mode keys and updates landscape/portrait setting descriptions across many locale files to document mode-based values and options.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through fields of code so bright,
Five choices for the backdrop’s light.
If photos vanish or albums roam,
A cat fallback will guide you home.
Nose twitch — the landing page looks right. 🥕✨

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Implements Feature 025 - Dynamic Landing Background Options (#1106).

Adds 5 background modes for landscape and portrait orientations:
- static: URL passthrough (existing behavior, default)
- photo_id: Specific photo by ID (no public access check)
- random: Random public photo
- latest_album_cover: Latest album's cover
- random_from_album: Random photo from album

Implementation:
- Add LandingBackgroundModeType enum with proper backed enum values
- Add landing_background_landscape_mode and landing_background_portrait_mode enum configs
- Use ConfigManager::getValueAsEnum() for type-safe mode retrieval
- Implement resolveBackgroundUrl() with graceful fallback (no exceptions)
- Update English translations

Spec impact: docs/specs/4-architecture/features/025-dynamic-landing-backgrounds/

Resolves: #1106
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
app/Http/Resources/GalleryConfigs/LandingPageResource.php (1)

111-111: Use nullsafe access for original size variant URL.

getOriginal()->url can throw when no original variant object exists, which pushes normal fallback flow into exception/logging.

♻️ Suggested fix
-return $photo->size_variants->getMedium()?->url ?? $photo->size_variants->getOriginal()->url ?? self::FALLBACK_IMAGE;
+return $photo->size_variants->getMedium()?->url ?? $photo->size_variants->getOriginal()?->url ?? self::FALLBACK_IMAGE;

Also applies to: 133-133, 173-173, 208-208


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f250817 and 9e65f32.

📒 Files selected for processing (7)
  • app/Http/Resources/GalleryConfigs/LandingPageResource.php
  • database/migrations/2026_03_03_120000_add_dynamic_landing_background_modes.php
  • docs/specs/4-architecture/features/025-dynamic-landing-backgrounds/plan.md
  • docs/specs/4-architecture/features/025-dynamic-landing-backgrounds/spec.md
  • docs/specs/4-architecture/features/025-dynamic-landing-backgrounds/tasks.md
  • docs/specs/4-architecture/roadmap.md
  • lang/en/all_settings.php

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
lang/pl/all_settings.php (1)

210-213: Polish translation file contains English text.

The new translation entries for landing_background_landscape_mode, landing_background_portrait_mode, landing_background_landscape, and landing_background_portrait are in English rather than Polish. If this is intentional (e.g., placeholders for later translation), no action is needed. Otherwise, consider translating these strings to Polish for consistency with the locale.

Also applies to: 550-553

lang/cz/all_settings.php (1)

550-553: Add an explicit visibility warning for latest_album_cover / random_from_album modes.

The option descriptions are clear, but they should explicitly warn admins that these modes can expose configured assets on the public landing page if misconfigured.

💡 Suggested wording update
-        'landing_background_landscape_mode' => 'Options: static (URL), photo_id (specific photo), random (random public photo), latest_album_cover (latest album cover), random_from_album (random from album).',
-        'landing_background_portrait_mode' => 'Options: static (URL), photo_id (specific photo), random (random public photo), latest_album_cover (latest album cover), random_from_album (random from album).',
+        'landing_background_landscape_mode' => 'Options: static (URL), photo_id (specific photo), random (random public photo), latest_album_cover (latest album cover), random_from_album (random from album). Ensure configured sources are safe for public display.',
+        'landing_background_portrait_mode' => 'Options: static (URL), photo_id (specific photo), random (random public photo), latest_album_cover (latest album cover), random_from_album (random from album). Ensure configured sources are safe for public display.',

Based on learnings In LandingPageResource (app/Http/Resources/GalleryConfigs/LandingPageResource.php), resolveLatestAlbumCover and resolveRandomFromAlbum intentionally do not apply PhotoQueryPolicy filters.

lang/ar/all_settings.php (1)

212-213: Clarify behavior when mode does not use a configured value.

At Line 212-213 and Line 552-553, the copy explains URL/photo/album IDs, but it doesn’t explicitly say that random and latest_album_cover ignore this value. Adding that note would reduce admin confusion.

Proposed wording tweak
-        'landing_background_landscape' => 'Value for landscape background (URL, photo ID, or album ID)',
-        'landing_background_portrait' => 'Value for portrait background (URL, photo ID, or album ID)',
+        'landing_background_landscape' => 'Value for landscape background (URL, photo ID, or album ID; unused for random and latest_album_cover)',
+        'landing_background_portrait' => 'Value for portrait background (URL, photo ID, or album ID; unused for random and latest_album_cover)',
...
-        'landing_background_landscape' => 'Depends on mode: URL for static, photo ID for photo_id, album ID for random_from_album. This image is also used when sharing the gallery link directly.',
-        'landing_background_portrait' => 'Depends on mode: URL for static, photo ID for photo_id, album ID for random_from_album.',
+        'landing_background_landscape' => 'Depends on mode: URL for static, photo ID for photo_id, album ID for random_from_album. Unused for random and latest_album_cover. This image is also used when sharing the gallery link directly.',
+        'landing_background_portrait' => 'Depends on mode: URL for static, photo ID for photo_id, album ID for random_from_album. Unused for random and latest_album_cover.',

Also applies to: 552-553

app/Http/Resources/GalleryConfigs/LandingPageResource.php (2)

78-82: Avoid logging raw background config values.

Line 80 logs the full configured value. For static URL mode, this can include sensitive query tokens. Prefer logging redacted/derived metadata instead of the full raw value.

🔒 Suggested adjustment
 			\Log::notice('Landing background resolution failed', [
 				'mode' => $mode?->value,
-				'value' => $value,
+				'value_present' => $value !== '',
+				'value_kind' => $mode === LandingBackgroundModeType::STATIC ? 'url' : 'id',
 				'error' => $e->getMessage(),
 			]);

115-116: Extract repeated photo URL fallback logic into one helper.

The same medium→original→fallback selection is duplicated four times; a private helper will reduce drift and simplify future updates.

Also applies to: 137-138, 177-178, 212-213


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e65f32 and f0daf56.

📒 Files selected for processing (24)
  • app/Enum/LandingBackgroundModeType.php
  • app/Http/Resources/GalleryConfigs/LandingPageResource.php
  • database/migrations/2026_03_03_120000_add_dynamic_landing_background_modes.php
  • lang/ar/all_settings.php
  • lang/bg/all_settings.php
  • lang/cz/all_settings.php
  • lang/de/all_settings.php
  • lang/el/all_settings.php
  • lang/es/all_settings.php
  • lang/fa/all_settings.php
  • lang/fr/all_settings.php
  • lang/hu/all_settings.php
  • lang/it/all_settings.php
  • lang/ja/all_settings.php
  • lang/nl/all_settings.php
  • lang/no/all_settings.php
  • lang/pl/all_settings.php
  • lang/pt/all_settings.php
  • lang/ru/all_settings.php
  • lang/sk/all_settings.php
  • lang/sv/all_settings.php
  • lang/vi/all_settings.php
  • lang/zh_CN/all_settings.php
  • lang/zh_TW/all_settings.php
✅ Files skipped from review due to trivial changes (1)
  • lang/nl/all_settings.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • database/migrations/2026_03_03_120000_add_dynamic_landing_background_modes.php

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
app/Http/Resources/GalleryConfigs/LandingPageResource.php (2)

115-115: Extract duplicated photo URL fallback logic into one helper.

The same URL-resolution chain appears in four methods. Centralizing it reduces drift and keeps fallback behavior consistent.

♻️ Proposed refactor
+	private function resolvePhotoUrl(?Photo $photo): string
+	{
+		if ($photo === null) {
+			return self::FALLBACK_IMAGE;
+		}
+
+		return $photo->size_variants->getMedium()?->url
+			?? $photo->size_variants->getOriginal()?->url
+			?? self::FALLBACK_IMAGE;
+	}
+
 	private function resolvePhotoById(string $value): string
 	{
 		$photo = Photo::query()->with(['size_variants'])->find($value);
-
-		if ($photo === null) {
-			return self::FALLBACK_IMAGE;
-		}
-
-		return $photo->size_variants->getMedium()?->url ?? $photo->size_variants->getOriginal()->url ?? self::FALLBACK_IMAGE;
+		return $this->resolvePhotoUrl($photo);
 	}

As per coding guidelines: "Avoid code duplication in both if and else statements."

Also applies to: 137-137, 177-177, 214-214


131-132: Consider a more scalable random-selection strategy for high-cardinality datasets.

inRandomOrder()->limit(1) is typically expensive on large tables and runs on a hot path. A cached shortlist or precomputed random candidate strategy would reduce DB load.

Also applies to: 206-207


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0daf56 and 27147d8.

📒 Files selected for processing (1)
  • app/Http/Resources/GalleryConfigs/LandingPageResource.php

@codecov
Copy link

codecov bot commented Mar 3, 2026

Codecov Report

❌ Patch coverage is 16.00000% with 63 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.06%. Comparing base (f250817) to head (27147d8).
⚠️ Report is 1 commits behind head on master.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ildyria ildyria merged commit 0210917 into master Mar 3, 2026
44 checks passed
@ildyria ildyria deleted the landing-background branch March 3, 2026 22:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Additional 'landing_background' config options

1 participant