Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b3eab7d
Theming: Add dynamic icon and favicon endpoints
juliusknorr Aug 11, 2016
e5f8f28
Core: Load mimetype icons from theming app if available
juliusknorr Aug 11, 2016
da6285b
Core: load favicon from theming app
juliusknorr Aug 11, 2016
2d65b8c
Theming: Add favicon-touch and fix icon creation with non svg images
juliusknorr Aug 14, 2016
64510bd
Theming: Add PHPdoc and icon fallback to theming logo
juliusknorr Aug 14, 2016
c7adcb8
Theming: Fix default parameters in icon routes
juliusknorr Aug 14, 2016
d1fcfe8
Theming: Add colorized icon css from icons.css
juliusknorr Aug 14, 2016
6c7ebb1
Theming: Add icon caching
juliusknorr Aug 16, 2016
4945592
Fix IconController after rebase
juliusknorr Aug 25, 2016
9ac5476
Add cachebuster to favicons
juliusknorr Aug 25, 2016
ac7f852
Theming: Add IconController tests
juliusknorr Aug 25, 2016
b466628
Improve unit tests for image generation
juliusknorr Aug 29, 2016
af8976a
Add IconBuilder class to encapsulate icon generation
juliusknorr Aug 30, 2016
2370348
Check if dynamic icons can be used
juliusknorr Aug 30, 2016
9e28a3b
Theming: Code cleanup and cache buster for mime icons
juliusknorr Aug 30, 2016
492d0b9
Caching for icon files using AppData
juliusknorr Sep 18, 2016
2e8dd21
Improve caching
juliusknorr Oct 14, 2016
43097ea
Fix svg resizing and remove deprecated method call
juliusknorr Oct 14, 2016
cc8b1d3
Fix icon-folder css
juliusknorr Oct 17, 2016
3a400f9
Replace null return with NotFoundException
juliusknorr Oct 17, 2016
78de213
Sanitize input and small fixes
juliusknorr Nov 4, 2016
d409fe1
Error handling and tests if file was not found
juliusknorr Nov 5, 2016
2ab4d1e
Use IAppManager instead of OC_App
juliusknorr Nov 18, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions apps/theming/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,23 @@
'url' => '/js/theming',
'verb' => 'GET',
],
[
'name' => 'Icon#getFavicon',
'url' => '/favicon/{app}',
'verb' => 'GET',
'defaults' => array('app' => 'core'),
],
[
'name' => 'Icon#getTouchIcon',
'url' => '/icon/{app}',
'verb' => 'GET',
'defaults' => array('app' => 'core'),
],
[
'name' => 'Icon#getThemedIcon',
'url' => '/img/{app}/{image}',
'verb' => 'GET',
'requirements' => array('image' => '.+')
],
]];

174 changes: 174 additions & 0 deletions apps/theming/lib/Controller/IconController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php
/**
* @copyright Copyright (c) 2016 Julius Haertl <jus@bitgrid.net>
*
* @author Julius Haertl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Theming\Controller;

use OCA\Theming\IconBuilder;
use OCA\Theming\ImageManager;
use OCA\Theming\ThemingDefaults;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\Http\FileDisplayResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Files\NotFoundException;
use OCP\IRequest;
use OCA\Theming\Util;
use OCP\IConfig;

class IconController extends Controller {
/** @var ThemingDefaults */
private $themingDefaults;
/** @var Util */
private $util;
/** @var ITimeFactory */
private $timeFactory;
/** @var IConfig */
private $config;
/** @var IconBuilder */
private $iconBuilder;
/** @var ImageManager */
private $imageManager;

/**
* IconController constructor.
*
* @param string $appName
* @param IRequest $request
* @param ThemingDefaults $themingDefaults
* @param Util $util
* @param ITimeFactory $timeFactory
* @param IConfig $config
* @param IconBuilder $iconBuilder
* @param ImageManager $imageManager
*/
public function __construct(
$appName,
IRequest $request,
ThemingDefaults $themingDefaults,
Util $util,
ITimeFactory $timeFactory,
IConfig $config,
IconBuilder $iconBuilder,
ImageManager $imageManager
) {
parent::__construct($appName, $request);

$this->themingDefaults = $themingDefaults;
$this->util = $util;
$this->timeFactory = $timeFactory;
$this->config = $config;
$this->iconBuilder = $iconBuilder;
$this->imageManager = $imageManager;
}

/**
* @PublicPage
* @NoCSRFRequired
*
* @param $app string app name
* @param $image string image file name (svg required)
* @return FileDisplayResponse|NotFoundResponse
*/
public function getThemedIcon($app, $image) {
try {
$iconFile = $this->imageManager->getCachedImage("icon-" . $app . '-' . str_replace("/","_",$image));
} catch (NotFoundException $exception) {
$icon = $this->iconBuilder->colorSvg($app, $image);
$iconFile = $this->imageManager->setCachedImage("icon-" . $app . '-' . str_replace("/","_",$image), $icon);
}
if ($iconFile !== false) {
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/svg+xml']);
$response->cacheFor(86400);
$expires = new \DateTime();
$expires->setTimestamp($this->timeFactory->getTime());
$expires->add(new \DateInterval('PT24H'));
$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
$response->addHeader('Pragma', 'cache');
return $response;
} else {
return new NotFoundResponse();
}
}

/**
* Return a 32x32 favicon as png
*
* @PublicPage
* @NoCSRFRequired
*
* @param $app string app name
* @return FileDisplayResponse|NotFoundResponse
*/
public function getFavicon($app = "core") {
if ($this->themingDefaults->shouldReplaceIcons()) {
try {
$iconFile = $this->imageManager->getCachedImage('favIcon-' . $app);
} catch (NotFoundException $exception) {
$icon = $this->iconBuilder->getFavicon($app);
$iconFile = $this->imageManager->setCachedImage('favIcon-' . $app, $icon);
}
if ($iconFile !== false) {
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
$response->cacheFor(86400);
$expires = new \DateTime();
$expires->setTimestamp($this->timeFactory->getTime());
$expires->add(new \DateInterval('PT24H'));
$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
$response->addHeader('Pragma', 'cache');
return $response;
}
}
return new NotFoundResponse();
}

/**
* Return a 512x512 icon for touch devices
*
* @PublicPage
* @NoCSRFRequired
*
* @param $app string app name
* @return FileDisplayResponse|NotFoundResponse
*/
public function getTouchIcon($app = "core") {
if ($this->themingDefaults->shouldReplaceIcons()) {
try {
$iconFile = $this->imageManager->getCachedImage('touchIcon-' . $app);
} catch (NotFoundException $exception) {
$icon = $this->iconBuilder->getTouchIcon($app);
$iconFile = $this->imageManager->setCachedImage('touchIcon-' . $app, $icon);
}
if ($iconFile !== false) {
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/png']);
$response->cacheFor(86400);
$expires = new \DateTime();
$expires->setTimestamp($this->timeFactory->getTime());
$expires->add(new \DateInterval('PT24H'));
$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
$response->addHeader('Pragma', 'cache');
return $response;
}
}
return new NotFoundResponse();
}
}
11 changes: 11 additions & 0 deletions apps/theming/lib/Controller/ThemingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,15 @@ public function getStylesheet() {
$responseCss .= '.nc-theming-contrast {color: #ffffff}' . "\n";
}

if($logo !== '' or $color !== '') {
$responseCss .= '.icon-file,.icon-filetype-text {' .
'background-image: url(\'./img/core/filetypes/text.svg?v='.$cacheBusterValue.'\');' . "}\n" .
'.icon-folder, .icon-filetype-folder {' .
'background-image: url(\'./img/core/filetypes/folder.svg?v='.$cacheBusterValue.'\');' . "}\n" .
'.icon-filetype-folder-drag-accept {' .
'background-image: url(\'./img/core/filetypes/folder-drag-accept.svg?v='.$cacheBusterValue.'\')!important;' . "}\n";
}

$response = new DataDownloadResponse($responseCss, 'style', 'text/css');
$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
$response->addHeader('Pragma', 'cache');
Expand All @@ -416,13 +425,15 @@ public function getStylesheet() {
* @return DataDownloadResponse
*/
public function getJavascript() {
$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
$responseJS = '(function() {
OCA.Theming = {
name: ' . json_encode($this->template->getName()) . ',
url: ' . json_encode($this->template->getBaseUrl()) . ',
slogan: ' . json_encode($this->template->getSlogan()) . ',
color: ' . json_encode($this->template->getMailHeaderColor()) . ',
inverted: ' . json_encode($this->util->invertTextColor($this->template->getMailHeaderColor())) . ',
cacheBuster: ' . json_encode($cacheBusterValue). '
};
})();';
$response = new Http\DataDisplayResponse($responseJS);
Expand Down
Loading