Add basic support for thumbnails
authorAlexander Ebert <ebert@woltlab.com>
Thu, 15 Feb 2024 18:26:05 +0000 (19:26 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 8 Jun 2024 10:19:38 +0000 (12:19 +0200)
ts/WoltLabSuite/Core/Component/File/Upload.ts
wcfsetup/install/files/lib/action/FileUploadAction.class.php
wcfsetup/install/files/lib/data/file/File.class.php
wcfsetup/install/files/lib/system/file/processor/AttachmentFileProcessor.class.php
wcfsetup/install/files/lib/system/file/processor/IFileProcessor.class.php
wcfsetup/install/files/lib/system/file/processor/ThumbnailFormat.class.php [new file with mode: 0644]

index cce4d261b29e31cc538894970ce60b614f404cac..73c3a438aa15713210dc0a12d644d635f0f86ed1 100644 (file)
@@ -14,6 +14,7 @@ type UploadResponse =
     } & UploadCompleted);
 
 export type UploadCompleted = {
+  endpointThumbnails: string;
   fileID: string;
   typeName: string;
   data: Record<string, unknown>;
@@ -68,11 +69,16 @@ async function upload(element: WoltlabCoreFileUploadElement, file: File): Promis
         const event = new CustomEvent<UploadCompleted>("uploadCompleted", {
           detail: {
             data: response.data,
+            endpointThumbnails: response.endpointThumbnails,
             fileID: response.fileID,
             typeName: response.typeName,
           },
         });
         element.dispatchEvent(event);
+
+        if (response.endpointThumbnails !== "") {
+          // TODO: Dispatch the request to generate thumbnails.
+        }
       }
     } catch (e) {
       // TODO: Handle errors
index bda5a61c4f16cdefa01de0663b9bbcd25b9b3234..aa6431a045c682568720da9f4d1c6e94bd06dbc1 100644 (file)
@@ -129,9 +129,19 @@ final class FileUploadAction implements RequestHandlerInterface
 
             $processor->adopt($file, $context);
 
+            $endpointThumbnails = '';
+            if ($file->isImage()) {
+                $thumbnailFormats = $processor->getThumbnailFormats();
+                if ($thumbnailFormats !== []) {
+                    // TODO: Endpoint to generate thumbnails.
+                    $endpointThumbnails = '';
+                }
+            }
+
             // TODO: This is just debug code.
             return new JsonResponse([
                 'completed' => true,
+                'endpointThumbnails' => $endpointThumbnails,
                 'fileID' => $file->fileID,
                 'typeName' => $file->typeName,
                 'data' => $processor->getUploadResponse($file),
index f1e2b64bf55cfd3f68b09bc22101d3213523e806..4a7fc6e9bb715ad7931f07a6b581d4e0d26f672c 100644 (file)
@@ -7,6 +7,7 @@ use wcf\data\DatabaseObject;
 use wcf\system\file\processor\FileProcessor;
 use wcf\system\file\processor\IFileProcessor;
 use wcf\system\request\LinkHandler;
+use wcf\util\FileUtil;
 
 /**
  * @author Alexander Ebert
@@ -55,4 +56,17 @@ class File extends DatabaseObject
     {
         return FileProcessor::getInstance()->forTypeName($this->typeName);
     }
+
+    public function isImage(): bool
+    {
+        $mimeType = FileUtil::getMimeType($this->getPath() . $this->getSourceFilename());
+
+        return match ($mimeType) {
+            'image/gif' => true,
+            'image/jpg', 'image/jpeg' => true,
+            'image/png' => true,
+            'image/webp' => true,
+            default => false,
+        };
+    }
 }
index 0ef55e1bb0a39330f24f435aa2d58b2f038e06bd..88c8c92d36815fb42a16cacad89034da034f10d0 100644 (file)
@@ -15,11 +15,13 @@ use wcf\system\attachment\AttachmentHandler;
  */
 final class AttachmentFileProcessor implements IFileProcessor
 {
+    #[\Override]
     public function getTypeName(): string
     {
         return 'com.woltlab.wcf.attachment';
     }
 
+    #[\Override]
     public function getAllowedFileExtensions(array $context): array
     {
         // TODO: Properly validate the shape of `$context`.
@@ -33,6 +35,7 @@ final class AttachmentFileProcessor implements IFileProcessor
         return $attachmentHandler->getAllowedExtensions();
     }
 
+    #[\Override]
     public function adopt(File $file, array $context): void
     {
         // TODO: Properly validate the shape of `$context`.
@@ -53,6 +56,7 @@ final class AttachmentFileProcessor implements IFileProcessor
         ]);
     }
 
+    #[\Override]
     public function acceptUpload(string $filename, int $fileSize, array $context): FileProcessorPreflightResult
     {
         // TODO: Properly validate the shape of `$context`.
@@ -91,6 +95,7 @@ final class AttachmentFileProcessor implements IFileProcessor
         return FileProcessorPreflightResult::Passed;
     }
 
+    #[\Override]
     public function canDownload(File $file): bool
     {
         $attachment = Attachment::findByFileID($file->fileID);
@@ -101,6 +106,7 @@ final class AttachmentFileProcessor implements IFileProcessor
         return $attachment->canDownload();
     }
 
+    #[\Override]
     public function getUploadResponse(File $file): array
     {
         $attachment = Attachment::findByFileID($file->fileID);
@@ -113,6 +119,7 @@ final class AttachmentFileProcessor implements IFileProcessor
         ];
     }
 
+    #[\Override]
     public function toHtmlElement(string $objectType, int $objectID, string $tmpHash, int $parentObjectID): string
     {
         return FileProcessor::getInstance()->getHtmlElement(
@@ -125,4 +132,23 @@ final class AttachmentFileProcessor implements IFileProcessor
             ],
         );
     }
+
+    #[\Override]
+    public function getThumbnailFormats(): array
+    {
+        return [
+            new ThumbnailFormat(
+                'tiny',
+                144,
+                144,
+                false,
+            ),
+            new ThumbnailFormat(
+                'default',
+                \ATTACHMENT_THUMBNAIL_HEIGHT,
+                \ATTACHMENT_THUMBNAIL_WIDTH,
+                !!\ATTACHMENT_RETAIN_DIMENSIONS,
+            ),
+        ];
+    }
 }
index 00bef07067a55c76ba0f98e204251957b9774670..309624991bcc6bc99a86b3e97355a64c583c3ae8 100644 (file)
@@ -23,4 +23,9 @@ interface IFileProcessor
     public function getTypeName(): string;
 
     public function getUploadResponse(File $file): array;
+
+    /**
+     * @return ThumbnailFormat[]
+     */
+    public function getThumbnailFormats(): array;
 }
diff --git a/wcfsetup/install/files/lib/system/file/processor/ThumbnailFormat.class.php b/wcfsetup/install/files/lib/system/file/processor/ThumbnailFormat.class.php
new file mode 100644 (file)
index 0000000..41cd45c
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+namespace wcf\system\file\processor;
+
+final class ThumbnailFormat
+{
+    public function __construct(
+        public readonly string $identifier,
+        public readonly int $height,
+        public readonly int $width,
+        public readonly bool $retainDimensions,
+    ) {
+    }
+}