From: Alexander Ebert Date: Sun, 29 Oct 2017 17:26:38 +0000 (+0100) Subject: Added support for HD preview images for styles X-Git-Tag: 3.1.0_Beta_3~44 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=2e572b2928c7e9f46519be4afd44a02cc891f2bb;p=GitHub%2FWoltLab%2FWCF.git Added support for HD preview images for styles Closes #2459 --- diff --git a/com.woltlab.wcf/defaultStyle.tar b/com.woltlab.wcf/defaultStyle.tar index 7e13802b7a..a401dd01b6 100644 Binary files a/com.woltlab.wcf/defaultStyle.tar and b/com.woltlab.wcf/defaultStyle.tar differ diff --git a/com.woltlab.wcf/templates/styleChooser.tpl b/com.woltlab.wcf/templates/styleChooser.tpl index 1d415b3ee8..e9b0fb0eab 100644 --- a/com.woltlab.wcf/templates/styleChooser.tpl +++ b/com.woltlab.wcf/templates/styleChooser.tpl @@ -3,7 +3,7 @@
  • - +
    diff --git a/wcfsetup/install/files/acp/templates/styleAdd.tpl b/wcfsetup/install/files/acp/templates/styleAdd.tpl index faf10f7005..53a82c6fe4 100644 --- a/wcfsetup/install/files/acp/templates/styleAdd.tpl +++ b/wcfsetup/install/files/acp/templates/styleAdd.tpl @@ -13,7 +13,8 @@ }); {if $action == 'edit'}new AcpUiStyleFaviconUpload({@$style->styleID});{/if} - new AcpUiStyleImageUpload({if $action == 'add'}0{else}{@$style->styleID}{/if}, '{$tmpHash}'); + new AcpUiStyleImageUpload({if $action == 'add'}0{else}{@$style->styleID}{/if}, '{$tmpHash}', false); + new AcpUiStyleImageUpload({if $action == 'add'}0{else}{@$style->styleID}{/if}, '{$tmpHash}', true); new UiToggleInput('input[name="useGoogleFont"]', { show: ['#wcfFontFamilyGoogleContainer'] @@ -255,6 +256,16 @@ {lang}wcf.acp.style.image.description{/lang} + +
    +
    +
    + +
    +
    + {lang}wcf.acp.style.image2x.description{/lang} +
    + {if $availableTemplateGroups|count}
    diff --git a/wcfsetup/install/files/acp/templates/styleList.tpl b/wcfsetup/install/files/acp/templates/styleList.tpl index 04d1681b9c..0f3c6dc8a5 100644 --- a/wcfsetup/install/files/acp/templates/styleList.tpl +++ b/wcfsetup/install/files/acp/templates/styleList.tpl @@ -34,7 +34,9 @@ {foreach from=$objects item=style}
  • - + + +

    {$style->styleName}

    diff --git a/wcfsetup/install/files/images/stylePreview@2x.png b/wcfsetup/install/files/images/stylePreview@2x.png new file mode 100644 index 0000000000..5ad3fc379f Binary files /dev/null and b/wcfsetup/install/files/images/stylePreview@2x.png differ diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Style/Image/Upload.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Style/Image/Upload.js index 1347f74b03..0170602a51 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Style/Image/Upload.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Acp/Ui/Style/Image/Upload.js @@ -12,11 +12,12 @@ define(['Core', 'Dom/Traverse', 'Language', 'Ui/Notification', 'Upload'], functi /** * @constructor */ - function AcpUiStyleImageUpload(styleId, tmpHash) { + function AcpUiStyleImageUpload(styleId, tmpHash, is2x) { + this._is2x = (is2x === true); this._styleId = ~~styleId; this._tmpHash = tmpHash; - Upload.call(this, 'uploadImage', 'styleImage', { + Upload.call(this, 'uploadImage' + (this._is2x ? '2x' : ''), 'styleImage' + (this._is2x ? '2x' : ''), { className: 'wcf\\data\\style\\StyleAction' }); } @@ -33,6 +34,7 @@ define(['Core', 'Dom/Traverse', 'Language', 'Ui/Notification', 'Upload'], functi */ _getParameters: function() { return { + is2x: this._is2x, styleId: this._styleId, tmpHash: this._tmpHash }; diff --git a/wcfsetup/install/files/lib/acp/form/StyleEditForm.class.php b/wcfsetup/install/files/lib/acp/form/StyleEditForm.class.php index 9e8c98f85e..f479c2b5a4 100644 --- a/wcfsetup/install/files/lib/acp/form/StyleEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/StyleEditForm.class.php @@ -4,7 +4,6 @@ use wcf\data\style\Style; use wcf\data\style\StyleAction; use wcf\form\AbstractForm; use wcf\system\exception\IllegalLinkException; -use wcf\system\exception\UserInputException; use wcf\system\language\I18nHandler; use wcf\system\WCF; @@ -26,7 +25,7 @@ class StyleEditForm extends StyleAddForm { * style object * @var Style */ - public $style = null; + public $style; /** * style id diff --git a/wcfsetup/install/files/lib/data/style/Style.class.php b/wcfsetup/install/files/lib/data/style/Style.class.php index 99e8791b7a..ecfd258b1f 100644 --- a/wcfsetup/install/files/lib/data/style/Style.class.php +++ b/wcfsetup/install/files/lib/data/style/Style.class.php @@ -22,6 +22,7 @@ use wcf\system\WCF; * @property-read string $styleVersion version number of the style * @property-read string $styleDate date when the used version of the style has been published * @property-read string $image link or path (relative to `WCF_DIR`) to the preview image of the style + * @property-read string $image2x link or path (relative to `WCF_DIR`) to the preview image of the style (2x version) * @property-read string $copyright copyright text of the style * @property-read string $license name of the style's license * @property-read string $authorName name(s) of the style's author(s) @@ -136,6 +137,19 @@ class Style extends DatabaseObject { return WCF::getPath().'images/stylePreview.png'; } + /** + * Returns the style preview image path (2x version). + * + * @return string + */ + public function getPreviewImage2x() { + if ($this->image2x && file_exists(WCF_DIR.'images/'.$this->image2x)) { + return WCF::getPath().'images/'.$this->image2x; + } + + return WCF::getPath().'images/stylePreview@2x.png'; + } + public function getFaviconAppleTouchIcon() { return $this->getFaviconPath('apple-touch-icon.png'); } diff --git a/wcfsetup/install/files/lib/data/style/StyleAction.class.php b/wcfsetup/install/files/lib/data/style/StyleAction.class.php index 284f680f3f..513917105f 100644 --- a/wcfsetup/install/files/lib/data/style/StyleAction.class.php +++ b/wcfsetup/install/files/lib/data/style/StyleAction.class.php @@ -220,30 +220,47 @@ class StyleAction extends AbstractDatabaseObjectAction implements IToggleAction, return; } - $fileExtension = WCF::getSession()->getVar('stylePreview-'.$this->parameters['tmpHash']); - if ($fileExtension !== null) { - $oldFilename = WCF_DIR.'images/stylePreview-'.$this->parameters['tmpHash'].'.'.$fileExtension; - if (file_exists($oldFilename)) { - $filename = 'stylePreview-'.$style->styleID.'.'.$fileExtension; - if (@rename($oldFilename, WCF_DIR.'images/'.$filename)) { - // delete old file if it has a different file extension - if ($style->image != $filename) { - @unlink(WCF_DIR.'images/'.$style->image); - - // update filename in database - $sql = "UPDATE wcf".WCF_N."_style - SET image = ? - WHERE styleID = ?"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute([ - $filename, - $style->styleID - ]); + foreach (['', '@2x'] as $type) { + $fileExtension = WCF::getSession()->getVar('stylePreview-' . $this->parameters['tmpHash'] . $type); + if ($fileExtension !== null) { + $oldFilename = WCF_DIR . 'images/stylePreview-' . $this->parameters['tmpHash'] . $type . '.' . $fileExtension; + if (file_exists($oldFilename)) { + $filename = 'stylePreview-' . $style->styleID . $type . '.' . $fileExtension; + if (@rename($oldFilename, WCF_DIR . 'images/' . $filename)) { + // delete old file if it has a different file extension + if ($type === '') { + if ($style->image != $filename) { + @unlink(WCF_DIR . 'images/' . $style->image); + + // update filename in database + $sql = "UPDATE wcf" . WCF_N . "_style + SET image = ? + WHERE styleID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([ + $filename, $style->styleID + ]); + } + } + else { + if ($style->image2x != $filename) { + @unlink(WCF_DIR . 'images/' . $style->image2x); + + // update filename in database + $sql = "UPDATE wcf" . WCF_N . "_style + SET image2x = ? + WHERE styleID = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([ + $filename, $style->styleID + ]); + } + } + } + else { + // remove temp file + @unlink($oldFilename); } - } - else { - // remove temp file - @unlink($oldFilename); } } } @@ -340,6 +357,7 @@ BROWSERCONFIG; throw new PermissionDeniedException(); } + $this->readBoolean('is2x', true); $this->readString('tmpHash'); $this->readInteger('styleID', true); @@ -373,6 +391,8 @@ BROWSERCONFIG; $files = $this->parameters['__files']->getFiles(); $file = $files[0]; + $multiplier = ($this->parameters['is2x']) ? 2 : 1; + try { if (!$file->getValidationErrorType()) { // shrink preview image if necessary @@ -391,11 +411,11 @@ BROWSERCONFIG; throw new UserInputException('image'); } - if ($imageData[0] > Style::PREVIEW_IMAGE_MAX_WIDTH || $imageData[1] > Style::PREVIEW_IMAGE_MAX_HEIGHT) { + if ($imageData[0] > (Style::PREVIEW_IMAGE_MAX_WIDTH * $multiplier) || $imageData[1] > (Style::PREVIEW_IMAGE_MAX_HEIGHT * $multiplier)) { $adapter = ImageHandler::getInstance()->getAdapter(); $adapter->loadFile($fileLocation); $fileLocation = FileUtil::getTemporaryFilename(); - $thumbnail = $adapter->createThumbnail(Style::PREVIEW_IMAGE_MAX_WIDTH, Style::PREVIEW_IMAGE_MAX_HEIGHT, false); + $thumbnail = $adapter->createThumbnail(Style::PREVIEW_IMAGE_MAX_WIDTH * $multiplier, Style::PREVIEW_IMAGE_MAX_HEIGHT * $multiplier, false); $adapter->writeImage($thumbnail, $fileLocation); } } @@ -404,23 +424,23 @@ BROWSERCONFIG; } // move uploaded file - if (@copy($fileLocation, WCF_DIR.'images/stylePreview-'.$this->parameters['tmpHash'].'.'.$file->getFileExtension())) { + if (@copy($fileLocation, WCF_DIR.'images/stylePreview-'.$this->parameters['tmpHash'].($this->parameters['is2x'] ? '@2x' : '').'.'.$file->getFileExtension())) { @unlink($fileLocation); // store extension within session variables - WCF::getSession()->register('stylePreview-'.$this->parameters['tmpHash'], $file->getFileExtension()); + WCF::getSession()->register('stylePreview-'.$this->parameters['tmpHash'].($this->parameters['is2x'] ? '@2x' : ''), $file->getFileExtension()); if ($this->parameters['styleID']) { $this->updateStylePreviewImage($this->style); return [ - 'url' => WCF::getPath().'images/stylePreview-'.$this->parameters['styleID'].'.'.$file->getFileExtension() + 'url' => WCF::getPath().'images/stylePreview-'.$this->parameters['styleID'].($this->parameters['is2x'] ? '@2x' : '').'.'.$file->getFileExtension() ]; } // return result return [ - 'url' => WCF::getPath().'images/stylePreview-'.$this->parameters['tmpHash'].'.'.$file->getFileExtension() + 'url' => WCF::getPath().'images/stylePreview-'.$this->parameters['tmpHash'].($this->parameters['is2x'] ? '@2x' : '').'.'.$file->getFileExtension() ]; } else { diff --git a/wcfsetup/install/files/lib/data/style/StyleEditor.class.php b/wcfsetup/install/files/lib/data/style/StyleEditor.class.php index a8bd2a2d83..fd459f0d2c 100644 --- a/wcfsetup/install/files/lib/data/style/StyleEditor.class.php +++ b/wcfsetup/install/files/lib/data/style/StyleEditor.class.php @@ -144,7 +144,7 @@ class StyleEditor extends DatabaseObjectEditor implements IEditableCachedObject $xpath = $xml->xpath(); $data = [ - 'name' => '', 'description' => [], 'version' => '', 'image' => '', 'copyright' => '', 'default' => false, + 'name' => '', 'description' => [], 'version' => '', 'image' => '', 'image2x' => '', 'copyright' => '', 'default' => false, 'license' => '', 'authorName' => '', 'authorURL' => '', 'templates' => '', 'images' => '', 'variables' => '', 'date' => '0000-00-00', 'imagesPath' => '', 'packageName' => '', 'apiVersion' => '3.0' ]; @@ -217,6 +217,7 @@ class StyleEditor extends DatabaseObjectEditor implements IEditableCachedObject case 'copyright': case 'image': + case 'image2x': case 'license': $data[$element->tagName] = $element->nodeValue; break; @@ -500,33 +501,6 @@ class StyleEditor extends DatabaseObjectEditor implements IEditableCachedObject $styleData['packageID'] = $packageID; $style = new StyleEditor(self::create($styleData)); - // import preview image - if (!empty($data['image'])) { - $fileExtension = mb_substr($data['image'], mb_strrpos($data['image'], '.')); - $index = $tar->getIndexByFilename($data['image']); - if ($index !== false) { - $filename = WCF_DIR.'images/stylePreview-'.$style->styleID.$fileExtension; - $tar->extract($index, $filename); - FileUtil::makeWritable($filename); - - if (file_exists($filename)) { - try { - if (($imageData = getimagesize($filename)) !== false) { - switch ($imageData[2]) { - case IMAGETYPE_PNG: - case IMAGETYPE_JPEG: - case IMAGETYPE_GIF: - $style->update(['image' => 'stylePreview-'.$style->styleID.$fileExtension]); - } - } - } - catch (SystemException $e) { - // broken image - } - } - } - } - // handle descriptions if (!empty($data['description'])) { self::saveLocalizedDescriptions($style, $data['description']); @@ -555,6 +529,35 @@ class StyleEditor extends DatabaseObjectEditor implements IEditableCachedObject $style->update($styleData); } + // import preview image + foreach (['image', 'image2x'] as $type) { + if (!empty($data[$type])) { + $fileExtension = mb_substr($data[$type], mb_strrpos($data[$type], '.')); + $index = $tar->getIndexByFilename($data[$type]); + if ($index !== false) { + $filename = WCF_DIR . 'images/stylePreview-' . $style->styleID . ($type === 'image2x' ? '@2x' : '') . $fileExtension; + $tar->extract($index, $filename); + FileUtil::makeWritable($filename); + + if (file_exists($filename)) { + try { + if (($imageData = getimagesize($filename)) !== false) { + switch ($imageData[2]) { + case IMAGETYPE_PNG: + case IMAGETYPE_JPEG: + case IMAGETYPE_GIF: + $style->update([$type => 'stylePreview-' . $style->styleID . ($type === 'image2x' ? '@2x' : '') . $fileExtension]); + } + } + } + catch (SystemException $e) { + // broken image + } + } + } + } + } + $tar->close(); return $style; @@ -651,6 +654,9 @@ class StyleEditor extends DatabaseObjectEditor implements IEditableCachedObject if ($this->image && @file_exists(WCF_DIR.'images/'.$this->image)) { $styleTar->add(WCF_DIR.'images/'.$this->image, '', FileUtil::addTrailingSlash(dirname(WCF_DIR.'images/'.$this->image))); } + if ($this->image2x && @file_exists(WCF_DIR.'images/'.$this->image2x)) { + $styleTar->add(WCF_DIR.'images/'.$this->image2x, '', FileUtil::addTrailingSlash(dirname(WCF_DIR.'images/'.$this->image2x))); + } // fetch style description $sql = "SELECT language.languageCode, language_item.languageItemValue @@ -680,6 +686,7 @@ class StyleEditor extends DatabaseObjectEditor implements IEditableCachedObject $xml->writeElement('version', $this->styleVersion); $xml->writeElement('apiVersion', $this->apiVersion); if ($this->image) $xml->writeElement('image', $this->image); + if ($this->image2x) $xml->writeElement('image2x', $this->image2x); if ($this->copyright) $xml->writeElement('copyright', $this->copyright); if ($this->license) $xml->writeElement('license', $this->license); $xml->endElement(); diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 471337eb4c..e68646b6b7 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -1945,6 +1945,8 @@ Als Benachrichtigungs-URL in der Konfiguration der sofortigen Zahlungsbestätigu + + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 4d25ef8148..4c04ea1eb2 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -1888,6 +1888,8 @@ When prompted for the notification URL for the instant payment notifications, pl + + diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index ca08ce48f2..1c802e8dbd 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -1252,6 +1252,7 @@ CREATE TABLE wcf1_style ( styleVersion VARCHAR(255) NOT NULL DEFAULT '', styleDate CHAR(10) NOT NULL DEFAULT '0000-00-00', image VARCHAR(255) NOT NULL DEFAULT '', + image2x VARCHAR(255) NOT NULL DEFAULT '', copyright VARCHAR(255) NOT NULL DEFAULT '', license VARCHAR(255) NOT NULL DEFAULT '', authorName VARCHAR(255) NOT NULL DEFAULT '',