From 949cc17b0da782c38df3a684eb6e3b0b7a2816b8 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 28 Jan 2026 23:10:17 +0000 Subject: [PATCH] Fix preset thumbnail route conflict, improve docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/RSpade/Core/Files/CLAUDE.md | 49 ++++++++++++++++--- .../Core/Files/File_Attachment_Controller.php | 4 +- .../Core/Files/File_Attachment_Model.php | 2 +- app/RSpade/Core/Files/THUMBNAILS.md | 2 +- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/app/RSpade/Core/Files/CLAUDE.md b/app/RSpade/Core/Files/CLAUDE.md index aa0d80f25..01e491153 100755 --- a/app/RSpade/Core/Files/CLAUDE.md +++ b/app/RSpade/Core/Files/CLAUDE.md @@ -97,18 +97,55 @@ $name = $photo->original_filename; ## Thumbnail System -Thumbnails are generated on-demand and cached: +Thumbnails are generated on-demand and cached. -**Preset types** (defined in config): -- `cover` - Cover image aspect ratio -- `square` - 1:1 aspect ratio -- `landscape` - 16:9 aspect ratio +**Dynamic thumbnail types** (for `get_thumbnail_url()`): +- `'cover'` - Crops image to fill exact dimensions +- `'fit'` - Scales image to fit within dimensions, maintaining aspect ratio + +**Retina support**: Thumbnails are automatically generated at 2x the requested dimensions. +Request your CSS display size - a 300x200 request generates a 600x400 image. **Dynamic thumbnails**: -- Limited to `max_dynamic_size` (default 2000px) +- Limited to `max_dynamic_size` (default 800px base, 1600px actual with 2x) - Cached for performance - Automatic cleanup via scheduled task +**Preset thumbnails** (for `get_thumbnail_url_preset()`): + +Presets must be defined in config before use: + +```php +// rsx/resource/config/rsx.php +'thumbnails' => [ + 'presets' => [ + 'profile' => [ + 'type' => 'cover', // 'cover' or 'fit' + 'width' => 150, // base width (CSS display size) + 'height' => 150, // base height + ], + 'card_image' => [ + 'type' => 'cover', + 'width' => 400, + 'height' => 250, + ], + 'document_preview' => [ + 'type' => 'fit', + 'width' => 800, + 'height' => 600, + ], + ], +], +``` + +Usage: +```php +$photo->get_thumbnail_url_preset('profile') +// Generates: /_thumbnail/preset/{key}/profile +``` + +**Best practice**: Create a preset for every fixed-size thumbnail in your application (profile photos, card images, list thumbnails, etc.). Presets are preserved permanently. Only use dynamic thumbnails when the size is determined at runtime or varies based on context (e.g., responsive galleries, user-resizable containers). + ## Controller Implementation Pattern ```php diff --git a/app/RSpade/Core/Files/File_Attachment_Controller.php b/app/RSpade/Core/Files/File_Attachment_Controller.php index a4adde4ec..ebe445cc3 100644 --- a/app/RSpade/Core/Files/File_Attachment_Controller.php +++ b/app/RSpade/Core/Files/File_Attachment_Controller.php @@ -493,14 +493,14 @@ class File_Attachment_Controller extends Rsx_Controller_Abstract /** * Generate preset thumbnail for image attachments * - * Route: /_thumbnail/:key/preset/:preset_name + * Route: /_thumbnail/preset/:key/:preset_name * * Security: Checks file.thumbnail.authorize only * * @param string $key Attachment key * @param string $preset_name Preset name from config */ - #[Route('/_thumbnail/:key/preset/:preset_name', methods: ['GET'])] + #[Route('/_thumbnail/preset/:key/:preset_name', methods: ['GET'])] #[Auth('Permission::anybody()')] public static function thumbnail_preset(Request $request, array $params = []) { diff --git a/app/RSpade/Core/Files/File_Attachment_Model.php b/app/RSpade/Core/Files/File_Attachment_Model.php index bc59884af..69380bf4d 100644 --- a/app/RSpade/Core/Files/File_Attachment_Model.php +++ b/app/RSpade/Core/Files/File_Attachment_Model.php @@ -287,7 +287,7 @@ class File_Attachment_Model extends Rsx_Site_Model_Abstract throw new Exception("Thumbnail preset '{$preset_name}' not defined in config"); } - return url("/_thumbnail/{$this->key}/preset/{$preset_name}"); + return url("/_thumbnail/preset/{$this->key}/{$preset_name}"); } /** diff --git a/app/RSpade/Core/Files/THUMBNAILS.md b/app/RSpade/Core/Files/THUMBNAILS.md index 7b26101a8..2eb8a8047 100755 --- a/app/RSpade/Core/Files/THUMBNAILS.md +++ b/app/RSpade/Core/Files/THUMBNAILS.md @@ -53,7 +53,7 @@ Edge case: Identical file content uploaded with different extensions (e.g., `doc ### Request Processing -**Route**: `/_thumbnail/:key/:type/:width/:height` (dynamic) or `/_thumbnail/:key/preset/:preset_name` (preset) +**Route**: `/_thumbnail/:key/:type/:width/:height` (dynamic) or `/_thumbnail/preset/:key/:preset_name` (preset) **Common Flow** (via `generate_and_serve_thumbnail()`): 1. Validate authorization (`file.thumbnail.authorize` event)