diff options
author | John Molakvoæ <skjnldsv@protonmail.com> | 2022-10-20 13:18:06 +0200 |
---|---|---|
committer | John Molakvoæ <skjnldsv@protonmail.com> | 2022-11-29 11:22:13 +0100 |
commit | cedae7c6d74e11c8aaa59b09a38db04dbebc818d (patch) | |
tree | b95c77675542e0654084dd41f5d1f07a413b4db7 /apps/theming/src/components/BackgroundSettings.vue | |
parent | a884f311b78341612adeb6d62f707dda1bae39e7 (diff) | |
download | nextcloud-server-cedae7c6d74e11c8aaa59b09a38db04dbebc818d.tar.gz nextcloud-server-cedae7c6d74e11c8aaa59b09a38db04dbebc818d.zip |
Allow to remove the background and select a custom colour
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
Diffstat (limited to 'apps/theming/src/components/BackgroundSettings.vue')
-rw-r--r-- | apps/theming/src/components/BackgroundSettings.vue | 215 |
1 files changed, 127 insertions, 88 deletions
diff --git a/apps/theming/src/components/BackgroundSettings.vue b/apps/theming/src/components/BackgroundSettings.vue index 45e627fd378..9890f9ad3f0 100644 --- a/apps/theming/src/components/BackgroundSettings.vue +++ b/apps/theming/src/components/BackgroundSettings.vue @@ -26,68 +26,75 @@ <template> <div class="background-selector"> <!-- Custom background --> - <button class="background filepicker" - :class="{ active: background === 'custom' }" + <button class="background background__filepicker" + :class="{ 'background--active': backgroundImage === 'custom' }" tabindex="0" @click="pickFile"> - {{ t('theming', 'Pick from Files') }} + {{ t('theming', 'Custom background') }} </button> <!-- Default background --> - <button class="background default" + <button class="background background__default" + :class="{ 'icon-loading': loading === 'default', 'background--active': backgroundImage === 'default' }" + :data-color-bright="invertTextColor(Theming.defaultColor)" + :style="{ '--border-color': Theming.defaultColor }" tabindex="0" - :class="{ 'icon-loading': loading === 'default', active: background === 'default' }" @click="setDefault"> - {{ t('theming', 'Default image') }} + {{ t('theming', 'Default background') }} + <Check :size="44" /> </button> <!-- Custom color picker --> <NcColorPicker v-model="Theming.color" @input="debouncePickColor"> - <button class="background color" - :class="{ active: background === Theming.color}" - tabindex="0" + <button class="background background__color" :data-color="Theming.color" :data-color-bright="invertTextColor(Theming.color)" - :style="{ backgroundColor: Theming.color, color: invertTextColor(Theming.color) ? '#000000' : '#ffffff'}"> - {{ t('theming', 'Custom color') }} + :style="{ backgroundColor: Theming.color, '--border-color': Theming.color}" + tabindex="0"> + {{ t('theming', 'Change color') }} </button> </NcColorPicker> - <!-- Default admin primary color --> - <button class="background color" - :class="{ active: background === Theming.defaultColor }" - tabindex="0" - :data-color="Theming.defaultColor" - :data-color-bright="invertTextColor(Theming.defaultColor)" - :style="{ color: invertTextColor(Theming.defaultColor) ? '#000000' : '#ffffff'}" - @click="debouncePickColor"> - {{ t('theming', 'Plain background') }} - </button> - <!-- Background set selection --> <button v-for="shippedBackground in shippedBackgrounds" :key="shippedBackground.name" v-tooltip="shippedBackground.details.attribution" - :class="{ 'icon-loading': loading === shippedBackground.name, active: background === shippedBackground.name }" - tabindex="0" - class="background" + :class="{ 'icon-loading': loading === shippedBackground.name, 'background--active': backgroundImage === shippedBackground.name }" :data-color-bright="shippedBackground.details.theming === 'dark'" - :style="{ 'background-image': 'url(' + shippedBackground.preview + ')' }" - @click="setShipped(shippedBackground.name)" /> + :style="{ backgroundImage: 'url(' + shippedBackground.preview + ')', '--border-color': shippedBackground.details.primary_color }" + class="background background__shipped" + tabindex="0" + @click="setShipped(shippedBackground.name)"> + <Check :size="44" /> + </button> + + <!-- Remove background --> + <button class="background background__delete" + tabindex="0" + @click="removeBackground"> + {{ t('theming', 'Remove background') }} + <Close :size="24" /> + </button> </div> </template> <script> -import { generateUrl } from '@nextcloud/router' -import { getBackgroundUrl } from '../helpers/getBackgroundUrl.js' +import { generateFilePath, generateUrl } from '@nextcloud/router' import { loadState } from '@nextcloud/initial-state' -import { prefixWithBaseUrl } from '../helpers/prefixWithBaseUrl.js' import axios from '@nextcloud/axios' +import Check from 'vue-material-design-icons/Check.vue' +import Close from 'vue-material-design-icons/Close.vue' import debounce from 'debounce' import NcColorPicker from '@nextcloud/vue/dist/Components/NcColorPicker' import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip' +const backgroundColor = loadState('theming', 'backgroundColor') +const backgroundImage = loadState('theming', 'backgroundImage') const shippedBackgroundList = loadState('theming', 'shippedBackgrounds') +const themingDefaultBackground = loadState('theming', 'themingDefaultBackground') +const defaultShippedBackground = loadState('theming', 'defaultShippedBackground') + +const prefixWithBaseUrl = (url) => generateFilePath('theming', '', 'img/background/') + url export default { name: 'BackgroundSettings', @@ -96,38 +103,49 @@ export default { }, components: { + Check, + Close, NcColorPicker, }, - props: { - background: { - type: String, - default: 'default', - }, - themingDefaultBackground: { - type: String, - default: '', - }, - }, - data() { return { - backgroundImage: generateUrl('/apps/theming/background') + '?v=' + Date.now(), loading: false, Theming: loadState('theming', 'data', {}), + + // User background image and color settings + backgroundImage, + backgroundColor, } }, computed: { shippedBackgrounds() { - return Object.keys(shippedBackgroundList).map(fileName => { - return { - name: fileName, - url: prefixWithBaseUrl(fileName), - preview: prefixWithBaseUrl('preview/' + fileName), - details: shippedBackgroundList[fileName], - } - }) + return Object.keys(shippedBackgroundList) + .map(fileName => { + return { + name: fileName, + url: prefixWithBaseUrl(fileName), + preview: prefixWithBaseUrl('preview/' + fileName), + details: shippedBackgroundList[fileName], + } + }) + .filter(background => { + // If the admin did not changed the global background + // let's hide the default background to not show it twice + if (!this.isGlobalBackgroundDeleted && !this.isGlobalBackgroundDefault) { + return background.name !== defaultShippedBackground + } + return true + }) + }, + + isGlobalBackgroundDefault() { + return !!themingDefaultBackground + }, + + isGlobalBackgroundDeleted() { + return themingDefaultBackground === 'backgroundColor' }, }, @@ -163,20 +181,24 @@ export default { : null }, + /** + * Update local state + * + * @param {object} data destructuring object + * @param {string} data.backgroundColor background color value + * @param {string} data.backgroundImage background image value + * @param {string} data.version cache buster number + * @see https://github.com/nextcloud/server/blob/c78bd45c64d9695724fc44fe8453a88824b85f2f/apps/theming/lib/Controller/UserThemeController.php#L187-L191 + */ async update(data) { - const background = data.type === 'custom' || data.type === 'default' ? data.type : data.value - this.backgroundImage = getBackgroundUrl(background, data.version, this.themingDefaultBackground) - if (data.type === 'color' || (data.type === 'default' && this.themingDefaultBackground === 'backgroundColor')) { - this.$emit('update:background', data) - this.loading = false - return - } - const image = new Image() - image.onload = () => { - this.$emit('update:background', data) - this.loading = false - } - image.src = this.backgroundImage + // Update state + this.backgroundImage = data.backgroundImage + this.backgroundColor = data.backgroundColor + this.Theming.color = data.backgroundColor + + // Notify parent and reload style + this.$emit('update:background') + this.loading = false }, async setDefault() { @@ -197,15 +219,21 @@ export default { this.update(result.data) }, - debouncePickColor: debounce(function() { - this.pickColor(...arguments) - }, 200), + async removeBackground() { + this.loading = 'remove' + const result = await axios.delete(generateUrl('/apps/theming/background/custom')) + this.update(result.data) + }, + async pickColor(event) { this.loading = 'color' const color = event?.target?.dataset?.color || this.Theming?.color || '#0082c9' const result = await axios.post(generateUrl('/apps/theming/background/color'), { value: color }) this.update(result.data) }, + debouncePickColor: debounce(function() { + this.pickColor(...arguments) + }, 200), pickFile() { window.OC.dialogs.filepicker(t('theming', 'Select a background from your files'), (path, type) => { @@ -225,50 +253,61 @@ export default { justify-content: center; .background { + overflow: hidden; width: 176px; height: 96px; margin: 8px; - background-size: cover; - background-position: center center; text-align: center; - border-radius: var(--border-radius-large); border: 2px solid var(--color-main-background); - overflow: hidden; + border-radius: var(--border-radius-large); + background-position: center center; + background-size: cover; - &.current { - background-image: var(--color-background-dark); + &__default { + background-color: var(--color-primary-default); + background-image: var(--image-background-default); } - &.filepicker, &.default, &.color { + &__filepicker, &__default, &__color { border-color: var(--color-border); } - &.color { - background-color: var(--color-primary-default); + &__color { color: var(--color-primary-text); + background-color: var(--color-primary-default); + } + + // Text and svg icon dark on bright background + &[data-color-bright] { + color: black; } - &.active, + &--active, &:hover, &:focus { - border: 2px solid var(--color-primary); + // Use theme color primary, see inline css variable in template + border: 2px solid var(--border-color, var(--color-primary)) !important; } - &.active:not(.icon-loading) { - &:after { - background-image: var(--original-icon-checkmark-white); - background-repeat: no-repeat; - background-position: center; - background-size: 44px; - content: ''; - display: block; - height: 100%; + // Icon + span { + margin: 4px; + } + + &__default, + &__shipped { + color: white; + span { + display: none; } + } - &[data-color-bright]:after { - background-image: var(--original-icon-checkmark-dark); + &--active:not(.icon-loading) { + span { + display: block; } } } } + </style> |