Signed-off-by: Julius Härtl <jus@bitgrid.net>tags/v20.0.0beta1
@@ -29,6 +29,6 @@ return [ | |||
['name' => 'dashboard#index', 'url' => '/', 'verb' => 'GET'], | |||
['name' => 'dashboard#updateLayout', 'url' => '/layout', 'verb' => 'POST'], | |||
['name' => 'dashboard#getBackground', 'url' => '/background', 'verb' => 'GET'], | |||
['name' => 'dashboard#setBackground', 'url' => '/background', 'verb' => 'POST'], | |||
['name' => 'dashboard#setBackground', 'url' => '/background/{type}', 'verb' => 'POST'], | |||
] | |||
]; |
@@ -108,6 +108,7 @@ class DashboardController extends Controller { | |||
$this->inititalStateService->provideInitialState('dashboard', 'firstRun', $this->config->getUserValue($this->userId, 'dashboard', 'firstRun', '1') === '1'); | |||
$this->inititalStateService->provideInitialState('dashboard', 'shippedBackgrounds', BackgroundService::SHIPPED_BACKGROUNDS); | |||
$this->inititalStateService->provideInitialState('dashboard', 'background', $this->config->getUserValue($this->userId, 'dashboard', 'background', 'default')); | |||
$this->inititalStateService->provideInitialState('dashboard', 'version', $this->config->getUserValue($this->userId, 'dashboard', 'backgroundVersion', 0)); | |||
$this->config->setUserValue($this->userId, 'dashboard', 'firstRun', '0'); | |||
return new TemplateResponse('dashboard', 'index'); | |||
@@ -126,18 +127,35 @@ class DashboardController extends Controller { | |||
/** | |||
* @NoAdminRequired | |||
*/ | |||
public function setBackground($path = null, $url = null, $shipped = null): JSONResponse { | |||
if ($shipped !== null) { | |||
$this->backgroundService->setShippedBackground($shipped); | |||
} else if ($path !== null) { | |||
$this->backgroundService->setFileBackground($path); | |||
} else if ($url !== null) { | |||
$this->backgroundService->setUrlBackground($url); | |||
} else { | |||
$this->backgroundService->setDefaultBackground(); | |||
public function setBackground(string $type = 'default', $value): JSONResponse { | |||
$currentVersion = $this->config->getUserValue($this->userId, 'dashboard', 'backgroundVersion', 0); | |||
try { | |||
switch ($type) { | |||
case 'shipped': | |||
$this->backgroundService->setShippedBackground($value); | |||
break; | |||
case 'custom': | |||
$this->backgroundService->setFileBackground($value); | |||
break; | |||
case 'color': | |||
$this->backgroundService->setColorBackground($value); | |||
break; | |||
case 'default': | |||
$this->backgroundService->setDefaultBackground(); | |||
break; | |||
default: | |||
return new JSONResponse(['error' => 'Invalid type provided'], Http::STATUS_BAD_REQUEST); | |||
} | |||
} catch (\InvalidArgumentException $e) { | |||
return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST); | |||
} | |||
return new JSONResponse([]); | |||
$currentVersion++; | |||
$this->config->setUserValue($this->userId, 'dashboard', 'backgroundVersion', $currentVersion); | |||
return new JSONResponse([ | |||
'type' => $type, | |||
'value' => $value, | |||
'version' => $this->config->getUserValue($this->userId, 'dashboard', 'backgroundVersion', $currentVersion) | |||
]); | |||
} | |||
/** |
@@ -74,19 +74,17 @@ class BackgroundService { | |||
} | |||
public function setShippedBackground($fileName) { | |||
if (!in_array($fileName, self::SHIPPED_BACKGROUNDS)) { | |||
throw new \InvalidArgumentException('The given file name is invalid'); | |||
} | |||
$this->config->setUserValue($this->userId, 'dashboard', 'background', $fileName); | |||
} | |||
public function setUrlBackground($url) { | |||
$this->config->setUserValue($this->userId, 'dashboard', 'background', 'custom'); | |||
if (substr($url, 0, 1) === '/') { | |||
$url = \OC::$server->getURLGenerator()->getAbsoluteURL($url); | |||
public function setColorBackground(string $color) { | |||
if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) { | |||
throw new \InvalidArgumentException('The given color is invalid'); | |||
} | |||
$client = \OC::$server->getHTTPClientService()->newClient(); | |||
$response = $client->get($url); | |||
$content = $response->getBody(); | |||
$newFile = $this->dashboardUserFolder->newFile('background.jpg', $content); | |||
$this->config->setUserValue($this->userId, 'dashboard', 'background', $color); | |||
} | |||
public function getBackground() { |
@@ -1,5 +1,5 @@ | |||
<template> | |||
<div id="app-dashboard" :style="{ backgroundImage: `url(${backgroundImage})` }"> | |||
<div id="app-dashboard" :style="backgroundStyle"> | |||
<h2>{{ greeting.text }}</h2> | |||
<div class="statuses"> | |||
<div v-for="status in registeredStatus" | |||
@@ -73,28 +73,16 @@ import { getCurrentUser } from '@nextcloud/auth' | |||
import { Modal } from '@nextcloud/vue' | |||
import Draggable from 'vuedraggable' | |||
import axios from '@nextcloud/axios' | |||
import { generateUrl, generateFilePath } from '@nextcloud/router' | |||
import { generateUrl } from '@nextcloud/router' | |||
import isMobile from './mixins/isMobile' | |||
import BackgroundSettings from './components/BackgroundSettings' | |||
import getBackgroundUrl from './helpers/getBackgroundUrl' | |||
import prefixWithBaseUrl from './helpers/prefixWithBaseUrl' | |||
const panels = loadState('dashboard', 'panels') | |||
const firstRun = loadState('dashboard', 'firstRun') | |||
const background = loadState('dashboard', 'background') | |||
const prefixWithBaseUrl = (url) => generateFilePath('dashboard', '', 'img/') + url | |||
// FIXME: move out duplicate | |||
const getBackgroundUrl = (background, time = 0) => { | |||
if (background === 'default') { | |||
if (window.OCA.Accessibility.theme === 'dark') { | |||
return prefixWithBaseUrl('eduardo-neves-pedra-azul.jpg') | |||
} | |||
return prefixWithBaseUrl('kamil-porembinski-clouds.jpg') | |||
} else if (background === 'custom') { | |||
return generateUrl('/apps/dashboard/background') + '?v=' + time | |||
} | |||
return prefixWithBaseUrl(background) | |||
} | |||
const version = loadState('dashboard', 'version') | |||
export default { | |||
name: 'App', | |||
@@ -121,13 +109,21 @@ export default { | |||
appStoreUrl: generateUrl('/settings/apps/dashboard'), | |||
statuses: {}, | |||
background, | |||
backgroundTime: Date.now(), | |||
version, | |||
defaultBackground: window.OCA.Accessibility.theme === 'dark' ? prefixWithBaseUrl('flickr-148302424@N05-36591009215.jpg?v=1') : prefixWithBaseUrl('flickr-paszczak000-8715851521.jpg?v=1'), | |||
} | |||
}, | |||
computed: { | |||
backgroundImage() { | |||
return getBackgroundUrl(this.background, this.backgroundTime) | |||
return getBackgroundUrl(this.background, this.version) | |||
}, | |||
backgroundStyle() { | |||
if (this.background.match(/#[0-9A-Fa-f]{6}/g)) { | |||
return null | |||
} | |||
return { | |||
backgroundImage: `url(${this.backgroundImage})`, | |||
} | |||
}, | |||
tooltip() { | |||
if (!this.firstRun) { | |||
@@ -269,8 +265,9 @@ export default { | |||
this.firstRun = false | |||
}, 1000) | |||
}, | |||
updateBackground(backgroundType) { | |||
this.background = backgroundType | |||
updateBackground(data) { | |||
this.background = data.type === 'custom' || data.type === 'default' ? data.type : data.value | |||
this.version = data.version | |||
}, | |||
}, | |||
} |
@@ -41,6 +41,15 @@ | |||
{{ t('dashboard', 'Default images') }} | |||
</div> | |||
</a> | |||
<a class="background color" | |||
tabindex="0" | |||
@click="pickColor" | |||
@keyup.enter="pickColor" | |||
@keyup.space="pickColor"> | |||
<div class="background--preview"> | |||
{{ t('dashboard', 'Plain background') }} | |||
</div> | |||
</a> | |||
<a v-for="background in shippedBackgrounds" | |||
:key="background.name" | |||
tabindex="0" | |||
@@ -56,24 +65,12 @@ | |||
<script> | |||
import axios from '@nextcloud/axios' | |||
import { generateUrl, generateFilePath } from '@nextcloud/router' | |||
import { generateUrl } from '@nextcloud/router' | |||
import { loadState } from '@nextcloud/initial-state' | |||
const prefixWithBaseUrl = (url) => generateFilePath('dashboard', '', 'img/') + url | |||
import getBackgroundUrl from './../helpers/getBackgroundUrl' | |||
import prefixWithBaseUrl from './../helpers/prefixWithBaseUrl' | |||
const shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds') | |||
const getBackgroundUrl = (background, time = 0) => { | |||
if (background === 'default') { | |||
if (window.OCA.Accessibility.theme === 'dark') { | |||
return prefixWithBaseUrl('eduardo-neves-pedra-azul.jpg') | |||
} | |||
return prefixWithBaseUrl('kamil-porembinski-clouds.jpg') | |||
} else if (background === 'custom') { | |||
return generateUrl('/apps/dashboard/background') + '?v=' + time | |||
} | |||
return prefixWithBaseUrl(background) | |||
} | |||
export default { | |||
name: 'BackgroundSettings', | |||
data() { | |||
@@ -93,35 +90,36 @@ export default { | |||
}, | |||
}, | |||
methods: { | |||
async update(state) { | |||
const date = Date.now() | |||
this.backgroundImage = getBackgroundUrl(state, date) | |||
async update(data) { | |||
const background = data.type === 'custom' || data.type === 'default' ? data.type : data.value | |||
this.backgroundImage = getBackgroundUrl(background, data.version) | |||
const image = new Image() | |||
image.onload = () => { | |||
this.$emit('updateBackground', state) | |||
this.$emit('updateBackground', data) | |||
this.loading = false | |||
} | |||
image.src = this.backgroundImage | |||
}, | |||
async setDefault() { | |||
console.debug('SetDefault') | |||
await axios.post(generateUrl('/apps/dashboard/background')) | |||
this.update('default') | |||
this.loading = 'default' | |||
const result = await axios.post(generateUrl('/apps/dashboard/background/default')) | |||
this.update(result.data) | |||
}, | |||
async setShipped(shipped) { | |||
this.loading = shipped | |||
await axios.post(generateUrl('/apps/dashboard/background'), { shipped }) | |||
this.update(shipped) | |||
}, | |||
async setUrl(url) { | |||
this.loading = true | |||
await axios.post(generateUrl('/apps/dashboard/background'), { url }) | |||
this.update('custom') | |||
const result = await axios.post(generateUrl('/apps/dashboard/background/shipped'), { value: shipped }) | |||
this.update(result.data) | |||
}, | |||
async setFile(path) { | |||
this.loading = true | |||
await axios.post(generateUrl('/apps/dashboard/background'), { path }) | |||
this.update('custom') | |||
this.loading = 'custom' | |||
const result = await axios.post(generateUrl('/apps/dashboard/background/custom'), { value: path }) | |||
this.update(result.data) | |||
}, | |||
async pickColor() { | |||
this.loading = 'color' | |||
const color = OCA && OCA.Theming ? OCA.Theming.color : '#0082c9' | |||
const result = await axios.post(generateUrl('/apps/dashboard/background/color'), { value: color }) | |||
this.update(result.data) | |||
}, | |||
pickFile() { | |||
window.OC.dialogs.filepicker(t('dashboard', 'Insert from {productName}', { productName: OC.theme.name }), (path, type) => { | |||
@@ -161,13 +159,18 @@ export default { | |||
background-position: center center; | |||
} | |||
&.filepicker, &.default { | |||
&.filepicker, &.default, &.color { | |||
border: 2px solid var(--color-border); | |||
.background--preview { | |||
line-height: 100px; | |||
} | |||
} | |||
&.color .background--preview { | |||
background-color: var(--color-primary); | |||
color: var(--color-primary-text); | |||
} | |||
&:hover, | |||
&:focus { | |||
border: 2px solid var(--color-primary); |
@@ -0,0 +1,36 @@ | |||
/* | |||
* @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net> | |||
* | |||
* @author Julius Härtl <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/>. | |||
* | |||
*/ | |||
import { generateUrl } from '@nextcloud/router' | |||
import prefixWithBaseUrl from './prefixWithBaseUrl' | |||
export default (background, time = 0) => { | |||
if (background === 'default') { | |||
if (window.OCA.Accessibility.theme === 'dark') { | |||
return prefixWithBaseUrl('eduardo-neves-pedra-azul.jpg') | |||
} | |||
return prefixWithBaseUrl('kamil-porembinski-clouds.jpg') | |||
} else if (background === 'custom') { | |||
return generateUrl('/apps/dashboard/background') + '?v=' + time | |||
} | |||
return prefixWithBaseUrl(background) | |||
} |
@@ -0,0 +1,24 @@ | |||
/* | |||
* @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net> | |||
* | |||
* @author Julius Härtl <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/>. | |||
* | |||
*/ | |||
import { generateFilePath } from '@nextcloud/router' | |||
export default (url) => generateFilePath('dashboard', '', 'img/') + url |