]> source.dussan.org Git - nextcloud-server.git/commitdiff
Allow to set a primary color background
authorJulius Härtl <jus@bitgrid.net>
Mon, 17 Aug 2020 19:29:29 +0000 (21:29 +0200)
committerJulius Härtl <jus@bitgrid.net>
Wed, 19 Aug 2020 15:07:28 +0000 (17:07 +0200)
Signed-off-by: Julius Härtl <jus@bitgrid.net>
apps/dashboard/appinfo/routes.php
apps/dashboard/lib/Controller/DashboardController.php
apps/dashboard/lib/Service/BackgroundService.php
apps/dashboard/src/App.vue
apps/dashboard/src/components/BackgroundSettings.vue
apps/dashboard/src/helpers/getBackgroundUrl.js [new file with mode: 0644]
apps/dashboard/src/helpers/prefixWithBaseUrl.js [new file with mode: 0644]

index 704311bddf5228d981b90426526fa48667a8c08a..c4df1f732f8a37078a4716dd3b30d2f10e468bb2 100644 (file)
@@ -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'],
        ]
 ];
index bd83ca458495f4857084fe6638773a5201470f04..3f4c9fdbfa4a75b23c4776ef24c17f3c0a521214 100644 (file)
@@ -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)
+               ]);
        }
 
        /**
index a651d11618f8bff30c4e93556946a7163dc85e81..d4de491aeaa075e1a1522acf3f2b02ef6caa96cf 100644 (file)
@@ -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() {
index e266d64c6dd03d90099adba5c2e6b8b8ae2c14a2..c59e4732373e790dc52b5c6385bff39d1f4fea05 100644 (file)
@@ -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
                },
        },
 }
index 9c4bfcfa5ecb148cbaf044fca997512fbca1b1f7..757711f96bbcf2ddea29c2e2fe5645c6d76c6de7 100644 (file)
                                {{ 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"
 
 <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);
diff --git a/apps/dashboard/src/helpers/getBackgroundUrl.js b/apps/dashboard/src/helpers/getBackgroundUrl.js
new file mode 100644 (file)
index 0000000..6090786
--- /dev/null
@@ -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)
+}
diff --git a/apps/dashboard/src/helpers/prefixWithBaseUrl.js b/apps/dashboard/src/helpers/prefixWithBaseUrl.js
new file mode 100644 (file)
index 0000000..7afbf28
--- /dev/null
@@ -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