['name' => 'dashboard#index', 'url' => '/', 'verb' => 'GET'],
['name' => 'dashboard#updateLayout', 'url' => '/layout', 'verb' => 'POST'],
['name' => 'dashboard#updateStatuses', 'url' => '/statuses', 'verb' => 'POST'],
- ['name' => 'dashboard#getBackground', 'url' => '/background', 'verb' => 'GET'],
- ['name' => 'dashboard#setBackground', 'url' => '/background/{type}', 'verb' => 'POST'],
],
'ocs' => [
['name' => 'dashboardApi#getWidgetItems', 'url' => '/api/v1/widget-items', 'verb' => 'GET'],
*/
namespace OCA\Dashboard\Controller;
-use OCA\Dashboard\Service\BackgroundService;
use OCA\Files\Event\LoadSidebar;
use OCA\Viewer\Event\LoadViewer;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
-use OCP\AppFramework\Http\FileDisplayResponse;
use OCP\AppFramework\Http\JSONResponse;
-use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\Http\TemplateResponse;
-use OCP\App\IAppManager;
use OCP\AppFramework\Services\IInitialState;
use OCP\Dashboard\IManager;
use OCP\Dashboard\IWidget;
private $inititalState;
/** @var IEventDispatcher */
private $eventDispatcher;
- /** @var IAppManager */
- private $appManager;
/** @var IManager */
private $dashboardManager;
/** @var IConfig */
private $config;
/** @var string */
private $userId;
- /**
- * @var BackgroundService
- */
- private $backgroundService;
public function __construct(
string $appName,
IRequest $request,
IInitialState $initialState,
IEventDispatcher $eventDispatcher,
- IAppManager $appManager,
IManager $dashboardManager,
IConfig $config,
- BackgroundService $backgroundService,
$userId
) {
parent::__construct($appName, $request);
$this->inititalState = $initialState;
$this->eventDispatcher = $eventDispatcher;
- $this->appManager = $appManager;
$this->dashboardManager = $dashboardManager;
$this->config = $config;
- $this->backgroundService = $backgroundService;
$this->userId = $userId;
}
// It does not matter if some statuses are missing from the array, missing ones are considered enabled
$statuses = ($statuses && count($statuses) > 0) ? $statuses : ['weather' => true];
- // if theming app is enabled and wants to override default, we pass it
- $themingDefaultBackground = $this->appManager->isEnabledForUser('theming')
- ? $this->config->getAppValue('theming', 'backgroundMime', '')
- : '';
- $this->inititalState->provideInitialState('themingDefaultBackground', $themingDefaultBackground);
$this->inititalState->provideInitialState('panels', $widgets);
$this->inititalState->provideInitialState('statuses', $statuses);
$this->inititalState->provideInitialState('layout', $userLayout);
$this->inititalState->provideInitialState('firstRun', $this->config->getUserValue($this->userId, 'dashboard', 'firstRun', '1') === '1');
- $this->inititalState->provideInitialState('shippedBackgrounds', BackgroundService::SHIPPED_BACKGROUNDS);
- $this->inititalState->provideInitialState('background', $this->config->getUserValue($this->userId, 'dashboard', 'background', 'default'));
- $this->inititalState->provideInitialState('version', $this->config->getUserValue($this->userId, 'dashboard', 'backgroundVersion', 0));
$this->config->setUserValue($this->userId, 'dashboard', 'firstRun', '0');
$response = new TemplateResponse('dashboard', 'index', [
$this->config->setUserValue($this->userId, 'dashboard', 'statuses', $statuses);
return new JSONResponse(['statuses' => $statuses]);
}
-
- /**
- * @NoAdminRequired
- */
- public function setBackground(string $type = 'default', string $value = ''): JSONResponse {
- $currentVersion = (int)$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);
- } catch (\Throwable $e) {
- return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
- }
- $currentVersion++;
- $this->config->setUserValue($this->userId, 'dashboard', 'backgroundVersion', (string)$currentVersion);
- return new JSONResponse([
- 'type' => $type,
- 'value' => $value,
- 'version' => $this->config->getUserValue($this->userId, 'dashboard', 'backgroundVersion', $currentVersion)
- ]);
- }
-
- /**
- * @NoAdminRequired
- * @NoCSRFRequired
- */
- public function getBackground(): Http\Response {
- $file = $this->backgroundService->getBackground();
- if ($file !== null) {
- $response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
- $response->cacheFor(24 * 60 * 60);
- return $response;
- }
- return new NotFoundResponse();
- }
}
+++ /dev/null
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
- *
- * @author Jan C. Borchardt <hey@jancborchardt.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/>.
- *
- */
-namespace OCA\Dashboard\Service;
-
-use InvalidArgumentException;
-use OC\User\NoUserException;
-use OCP\Files\File;
-use OCP\Files\IAppData;
-use OCP\Files\IRootFolder;
-use OCP\Files\NotFoundException;
-use OCP\Files\NotPermittedException;
-use OCP\Files\SimpleFS\ISimpleFile;
-use OCP\Files\SimpleFS\ISimpleFolder;
-use OCP\IConfig;
-use OCP\Lock\LockedException;
-use OCP\PreConditionNotMetException;
-
-class BackgroundService {
- // true when the background is bright and need dark icons
- public const THEMING_MODE_DARK = 'dark';
-
- public const SHIPPED_BACKGROUNDS = [
- 'anatoly-mikhaltsov-butterfly-wing-scale.jpg' => [
- 'attribution' => 'Butterfly wing scale (Anatoly Mikhaltsov, CC BY-SA)',
- 'attribution_url' => 'https://commons.wikimedia.org/wiki/File:%D0%A7%D0%B5%D1%88%D1%83%D0%B9%D0%BA%D0%B8_%D0%BA%D1%80%D1%8B%D0%BB%D0%B0_%D0%B1%D0%B0%D0%B1%D0%BE%D1%87%D0%BA%D0%B8.jpg',
- ],
- 'bernie-cetonia-aurata-take-off-composition.jpg' => [
- 'attribution' => 'Cetonia aurata take off composition (Bernie, Public Domain)',
- 'attribution_url' => 'https://commons.wikimedia.org/wiki/File:Cetonia_aurata_take_off_composition_05172009.jpg',
- 'theming' => self::THEMING_MODE_DARK,
- ],
- 'dejan-krsmanovic-ribbed-red-metal.jpg' => [
- 'attribution' => 'Ribbed red metal (Dejan Krsmanovic, CC BY)',
- 'attribution_url' => 'https://www.flickr.com/photos/dejankrsmanovic/42971456774/',
- ],
- 'eduardo-neves-pedra-azul.jpg' => [
- 'attribution' => 'Pedra azul milky way (Eduardo Neves, CC BY-SA)',
- 'attribution_url' => 'https://commons.wikimedia.org/wiki/File:Pedra_Azul_Milky_Way.jpg',
- ],
- 'european-space-agency-barents-bloom.jpg' => [
- 'attribution' => 'Barents bloom (European Space Agency, CC BY-SA)',
- 'attribution_url' => 'https://www.esa.int/ESA_Multimedia/Images/2016/08/Barents_bloom',
- ],
- 'hannes-fritz-flippity-floppity.jpg' => [
- 'attribution' => 'Flippity floppity (Hannes Fritz, CC BY-SA)',
- 'attribution_url' => 'http://hannes.photos/flippity-floppity',
- ],
- 'hannes-fritz-roulette.jpg' => [
- 'attribution' => 'Roulette (Hannes Fritz, CC BY-SA)',
- 'attribution_url' => 'http://hannes.photos/roulette',
- ],
- 'hannes-fritz-sea-spray.jpg' => [
- 'attribution' => 'Sea spray (Hannes Fritz, CC BY-SA)',
- 'attribution_url' => 'http://hannes.photos/sea-spray',
- ],
- 'kamil-porembinski-clouds.jpg' => [
- 'attribution' => 'Clouds (Kamil Porembiński, CC BY-SA)',
- 'attribution_url' => 'https://www.flickr.com/photos/paszczak000/8715851521/',
- ],
- 'bernard-spragg-new-zealand-fern.jpg' => [
- 'attribution' => 'New zealand fern (Bernard Spragg, CC0)',
- 'attribution_url' => 'https://commons.wikimedia.org/wiki/File:NZ_Fern.(Blechnum_chambersii)_(11263534936).jpg',
- ],
- 'rawpixel-pink-tapioca-bubbles.jpg' => [
- 'attribution' => 'Pink tapioca bubbles (Rawpixel, CC BY)',
- 'attribution_url' => 'https://www.flickr.com/photos/byrawpixel/27665140298/in/photostream/',
- 'theming' => self::THEMING_MODE_DARK,
- ],
- 'nasa-waxing-crescent-moon.jpg' => [
- 'attribution' => 'Waxing crescent moon (NASA, Public Domain)',
- 'attribution_url' => 'https://www.nasa.gov/image-feature/a-waxing-crescent-moon',
- ],
- 'tommy-chau-already.jpg' => [
- 'attribution' => 'Cityscape (Tommy Chau, CC BY)',
- 'attribution_url' => 'https://www.flickr.com/photos/90975693@N05/16910999368',
- ],
- 'tommy-chau-lion-rock-hill.jpg' => [
- 'attribution' => 'Lion rock hill (Tommy Chau, CC BY)',
- 'attribution_url' => 'https://www.flickr.com/photos/90975693@N05/17136440246',
- 'theming' => self::THEMING_MODE_DARK,
- ],
- 'lali-masriera-yellow-bricks.jpg' => [
- 'attribution' => 'Yellow bricks (Lali Masriera, CC BY)',
- 'attribution_url' => 'https://www.flickr.com/photos/visualpanic/3982464447',
- 'theming' => self::THEMING_MODE_DARK,
- ]
- ];
- /**
- * @var IRootFolder
- */
- private $rootFolder;
- /**
- * @var IAppData
- */
- private $appData;
- /**
- * @var IConfig
- */
- private $config;
- private $userId;
-
- public function __construct(IRootFolder $rootFolder, IAppData $appData, IConfig $config, $userId) {
- if ($userId === null) {
- return;
- }
- $this->rootFolder = $rootFolder;
- $this->appData = $appData;
- $this->config = $config;
- $this->userId = $userId;
- }
-
- public function setDefaultBackground(): void {
- $this->config->deleteUserValue($this->userId, 'dashboard', 'background');
- }
-
- /**
- * @param $path
- * @throws NotFoundException
- * @throws NotPermittedException
- * @throws LockedException
- * @throws PreConditionNotMetException
- * @throws NoUserException
- */
- public function setFileBackground($path): void {
- $this->config->setUserValue($this->userId, 'dashboard', 'background', 'custom');
- $userFolder = $this->rootFolder->getUserFolder($this->userId);
- /** @var File $file */
- $file = $userFolder->get($path);
- $image = new \OCP\Image();
- if ($image->loadFromFileHandle($file->fopen('r')) === false) {
- throw new InvalidArgumentException('Invalid image file');
- }
- $this->getAppDataFolder()->newFile('background.jpg', $file->fopen('r'));
- }
-
- public function setShippedBackground($fileName): void {
- if (!array_key_exists($fileName, self::SHIPPED_BACKGROUNDS)) {
- throw new InvalidArgumentException('The given file name is invalid');
- }
- $this->config->setUserValue($this->userId, 'dashboard', 'background', $fileName);
- }
-
- public function setColorBackground(string $color): void {
- if (!preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) {
- throw new InvalidArgumentException('The given color is invalid');
- }
- $this->config->setUserValue($this->userId, 'dashboard', 'background', $color);
- }
-
- public function getBackground(): ?ISimpleFile {
- $background = $this->config->getUserValue($this->userId, 'dashboard', 'background', 'default');
- if ($background === 'custom') {
- try {
- return $this->getAppDataFolder()->getFile('background.jpg');
- } catch (NotFoundException | NotPermittedException $e) {
- }
- }
- return null;
- }
-
- /**
- * @return ISimpleFolder
- * @throws NotPermittedException
- */
- private function getAppDataFolder(): ISimpleFolder {
- try {
- return $this->appData->getFolder($this->userId);
- } catch (NotFoundException $e) {
- return $this->appData->newFolder($this->userId);
- }
- }
-}
<a v-if="isAdmin" :href="appStoreUrl" class="button">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>
- <h3>{{ t('dashboard', 'Change background image') }}</h3>
- <BackgroundSettings :background="background"
- :theming-default-background="themingDefaultBackground"
- @update:background="updateBackground" />
-
<h3>{{ t('dashboard', 'Weather service') }}</h3>
<p>
{{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}
</template>
<script>
-import { generateUrl } from '@nextcloud/router'
+import { generateUrl, imagePath } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { loadState } from '@nextcloud/initial-state'
import axios from '@nextcloud/axios'
import Pencil from 'vue-material-design-icons/Pencil.vue'
import Vue from 'vue'
-import isMobile from './mixins/isMobile'
-import BackgroundSettings from './components/BackgroundSettings'
-import getBackgroundUrl from './helpers/getBackgroundUrl'
+import isMobile from './mixins/isMobile.js'
+import { getBackgroundUrl } from './helpers/getBackgroundUrl.js'
const panels = loadState('dashboard', 'panels')
const firstRun = loadState('dashboard', 'firstRun')
-const background = loadState('dashboard', 'background')
-const themingDefaultBackground = loadState('dashboard', 'themingDefaultBackground')
-const version = loadState('dashboard', 'version')
-const shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')
+
+const background = loadState('theming', 'background')
+const backgroundVersion = loadState('theming', 'backgroundVersion')
+const themingDefaultBackground = loadState('theming', 'themingDefaultBackground')
+const shippedBackgroundList = loadState('theming', 'shippedBackgrounds')
const statusInfo = {
weather: {
export default {
name: 'DashboardApp',
components: {
- BackgroundSettings,
NcButton,
Draggable,
NcModal,
statuses: {},
background,
themingDefaultBackground,
- version,
}
},
computed: {
backgroundImage() {
- return getBackgroundUrl(this.background, this.version, this.themingDefaultBackground)
+ return getBackgroundUrl(this.background, backgroundVersion, this.themingDefaultBackground)
},
backgroundStyle() {
if ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')
backgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,
}
},
-
greeting() {
const time = this.timer.getHours()
},
methods: {
+ updateGlobalStyles() {
+ // Override primary-invert-if-bright and color-primary-text if background is set
+ const isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'
+ if (isBackgroundBright) {
+ document.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')
+ document.querySelector('#header').style.setProperty('--color-primary-text', '#000000')
+ // document.body.removeAttribute('data-theme-dark')
+ // document.body.setAttribute('data-theme-light', 'true')
+ } else {
+ document.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')
+ document.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')
+ // document.body.removeAttribute('data-theme-light')
+ // document.body.setAttribute('data-theme-dark', 'true')
+ }
+
+ const themeElements = [document.documentElement, document.querySelector('#header'), document.querySelector('body')]
+ for (const element of themeElements) {
+ if (this.background === 'default') {
+ element.style.setProperty('--image-main-background', `url('${imagePath('core', 'app-background.jpg')}')`)
+ } else if (this.background.match(/#[0-9A-Fa-f]{6}/g)) {
+ element.style.setProperty('--image-main-background', undefined)
+ } else {
+ element.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)
+ }
+ }
+ },
/**
* Method to register panels that will be called by the integrating apps
*
this.firstRun = false
}, 1000)
},
- updateBackground(data) {
- this.background = data.type === 'custom' || data.type === 'default' ? data.type : data.value
- this.version = data.version
- this.updateGlobalStyles()
- },
- updateGlobalStyles() {
- // Override primary-invert-if-bright and color-primary-text if background is set
- const isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'
- if (isBackgroundBright) {
- document.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')
- document.querySelector('#header').style.setProperty('--color-primary-text', '#000000')
- // document.body.removeAttribute('data-theme-dark')
- // document.body.setAttribute('data-theme-light', 'true')
- } else {
- document.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')
- document.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')
- // document.body.removeAttribute('data-theme-light')
- // document.body.setAttribute('data-theme-dark', 'true')
- }
-
- document.documentElement.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)
- document.querySelector('#header').style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)
- document.querySelector('body').style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)
- },
updateSkipLink() {
// Make sure "Skip to main content" link points to the app content
document.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')
+++ /dev/null
-<!--
- - @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/>.
- -
- -->
-
-<template>
- <div class="background-selector">
- <button class="background filepicker"
- :class="{ active: background === 'custom' }"
- tabindex="0"
- @click="pickFile">
- {{ t('dashboard', 'Pick from Files') }}
- </button>
- <button class="background default"
- tabindex="0"
- :class="{ 'icon-loading': loading === 'default', active: background === 'default' }"
- @click="setDefault">
- {{ t('dashboard', 'Default image') }}
- </button>
- <button class="background color"
- :class="{ active: background === 'custom' }"
- tabindex="0"
- @click="pickColor">
- {{ t('dashboard', 'Plain background') }}
- </button>
- <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"
- :style="{ 'background-image': 'url(' + shippedBackground.preview + ')' }"
- @click="setShipped(shippedBackground.name)" />
- </div>
-</template>
-
-<script>
-import axios from '@nextcloud/axios'
-import { generateUrl } from '@nextcloud/router'
-import { loadState } from '@nextcloud/initial-state'
-import getBackgroundUrl from './../helpers/getBackgroundUrl'
-import prefixWithBaseUrl from './../helpers/prefixWithBaseUrl'
-const shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')
-
-export default {
- name: 'BackgroundSettings',
- props: {
- background: {
- type: String,
- default: 'default',
- },
- themingDefaultBackground: {
- type: String,
- default: '',
- },
- },
- data() {
- return {
- backgroundImage: generateUrl('/apps/dashboard/background') + '?v=' + Date.now(),
- loading: false,
- }
- },
- computed: {
- shippedBackgrounds() {
- return Object.keys(shippedBackgroundList).map((item) => {
- return {
- name: item,
- url: prefixWithBaseUrl(item),
- preview: prefixWithBaseUrl('previews/' + item),
- details: shippedBackgroundList[item],
- }
- })
- },
- },
- methods: {
- 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
- },
- async setDefault() {
- this.loading = 'default'
- const result = await axios.post(generateUrl('/apps/dashboard/background/default'))
- this.update(result.data)
- },
- async setShipped(shipped) {
- this.loading = shipped
- const result = await axios.post(generateUrl('/apps/dashboard/background/shipped'), { value: shipped })
- this.update(result.data)
- },
- async setFile(path) {
- 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) => {
- if (type === OC.dialogs.FILEPICKER_TYPE_CHOOSE) {
- this.setFile(path)
- }
- }, false, ['image/png', 'image/gif', 'image/jpeg', 'image/svg'], true, OC.dialogs.FILEPICKER_TYPE_CHOOSE)
- },
- },
-}
-</script>
-
-<style scoped lang="scss">
-.background-selector {
- display: flex;
- flex-wrap: wrap;
- justify-content: center;
-
- .background {
- 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;
-
- &.current {
- background-image: var(--color-background-dark);
- }
-
- &.filepicker, &.default, &.color {
- border-color: var(--color-border);
- }
-
- &.color {
- background-color: var(--color-primary);
- color: var(--color-primary-text);
- }
-
- &.active,
- &:hover,
- &:focus {
- border: 2px solid var(--color-primary);
- }
-
- &.active:not(.icon-loading):after {
- background-image: var(--icon-checkmark-white);
- background-repeat: no-repeat;
- background-position: center;
- background-size: 44px;
- content: '';
- display: block;
- height: 100%;
- }
- }
-}
-</style>
*/
import { generateUrl } from '@nextcloud/router'
-import prefixWithBaseUrl from './prefixWithBaseUrl'
+import { prefixWithBaseUrl } from './prefixWithBaseUrl.js'
-export default (background, time = 0, themingDefaultBackground = '') => {
+export const getBackgroundUrl = (background, time = 0, themingDefaultBackground = '') => {
const enabledThemes = window.OCA?.Theming?.enabledThemes || []
const isDarkTheme = (enabledThemes.length === 0 || enabledThemes[0] === 'default')
? window.matchMedia('(prefers-color-scheme: dark)').matches
return prefixWithBaseUrl('kamil-porembinski-clouds.jpg')
} else if (background === 'custom') {
- return generateUrl('/apps/dashboard/background') + '?v=' + time
+ return generateUrl('/apps/theming/background') + '?v=' + time
}
return prefixWithBaseUrl(background)
import { generateFilePath } from '@nextcloud/router'
-export default (url) => generateFilePath('dashboard', '', 'img/') + url
+export const prefixWithBaseUrl = (url) => generateFilePath('theming', '', 'img/background/') + url
'verb' => 'GET',
'requirements' => ['image' => '.+']
],
+ [
+ 'name' => 'userTheme#getBackground',
+ 'url' => '/background',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'userTheme#setBackground',
+ 'url' => '/background/{type}',
+ 'verb' => 'POST',
+ ],
],
'ocs' => [
[
*/
namespace OCA\Theming\Controller;
+use OCA\Theming\AppInfo\Application;
use OCA\Theming\ITheme;
+use OCA\Theming\Service\BackgroundService;
use OCA\Theming\Service\ThemesService;
+use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\Http\FileDisplayResponse;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCS\OCSForbiddenException;
use OCP\AppFramework\OCSController;
private IConfig $config;
private IUserSession $userSession;
private ThemesService $themesService;
+ private BackgroundService $backgroundService;
/**
* Config constructor.
IRequest $request,
IConfig $config,
IUserSession $userSession,
- ThemesService $themesService) {
+ ThemesService $themesService,
+ BackgroundService $backgroundService) {
parent::__construct($appName, $request);
$this->config = $config;
$this->userSession = $userSession;
$this->themesService = $themesService;
+ $this->backgroundService = $backgroundService;
$this->userId = $userSession->getUser()->getUID();
}
*/
public function disableTheme(string $themeId): DataResponse {
$theme = $this->validateTheme($themeId);
-
+
// Enable selected theme
$this->themesService->disableTheme($theme);
return new DataResponse();
return $themes[$themeId];
}
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ */
+ public function getBackground(): Http\Response {
+ $file = $this->backgroundService->getBackground();
+ if ($file !== null) {
+ $response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
+ $response->cacheFor(24 * 60 * 60, false, true);
+ return $response;
+ }
+ return new NotFoundResponse();
+ }
+
+ /**
+ * @NoAdminRequired
+ */
+ public function setBackground(string $type = 'default', string $value = ''): JSONResponse {
+ $currentVersion = (int)$this->config->getUserValue($this->userId, Application::APP_ID, '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);
+ } catch (\Throwable $e) {
+ return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ $currentVersion++;
+ $this->config->setUserValue($this->userId, Application::APP_ID, 'backgroundVersion', (string)$currentVersion);
+ return new JSONResponse([
+ 'type' => $type,
+ 'value' => $value,
+ 'version' => $this->config->getUserValue($this->userId, Application::APP_ID, 'backgroundVersion', $currentVersion)
+ ]);
+ }
}
namespace OCA\Theming\Listener;
use OCA\Theming\AppInfo\Application;
+use OCA\Theming\Service\BackgroundService;
use OCA\Theming\Service\JSDataService;
use OCA\Theming\Service\ThemeInjectionService;
-use OCA\Theming\Service\ThemesService;
+use OCP\AppFramework\Services\IInitialState;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IConfig;
-use OCP\IInitialStateService;
-use OCP\IServerContainer;
-use OCP\IURLGenerator;
+use OCP\IUserSession;
+use Psr\Container\ContainerInterface;
class BeforeTemplateRenderedListener implements IEventListener {
- private IInitialStateService $initialStateService;
- private IServerContainer $serverContainer;
+ private IInitialState $initialState;
+ private ContainerInterface $container;
private ThemeInjectionService $themeInjectionService;
+ private IUserSession $userSession;
+ private IConfig $config;
public function __construct(
- IInitialStateService $initialStateService,
- IServerContainer $serverContainer,
- ThemeInjectionService $themeInjectionService
+ IInitialState $initialState,
+ ContainerInterface $container,
+ ThemeInjectionService $themeInjectionService,
+ IUserSession $userSession,
+ IConfig $config
) {
- $this->initialStateService = $initialStateService;
- $this->serverContainer = $serverContainer;
+ $this->initialState = $initialState;
+ $this->container = $container;
$this->themeInjectionService = $themeInjectionService;
+ $this->userSession = $userSession;
+ $this->config = $config;
}
public function handle(Event $event): void {
- $serverContainer = $this->serverContainer;
- $this->initialStateService->provideLazyInitialState(Application::APP_ID, 'data', function () use ($serverContainer) {
- return $serverContainer->query(JSDataService::class);
- });
+ $this->initialState->provideLazyInitialState(
+ 'data',
+ fn () => $this->container->get(JSDataService::class),
+ );
$this->themeInjectionService->injectHeaders();
+ $user = $this->userSession->getUser();
+
+ if (!empty($user)) {
+ $userId = $user->getUID();
+
+ $this->initialState->provideInitialState(
+ 'background',
+ $this->config->getUserValue($userId, Application::APP_ID, 'background', 'default'),
+ );
+
+ $this->initialState->provideInitialState(
+ 'backgroundVersion',
+ $this->config->getUserValue($userId, Application::APP_ID, 'backgroundVersion', 0),
+ );
+
+ $this->initialState->provideInitialState(
+ 'themingDefaultBackground',
+ $this->config->getAppValue('theming', 'backgroundMime', ''),
+ );
+
+ $this->initialState->provideInitialState(
+ 'shippedBackgrounds',
+ BackgroundService::SHIPPED_BACKGROUNDS,
+ );
+ }
+
// Making sure to inject just after core
\OCP\Util::addScript('theming', 'theming', 'core');
}
--- /dev/null
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Jan C. Borchardt <hey@jancborchardt.net>
+ * @author Julius Härtl <jus@bitgrid.net>
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @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\Service;
+
+use InvalidArgumentException;
+use OC\User\NoUserException;
+use OCA\Theming\AppInfo\Application;
+use OCP\Files\File;
+use OCP\Files\IAppData;
+use OCP\Files\IRootFolder;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\IConfig;
+use OCP\Lock\LockedException;
+use OCP\PreConditionNotMetException;
+
+class BackgroundService {
+ // true when the background is bright and need dark icons
+ public const THEMING_MODE_DARK = 'dark';
+
+ public const SHIPPED_BACKGROUNDS = [
+ 'anatoly-mikhaltsov-butterfly-wing-scale.jpg' => [
+ 'attribution' => 'Butterfly wing scale (Anatoly Mikhaltsov, CC BY-SA)',
+ 'attribution_url' => 'https://commons.wikimedia.org/wiki/File:%D0%A7%D0%B5%D1%88%D1%83%D0%B9%D0%BA%D0%B8_%D0%BA%D1%80%D1%8B%D0%BB%D0%B0_%D0%B1%D0%B0%D0%B1%D0%BE%D1%87%D0%BA%D0%B8.jpg',
+ ],
+ 'bernie-cetonia-aurata-take-off-composition.jpg' => [
+ 'attribution' => 'Cetonia aurata take off composition (Bernie, Public Domain)',
+ 'attribution_url' => 'https://commons.wikimedia.org/wiki/File:Cetonia_aurata_take_off_composition_05172009.jpg',
+ 'theming' => self::THEMING_MODE_DARK,
+ ],
+ 'dejan-krsmanovic-ribbed-red-metal.jpg' => [
+ 'attribution' => 'Ribbed red metal (Dejan Krsmanovic, CC BY)',
+ 'attribution_url' => 'https://www.flickr.com/photos/dejankrsmanovic/42971456774/',
+ ],
+ 'eduardo-neves-pedra-azul.jpg' => [
+ 'attribution' => 'Pedra azul milky way (Eduardo Neves, CC BY-SA)',
+ 'attribution_url' => 'https://commons.wikimedia.org/wiki/File:Pedra_Azul_Milky_Way.jpg',
+ ],
+ 'european-space-agency-barents-bloom.jpg' => [
+ 'attribution' => 'Barents bloom (European Space Agency, CC BY-SA)',
+ 'attribution_url' => 'https://www.esa.int/ESA_Multimedia/Images/2016/08/Barents_bloom',
+ ],
+ 'hannes-fritz-flippity-floppity.jpg' => [
+ 'attribution' => 'Flippity floppity (Hannes Fritz, CC BY-SA)',
+ 'attribution_url' => 'http://hannes.photos/flippity-floppity',
+ ],
+ 'hannes-fritz-roulette.jpg' => [
+ 'attribution' => 'Roulette (Hannes Fritz, CC BY-SA)',
+ 'attribution_url' => 'http://hannes.photos/roulette',
+ ],
+ 'hannes-fritz-sea-spray.jpg' => [
+ 'attribution' => 'Sea spray (Hannes Fritz, CC BY-SA)',
+ 'attribution_url' => 'http://hannes.photos/sea-spray',
+ ],
+ 'kamil-porembinski-clouds.jpg' => [
+ 'attribution' => 'Clouds (Kamil Porembiński, CC BY-SA)',
+ 'attribution_url' => 'https://www.flickr.com/photos/paszczak000/8715851521/',
+ ],
+ 'bernard-spragg-new-zealand-fern.jpg' => [
+ 'attribution' => 'New zealand fern (Bernard Spragg, CC0)',
+ 'attribution_url' => 'https://commons.wikimedia.org/wiki/File:NZ_Fern.(Blechnum_chambersii)_(11263534936).jpg',
+ ],
+ 'rawpixel-pink-tapioca-bubbles.jpg' => [
+ 'attribution' => 'Pink tapioca bubbles (Rawpixel, CC BY)',
+ 'attribution_url' => 'https://www.flickr.com/photos/byrawpixel/27665140298/in/photostream/',
+ 'theming' => self::THEMING_MODE_DARK,
+ ],
+ 'nasa-waxing-crescent-moon.jpg' => [
+ 'attribution' => 'Waxing crescent moon (NASA, Public Domain)',
+ 'attribution_url' => 'https://www.nasa.gov/image-feature/a-waxing-crescent-moon',
+ ],
+ 'tommy-chau-already.jpg' => [
+ 'attribution' => 'Cityscape (Tommy Chau, CC BY)',
+ 'attribution_url' => 'https://www.flickr.com/photos/90975693@N05/16910999368',
+ ],
+ 'tommy-chau-lion-rock-hill.jpg' => [
+ 'attribution' => 'Lion rock hill (Tommy Chau, CC BY)',
+ 'attribution_url' => 'https://www.flickr.com/photos/90975693@N05/17136440246',
+ 'theming' => self::THEMING_MODE_DARK,
+ ],
+ 'lali-masriera-yellow-bricks.jpg' => [
+ 'attribution' => 'Yellow bricks (Lali Masriera, CC BY)',
+ 'attribution_url' => 'https://www.flickr.com/photos/visualpanic/3982464447',
+ 'theming' => self::THEMING_MODE_DARK,
+ ]
+ ];
+
+ private IRootFolder $rootFolder;
+ private IAppData $appData;
+ private IConfig $config;
+ private string $userId;
+
+ public function __construct(
+ IRootFolder $rootFolder,
+ IAppData $appData,
+ IConfig $config,
+ ?string $userId
+ ) {
+ if ($userId === null) {
+ return;
+ }
+ $this->rootFolder = $rootFolder;
+ $this->appData = $appData;
+ $this->config = $config;
+ $this->userId = $userId;
+ }
+
+ public function setDefaultBackground(): void {
+ $this->config->deleteUserValue($this->userId, Application::APP_ID, 'background');
+ }
+
+ /**
+ * @param $path
+ * @throws NotFoundException
+ * @throws NotPermittedException
+ * @throws LockedException
+ * @throws PreConditionNotMetException
+ * @throws NoUserException
+ */
+ public function setFileBackground($path): void {
+ $this->config->setUserValue($this->userId, Application::APP_ID, 'background', 'custom');
+ $userFolder = $this->rootFolder->getUserFolder($this->userId);
+ /** @var File $file */
+ $file = $userFolder->get($path);
+ $image = new \OCP\Image();
+ if ($image->loadFromFileHandle($file->fopen('r')) === false) {
+ throw new InvalidArgumentException('Invalid image file');
+ }
+ $this->getAppDataFolder()->newFile('background.jpg', $file->fopen('r'));
+ }
+
+ public function setShippedBackground($fileName): void {
+ if (!array_key_exists($fileName, self::SHIPPED_BACKGROUNDS)) {
+ throw new InvalidArgumentException('The given file name is invalid');
+ }
+ $this->config->setUserValue($this->userId, Application::APP_ID, 'background', $fileName);
+ }
+
+ public function setColorBackground(string $color): void {
+ if (!preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) {
+ throw new InvalidArgumentException('The given color is invalid');
+ }
+ $this->config->setUserValue($this->userId, Application::APP_ID, 'background', $color);
+ }
+
+ public function getBackground(): ?ISimpleFile {
+ $background = $this->config->getUserValue($this->userId, Application::APP_ID, 'background', 'default');
+ if ($background === 'custom') {
+ try {
+ return $this->getAppDataFolder()->getFile('background.jpg');
+ } catch (NotFoundException | NotPermittedException $e) {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return ISimpleFolder
+ * @throws NotPermittedException
+ */
+ private function getAppDataFolder(): ISimpleFolder {
+ try {
+ return $this->appData->getFolder($this->userId);
+ } catch (NotFoundException $e) {
+ return $this->appData->newFolder($this->userId);
+ }
+ }
+}
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
-use OCP\IUserSession;
use OCP\Settings\ISettings;
use OCP\Util;
protected string $appName;
private IConfig $config;
- private IUserSession $userSession;
private ThemesService $themesService;
private IInitialState $initialStateService;
public function __construct(string $appName,
IConfig $config,
- IUserSession $userSession,
ThemesService $themesService,
IInitialState $initialStateService) {
$this->appName = $appName;
$this->config = $config;
- $this->userSession = $userSession;
$this->themesService = $themesService;
$this->initialStateService = $initialStateService;
}
*/
namespace OCA\Theming\Themes;
+use OCA\Theming\AppInfo\Application;
use OCA\Theming\ImageManager;
+use OCA\Theming\ITheme;
use OCA\Theming\ThemingDefaults;
use OCA\Theming\Util;
-use OCA\Theming\ITheme;
use OCP\App\IAppManager;
use OCP\IConfig;
use OCP\IL10N;
$colorPrimaryElementLight = $this->util->mix($colorPrimaryElement, $colorMainBackground, -80);
$hasCustomLogoHeader = $this->imageManager->hasImage('logo') || $this->imageManager->hasImage('logoheader');
- $hasCustomPrimaryColour = !empty($this->config->getAppValue('theming', 'color'));
+ $hasCustomPrimaryColour = !empty($this->config->getAppValue(Application::APP_ID, 'color'));
$variables = [
'--color-main-background' => $colorMainBackground,
'--image-main-background' => "url('" . $this->urlGenerator->imagePath('core', 'app-background.jpg') . "')",
];
- $backgroundDeleted = $this->config->getAppValue('theming', 'backgroundMime', '') === 'backgroundColor';
+ $backgroundDeleted = $this->config->getAppValue(Application::APP_ID, 'backgroundMime', '') === 'backgroundColor';
// If primary as background has been request or if we have a custom primary colour
// let's not define the background image
if ($backgroundDeleted || $hasCustomPrimaryColour) {
$appManager = Server::get(IAppManager::class);
$userSession = Server::get(IUserSession::class);
$user = $userSession->getUser();
- if ($appManager->isEnabledForUser('dashboard') && $user !== null) {
- $dashboardBackground = $this->config->getUserValue($user->getUID(), 'dashboard', 'background', 'default');
+ if ($appManager->isEnabledForUser(Application::APP_ID) && $user !== null) {
+ $themingBackground = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background', 'default');
- if ($dashboardBackground === 'custom') {
- $variables['--image-main-background'] = "url('" . $this->urlGenerator->linkToRouteAbsolute('dashboard.dashboard.getBackground') . "')";
- } elseif ($dashboardBackground !== 'default' && substr($dashboardBackground, 0, 1) !== '#') {
- $variables['--image-main-background'] = "url('/apps/dashboard/img/" . $dashboardBackground . "')";
+ if ($themingBackground === 'custom') {
+ $variables['--image-main-background'] = "url('" . $this->urlGenerator->linkToRouteAbsolute('theming.theming.getBackground') . "')";
+ } elseif ($themingBackground !== 'default' && substr($themingBackground, 0, 1) !== '#') {
+ $variables['--image-main-background'] = "url('" . $this->urlGenerator->linkTo(Application::APP_ID, "/img/background/$themingBackground") . "')";
}
}
+<!--
+ - @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
+ - @copyright Copyright (c) 2022 Greta Doci <gretadoci@gmail.com>
+ -
+ - @author Christopher Ng <chrng8@gmail.com>
+ -
+ - @license AGPL-3.0-or-later
+ -
+ - 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/>.
+ -
+-->
+
<template>
- <NcSettingsSection class="theming" :title="t('themes', 'Appearance and accessibility')">
- <p v-html="description" />
- <p v-html="descriptionDetail" />
-
- <div class="theming__preview-list">
- <ItemPreview v-for="theme in themes"
- :key="theme.id"
- :enforced="theme.id === enforceTheme"
- :selected="selectedTheme.id === theme.id"
- :theme="theme"
- :unique="themes.length === 1"
- type="theme"
- @change="changeTheme" />
- </div>
-
- <div class="theming__preview-list">
- <ItemPreview v-for="theme in fonts"
- :key="theme.id"
- :selected="theme.enabled"
- :theme="theme"
- :unique="fonts.length === 1"
- type="font"
- @change="changeFont" />
- </div>
- </NcSettingsSection>
+ <section>
+ <NcSettingsSection class="theming" :title="t('theming', 'Appearance and accessibility')">
+ <p v-html="description" />
+ <p v-html="descriptionDetail" />
+
+ <div class="theming__preview-list">
+ <ItemPreview v-for="theme in themes"
+ :key="theme.id"
+ :enforced="theme.id === enforceTheme"
+ :selected="selectedTheme.id === theme.id"
+ :theme="theme"
+ :unique="themes.length === 1"
+ type="theme"
+ @change="changeTheme" />
+ </div>
+
+ <div class="theming__preview-list">
+ <ItemPreview v-for="theme in fonts"
+ :key="theme.id"
+ :selected="theme.enabled"
+ :theme="theme"
+ :unique="fonts.length === 1"
+ type="font"
+ @change="changeFont" />
+ </div>
+ </NcSettingsSection>
+ <NcSettingsSection :title="t('theming', 'Background')"
+ class="background">
+ <p>{{ t('theming', 'Set a custom background') }}</p>
+ <BackgroundSettings class="background__grid"
+ :background="background"
+ :theming-default-background="themingDefaultBackground"
+ @update:background="updateBackground" />
+ </NcSettingsSection>
+ </section>
</template>
<script>
-import { generateOcsUrl } from '@nextcloud/router'
+import { generateOcsUrl, imagePath } from '@nextcloud/router'
import { loadState } from '@nextcloud/initial-state'
import axios from '@nextcloud/axios'
import NcSettingsSection from '@nextcloud/vue/dist/Components/NcSettingsSection'
-import ItemPreview from './components/ItemPreview'
+import BackgroundSettings from './components/BackgroundSettings.vue'
+import ItemPreview from './components/ItemPreview.vue'
+
+import { getBackgroundUrl } from '../src/helpers/getBackgroundUrl.js'
const availableThemes = loadState('theming', 'themes', [])
const enforceTheme = loadState('theming', 'enforceTheme', '')
+const background = loadState('theming', 'background')
+const backgroundVersion = loadState('theming', 'backgroundVersion')
+const themingDefaultBackground = loadState('theming', 'themingDefaultBackground')
+const shippedBackgroundList = loadState('theming', 'shippedBackgrounds')
+
console.debug('Available themes', availableThemes)
export default {
components: {
ItemPreview,
NcSettingsSection,
+ BackgroundSettings,
},
data() {
return {
availableThemes,
enforceTheme,
+ background,
+ themingDefaultBackground,
}
},
computed: {
+ backgroundImage() {
+ return getBackgroundUrl(this.background, backgroundVersion, this.themingDefaultBackground)
+ },
+ backgroundStyle() {
+ if ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')
+ || this.background.match(/#[0-9A-Fa-f]{6}/g)) {
+ return null
+ }
+
+ return {
+ backgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,
+ }
+ },
themes() {
return this.availableThemes.filter(theme => theme.type === 1)
},
return '<a target="_blank" href="https://nextcloud.com/design" rel="noreferrer nofollow">'
},
},
+ mounted() {
+ this.updateGlobalStyles()
+ },
methods: {
+ updateBackground(data) {
+ this.background = (data.type === 'custom' || data.type === 'default') ? data.type : data.value
+ this.updateGlobalStyles()
+ },
+ updateGlobalStyles() {
+ // Override primary-invert-if-bright and color-primary-text if background is set
+ const isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'
+ if (isBackgroundBright) {
+ document.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')
+ document.querySelector('#header').style.setProperty('--color-primary-text', '#000000')
+ // document.body.removeAttribute('data-theme-dark')
+ // document.body.setAttribute('data-theme-light', 'true')
+ } else {
+ document.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')
+ document.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')
+ // document.body.removeAttribute('data-theme-light')
+ // document.body.setAttribute('data-theme-dark', 'true')
+ }
+
+ const themeElements = [document.documentElement, document.querySelector('#header'), document.querySelector('body')]
+ for (const element of themeElements) {
+ if (this.background === 'default') {
+ element.style.setProperty('--image-main-background', `url('${imagePath('core', 'app-background.jpg')}')`)
+ } else if (this.background.match(/#[0-9A-Fa-f]{6}/g)) {
+ element.style.setProperty('--image-main-background', undefined)
+ } else {
+ element.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)
+ }
+ }
+ },
changeTheme({ enabled, id }) {
// Reset selected and select new one
this.themes.forEach(theme => {
}
}
+.background {
+ &__grid {
+ margin-top: 30px;
+ }
+}
+
@media (max-width: 1440px) {
.theming__preview-list {
display: flex;
flex-direction: column;
}
}
-
</style>
--- /dev/null
+<!--
+ - @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
+ - @copyright Copyright (c) 2022 Greta Doci <gretadoci@gmail.com>
+ -
+ - @author Julius Härtl <jus@bitgrid.net>
+ - @author Greta Doci <gretadoci@gmail.com>
+ - @author Christopher Ng <chrng8@gmail.com>
+ -
+ - @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/>.
+ -
+ -->
+
+<template>
+ <div class="background-selector">
+ <button class="background filepicker"
+ :class="{ active: background === 'custom' }"
+ tabindex="0"
+ @click="pickFile">
+ {{ t('theming', 'Pick from Files') }}
+ </button>
+ <button class="background default"
+ tabindex="0"
+ :class="{ 'icon-loading': loading === 'default', active: background === 'default' }"
+ @click="setDefault">
+ {{ t('theming', 'Default image') }}
+ </button>
+ <button class="background color"
+ :class="{ active: background === 'custom' }"
+ tabindex="0"
+ @click="pickColor">
+ {{ t('theming', 'Plain background') }}
+ </button>
+ <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"
+ :style="{ 'background-image': 'url(' + shippedBackground.preview + ')' }"
+ @click="setShipped(shippedBackground.name)" />
+ </div>
+</template>
+
+<script>
+import axios from '@nextcloud/axios'
+import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
+import { generateUrl } from '@nextcloud/router'
+import { loadState } from '@nextcloud/initial-state'
+import { getBackgroundUrl } from '../helpers/getBackgroundUrl.js'
+import { prefixWithBaseUrl } from '../helpers/prefixWithBaseUrl.js'
+
+const shippedBackgroundList = loadState('theming', 'shippedBackgrounds')
+
+export default {
+ name: 'BackgroundSettings',
+ directives: {
+ Tooltip,
+ },
+ props: {
+ background: {
+ type: String,
+ default: 'default',
+ },
+ themingDefaultBackground: {
+ type: String,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ backgroundImage: generateUrl('/apps/theming/background') + '?v=' + Date.now(),
+ loading: false,
+ }
+ },
+ computed: {
+ shippedBackgrounds() {
+ return Object.keys(shippedBackgroundList).map(fileName => {
+ return {
+ name: fileName,
+ url: prefixWithBaseUrl(fileName),
+ preview: prefixWithBaseUrl('preview/' + fileName),
+ details: shippedBackgroundList[fileName],
+ }
+ })
+ },
+ },
+ methods: {
+ 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
+ },
+ async setDefault() {
+ this.loading = 'default'
+ const result = await axios.post(generateUrl('/apps/theming/background/default'))
+ this.update(result.data)
+ },
+ async setShipped(shipped) {
+ this.loading = shipped
+ const result = await axios.post(generateUrl('/apps/theming/background/shipped'), { value: shipped })
+ this.update(result.data)
+ },
+ async setFile(path) {
+ this.loading = 'custom'
+ const result = await axios.post(generateUrl('/apps/theming/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/theming/background/color'), { value: color })
+ this.update(result.data)
+ },
+ pickFile() {
+ window.OC.dialogs.filepicker(t('theming', 'Insert from {productName}', { productName: OC.theme.name }), (path, type) => {
+ if (type === OC.dialogs.FILEPICKER_TYPE_CHOOSE) {
+ this.setFile(path)
+ }
+ }, false, ['image/png', 'image/gif', 'image/jpeg', 'image/svg'], true, OC.dialogs.FILEPICKER_TYPE_CHOOSE)
+ },
+ },
+}
+</script>
+
+<style scoped lang="scss">
+.background-selector {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+
+ .background {
+ 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;
+
+ &.current {
+ background-image: var(--color-background-dark);
+ }
+
+ &.filepicker, &.default, &.color {
+ border-color: var(--color-border);
+ }
+
+ &.color {
+ background-color: var(--color-primary);
+ color: var(--color-primary-text);
+ }
+
+ &.active,
+ &:hover,
+ &:focus {
+ border: 2px solid var(--color-primary);
+ }
+
+ &.active:not(.icon-loading):after {
+ background-image: var(--icon-checkmark-white);
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: 44px;
+ content: '';
+ display: block;
+ height: 100%;
+ }
+ }
+}
+</style>
--- /dev/null
+/**
+ * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Avior <florian.bouillon@delta-wings.net>
+ * @author Julien Veyssier <eneiluj@posteo.net>
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * 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/>.
+ *
+ */
+
+// FIXME hoist this into a package? The same logic is used in `apps/dashboard/src/helpers/getBackgroundUrl.js`
+
+import { generateUrl } from '@nextcloud/router'
+import { prefixWithBaseUrl } from './prefixWithBaseUrl.js'
+
+export const getBackgroundUrl = (background, time = 0, themingDefaultBackground = '') => {
+ const enabledThemes = window.OCA?.Theming?.enabledThemes || []
+ const isDarkTheme = (enabledThemes.length === 0 || enabledThemes[0] === 'default')
+ ? window.matchMedia('(prefers-color-scheme: dark)').matches
+ : enabledThemes.join('').indexOf('dark') !== -1
+
+ if (background === 'default') {
+ if (themingDefaultBackground && themingDefaultBackground !== 'backgroundColor') {
+ return generateUrl('/apps/theming/image/background') + '?v=' + window.OCA.Theming.cacheBuster
+ }
+
+ if (isDarkTheme) {
+ return prefixWithBaseUrl('eduardo-neves-pedra-azul.jpg')
+ }
+
+ return prefixWithBaseUrl('kamil-porembinski-clouds.jpg')
+ } else if (background === 'custom') {
+ return generateUrl('/apps/theming/background') + '?v=' + time
+ }
+
+ return prefixWithBaseUrl(background)
+}
--- /dev/null
+/**
+ * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * 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/>.
+ *
+ */
+
+// FIXME hoist this into a package? The same logic is used in `apps/dashboard/src/helpers/prefixWithBaseUrl.js`
+
+import { generateFilePath } from '@nextcloud/router'
+
+export const prefixWithBaseUrl = (url) => generateFilePath('theming', '', 'img/background/') + url
*/
namespace OCA\Theming\Tests\Controller;
+use OCA\Theming\AppInfo\Application;
use OCA\Theming\Controller\UserThemeController;
use OCA\Theming\ITheme;
+use OCA\Theming\Service\BackgroundService;
use OCA\Theming\Themes\DarkHighContrastTheme;
use OCA\Theming\Themes\DarkTheme;
use OCA\Theming\Themes\DefaultTheme;
private $userSession;
/** @var ThemeService|MockObject */
private $themesService;
+ /** @var BackgroundService|MockObject */
+ private $backgroundService;
+
/** @var ITheme[] */
private $themes;
$this->config = $this->createMock(IConfig::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->themesService = $this->createMock(ThemesService::class);
+ $this->backgroundService = $this->createMock(BackgroundService::class);
$this->themes = [
'default' => $this->createMock(DefaultTheme::class),
->willReturn('user');
$this->userThemeController = new UserThemeController(
- 'theming',
+ Application::APP_ID,
$this->request,
$this->config,
$this->userSession,
$this->themesService,
+ $this->backgroundService,
);
parent::setUp();
use OCP\IConfig;
use OCP\IL10N;
use OCP\IURLGenerator;
-use OCP\IUserSession;
use Test\TestCase;
class PersonalTest extends TestCase {
private IConfig $config;
- private IUserSession $userSession;
private ThemesService $themesService;
private IInitialState $initialStateService;
protected function setUp(): void {
parent::setUp();
$this->config = $this->createMock(IConfig::class);
- $this->userSession = $this->createMock(IUserSession::class);
$this->themesService = $this->createMock(ThemesService::class);
$this->initialStateService = $this->createMock(IInitialState::class);
$this->admin = new Personal(
Application::APP_ID,
$this->config,
- $this->userSession,
$this->themesService,
$this->initialStateService
);
/*! For license information please see dashboard-main.js.LICENSE.txt */
-!function(){"use strict";var n,e={18719:function(n,e,a){var o=a(20144),r=a(79753),i=a(22200),s=a(16453),d=a(4820),l=a(10861),c=a.n(l),u=a(9980),p=a.n(u),A=a(70110),h=a.n(A),g=a(91482),b={data:function(){return{isMobile:this._isMobile()}},beforeMount:function(){window.addEventListener("resize",this._onResize)},beforeDestroy:function(){window.removeEventListener("resize",this._onResize)},methods:{_onResize:function(){this.isMobile=this._isMobile()},_isMobile:function(){return document.documentElement.clientWidth<768}}},m=function(t){return(0,r.generateFilePath)("dashboard","","img/")+t},v=function(t){var n,e,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i=(null===(n=window.OCA)||void 0===n||null===(e=n.Theming)||void 0===e?void 0:e.enabledThemes)||[],s=0===i.length||"default"===i[0]?window.matchMedia("(prefers-color-scheme: dark)").matches:-1!==i.join("").indexOf("dark");return"default"===t?o&&"backgroundColor"!==o?(0,r.generateUrl)("/apps/theming/image/background")+"?v="+window.OCA.Theming.cacheBuster:m(s?"eduardo-neves-pedra-azul.jpg":"kamil-porembinski-clouds.jpg"):"custom"===t?(0,r.generateUrl)("/apps/dashboard/background")+"?v="+a:m(t)};function f(t,n,e,a,o,r,i){try{var s=t[r](i),d=s.value}catch(t){return void e(t)}s.done?n(d):Promise.resolve(d).then(a,o)}function C(t){return function(){var n=this,e=arguments;return new Promise((function(a,o){var r=t.apply(n,e);function i(t){f(r,a,o,i,s,"next",t)}function s(t){f(r,a,o,i,s,"throw",t)}i(void 0)}))}}var k=(0,s.loadState)("dashboard","shippedBackgrounds"),x={name:"BackgroundSettings",props:{background:{type:String,default:"default"},themingDefaultBackground:{type:String,default:""}},data:function(){return{backgroundImage:(0,r.generateUrl)("/apps/dashboard/background")+"?v="+Date.now(),loading:!1}},computed:{shippedBackgrounds:function(){return Object.keys(k).map((function(t){return{name:t,url:m(t),preview:m("previews/"+t),details:k[t]}}))}},methods:{update:function(t){var n=this;return C(regeneratorRuntime.mark((function e(){var a,o;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(a="custom"===t.type||"default"===t.type?t.type:t.value,n.backgroundImage=v(a,t.version,n.themingDefaultBackground),"color"!==t.type&&("default"!==t.type||"backgroundColor"!==n.themingDefaultBackground)){e.next=6;break}return n.$emit("update:background",t),n.loading=!1,e.abrupt("return");case 6:(o=new Image).onload=function(){n.$emit("update:background",t),n.loading=!1},o.src=n.backgroundImage;case 9:case"end":return e.stop()}}),e)})))()},setDefault:function(){var t=this;return C(regeneratorRuntime.mark((function n(){var e;return regeneratorRuntime.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return t.loading="default",n.next=3,d.default.post((0,r.generateUrl)("/apps/dashboard/background/default"));case 3:e=n.sent,t.update(e.data);case 5:case"end":return n.stop()}}),n)})))()},setShipped:function(t){var n=this;return C(regeneratorRuntime.mark((function e(){var a;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n.loading=t,e.next=3,d.default.post((0,r.generateUrl)("/apps/dashboard/background/shipped"),{value:t});case 3:a=e.sent,n.update(a.data);case 5:case"end":return e.stop()}}),e)})))()},setFile:function(t){var n=this;return C(regeneratorRuntime.mark((function e(){var a;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n.loading="custom",e.next=3,d.default.post((0,r.generateUrl)("/apps/dashboard/background/custom"),{value:t});case 3:a=e.sent,n.update(a.data);case 5:case"end":return e.stop()}}),e)})))()},pickColor:function(){var t=this;return C(regeneratorRuntime.mark((function n(){var e,a;return regeneratorRuntime.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return t.loading="color",e=OCA&&OCA.Theming?OCA.Theming.color:"#0082c9",n.next=4,d.default.post((0,r.generateUrl)("/apps/dashboard/background/color"),{value:e});case 4:a=n.sent,t.update(a.data);case 6:case"end":return n.stop()}}),n)})))()},pickFile:function(){var n=this;window.OC.dialogs.filepicker(t("dashboard","Insert from {productName}",{productName:OC.theme.name}),(function(t,e){e===OC.dialogs.FILEPICKER_TYPE_CHOOSE&&n.setFile(t)}),!1,["image/png","image/gif","image/jpeg","image/svg"],!0,OC.dialogs.FILEPICKER_TYPE_CHOOSE)}}},y=x,w=a(93379),S=a.n(w),_=a(7795),B=a.n(_),D=a(90569),O=a.n(D),P=a(3565),N=a.n(P),I=a(19216),E=a.n(I),F=a(44589),T=a.n(F),G=a(32238),U={};U.styleTagTransform=T(),U.setAttributes=N(),U.insert=O().bind(null,"head"),U.domAPI=B(),U.insertStyleElement=E(),S()(G.Z,U),G.Z&&G.Z.locals&&G.Z.locals;var j=a(51900),z=(0,j.Z)(y,(function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",{staticClass:"background-selector"},[e("button",{staticClass:"background filepicker",class:{active:"custom"===t.background},attrs:{tabindex:"0"},on:{click:t.pickFile}},[t._v("\n\t\t"+t._s(t.t("dashboard","Pick from Files"))+"\n\t")]),t._v(" "),e("button",{staticClass:"background default",class:{"icon-loading":"default"===t.loading,active:"default"===t.background},attrs:{tabindex:"0"},on:{click:t.setDefault}},[t._v("\n\t\t"+t._s(t.t("dashboard","Default image"))+"\n\t")]),t._v(" "),e("button",{staticClass:"background color",class:{active:"custom"===t.background},attrs:{tabindex:"0"},on:{click:t.pickColor}},[t._v("\n\t\t"+t._s(t.t("dashboard","Plain background"))+"\n\t")]),t._v(" "),t._l(t.shippedBackgrounds,(function(n){return e("button",{directives:[{name:"tooltip",rawName:"v-tooltip",value:n.details.attribution,expression:"shippedBackground.details.attribution"}],key:n.name,staticClass:"background",class:{"icon-loading":t.loading===n.name,active:t.background===n.name},style:{"background-image":"url("+n.preview+")"},attrs:{tabindex:"0"},on:{click:function(e){return t.setShipped(n.name)}}})}))],2)}),[],!1,null,"77b70ba2",null).exports,L=(0,s.loadState)("dashboard","panels"),R=(0,s.loadState)("dashboard","firstRun"),M=(0,s.loadState)("dashboard","background"),Z=(0,s.loadState)("dashboard","themingDefaultBackground"),q=(0,s.loadState)("dashboard","version"),W=(0,s.loadState)("dashboard","shippedBackgrounds"),H={weather:{text:t("dashboard","Weather"),icon:"icon-weather-status"},status:{text:t("dashboard","Status"),icon:"icon-user-status-online"}},$={name:"DashboardApp",components:{BackgroundSettings:z,NcButton:c(),Draggable:p(),NcModal:h(),Pencil:g.default},mixins:[b],data:function(){var t,n;return{isAdmin:(0,i.getCurrentUser)().isAdmin,timer:new Date,registeredStatus:[],callbacks:{},callbacksStatus:{},allCallbacksStatus:{},statusInfo:H,enabledStatuses:(0,s.loadState)("dashboard","statuses"),panels:L,firstRun:R,displayName:null===(t=(0,i.getCurrentUser)())||void 0===t?void 0:t.displayName,uid:null===(n=(0,i.getCurrentUser)())||void 0===n?void 0:n.uid,layout:(0,s.loadState)("dashboard","layout").filter((function(t){return L[t]})),modal:!1,appStoreUrl:(0,r.generateUrl)("/settings/apps/dashboard"),statuses:{},background:M,themingDefaultBackground:Z,version:q}},computed:{backgroundImage:function(){return v(this.background,this.version,this.themingDefaultBackground)},backgroundStyle:function(){return"default"===this.background&&"backgroundColor"===this.themingDefaultBackground||this.background.match(/#[0-9A-Fa-f]{6}/g)?null:{backgroundImage:"default"===this.background?"var(--image-main-background)":"url('".concat(this.backgroundImage,"')")}},greeting:function(){var n,e=this.timer.getHours();n=e>=22||e<5?"night":e>=18?"evening":e>=12?"afternoon":"morning";var a={morning:{generic:t("dashboard","Good morning"),withName:t("dashboard","Good morning, {name}",{name:this.displayName},void 0,{escape:!1})},afternoon:{generic:t("dashboard","Good afternoon"),withName:t("dashboard","Good afternoon, {name}",{name:this.displayName},void 0,{escape:!1})},evening:{generic:t("dashboard","Good evening"),withName:t("dashboard","Good evening, {name}",{name:this.displayName},void 0,{escape:!1})},night:{generic:t("dashboard","Hello"),withName:t("dashboard","Hello, {name}",{name:this.displayName},void 0,{escape:!1})}};return{text:this.displayName&&this.uid!==this.displayName?a[n].withName:a[n].generic}},isActive:function(){var t=this;return function(n){return t.layout.indexOf(n.id)>-1}},isStatusActive:function(){var t=this;return function(n){return!(n in t.enabledStatuses)||t.enabledStatuses[n]}},sortedAllStatuses:function(){return Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)},sortedPanels:function(){var t=this;return Object.values(this.panels).sort((function(n,e){var a=t.layout.indexOf(n.id),o=t.layout.indexOf(e.id);return-1===a||-1===o?o-a||n.id-e.id:a-o||n.id-e.id}))},sortedRegisteredStatus:function(){return this.registeredStatus.slice().sort(this.sortStatuses)}},watch:{callbacks:function(){this.rerenderPanels()},callbacksStatus:function(){for(var t in this.callbacksStatus){var n=this.$refs["status-"+t];this.statuses[t]&&this.statuses[t].mounted||(n?(this.callbacksStatus[t](n[0]),o.ZP.set(this.statuses,t,{mounted:!0})):console.error("Failed to register panel in the frontend as no backend data was provided for "+t))}}},mounted:function(){var t=this;this.updateGlobalStyles(),this.updateSkipLink(),window.addEventListener("scroll",this.handleScroll),setInterval((function(){t.timer=new Date}),3e4),this.firstRun&&window.addEventListener("scroll",this.disableFirstrunHint)},destroyed:function(){window.removeEventListener("scroll",this.handleScroll)},methods:{register:function(t,n){o.ZP.set(this.callbacks,t,n)},registerStatus:function(t,n){var e=this;o.ZP.set(this.allCallbacksStatus,t,n),this.isStatusActive(t)&&(this.registeredStatus.push(t),this.$nextTick((function(){o.ZP.set(e.callbacksStatus,t,n)})))},rerenderPanels:function(){for(var t in this.callbacks){var n=this.$refs[t];-1!==this.layout.indexOf(t)&&(this.panels[t]&&this.panels[t].mounted||(n?(this.callbacks[t](n[0],{widget:this.panels[t]}),o.ZP.set(this.panels[t],"mounted",!0)):console.error("Failed to register panel in the frontend as no backend data was provided for "+t)))}},saveLayout:function(){d.default.post((0,r.generateUrl)("/apps/dashboard/layout"),{layout:this.layout.join(",")})},saveStatuses:function(){d.default.post((0,r.generateUrl)("/apps/dashboard/statuses"),{statuses:JSON.stringify(this.enabledStatuses)})},showModal:function(){this.modal=!0,this.firstRun=!1},closeModal:function(){this.modal=!1},updateCheckbox:function(t,n){var e=this,a=this.layout.indexOf(t.id);!n&&a>-1?this.layout.splice(a,1):this.layout.push(t.id),o.ZP.set(this.panels[t.id],"mounted",!1),this.saveLayout(),this.$nextTick((function(){return e.rerenderPanels()}))},disableFirstrunHint:function(){var t=this;window.removeEventListener("scroll",this.disableFirstrunHint),setTimeout((function(){t.firstRun=!1}),1e3)},updateBackground:function(t){this.background="custom"===t.type||"default"===t.type?t.type:t.value,this.version=t.version,this.updateGlobalStyles()},updateGlobalStyles:function(){var t;"dark"===(null===(t=W[this.background])||void 0===t?void 0:t.theming)?(document.querySelector("#header").style.setProperty("--primary-invert-if-bright","invert(100%)"),document.querySelector("#header").style.setProperty("--color-primary-text","#000000")):(document.querySelector("#header").style.setProperty("--primary-invert-if-bright","no"),document.querySelector("#header").style.setProperty("--color-primary-text","#ffffff")),document.documentElement.style.setProperty("--image-main-background",this.backgroundStyle.backgroundImage),document.querySelector("#header").style.setProperty("--image-main-background",this.backgroundStyle.backgroundImage),document.querySelector("body").style.setProperty("--image-main-background",this.backgroundStyle.backgroundImage)},updateSkipLink:function(){document.getElementsByClassName("skip-navigation")[0].setAttribute("href","#app-dashboard")},updateStatusCheckbox:function(t,n){n?this.enableStatus(t):this.disableStatus(t)},enableStatus:function(t){this.enabledStatuses[t]=!0,this.registerStatus(t,this.allCallbacksStatus[t]),this.saveStatuses()},disableStatus:function(t){var n=this;this.enabledStatuses[t]=!1;var e=this.registeredStatus.findIndex((function(n){return n===t}));-1!==e&&(this.registeredStatus.splice(e,1),o.ZP.set(this.statuses,t,{mounted:!1}),this.$nextTick((function(){o.ZP.delete(n.callbacksStatus,t)}))),this.saveStatuses()},sortStatuses:function(t,n){var e=t.toLowerCase(),a=n.toLowerCase();return e>a?1:e<a?-1:0},handleScroll:function(){window.scrollY>70?document.body.classList.add("dashboard--scrolled"):document.body.classList.remove("dashboard--scrolled")}}},Y=a(65667),K={};K.styleTagTransform=T(),K.setAttributes=N(),K.insert=O().bind(null,"head"),K.domAPI=B(),K.insertStyleElement=E(),S()(Y.Z,K),Y.Z&&Y.Z.locals&&Y.Z.locals;var V=a(73729),Q={};Q.styleTagTransform=T(),Q.setAttributes=N(),Q.insert=O().bind(null,"head"),Q.domAPI=B(),Q.insertStyleElement=E(),S()(V.Z,Q),V.Z&&V.Z.locals&&V.Z.locals;var J=(0,j.Z)($,(function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",{attrs:{id:"app-dashboard"}},[e("h2",[t._v(t._s(t.greeting.text))]),t._v(" "),e("ul",{staticClass:"statuses"},t._l(t.sortedRegisteredStatus,(function(t){return e("div",{key:t,attrs:{id:"status-"+t}},[e("div",{ref:"status-"+t,refInFor:!0})])})),0),t._v(" "),e("Draggable",t._b({staticClass:"panels",attrs:{handle:".panel--header"},on:{end:t.saveLayout},model:{value:t.layout,callback:function(n){t.layout=n},expression:"layout"}},"Draggable",{swapThreshold:.3,delay:500,delayOnTouchOnly:!0,touchStartThreshold:3},!1),t._l(t.layout,(function(n){return e("div",{key:t.panels[n].id,staticClass:"panel"},[e("div",{staticClass:"panel--header"},[e("h2",[e("div",{class:t.panels[n].iconClass,attrs:{role:"img"}}),t._v("\n\t\t\t\t\t"+t._s(t.panels[n].title)+"\n\t\t\t\t")])]),t._v(" "),e("div",{staticClass:"panel--content",class:{loading:!t.panels[n].mounted}},[e("div",{ref:t.panels[n].id,refInFor:!0,attrs:{"data-id":t.panels[n].id}})])])})),0),t._v(" "),e("div",{staticClass:"footer"},[e("NcButton",{on:{click:t.showModal},scopedSlots:t._u([{key:"icon",fn:function(){return[e("Pencil",{attrs:{size:20}})]},proxy:!0}])},[t._v("\n\t\t\t"+t._s(t.t("dashboard","Customize"))+"\n\t\t")])],1),t._v(" "),t.modal?e("NcModal",{attrs:{size:"large"},on:{close:t.closeModal}},[e("div",{staticClass:"modal__content"},[e("h3",[t._v(t._s(t.t("dashboard","Edit widgets")))]),t._v(" "),e("ol",{staticClass:"panels"},t._l(t.sortedAllStatuses,(function(n){return e("li",{key:n,class:"panel-"+n},[e("input",{staticClass:"checkbox",attrs:{id:"status-checkbox-"+n,type:"checkbox"},domProps:{checked:t.isStatusActive(n)},on:{input:function(e){return t.updateStatusCheckbox(n,e.target.checked)}}}),t._v(" "),e("label",{attrs:{for:"status-checkbox-"+n}},[e("div",{class:t.statusInfo[n].icon,attrs:{role:"img"}}),t._v("\n\t\t\t\t\t\t"+t._s(t.statusInfo[n].text)+"\n\t\t\t\t\t")])])})),0),t._v(" "),e("Draggable",t._b({staticClass:"panels",attrs:{tag:"ol",handle:".draggable"},on:{end:t.saveLayout},model:{value:t.layout,callback:function(n){t.layout=n},expression:"layout"}},"Draggable",{swapThreshold:.3,delay:500,delayOnTouchOnly:!0,touchStartThreshold:3},!1),t._l(t.sortedPanels,(function(n){return e("li",{key:n.id,class:"panel-"+n.id},[e("input",{staticClass:"checkbox",attrs:{id:"panel-checkbox-"+n.id,type:"checkbox"},domProps:{checked:t.isActive(n)},on:{input:function(e){return t.updateCheckbox(n,e.target.checked)}}}),t._v(" "),e("label",{class:{draggable:t.isActive(n)},attrs:{for:"panel-checkbox-"+n.id}},[e("div",{class:n.iconClass,attrs:{role:"img"}}),t._v("\n\t\t\t\t\t\t"+t._s(n.title)+"\n\t\t\t\t\t")])])})),0),t._v(" "),t.isAdmin?e("a",{staticClass:"button",attrs:{href:t.appStoreUrl}},[t._v(t._s(t.t("dashboard","Get more widgets from the App Store")))]):t._e(),t._v(" "),e("h3",[t._v(t._s(t.t("dashboard","Change background image")))]),t._v(" "),e("BackgroundSettings",{attrs:{background:t.background,"theming-default-background":t.themingDefaultBackground},on:{"update:background":t.updateBackground}}),t._v(" "),e("h3",[t._v(t._s(t.t("dashboard","Weather service")))]),t._v(" "),e("p",[t._v("\n\t\t\t\t"+t._s(t.t("dashboard","For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information."))+"\n\t\t\t")]),t._v(" "),e("p",{staticClass:"credits--end"},[e("a",{attrs:{href:"https://api.met.no/doc/TermsOfService",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","Weather data from Met.no")))]),t._v(",\n\t\t\t\t"),e("a",{attrs:{href:"https://wiki.osmfoundation.org/wiki/Privacy_Policy",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","geocoding with Nominatim")))]),t._v(",\n\t\t\t\t"),e("a",{attrs:{href:"https://www.opentopodata.org/#public-api",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","elevation data from OpenTopoData")))]),t._v(".\n\t\t\t")])],1)]):t._e()],1)}),[],!1,null,"28cc8d42",null).exports,X=a(9944),tt=a(15168),nt=a.n(tt);a.nc=btoa((0,i.getRequestToken)()),o.ZP.directive("Tooltip",nt()),o.ZP.prototype.t=X.translate,window.OCA.Files||(window.OCA.Files={}),Object.assign(window.OCA.Files,{App:{fileList:{filesClient:OC.Files.getClient()}}},window.OCA.Files);var et=new(o.ZP.extend(J))({}).$mount("#app-content-vue");window.OCA.Dashboard={register:function(t,n){return et.register(t,n)},registerStatus:function(t,n){return et.registerStatus(t,n)}}},65667:function(t,n,e){var a=e(87537),o=e.n(a),r=e(23645),i=e.n(r)()(o());i.push([t.id,"#app-dashboard[data-v-28cc8d42]{width:100%;min-height:100%;background-size:cover;background-position:center center;background-repeat:no-repeat;background-attachment:fixed}#app-dashboard>h2[data-v-28cc8d42]{color:var(--color-primary-text);text-align:center;font-size:32px;line-height:130%;padding:1rem 0}.panels[data-v-28cc8d42]{width:auto;margin:auto;max-width:1500px;display:flex;justify-content:center;flex-direction:row;align-items:flex-start;flex-wrap:wrap}.panel[data-v-28cc8d42],.panels>div[data-v-28cc8d42]{width:320px;max-width:100%;margin:16px;background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);border-radius:var(--border-radius-large)}#body-user.theme--highcontrast .panel[data-v-28cc8d42],#body-user.theme--highcontrast .panels>div[data-v-28cc8d42]{border:2px solid var(--color-border)}.panel.sortable-ghost[data-v-28cc8d42],.panels>div.sortable-ghost[data-v-28cc8d42]{opacity:.1}.panel>.panel--header[data-v-28cc8d42],.panels>div>.panel--header[data-v-28cc8d42]{display:flex;z-index:1;top:50px;padding:16px;cursor:grab}.panel>.panel--header[data-v-28cc8d42],.panel>.panel--header[data-v-28cc8d42] *,.panels>div>.panel--header[data-v-28cc8d42],.panels>div>.panel--header[data-v-28cc8d42] *{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.panel>.panel--header[data-v-28cc8d42]:active,.panels>div>.panel--header[data-v-28cc8d42]:active{cursor:grabbing}.panel>.panel--header a[data-v-28cc8d42],.panels>div>.panel--header a[data-v-28cc8d42]{flex-grow:1}.panel>.panel--header>h2[data-v-28cc8d42],.panels>div>.panel--header>h2[data-v-28cc8d42]{display:block;align-items:center;flex-grow:1;margin:0;font-size:20px;line-height:24px;font-weight:bold;padding:16px 8px;height:56px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:grab}.panel>.panel--header>h2 div[data-v-28cc8d42],.panels>div>.panel--header>h2 div[data-v-28cc8d42]{background-size:32px;width:32px;height:32px;margin-right:16px;background-position:center;float:left}.panel>.panel--content[data-v-28cc8d42],.panels>div>.panel--content[data-v-28cc8d42]{margin:0 16px 16px 16px;height:424px;overflow:visible}@media only screen and (max-width: 709px){.panel>.panel--content[data-v-28cc8d42],.panels>div>.panel--content[data-v-28cc8d42]{height:auto}}.footer[data-v-28cc8d42]{display:flex;justify-content:center;transition:bottom var(--animation-slow) ease-in-out;padding:1rem 0}.edit-panels[data-v-28cc8d42]{display:inline-block;margin:auto;background-position:16px center;padding:12px 16px;padding-left:36px;border-radius:var(--border-radius-pill);max-width:200px;opacity:1;text-align:center}.button[data-v-28cc8d42],.button-vue[data-v-28cc8d42],.edit-panels[data-v-28cc8d42],.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle{background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);opacity:1 !important}.button[data-v-28cc8d42]:hover,.button[data-v-28cc8d42]:focus,.button[data-v-28cc8d42]:active,.button-vue[data-v-28cc8d42]:hover,.button-vue[data-v-28cc8d42]:focus,.button-vue[data-v-28cc8d42]:active,.edit-panels[data-v-28cc8d42]:hover,.edit-panels[data-v-28cc8d42]:focus,.edit-panels[data-v-28cc8d42]:active,.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle:hover,.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle:focus,.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle:active,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle:hover,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle:focus,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle:active{background-color:var(--color-background-hover) !important}.button[data-v-28cc8d42]:focus-visible,.button-vue[data-v-28cc8d42]:focus-visible,.edit-panels[data-v-28cc8d42]:focus-visible,.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle:focus-visible,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle:focus-visible{box-shadow:0 0 0 2px var(--color-main-text) !important}.modal__content[data-v-28cc8d42]{padding:32px 16px;text-align:center}.modal__content ol[data-v-28cc8d42]{display:flex;flex-direction:row;justify-content:center;list-style-type:none;padding-bottom:16px}.modal__content li label[data-v-28cc8d42]{position:relative;display:block;padding:48px 16px 14px 16px;margin:8px;width:140px;background-color:var(--color-background-hover);border:2px solid var(--color-main-background);border-radius:var(--border-radius-large);text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.modal__content li label div[data-v-28cc8d42]{position:absolute;top:16px;width:24px;height:24px;background-size:24px}.modal__content li label[data-v-28cc8d42]:hover{border-color:var(--color-primary)}.modal__content li:not(.panel-status) label div[data-v-28cc8d42]{filter:var(--background-invert-if-dark)}.modal__content li input[type=checkbox].checkbox+label[data-v-28cc8d42]:before{position:absolute;right:12px;top:16px}.modal__content li input:focus+label[data-v-28cc8d42]{border-color:var(--color-primary)}.modal__content h3[data-v-28cc8d42]{font-weight:bold}.modal__content h3[data-v-28cc8d42]:not(:first-of-type){margin-top:64px}.modal__content .button[data-v-28cc8d42]{display:inline-block;padding:10px 16px;margin:0}.modal__content p[data-v-28cc8d42]{max-width:650px;margin:0 auto}.modal__content p a[data-v-28cc8d42]:hover,.modal__content p a[data-v-28cc8d42]:focus{border-bottom:2px solid var(--color-border)}.modal__content .credits--end[data-v-28cc8d42]{padding-bottom:32px;color:var(--color-text-maxcontrast)}.modal__content .credits--end a[data-v-28cc8d42]{color:var(--color-text-maxcontrast)}.flip-list-move[data-v-28cc8d42]{transition:transform var(--animation-slow)}.statuses[data-v-28cc8d42]{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap;margin-bottom:36px}.statuses>div[data-v-28cc8d42]{margin:8px}","",{version:3,sources:["webpack://./apps/dashboard/src/DashboardApp.vue"],names:[],mappings:"AA6aA,gCACC,UAAA,CACA,eAAA,CACA,qBAAA,CACA,iCAAA,CACA,2BAAA,CACA,2BAAA,CAEA,mCACC,+BAAA,CACA,iBAAA,CACA,cAAA,CACA,gBAAA,CACA,cAAA,CAIF,yBACC,UAAA,CACA,WAAA,CACA,gBAAA,CACA,YAAA,CACA,sBAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CAGD,qDACC,WAAA,CACA,cAAA,CACA,WAAA,CACA,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,wCAAA,CAEA,mHACC,oCAAA,CAGD,mFACE,UAAA,CAGF,mFACC,YAAA,CACA,SAAA,CACA,QAAA,CACA,YAAA,CACA,WAAA,CAEA,4KACC,0BAAA,CACA,wBAAA,CACA,uBAAA,CACA,qBAAA,CACA,oBAAA,CACA,gBAAA,CAGD,iGACC,eAAA,CAGD,uFACC,WAAA,CAGD,yFACC,aAAA,CACA,kBAAA,CACA,WAAA,CACA,QAAA,CACA,cAAA,CACA,gBAAA,CACA,gBAAA,CACA,gBAAA,CACA,WAAA,CACA,kBAAA,CACA,eAAA,CACA,sBAAA,CACA,WAAA,CACA,iGACC,oBAAA,CACA,UAAA,CACA,WAAA,CACA,iBAAA,CACA,0BAAA,CACA,UAAA,CAKH,qFACC,uBAAA,CACA,YAAA,CAEA,gBAAA,CAID,0CACC,qFACC,WAAA,CAAA,CAKH,yBACC,YAAA,CACA,sBAAA,CACA,mDAAA,CACA,cAAA,CAGD,8BACC,oBAAA,CACA,WAAA,CACA,+BAAA,CACA,iBAAA,CACA,iBAAA,CACA,uCAAA,CACA,eAAA,CACA,SAAA,CACA,iBAAA,CAGD,0OAKC,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,oBAAA,CAEA,6xBAGC,yDAAA,CAED,gTACC,sDAAA,CAIF,iCACC,iBAAA,CACA,iBAAA,CAEA,oCACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,oBAAA,CACA,mBAAA,CAGA,0CACC,iBAAA,CACA,aAAA,CACA,2BAAA,CACA,UAAA,CACA,WAAA,CACA,8CAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CACA,eAAA,CACA,sBAAA,CACA,kBAAA,CAEA,8CACC,iBAAA,CACA,QAAA,CACA,UAAA,CACA,WAAA,CACA,oBAAA,CAGD,gDACC,iCAAA,CAKF,iEACC,uCAAA,CAGD,+EACC,iBAAA,CACA,UAAA,CACA,QAAA,CAGD,sDACC,iCAAA,CAIF,oCACC,gBAAA,CAEA,wDACC,eAAA,CAKF,yCACC,oBAAA,CACA,iBAAA,CACA,QAAA,CAGD,mCACC,eAAA,CACA,aAAA,CAEA,sFAEC,2CAAA,CAIF,+CACC,mBAAA,CACA,mCAAA,CAEA,iDACC,mCAAA,CAKH,iCACC,0CAAA,CAGD,2BACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACA,kBAAA,CAEA,+BACC,UAAA",sourcesContent:["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n#app-dashboard {\n\twidth: 100%;\n\tmin-height: 100%;\n\tbackground-size: cover;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\tbackground-attachment: fixed;\n\n\t> h2 {\n\t\tcolor: var(--color-primary-text);\n\t\ttext-align: center;\n\t\tfont-size: 32px;\n\t\tline-height: 130%;\n\t\tpadding: 1rem 0;\n\t}\n}\n\n.panels {\n\twidth: auto;\n\tmargin: auto;\n\tmax-width: 1500px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tflex-wrap: wrap;\n}\n\n.panel, .panels > div {\n\twidth: 320px;\n\tmax-width: 100%;\n\tmargin: 16px;\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\tborder-radius: var(--border-radius-large);\n\n\t#body-user.theme--highcontrast & {\n\t\tborder: 2px solid var(--color-border);\n\t}\n\n\t&.sortable-ghost {\n\t\t opacity: 0.1;\n\t}\n\n\t& > .panel--header {\n\t\tdisplay: flex;\n\t\tz-index: 1;\n\t\ttop: 50px;\n\t\tpadding: 16px;\n\t\tcursor: grab;\n\n\t\t&, ::v-deep * {\n\t\t\t-webkit-touch-callout: none;\n\t\t\t-webkit-user-select: none;\n\t\t\t-khtml-user-select: none;\n\t\t\t-moz-user-select: none;\n\t\t\t-ms-user-select: none;\n\t\t\tuser-select: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tcursor: grabbing;\n\t\t}\n\n\t\ta {\n\t\t\tflex-grow: 1;\n\t\t}\n\n\t\t> h2 {\n\t\t\tdisplay: block;\n\t\t\talign-items: center;\n\t\t\tflex-grow: 1;\n\t\t\tmargin: 0;\n\t\t\tfont-size: 20px;\n\t\t\tline-height: 24px;\n\t\t\tfont-weight: bold;\n\t\t\tpadding: 16px 8px;\n\t\t\theight: 56px;\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: grab;\n\t\t\tdiv {\n\t\t\t\tbackground-size: 32px;\n\t\t\t\twidth: 32px;\n\t\t\t\theight: 32px;\n\t\t\t\tmargin-right: 16px;\n\t\t\t\tbackground-position: center;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .panel--content {\n\t\tmargin: 0 16px 16px 16px;\n\t\theight: 424px;\n\t\t// We specifically do not want scrollbars inside widgets\n\t\toverflow: visible;\n\t}\n\n\t// No need to extend height of widgets if only one column is shown\n\t@media only screen and (max-width: 709px) {\n\t\t& > .panel--content {\n\t\t\theight: auto;\n\t\t}\n\t}\n}\n\n.footer {\n\tdisplay: flex;\n\tjustify-content: center;\n\ttransition: bottom var(--animation-slow) ease-in-out;\n\tpadding: 1rem 0;\n}\n\n.edit-panels {\n\tdisplay: inline-block;\n\tmargin:auto;\n\tbackground-position: 16px center;\n\tpadding: 12px 16px;\n\tpadding-left: 36px;\n\tborder-radius: var(--border-radius-pill);\n\tmax-width: 200px;\n\topacity: 1;\n\ttext-align: center;\n}\n\n.button,\n.button-vue,\n.edit-panels,\n.statuses ::v-deep .action-item .action-item__menutoggle,\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\topacity: 1 !important;\n\n\t&:hover,\n\t&:focus,\n\t&:active {\n\t\tbackground-color: var(--color-background-hover)!important;\n\t}\n\t&:focus-visible {\n\t\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\n\t}\n}\n\n.modal__content {\n\tpadding: 32px 16px;\n\ttext-align: center;\n\n\tol {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tjustify-content: center;\n\t\tlist-style-type: none;\n\t\tpadding-bottom: 16px;\n\t}\n\tli {\n\t\tlabel {\n\t\t\tposition: relative;\n\t\t\tdisplay: block;\n\t\t\tpadding: 48px 16px 14px 16px;\n\t\t\tmargin: 8px;\n\t\t\twidth: 140px;\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t\tborder: 2px solid var(--color-main-background);\n\t\t\tborder-radius: var(--border-radius-large);\n\t\t\ttext-align: left;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\n\t\t\tdiv {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 16px;\n\t\t\t\twidth: 24px;\n\t\t\t\theight: 24px;\n\t\t\t\tbackground-size: 24px;\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\tborder-color: var(--color-primary);\n\t\t\t}\n\t\t}\n\n\t\t// Do not invert status icons\n\t\t&:not(.panel-status) label div {\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\n\t\tinput[type='checkbox'].checkbox + label:before {\n\t\t\tposition: absolute;\n\t\t\tright: 12px;\n\t\t\ttop: 16px;\n\t\t}\n\n\t\tinput:focus + label {\n\t\t\tborder-color: var(--color-primary);\n\t\t}\n\t}\n\n\th3 {\n\t\tfont-weight: bold;\n\n\t\t&:not(:first-of-type) {\n\t\t\tmargin-top: 64px;\n\t\t}\n\t}\n\n\t// Adjust design of 'Get more widgets' button\n\t.button {\n\t\tdisplay: inline-block;\n\t\tpadding: 10px 16px;\n\t\tmargin: 0;\n\t}\n\n\tp {\n\t\tmax-width: 650px;\n\t\tmargin: 0 auto;\n\n\t\ta:hover,\n\t\ta:focus {\n\t\t\tborder-bottom: 2px solid var(--color-border);\n\t\t}\n\t}\n\n\t.credits--end {\n\t\tpadding-bottom: 32px;\n\t\tcolor: var(--color-text-maxcontrast);\n\n\t\ta {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\t}\n}\n\n.flip-list-move {\n\ttransition: transform var(--animation-slow);\n}\n\n.statuses {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\tflex-wrap: wrap;\n\tmargin-bottom: 36px;\n\n\t& > div {\n\t\tmargin: 8px;\n\t}\n}\n"],sourceRoot:""}]),n.Z=i},32238:function(t,n,e){var a=e(87537),o=e.n(a),r=e(23645),i=e.n(r)()(o());i.push([t.id,'.background-selector[data-v-77b70ba2]{display:flex;flex-wrap:wrap;justify-content:center}.background-selector .background[data-v-77b70ba2]{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}.background-selector .background.current[data-v-77b70ba2]{background-image:var(--color-background-dark)}.background-selector .background.filepicker[data-v-77b70ba2],.background-selector .background.default[data-v-77b70ba2],.background-selector .background.color[data-v-77b70ba2]{border-color:var(--color-border)}.background-selector .background.color[data-v-77b70ba2]{background-color:var(--color-primary);color:var(--color-primary-text)}.background-selector .background.active[data-v-77b70ba2],.background-selector .background[data-v-77b70ba2]:hover,.background-selector .background[data-v-77b70ba2]:focus{border:2px solid var(--color-primary)}.background-selector .background.active[data-v-77b70ba2]:not(.icon-loading):after{background-image:var(--icon-checkmark-white);background-repeat:no-repeat;background-position:center;background-size:44px;content:"";display:block;height:100%}',"",{version:3,sources:["webpack://./apps/dashboard/src/components/BackgroundSettings.vue"],names:[],mappings:"AA4IA,sCACC,YAAA,CACA,cAAA,CACA,sBAAA,CAEA,kDACC,WAAA,CACA,WAAA,CACA,UAAA,CACA,qBAAA,CACA,iCAAA,CACA,iBAAA,CACA,wCAAA,CACA,6CAAA,CACA,eAAA,CAEA,0DACC,6CAAA,CAGD,+KACC,gCAAA,CAGD,wDACC,qCAAA,CACA,+BAAA,CAGD,yKAGC,qCAAA,CAGD,kFACC,4CAAA,CACA,2BAAA,CACA,0BAAA,CACA,oBAAA,CACA,UAAA,CACA,aAAA,CACA,WAAA",sourcesContent:["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.background-selector {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tjustify-content: center;\n\n\t.background {\n\t\twidth: 176px;\n\t\theight: 96px;\n\t\tmargin: 8px;\n\t\tbackground-size: cover;\n\t\tbackground-position: center center;\n\t\ttext-align: center;\n\t\tborder-radius: var(--border-radius-large);\n\t\tborder: 2px solid var(--color-main-background);\n\t\toverflow: hidden;\n\n\t\t&.current {\n\t\t\tbackground-image: var(--color-background-dark);\n\t\t}\n\n\t\t&.filepicker, &.default, &.color {\n\t\t\tborder-color: var(--color-border);\n\t\t}\n\n\t\t&.color {\n\t\t\tbackground-color: var(--color-primary);\n\t\t\tcolor: var(--color-primary-text);\n\t\t}\n\n\t\t&.active,\n\t\t&:hover,\n\t\t&:focus {\n\t\t\tborder: 2px solid var(--color-primary);\n\t\t}\n\n\t\t&.active:not(.icon-loading):after {\n\t\t\tbackground-image: var(--icon-checkmark-white);\n\t\t\tbackground-repeat: no-repeat;\n\t\t\tbackground-position: center;\n\t\t\tbackground-size: 44px;\n\t\t\tcontent: '';\n\t\t\tdisplay: block;\n\t\t\theight: 100%;\n\t\t}\n\t}\n}\n"],sourceRoot:""}]),n.Z=i},73729:function(t,n,e){var a=e(87537),o=e.n(a),r=e(23645),i=e.n(r)()(o());i.push([t.id,"\nhtml, body {\n\tbackground-attachment: fixed;\n}\n#body-user #header {\n\tposition: fixed;\n}\n#content {\n\toverflow: auto;\n\tposition: static !important;\n}\n","",{version:3,sources:["webpack://./apps/dashboard/src/DashboardApp.vue"],names:[],mappings:";AA4qBA;CACA,4BAAA;AACA;AAEA;CACA,eAAA;AACA;AAEA;CACA,cAAA;CACA,2BAAA;AACA",sourcesContent:["<template>\n\t<div id=\"app-dashboard\">\n\t\t<h2>{{ greeting.text }}</h2>\n\t\t<ul class=\"statuses\">\n\t\t\t<div v-for=\"status in sortedRegisteredStatus\"\n\t\t\t\t:id=\"'status-' + status\"\n\t\t\t\t:key=\"status\">\n\t\t\t\t<div :ref=\"'status-' + status\" />\n\t\t\t</div>\n\t\t</ul>\n\n\t\t<Draggable v-model=\"layout\"\n\t\t\tclass=\"panels\"\n\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\thandle=\".panel--header\"\n\t\t\t@end=\"saveLayout\">\n\t\t\t<div v-for=\"panelId in layout\" :key=\"panels[panelId].id\" class=\"panel\">\n\t\t\t\t<div class=\"panel--header\">\n\t\t\t\t\t<h2>\n\t\t\t\t\t\t<div :class=\"panels[panelId].iconClass\" role=\"img\" />\n\t\t\t\t\t\t{{ panels[panelId].title }}\n\t\t\t\t\t</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"panel--content\" :class=\"{ loading: !panels[panelId].mounted }\">\n\t\t\t\t\t<div :ref=\"panels[panelId].id\" :data-id=\"panels[panelId].id\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Draggable>\n\n\t\t<div class=\"footer\">\n\t\t\t<NcButton @click=\"showModal\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('dashboard', 'Customize') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcModal v-if=\"modal\" size=\"large\" @close=\"closeModal\">\n\t\t\t<div class=\"modal__content\">\n\t\t\t\t<h3>{{ t('dashboard', 'Edit widgets') }}</h3>\n\t\t\t\t<ol class=\"panels\">\n\t\t\t\t\t<li v-for=\"status in sortedAllStatuses\" :key=\"status\" :class=\"'panel-' + status\">\n\t\t\t\t\t\t<input :id=\"'status-checkbox-' + status\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isStatusActive(status)\"\n\t\t\t\t\t\t\t@input=\"updateStatusCheckbox(status, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'status-checkbox-' + status\">\n\t\t\t\t\t\t\t<div :class=\"statusInfo[status].icon\" role=\"img\" />\n\t\t\t\t\t\t\t{{ statusInfo[status].text }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</ol>\n\t\t\t\t<Draggable v-model=\"layout\"\n\t\t\t\t\tclass=\"panels\"\n\t\t\t\t\ttag=\"ol\"\n\t\t\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\t\t\thandle=\".draggable\"\n\t\t\t\t\t@end=\"saveLayout\">\n\t\t\t\t\t<li v-for=\"panel in sortedPanels\" :key=\"panel.id\" :class=\"'panel-' + panel.id\">\n\t\t\t\t\t\t<input :id=\"'panel-checkbox-' + panel.id\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isActive(panel)\"\n\t\t\t\t\t\t\t@input=\"updateCheckbox(panel, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'panel-checkbox-' + panel.id\" :class=\"{ draggable: isActive(panel) }\">\n\t\t\t\t\t\t\t<div :class=\"panel.iconClass\" role=\"img\" />\n\t\t\t\t\t\t\t{{ panel.title }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</Draggable>\n\n\t\t\t\t<a v-if=\"isAdmin\" :href=\"appStoreUrl\" class=\"button\">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>\n\n\t\t\t\t<h3>{{ t('dashboard', 'Change background image') }}</h3>\n\t\t\t\t<BackgroundSettings :background=\"background\"\n\t\t\t\t\t:theming-default-background=\"themingDefaultBackground\"\n\t\t\t\t\t@update:background=\"updateBackground\" />\n\n\t\t\t\t<h3>{{ t('dashboard', 'Weather service') }}</h3>\n\t\t\t\t<p>\n\t\t\t\t\t{{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}\n\t\t\t\t</p>\n\t\t\t\t<p class=\"credits--end\">\n\t\t\t\t\t<a href=\"https://api.met.no/doc/TermsOfService\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'Weather data from Met.no') }}</a>,\n\t\t\t\t\t<a href=\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'geocoding with Nominatim') }}</a>,\n\t\t\t\t\t<a href=\"https://www.opentopodata.org/#public-api\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'elevation data from OpenTopoData') }}</a>.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcModal>\n\t</div>\n</template>\n\n<script>\nimport { generateUrl } from '@nextcloud/router'\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { loadState } from '@nextcloud/initial-state'\nimport axios from '@nextcloud/axios'\nimport NcButton from '@nextcloud/vue/dist/Components/NcButton'\nimport Draggable from 'vuedraggable'\nimport NcModal from '@nextcloud/vue/dist/Components/NcModal'\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\nimport Vue from 'vue'\n\nimport isMobile from './mixins/isMobile'\nimport BackgroundSettings from './components/BackgroundSettings'\nimport getBackgroundUrl from './helpers/getBackgroundUrl'\n\nconst panels = loadState('dashboard', 'panels')\nconst firstRun = loadState('dashboard', 'firstRun')\nconst background = loadState('dashboard', 'background')\nconst themingDefaultBackground = loadState('dashboard', 'themingDefaultBackground')\nconst version = loadState('dashboard', 'version')\nconst shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')\n\nconst statusInfo = {\n\tweather: {\n\t\ttext: t('dashboard', 'Weather'),\n\t\ticon: 'icon-weather-status',\n\t},\n\tstatus: {\n\t\ttext: t('dashboard', 'Status'),\n\t\ticon: 'icon-user-status-online',\n\t},\n}\n\nexport default {\n\tname: 'DashboardApp',\n\tcomponents: {\n\t\tBackgroundSettings,\n\t\tNcButton,\n\t\tDraggable,\n\t\tNcModal,\n\t\tPencil,\n\t},\n\tmixins: [\n\t\tisMobile,\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\tisAdmin: getCurrentUser().isAdmin,\n\t\t\ttimer: new Date(),\n\t\t\tregisteredStatus: [],\n\t\t\tcallbacks: {},\n\t\t\tcallbacksStatus: {},\n\t\t\tallCallbacksStatus: {},\n\t\t\tstatusInfo,\n\t\t\tenabledStatuses: loadState('dashboard', 'statuses'),\n\t\t\tpanels,\n\t\t\tfirstRun,\n\t\t\tdisplayName: getCurrentUser()?.displayName,\n\t\t\tuid: getCurrentUser()?.uid,\n\t\t\tlayout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),\n\t\t\tmodal: false,\n\t\t\tappStoreUrl: generateUrl('/settings/apps/dashboard'),\n\t\t\tstatuses: {},\n\t\t\tbackground,\n\t\t\tthemingDefaultBackground,\n\t\t\tversion,\n\t\t}\n\t},\n\tcomputed: {\n\t\tbackgroundImage() {\n\t\t\treturn getBackgroundUrl(this.background, this.version, this.themingDefaultBackground)\n\t\t},\n\t\tbackgroundStyle() {\n\t\t\tif ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')\n\t\t\t\t|| this.background.match(/#[0-9A-Fa-f]{6}/g)) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tbackgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,\n\t\t\t}\n\t\t},\n\n\t\tgreeting() {\n\t\t\tconst time = this.timer.getHours()\n\n\t\t\t// Determine part of the day\n\t\t\tlet partOfDay\n\t\t\tif (time >= 22 || time < 5) {\n\t\t\t\tpartOfDay = 'night'\n\t\t\t} else if (time >= 18) {\n\t\t\t\tpartOfDay = 'evening'\n\t\t\t} else if (time >= 12) {\n\t\t\t\tpartOfDay = 'afternoon'\n\t\t\t} else {\n\t\t\t\tpartOfDay = 'morning'\n\t\t\t}\n\n\t\t\t// Define the greetings\n\t\t\tconst good = {\n\t\t\t\tmorning: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good morning'),\n\t\t\t\t\twithName: t('dashboard', 'Good morning, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tafternoon: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good afternoon'),\n\t\t\t\t\twithName: t('dashboard', 'Good afternoon, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tevening: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good evening'),\n\t\t\t\t\twithName: t('dashboard', 'Good evening, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tnight: {\n\t\t\t\t\t// Don't use \"Good night\" as it's not a greeting\n\t\t\t\t\tgeneric: t('dashboard', 'Hello'),\n\t\t\t\t\twithName: t('dashboard', 'Hello, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\t// Figure out which greeting to show\n\t\t\tconst shouldShowName = this.displayName && this.uid !== this.displayName\n\t\t\treturn { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }\n\t\t},\n\n\t\tisActive() {\n\t\t\treturn (panel) => this.layout.indexOf(panel.id) > -1\n\t\t},\n\t\tisStatusActive() {\n\t\t\treturn (status) => !(status in this.enabledStatuses) || this.enabledStatuses[status]\n\t\t},\n\n\t\tsortedAllStatuses() {\n\t\t\treturn Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)\n\t\t},\n\t\tsortedPanels() {\n\t\t\treturn Object.values(this.panels).sort((a, b) => {\n\t\t\t\tconst indexA = this.layout.indexOf(a.id)\n\t\t\t\tconst indexB = this.layout.indexOf(b.id)\n\t\t\t\tif (indexA === -1 || indexB === -1) {\n\t\t\t\t\treturn indexB - indexA || a.id - b.id\n\t\t\t\t}\n\t\t\t\treturn indexA - indexB || a.id - b.id\n\t\t\t})\n\t\t},\n\t\tsortedRegisteredStatus() {\n\t\t\treturn this.registeredStatus.slice().sort(this.sortStatuses)\n\t\t},\n\t},\n\n\twatch: {\n\t\tcallbacks() {\n\t\t\tthis.rerenderPanels()\n\t\t},\n\t\tcallbacksStatus() {\n\t\t\tfor (const app in this.callbacksStatus) {\n\t\t\t\tconst element = this.$refs['status-' + app]\n\t\t\t\tif (this.statuses[app] && this.statuses[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacksStatus[app](element[0])\n\t\t\t\t\tVue.set(this.statuses, app, { mounted: true })\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.updateGlobalStyles()\n\t\tthis.updateSkipLink()\n\t\twindow.addEventListener('scroll', this.handleScroll)\n\n\t\tsetInterval(() => {\n\t\t\tthis.timer = new Date()\n\t\t}, 30000)\n\n\t\tif (this.firstRun) {\n\t\t\twindow.addEventListener('scroll', this.disableFirstrunHint)\n\t\t}\n\t},\n\tdestroyed() {\n\t\twindow.removeEventListener('scroll', this.handleScroll)\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Method to register panels that will be called by the integrating apps\n\t\t *\n\t\t * @param {string} app The unique app id for the widget\n\t\t * @param {Function} callback The callback function to register a panel which gets the DOM element passed as parameter\n\t\t */\n\t\tregister(app, callback) {\n\t\t\tVue.set(this.callbacks, app, callback)\n\t\t},\n\t\tregisterStatus(app, callback) {\n\t\t\t// always save callbacks in case user enables the status later\n\t\t\tVue.set(this.allCallbacksStatus, app, callback)\n\t\t\t// register only if status is enabled or missing from config\n\t\t\tif (this.isStatusActive(app)) {\n\t\t\t\tthis.registeredStatus.push(app)\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.set(this.callbacksStatus, app, callback)\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\trerenderPanels() {\n\t\t\tfor (const app in this.callbacks) {\n\t\t\t\tconst element = this.$refs[app]\n\t\t\t\tif (this.layout.indexOf(app) === -1) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (this.panels[app] && this.panels[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacks[app](element[0], {\n\t\t\t\t\t\twidget: this.panels[app],\n\t\t\t\t\t})\n\t\t\t\t\tVue.set(this.panels[app], 'mounted', true)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsaveLayout() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/layout'), {\n\t\t\t\tlayout: this.layout.join(','),\n\t\t\t})\n\t\t},\n\t\tsaveStatuses() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/statuses'), {\n\t\t\t\tstatuses: JSON.stringify(this.enabledStatuses),\n\t\t\t})\n\t\t},\n\t\tshowModal() {\n\t\t\tthis.modal = true\n\t\t\tthis.firstRun = false\n\t\t},\n\t\tcloseModal() {\n\t\t\tthis.modal = false\n\t\t},\n\t\tupdateCheckbox(panel, currentValue) {\n\t\t\tconst index = this.layout.indexOf(panel.id)\n\t\t\tif (!currentValue && index > -1) {\n\t\t\t\tthis.layout.splice(index, 1)\n\n\t\t\t} else {\n\t\t\t\tthis.layout.push(panel.id)\n\t\t\t}\n\t\t\tVue.set(this.panels[panel.id], 'mounted', false)\n\t\t\tthis.saveLayout()\n\t\t\tthis.$nextTick(() => this.rerenderPanels())\n\t\t},\n\t\tdisableFirstrunHint() {\n\t\t\twindow.removeEventListener('scroll', this.disableFirstrunHint)\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.firstRun = false\n\t\t\t}, 1000)\n\t\t},\n\t\tupdateBackground(data) {\n\t\t\tthis.background = data.type === 'custom' || data.type === 'default' ? data.type : data.value\n\t\t\tthis.version = data.version\n\t\t\tthis.updateGlobalStyles()\n\t\t},\n\t\tupdateGlobalStyles() {\n\t\t\t// Override primary-invert-if-bright and color-primary-text if background is set\n\t\t\tconst isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'\n\t\t\tif (isBackgroundBright) {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#000000')\n\t\t\t\t// document.body.removeAttribute('data-theme-dark')\n\t\t\t\t// document.body.setAttribute('data-theme-light', 'true')\n\t\t\t} else {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')\n\t\t\t\t// document.body.removeAttribute('data-theme-light')\n\t\t\t\t// document.body.setAttribute('data-theme-dark', 'true')\n\t\t\t}\n\n\t\t\tdocument.documentElement.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t\tdocument.querySelector('#header').style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t\tdocument.querySelector('body').style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t},\n\t\tupdateSkipLink() {\n\t\t\t// Make sure \"Skip to main content\" link points to the app content\n\t\t\tdocument.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')\n\t\t},\n\t\tupdateStatusCheckbox(app, checked) {\n\t\t\tif (checked) {\n\t\t\t\tthis.enableStatus(app)\n\t\t\t} else {\n\t\t\t\tthis.disableStatus(app)\n\t\t\t}\n\t\t},\n\t\tenableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = true\n\t\t\tthis.registerStatus(app, this.allCallbacksStatus[app])\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tdisableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = false\n\t\t\tconst i = this.registeredStatus.findIndex((s) => s === app)\n\t\t\tif (i !== -1) {\n\t\t\t\tthis.registeredStatus.splice(i, 1)\n\t\t\t\tVue.set(this.statuses, app, { mounted: false })\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.delete(this.callbacksStatus, app)\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tsortStatuses(a, b) {\n\t\t\tconst al = a.toLowerCase()\n\t\t\tconst bl = b.toLowerCase()\n\t\t\treturn al > bl\n\t\t\t\t? 1\n\t\t\t\t: al < bl\n\t\t\t\t\t? -1\n\t\t\t\t\t: 0\n\t\t},\n\t\thandleScroll() {\n\t\t\tif (window.scrollY > 70) {\n\t\t\t\tdocument.body.classList.add('dashboard--scrolled')\n\t\t\t} else {\n\t\t\t\tdocument.body.classList.remove('dashboard--scrolled')\n\t\t\t}\n\t\t},\n\t},\n}\n<\/script>\n\n<style lang=\"scss\" scoped>\n#app-dashboard {\n\twidth: 100%;\n\tmin-height: 100%;\n\tbackground-size: cover;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\tbackground-attachment: fixed;\n\n\t> h2 {\n\t\tcolor: var(--color-primary-text);\n\t\ttext-align: center;\n\t\tfont-size: 32px;\n\t\tline-height: 130%;\n\t\tpadding: 1rem 0;\n\t}\n}\n\n.panels {\n\twidth: auto;\n\tmargin: auto;\n\tmax-width: 1500px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tflex-wrap: wrap;\n}\n\n.panel, .panels > div {\n\twidth: 320px;\n\tmax-width: 100%;\n\tmargin: 16px;\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\tborder-radius: var(--border-radius-large);\n\n\t#body-user.theme--highcontrast & {\n\t\tborder: 2px solid var(--color-border);\n\t}\n\n\t&.sortable-ghost {\n\t\t opacity: 0.1;\n\t}\n\n\t& > .panel--header {\n\t\tdisplay: flex;\n\t\tz-index: 1;\n\t\ttop: 50px;\n\t\tpadding: 16px;\n\t\tcursor: grab;\n\n\t\t&, ::v-deep * {\n\t\t\t-webkit-touch-callout: none;\n\t\t\t-webkit-user-select: none;\n\t\t\t-khtml-user-select: none;\n\t\t\t-moz-user-select: none;\n\t\t\t-ms-user-select: none;\n\t\t\tuser-select: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tcursor: grabbing;\n\t\t}\n\n\t\ta {\n\t\t\tflex-grow: 1;\n\t\t}\n\n\t\t> h2 {\n\t\t\tdisplay: block;\n\t\t\talign-items: center;\n\t\t\tflex-grow: 1;\n\t\t\tmargin: 0;\n\t\t\tfont-size: 20px;\n\t\t\tline-height: 24px;\n\t\t\tfont-weight: bold;\n\t\t\tpadding: 16px 8px;\n\t\t\theight: 56px;\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: grab;\n\t\t\tdiv {\n\t\t\t\tbackground-size: 32px;\n\t\t\t\twidth: 32px;\n\t\t\t\theight: 32px;\n\t\t\t\tmargin-right: 16px;\n\t\t\t\tbackground-position: center;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .panel--content {\n\t\tmargin: 0 16px 16px 16px;\n\t\theight: 424px;\n\t\t// We specifically do not want scrollbars inside widgets\n\t\toverflow: visible;\n\t}\n\n\t// No need to extend height of widgets if only one column is shown\n\t@media only screen and (max-width: 709px) {\n\t\t& > .panel--content {\n\t\t\theight: auto;\n\t\t}\n\t}\n}\n\n.footer {\n\tdisplay: flex;\n\tjustify-content: center;\n\ttransition: bottom var(--animation-slow) ease-in-out;\n\tpadding: 1rem 0;\n}\n\n.edit-panels {\n\tdisplay: inline-block;\n\tmargin:auto;\n\tbackground-position: 16px center;\n\tpadding: 12px 16px;\n\tpadding-left: 36px;\n\tborder-radius: var(--border-radius-pill);\n\tmax-width: 200px;\n\topacity: 1;\n\ttext-align: center;\n}\n\n.button,\n.button-vue,\n.edit-panels,\n.statuses ::v-deep .action-item .action-item__menutoggle,\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\topacity: 1 !important;\n\n\t&:hover,\n\t&:focus,\n\t&:active {\n\t\tbackground-color: var(--color-background-hover)!important;\n\t}\n\t&:focus-visible {\n\t\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\n\t}\n}\n\n.modal__content {\n\tpadding: 32px 16px;\n\ttext-align: center;\n\n\tol {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tjustify-content: center;\n\t\tlist-style-type: none;\n\t\tpadding-bottom: 16px;\n\t}\n\tli {\n\t\tlabel {\n\t\t\tposition: relative;\n\t\t\tdisplay: block;\n\t\t\tpadding: 48px 16px 14px 16px;\n\t\t\tmargin: 8px;\n\t\t\twidth: 140px;\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t\tborder: 2px solid var(--color-main-background);\n\t\t\tborder-radius: var(--border-radius-large);\n\t\t\ttext-align: left;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\n\t\t\tdiv {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 16px;\n\t\t\t\twidth: 24px;\n\t\t\t\theight: 24px;\n\t\t\t\tbackground-size: 24px;\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\tborder-color: var(--color-primary);\n\t\t\t}\n\t\t}\n\n\t\t// Do not invert status icons\n\t\t&:not(.panel-status) label div {\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\n\t\tinput[type='checkbox'].checkbox + label:before {\n\t\t\tposition: absolute;\n\t\t\tright: 12px;\n\t\t\ttop: 16px;\n\t\t}\n\n\t\tinput:focus + label {\n\t\t\tborder-color: var(--color-primary);\n\t\t}\n\t}\n\n\th3 {\n\t\tfont-weight: bold;\n\n\t\t&:not(:first-of-type) {\n\t\t\tmargin-top: 64px;\n\t\t}\n\t}\n\n\t// Adjust design of 'Get more widgets' button\n\t.button {\n\t\tdisplay: inline-block;\n\t\tpadding: 10px 16px;\n\t\tmargin: 0;\n\t}\n\n\tp {\n\t\tmax-width: 650px;\n\t\tmargin: 0 auto;\n\n\t\ta:hover,\n\t\ta:focus {\n\t\t\tborder-bottom: 2px solid var(--color-border);\n\t\t}\n\t}\n\n\t.credits--end {\n\t\tpadding-bottom: 32px;\n\t\tcolor: var(--color-text-maxcontrast);\n\n\t\ta {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\t}\n}\n\n.flip-list-move {\n\ttransition: transform var(--animation-slow);\n}\n\n.statuses {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\tflex-wrap: wrap;\n\tmargin-bottom: 36px;\n\n\t& > div {\n\t\tmargin: 8px;\n\t}\n}\n</style>\n<style>\nhtml, body {\n\tbackground-attachment: fixed;\n}\n\n#body-user #header {\n\tposition: fixed;\n}\n\n#content {\n\toverflow: auto;\n\tposition: static !important;;\n}\n</style>\n"],sourceRoot:""}]),n.Z=i}},a={};function o(t){var n=a[t];if(void 0!==n)return n.exports;var r=a[t]={id:t,loaded:!1,exports:{}};return e[t].call(r.exports,r,r.exports,o),r.loaded=!0,r.exports}o.m=e,o.amdD=function(){throw new Error("define cannot be used indirect")},o.amdO={},n=[],o.O=function(t,e,a,r){if(!e){var i=1/0;for(c=0;c<n.length;c++){e=n[c][0],a=n[c][1],r=n[c][2];for(var s=!0,d=0;d<e.length;d++)(!1&r||i>=r)&&Object.keys(o.O).every((function(t){return o.O[t](e[d])}))?e.splice(d--,1):(s=!1,r<i&&(i=r));if(s){n.splice(c--,1);var l=a();void 0!==l&&(t=l)}}return t}r=r||0;for(var c=n.length;c>0&&n[c-1][2]>r;c--)n[c]=n[c-1];n[c]=[e,a,r]},o.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(n,{a:n}),n},o.d=function(t,n){for(var e in n)o.o(n,e)&&!o.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),o.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.nmd=function(t){return t.paths=[],t.children||(t.children=[]),t},o.j=4773,function(){o.b=document.baseURI||self.location.href;var t={4773:0};o.O.j=function(n){return 0===t[n]};var n=function(n,e){var a,r,i=e[0],s=e[1],d=e[2],l=0;if(i.some((function(n){return 0!==t[n]}))){for(a in s)o.o(s,a)&&(o.m[a]=s[a]);if(d)var c=d(o)}for(n&&n(e);l<i.length;l++)r=i[l],o.o(t,r)&&t[r]&&t[r][0](),t[r]=0;return o.O(c)},e=self.webpackChunknextcloud=self.webpackChunknextcloud||[];e.forEach(n.bind(null,0)),e.push=n.bind(null,e.push.bind(e))}(),o.nc=void 0;var r=o.O(void 0,[7874],(function(){return o(18719)}));r=o.O(r)}();
-//# sourceMappingURL=dashboard-main.js.map?v=cfaa13fca1577c385601
\ No newline at end of file
+!function(){"use strict";var n,e={31853:function(n,e,a){var o=a(20144),i=a(79753),r=a(22200),s=a(16453),d=a(4820),l=a(10861),c=a.n(l),u=a(9980),p=a.n(u),A=a(70110),h=a.n(A),g=a(91482),b={data:function(){return{isMobile:this._isMobile()}},beforeMount:function(){window.addEventListener("resize",this._onResize)},beforeDestroy:function(){window.removeEventListener("resize",this._onResize)},methods:{_onResize:function(){this.isMobile=this._isMobile()},_isMobile:function(){return document.documentElement.clientWidth<768}}},m=function(t){return(0,i.generateFilePath)("theming","","img/background/")+t},f=(0,s.loadState)("dashboard","panels"),v=(0,s.loadState)("dashboard","firstRun"),C=(0,s.loadState)("theming","background"),x=(0,s.loadState)("theming","backgroundVersion"),k=(0,s.loadState)("theming","themingDefaultBackground"),y=(0,s.loadState)("theming","shippedBackgrounds"),w={weather:{text:t("dashboard","Weather"),icon:"icon-weather-status"},status:{text:t("dashboard","Status"),icon:"icon-user-status-online"}},S={name:"DashboardApp",components:{NcButton:c(),Draggable:p(),NcModal:h(),Pencil:g.default},mixins:[b],data:function(){var t,n;return{isAdmin:(0,r.getCurrentUser)().isAdmin,timer:new Date,registeredStatus:[],callbacks:{},callbacksStatus:{},allCallbacksStatus:{},statusInfo:w,enabledStatuses:(0,s.loadState)("dashboard","statuses"),panels:f,firstRun:v,displayName:null===(t=(0,r.getCurrentUser)())||void 0===t?void 0:t.displayName,uid:null===(n=(0,r.getCurrentUser)())||void 0===n?void 0:n.uid,layout:(0,s.loadState)("dashboard","layout").filter((function(t){return f[t]})),modal:!1,appStoreUrl:(0,i.generateUrl)("/settings/apps/dashboard"),statuses:{},background:C,themingDefaultBackground:k}},computed:{backgroundImage:function(){return function(t){var n,e,a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",r=(null===(n=window.OCA)||void 0===n||null===(e=n.Theming)||void 0===e?void 0:e.enabledThemes)||[],s=0===r.length||"default"===r[0]?window.matchMedia("(prefers-color-scheme: dark)").matches:-1!==r.join("").indexOf("dark");return"default"===t?o&&"backgroundColor"!==o?(0,i.generateUrl)("/apps/theming/image/background")+"?v="+window.OCA.Theming.cacheBuster:m(s?"eduardo-neves-pedra-azul.jpg":"kamil-porembinski-clouds.jpg"):"custom"===t?(0,i.generateUrl)("/apps/theming/background")+"?v="+a:m(t)}(this.background,x,this.themingDefaultBackground)},backgroundStyle:function(){return"default"===this.background&&"backgroundColor"===this.themingDefaultBackground||this.background.match(/#[0-9A-Fa-f]{6}/g)?null:{backgroundImage:"default"===this.background?"var(--image-main-background)":"url('".concat(this.backgroundImage,"')")}},greeting:function(){var n,e=this.timer.getHours();n=e>=22||e<5?"night":e>=18?"evening":e>=12?"afternoon":"morning";var a={morning:{generic:t("dashboard","Good morning"),withName:t("dashboard","Good morning, {name}",{name:this.displayName},void 0,{escape:!1})},afternoon:{generic:t("dashboard","Good afternoon"),withName:t("dashboard","Good afternoon, {name}",{name:this.displayName},void 0,{escape:!1})},evening:{generic:t("dashboard","Good evening"),withName:t("dashboard","Good evening, {name}",{name:this.displayName},void 0,{escape:!1})},night:{generic:t("dashboard","Hello"),withName:t("dashboard","Hello, {name}",{name:this.displayName},void 0,{escape:!1})}};return{text:this.displayName&&this.uid!==this.displayName?a[n].withName:a[n].generic}},isActive:function(){var t=this;return function(n){return t.layout.indexOf(n.id)>-1}},isStatusActive:function(){var t=this;return function(n){return!(n in t.enabledStatuses)||t.enabledStatuses[n]}},sortedAllStatuses:function(){return Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)},sortedPanels:function(){var t=this;return Object.values(this.panels).sort((function(n,e){var a=t.layout.indexOf(n.id),o=t.layout.indexOf(e.id);return-1===a||-1===o?o-a||n.id-e.id:a-o||n.id-e.id}))},sortedRegisteredStatus:function(){return this.registeredStatus.slice().sort(this.sortStatuses)}},watch:{callbacks:function(){this.rerenderPanels()},callbacksStatus:function(){for(var t in this.callbacksStatus){var n=this.$refs["status-"+t];this.statuses[t]&&this.statuses[t].mounted||(n?(this.callbacksStatus[t](n[0]),o.ZP.set(this.statuses,t,{mounted:!0})):console.error("Failed to register panel in the frontend as no backend data was provided for "+t))}}},mounted:function(){var t=this;this.updateGlobalStyles(),this.updateSkipLink(),window.addEventListener("scroll",this.handleScroll),setInterval((function(){t.timer=new Date}),3e4),this.firstRun&&window.addEventListener("scroll",this.disableFirstrunHint)},destroyed:function(){window.removeEventListener("scroll",this.handleScroll)},methods:{updateGlobalStyles:function(){var t;"dark"===(null===(t=y[this.background])||void 0===t?void 0:t.theming)?(document.querySelector("#header").style.setProperty("--primary-invert-if-bright","invert(100%)"),document.querySelector("#header").style.setProperty("--color-primary-text","#000000")):(document.querySelector("#header").style.setProperty("--primary-invert-if-bright","no"),document.querySelector("#header").style.setProperty("--color-primary-text","#ffffff"));for(var n=0,e=[document.documentElement,document.querySelector("#header"),document.querySelector("body")];n<e.length;n++){var a=e[n];"default"===this.background?a.style.setProperty("--image-main-background","url('".concat((0,i.imagePath)("core","app-background.jpg"),"')")):this.background.match(/#[0-9A-Fa-f]{6}/g)?a.style.setProperty("--image-main-background",void 0):a.style.setProperty("--image-main-background",this.backgroundStyle.backgroundImage)}},register:function(t,n){o.ZP.set(this.callbacks,t,n)},registerStatus:function(t,n){var e=this;o.ZP.set(this.allCallbacksStatus,t,n),this.isStatusActive(t)&&(this.registeredStatus.push(t),this.$nextTick((function(){o.ZP.set(e.callbacksStatus,t,n)})))},rerenderPanels:function(){for(var t in this.callbacks){var n=this.$refs[t];-1!==this.layout.indexOf(t)&&(this.panels[t]&&this.panels[t].mounted||(n?(this.callbacks[t](n[0],{widget:this.panels[t]}),o.ZP.set(this.panels[t],"mounted",!0)):console.error("Failed to register panel in the frontend as no backend data was provided for "+t)))}},saveLayout:function(){d.default.post((0,i.generateUrl)("/apps/dashboard/layout"),{layout:this.layout.join(",")})},saveStatuses:function(){d.default.post((0,i.generateUrl)("/apps/dashboard/statuses"),{statuses:JSON.stringify(this.enabledStatuses)})},showModal:function(){this.modal=!0,this.firstRun=!1},closeModal:function(){this.modal=!1},updateCheckbox:function(t,n){var e=this,a=this.layout.indexOf(t.id);!n&&a>-1?this.layout.splice(a,1):this.layout.push(t.id),o.ZP.set(this.panels[t.id],"mounted",!1),this.saveLayout(),this.$nextTick((function(){return e.rerenderPanels()}))},disableFirstrunHint:function(){var t=this;window.removeEventListener("scroll",this.disableFirstrunHint),setTimeout((function(){t.firstRun=!1}),1e3)},updateSkipLink:function(){document.getElementsByClassName("skip-navigation")[0].setAttribute("href","#app-dashboard")},updateStatusCheckbox:function(t,n){n?this.enableStatus(t):this.disableStatus(t)},enableStatus:function(t){this.enabledStatuses[t]=!0,this.registerStatus(t,this.allCallbacksStatus[t]),this.saveStatuses()},disableStatus:function(t){var n=this;this.enabledStatuses[t]=!1;var e=this.registeredStatus.findIndex((function(n){return n===t}));-1!==e&&(this.registeredStatus.splice(e,1),o.ZP.set(this.statuses,t,{mounted:!1}),this.$nextTick((function(){o.ZP.delete(n.callbacksStatus,t)}))),this.saveStatuses()},sortStatuses:function(t,n){var e=t.toLowerCase(),a=n.toLowerCase();return e>a?1:e<a?-1:0},handleScroll:function(){window.scrollY>70?document.body.classList.add("dashboard--scrolled"):document.body.classList.remove("dashboard--scrolled")}}},_=S,B=a(93379),D=a.n(B),O=a(7795),P=a.n(O),N=a(90569),E=a.n(N),F=a(3565),T=a.n(F),G=a(19216),I=a.n(G),j=a(44589),z=a.n(j),L=a(59054),M={};M.styleTagTransform=z(),M.setAttributes=T(),M.insert=E().bind(null,"head"),M.domAPI=P(),M.insertStyleElement=I(),D()(L.Z,M),L.Z&&L.Z.locals&&L.Z.locals;var U=a(73729),q={};q.styleTagTransform=z(),q.setAttributes=T(),q.insert=E().bind(null,"head"),q.domAPI=P(),q.insertStyleElement=I(),D()(U.Z,q),U.Z&&U.Z.locals&&U.Z.locals;var R=(0,a(51900).Z)(_,(function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",{attrs:{id:"app-dashboard"}},[e("h2",[t._v(t._s(t.greeting.text))]),t._v(" "),e("ul",{staticClass:"statuses"},t._l(t.sortedRegisteredStatus,(function(t){return e("div",{key:t,attrs:{id:"status-"+t}},[e("div",{ref:"status-"+t,refInFor:!0})])})),0),t._v(" "),e("Draggable",t._b({staticClass:"panels",attrs:{handle:".panel--header"},on:{end:t.saveLayout},model:{value:t.layout,callback:function(n){t.layout=n},expression:"layout"}},"Draggable",{swapThreshold:.3,delay:500,delayOnTouchOnly:!0,touchStartThreshold:3},!1),t._l(t.layout,(function(n){return e("div",{key:t.panels[n].id,staticClass:"panel"},[e("div",{staticClass:"panel--header"},[e("h2",[e("div",{class:t.panels[n].iconClass,attrs:{role:"img"}}),t._v("\n\t\t\t\t\t"+t._s(t.panels[n].title)+"\n\t\t\t\t")])]),t._v(" "),e("div",{staticClass:"panel--content",class:{loading:!t.panels[n].mounted}},[e("div",{ref:t.panels[n].id,refInFor:!0,attrs:{"data-id":t.panels[n].id}})])])})),0),t._v(" "),e("div",{staticClass:"footer"},[e("NcButton",{on:{click:t.showModal},scopedSlots:t._u([{key:"icon",fn:function(){return[e("Pencil",{attrs:{size:20}})]},proxy:!0}])},[t._v("\n\t\t\t"+t._s(t.t("dashboard","Customize"))+"\n\t\t")])],1),t._v(" "),t.modal?e("NcModal",{attrs:{size:"large"},on:{close:t.closeModal}},[e("div",{staticClass:"modal__content"},[e("h3",[t._v(t._s(t.t("dashboard","Edit widgets")))]),t._v(" "),e("ol",{staticClass:"panels"},t._l(t.sortedAllStatuses,(function(n){return e("li",{key:n,class:"panel-"+n},[e("input",{staticClass:"checkbox",attrs:{id:"status-checkbox-"+n,type:"checkbox"},domProps:{checked:t.isStatusActive(n)},on:{input:function(e){return t.updateStatusCheckbox(n,e.target.checked)}}}),t._v(" "),e("label",{attrs:{for:"status-checkbox-"+n}},[e("div",{class:t.statusInfo[n].icon,attrs:{role:"img"}}),t._v("\n\t\t\t\t\t\t"+t._s(t.statusInfo[n].text)+"\n\t\t\t\t\t")])])})),0),t._v(" "),e("Draggable",t._b({staticClass:"panels",attrs:{tag:"ol",handle:".draggable"},on:{end:t.saveLayout},model:{value:t.layout,callback:function(n){t.layout=n},expression:"layout"}},"Draggable",{swapThreshold:.3,delay:500,delayOnTouchOnly:!0,touchStartThreshold:3},!1),t._l(t.sortedPanels,(function(n){return e("li",{key:n.id,class:"panel-"+n.id},[e("input",{staticClass:"checkbox",attrs:{id:"panel-checkbox-"+n.id,type:"checkbox"},domProps:{checked:t.isActive(n)},on:{input:function(e){return t.updateCheckbox(n,e.target.checked)}}}),t._v(" "),e("label",{class:{draggable:t.isActive(n)},attrs:{for:"panel-checkbox-"+n.id}},[e("div",{class:n.iconClass,attrs:{role:"img"}}),t._v("\n\t\t\t\t\t\t"+t._s(n.title)+"\n\t\t\t\t\t")])])})),0),t._v(" "),t.isAdmin?e("a",{staticClass:"button",attrs:{href:t.appStoreUrl}},[t._v(t._s(t.t("dashboard","Get more widgets from the App Store")))]):t._e(),t._v(" "),e("h3",[t._v(t._s(t.t("dashboard","Weather service")))]),t._v(" "),e("p",[t._v("\n\t\t\t\t"+t._s(t.t("dashboard","For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information."))+"\n\t\t\t")]),t._v(" "),e("p",{staticClass:"credits--end"},[e("a",{attrs:{href:"https://api.met.no/doc/TermsOfService",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","Weather data from Met.no")))]),t._v(",\n\t\t\t\t"),e("a",{attrs:{href:"https://wiki.osmfoundation.org/wiki/Privacy_Policy",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","geocoding with Nominatim")))]),t._v(",\n\t\t\t\t"),e("a",{attrs:{href:"https://www.opentopodata.org/#public-api",target:"_blank",rel:"noopener"}},[t._v(t._s(t.t("dashboard","elevation data from OpenTopoData")))]),t._v(".\n\t\t\t")])],1)]):t._e()],1)}),[],!1,null,"55a1daf8",null).exports,W=a(9944),Z=a(15168),H=a.n(Z);a.nc=btoa((0,r.getRequestToken)()),o.ZP.directive("Tooltip",H()),o.ZP.prototype.t=W.translate,window.OCA.Files||(window.OCA.Files={}),Object.assign(window.OCA.Files,{App:{fileList:{filesClient:OC.Files.getClient()}}},window.OCA.Files);var $=new(o.ZP.extend(R))({}).$mount("#app-content-vue");window.OCA.Dashboard={register:function(t,n){return $.register(t,n)},registerStatus:function(t,n){return $.registerStatus(t,n)}}},59054:function(t,n,e){var a=e(87537),o=e.n(a),i=e(23645),r=e.n(i)()(o());r.push([t.id,"#app-dashboard[data-v-55a1daf8]{width:100%;min-height:100%;background-size:cover;background-position:center center;background-repeat:no-repeat;background-attachment:fixed}#app-dashboard>h2[data-v-55a1daf8]{color:var(--color-primary-text);text-align:center;font-size:32px;line-height:130%;padding:1rem 0}.panels[data-v-55a1daf8]{width:auto;margin:auto;max-width:1500px;display:flex;justify-content:center;flex-direction:row;align-items:flex-start;flex-wrap:wrap}.panel[data-v-55a1daf8],.panels>div[data-v-55a1daf8]{width:320px;max-width:100%;margin:16px;background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);border-radius:var(--border-radius-large)}#body-user.theme--highcontrast .panel[data-v-55a1daf8],#body-user.theme--highcontrast .panels>div[data-v-55a1daf8]{border:2px solid var(--color-border)}.panel.sortable-ghost[data-v-55a1daf8],.panels>div.sortable-ghost[data-v-55a1daf8]{opacity:.1}.panel>.panel--header[data-v-55a1daf8],.panels>div>.panel--header[data-v-55a1daf8]{display:flex;z-index:1;top:50px;padding:16px;cursor:grab}.panel>.panel--header[data-v-55a1daf8],.panel>.panel--header[data-v-55a1daf8] *,.panels>div>.panel--header[data-v-55a1daf8],.panels>div>.panel--header[data-v-55a1daf8] *{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.panel>.panel--header[data-v-55a1daf8]:active,.panels>div>.panel--header[data-v-55a1daf8]:active{cursor:grabbing}.panel>.panel--header a[data-v-55a1daf8],.panels>div>.panel--header a[data-v-55a1daf8]{flex-grow:1}.panel>.panel--header>h2[data-v-55a1daf8],.panels>div>.panel--header>h2[data-v-55a1daf8]{display:block;align-items:center;flex-grow:1;margin:0;font-size:20px;line-height:24px;font-weight:bold;padding:16px 8px;height:56px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:grab}.panel>.panel--header>h2 div[data-v-55a1daf8],.panels>div>.panel--header>h2 div[data-v-55a1daf8]{background-size:32px;width:32px;height:32px;margin-right:16px;background-position:center;float:left}.panel>.panel--content[data-v-55a1daf8],.panels>div>.panel--content[data-v-55a1daf8]{margin:0 16px 16px 16px;height:424px;overflow:visible}@media only screen and (max-width: 709px){.panel>.panel--content[data-v-55a1daf8],.panels>div>.panel--content[data-v-55a1daf8]{height:auto}}.footer[data-v-55a1daf8]{display:flex;justify-content:center;transition:bottom var(--animation-slow) ease-in-out;padding:1rem 0}.edit-panels[data-v-55a1daf8]{display:inline-block;margin:auto;background-position:16px center;padding:12px 16px;padding-left:36px;border-radius:var(--border-radius-pill);max-width:200px;opacity:1;text-align:center}.button[data-v-55a1daf8],.button-vue[data-v-55a1daf8],.edit-panels[data-v-55a1daf8],.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle{background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);opacity:1 !important}.button[data-v-55a1daf8]:hover,.button[data-v-55a1daf8]:focus,.button[data-v-55a1daf8]:active,.button-vue[data-v-55a1daf8]:hover,.button-vue[data-v-55a1daf8]:focus,.button-vue[data-v-55a1daf8]:active,.edit-panels[data-v-55a1daf8]:hover,.edit-panels[data-v-55a1daf8]:focus,.edit-panels[data-v-55a1daf8]:active,.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle:hover,.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle:focus,.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle:active,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle:hover,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle:focus,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle:active{background-color:var(--color-background-hover) !important}.button[data-v-55a1daf8]:focus-visible,.button-vue[data-v-55a1daf8]:focus-visible,.edit-panels[data-v-55a1daf8]:focus-visible,.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle:focus-visible,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle:focus-visible{box-shadow:0 0 0 2px var(--color-main-text) !important}.modal__content[data-v-55a1daf8]{padding:32px 16px;text-align:center}.modal__content ol[data-v-55a1daf8]{display:flex;flex-direction:row;justify-content:center;list-style-type:none;padding-bottom:16px}.modal__content li label[data-v-55a1daf8]{position:relative;display:block;padding:48px 16px 14px 16px;margin:8px;width:140px;background-color:var(--color-background-hover);border:2px solid var(--color-main-background);border-radius:var(--border-radius-large);text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.modal__content li label div[data-v-55a1daf8]{position:absolute;top:16px;width:24px;height:24px;background-size:24px}.modal__content li label[data-v-55a1daf8]:hover{border-color:var(--color-primary)}.modal__content li:not(.panel-status) label div[data-v-55a1daf8]{filter:var(--background-invert-if-dark)}.modal__content li input[type=checkbox].checkbox+label[data-v-55a1daf8]:before{position:absolute;right:12px;top:16px}.modal__content li input:focus+label[data-v-55a1daf8]{border-color:var(--color-primary)}.modal__content h3[data-v-55a1daf8]{font-weight:bold}.modal__content h3[data-v-55a1daf8]:not(:first-of-type){margin-top:64px}.modal__content .button[data-v-55a1daf8]{display:inline-block;padding:10px 16px;margin:0}.modal__content p[data-v-55a1daf8]{max-width:650px;margin:0 auto}.modal__content p a[data-v-55a1daf8]:hover,.modal__content p a[data-v-55a1daf8]:focus{border-bottom:2px solid var(--color-border)}.modal__content .credits--end[data-v-55a1daf8]{padding-bottom:32px;color:var(--color-text-maxcontrast)}.modal__content .credits--end a[data-v-55a1daf8]{color:var(--color-text-maxcontrast)}.flip-list-move[data-v-55a1daf8]{transition:transform var(--animation-slow)}.statuses[data-v-55a1daf8]{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap;margin-bottom:36px}.statuses>div[data-v-55a1daf8]{margin:8px}","",{version:3,sources:["webpack://./apps/dashboard/src/DashboardApp.vue"],names:[],mappings:"AAuaA,gCACC,UAAA,CACA,eAAA,CACA,qBAAA,CACA,iCAAA,CACA,2BAAA,CACA,2BAAA,CAEA,mCACC,+BAAA,CACA,iBAAA,CACA,cAAA,CACA,gBAAA,CACA,cAAA,CAIF,yBACC,UAAA,CACA,WAAA,CACA,gBAAA,CACA,YAAA,CACA,sBAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CAGD,qDACC,WAAA,CACA,cAAA,CACA,WAAA,CACA,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,wCAAA,CAEA,mHACC,oCAAA,CAGD,mFACE,UAAA,CAGF,mFACC,YAAA,CACA,SAAA,CACA,QAAA,CACA,YAAA,CACA,WAAA,CAEA,4KACC,0BAAA,CACA,wBAAA,CACA,uBAAA,CACA,qBAAA,CACA,oBAAA,CACA,gBAAA,CAGD,iGACC,eAAA,CAGD,uFACC,WAAA,CAGD,yFACC,aAAA,CACA,kBAAA,CACA,WAAA,CACA,QAAA,CACA,cAAA,CACA,gBAAA,CACA,gBAAA,CACA,gBAAA,CACA,WAAA,CACA,kBAAA,CACA,eAAA,CACA,sBAAA,CACA,WAAA,CACA,iGACC,oBAAA,CACA,UAAA,CACA,WAAA,CACA,iBAAA,CACA,0BAAA,CACA,UAAA,CAKH,qFACC,uBAAA,CACA,YAAA,CAEA,gBAAA,CAID,0CACC,qFACC,WAAA,CAAA,CAKH,yBACC,YAAA,CACA,sBAAA,CACA,mDAAA,CACA,cAAA,CAGD,8BACC,oBAAA,CACA,WAAA,CACA,+BAAA,CACA,iBAAA,CACA,iBAAA,CACA,uCAAA,CACA,eAAA,CACA,SAAA,CACA,iBAAA,CAGD,0OAKC,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,oBAAA,CAEA,6xBAGC,yDAAA,CAED,gTACC,sDAAA,CAIF,iCACC,iBAAA,CACA,iBAAA,CAEA,oCACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,oBAAA,CACA,mBAAA,CAGA,0CACC,iBAAA,CACA,aAAA,CACA,2BAAA,CACA,UAAA,CACA,WAAA,CACA,8CAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CACA,eAAA,CACA,sBAAA,CACA,kBAAA,CAEA,8CACC,iBAAA,CACA,QAAA,CACA,UAAA,CACA,WAAA,CACA,oBAAA,CAGD,gDACC,iCAAA,CAKF,iEACC,uCAAA,CAGD,+EACC,iBAAA,CACA,UAAA,CACA,QAAA,CAGD,sDACC,iCAAA,CAIF,oCACC,gBAAA,CAEA,wDACC,eAAA,CAKF,yCACC,oBAAA,CACA,iBAAA,CACA,QAAA,CAGD,mCACC,eAAA,CACA,aAAA,CAEA,sFAEC,2CAAA,CAIF,+CACC,mBAAA,CACA,mCAAA,CAEA,iDACC,mCAAA,CAKH,iCACC,0CAAA,CAGD,2BACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACA,kBAAA,CAEA,+BACC,UAAA",sourcesContent:["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n#app-dashboard {\n\twidth: 100%;\n\tmin-height: 100%;\n\tbackground-size: cover;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\tbackground-attachment: fixed;\n\n\t> h2 {\n\t\tcolor: var(--color-primary-text);\n\t\ttext-align: center;\n\t\tfont-size: 32px;\n\t\tline-height: 130%;\n\t\tpadding: 1rem 0;\n\t}\n}\n\n.panels {\n\twidth: auto;\n\tmargin: auto;\n\tmax-width: 1500px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tflex-wrap: wrap;\n}\n\n.panel, .panels > div {\n\twidth: 320px;\n\tmax-width: 100%;\n\tmargin: 16px;\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\tborder-radius: var(--border-radius-large);\n\n\t#body-user.theme--highcontrast & {\n\t\tborder: 2px solid var(--color-border);\n\t}\n\n\t&.sortable-ghost {\n\t\t opacity: 0.1;\n\t}\n\n\t& > .panel--header {\n\t\tdisplay: flex;\n\t\tz-index: 1;\n\t\ttop: 50px;\n\t\tpadding: 16px;\n\t\tcursor: grab;\n\n\t\t&, ::v-deep * {\n\t\t\t-webkit-touch-callout: none;\n\t\t\t-webkit-user-select: none;\n\t\t\t-khtml-user-select: none;\n\t\t\t-moz-user-select: none;\n\t\t\t-ms-user-select: none;\n\t\t\tuser-select: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tcursor: grabbing;\n\t\t}\n\n\t\ta {\n\t\t\tflex-grow: 1;\n\t\t}\n\n\t\t> h2 {\n\t\t\tdisplay: block;\n\t\t\talign-items: center;\n\t\t\tflex-grow: 1;\n\t\t\tmargin: 0;\n\t\t\tfont-size: 20px;\n\t\t\tline-height: 24px;\n\t\t\tfont-weight: bold;\n\t\t\tpadding: 16px 8px;\n\t\t\theight: 56px;\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: grab;\n\t\t\tdiv {\n\t\t\t\tbackground-size: 32px;\n\t\t\t\twidth: 32px;\n\t\t\t\theight: 32px;\n\t\t\t\tmargin-right: 16px;\n\t\t\t\tbackground-position: center;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .panel--content {\n\t\tmargin: 0 16px 16px 16px;\n\t\theight: 424px;\n\t\t// We specifically do not want scrollbars inside widgets\n\t\toverflow: visible;\n\t}\n\n\t// No need to extend height of widgets if only one column is shown\n\t@media only screen and (max-width: 709px) {\n\t\t& > .panel--content {\n\t\t\theight: auto;\n\t\t}\n\t}\n}\n\n.footer {\n\tdisplay: flex;\n\tjustify-content: center;\n\ttransition: bottom var(--animation-slow) ease-in-out;\n\tpadding: 1rem 0;\n}\n\n.edit-panels {\n\tdisplay: inline-block;\n\tmargin:auto;\n\tbackground-position: 16px center;\n\tpadding: 12px 16px;\n\tpadding-left: 36px;\n\tborder-radius: var(--border-radius-pill);\n\tmax-width: 200px;\n\topacity: 1;\n\ttext-align: center;\n}\n\n.button,\n.button-vue,\n.edit-panels,\n.statuses ::v-deep .action-item .action-item__menutoggle,\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\topacity: 1 !important;\n\n\t&:hover,\n\t&:focus,\n\t&:active {\n\t\tbackground-color: var(--color-background-hover)!important;\n\t}\n\t&:focus-visible {\n\t\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\n\t}\n}\n\n.modal__content {\n\tpadding: 32px 16px;\n\ttext-align: center;\n\n\tol {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tjustify-content: center;\n\t\tlist-style-type: none;\n\t\tpadding-bottom: 16px;\n\t}\n\tli {\n\t\tlabel {\n\t\t\tposition: relative;\n\t\t\tdisplay: block;\n\t\t\tpadding: 48px 16px 14px 16px;\n\t\t\tmargin: 8px;\n\t\t\twidth: 140px;\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t\tborder: 2px solid var(--color-main-background);\n\t\t\tborder-radius: var(--border-radius-large);\n\t\t\ttext-align: left;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\n\t\t\tdiv {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 16px;\n\t\t\t\twidth: 24px;\n\t\t\t\theight: 24px;\n\t\t\t\tbackground-size: 24px;\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\tborder-color: var(--color-primary);\n\t\t\t}\n\t\t}\n\n\t\t// Do not invert status icons\n\t\t&:not(.panel-status) label div {\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\n\t\tinput[type='checkbox'].checkbox + label:before {\n\t\t\tposition: absolute;\n\t\t\tright: 12px;\n\t\t\ttop: 16px;\n\t\t}\n\n\t\tinput:focus + label {\n\t\t\tborder-color: var(--color-primary);\n\t\t}\n\t}\n\n\th3 {\n\t\tfont-weight: bold;\n\n\t\t&:not(:first-of-type) {\n\t\t\tmargin-top: 64px;\n\t\t}\n\t}\n\n\t// Adjust design of 'Get more widgets' button\n\t.button {\n\t\tdisplay: inline-block;\n\t\tpadding: 10px 16px;\n\t\tmargin: 0;\n\t}\n\n\tp {\n\t\tmax-width: 650px;\n\t\tmargin: 0 auto;\n\n\t\ta:hover,\n\t\ta:focus {\n\t\t\tborder-bottom: 2px solid var(--color-border);\n\t\t}\n\t}\n\n\t.credits--end {\n\t\tpadding-bottom: 32px;\n\t\tcolor: var(--color-text-maxcontrast);\n\n\t\ta {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\t}\n}\n\n.flip-list-move {\n\ttransition: transform var(--animation-slow);\n}\n\n.statuses {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\tflex-wrap: wrap;\n\tmargin-bottom: 36px;\n\n\t& > div {\n\t\tmargin: 8px;\n\t}\n}\n"],sourceRoot:""}]),n.Z=r},73729:function(t,n,e){var a=e(87537),o=e.n(a),i=e(23645),r=e.n(i)()(o());r.push([t.id,"\nhtml, body {\n\tbackground-attachment: fixed;\n}\n#body-user #header {\n\tposition: fixed;\n}\n#content {\n\toverflow: auto;\n\tposition: static !important;\n}\n","",{version:3,sources:["webpack://./apps/dashboard/src/DashboardApp.vue"],names:[],mappings:";AAsqBA;CACA,4BAAA;AACA;AAEA;CACA,eAAA;AACA;AAEA;CACA,cAAA;CACA,2BAAA;AACA",sourcesContent:["<template>\n\t<div id=\"app-dashboard\">\n\t\t<h2>{{ greeting.text }}</h2>\n\t\t<ul class=\"statuses\">\n\t\t\t<div v-for=\"status in sortedRegisteredStatus\"\n\t\t\t\t:id=\"'status-' + status\"\n\t\t\t\t:key=\"status\">\n\t\t\t\t<div :ref=\"'status-' + status\" />\n\t\t\t</div>\n\t\t</ul>\n\n\t\t<Draggable v-model=\"layout\"\n\t\t\tclass=\"panels\"\n\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\thandle=\".panel--header\"\n\t\t\t@end=\"saveLayout\">\n\t\t\t<div v-for=\"panelId in layout\" :key=\"panels[panelId].id\" class=\"panel\">\n\t\t\t\t<div class=\"panel--header\">\n\t\t\t\t\t<h2>\n\t\t\t\t\t\t<div :class=\"panels[panelId].iconClass\" role=\"img\" />\n\t\t\t\t\t\t{{ panels[panelId].title }}\n\t\t\t\t\t</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"panel--content\" :class=\"{ loading: !panels[panelId].mounted }\">\n\t\t\t\t\t<div :ref=\"panels[panelId].id\" :data-id=\"panels[panelId].id\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Draggable>\n\n\t\t<div class=\"footer\">\n\t\t\t<NcButton @click=\"showModal\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('dashboard', 'Customize') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcModal v-if=\"modal\" size=\"large\" @close=\"closeModal\">\n\t\t\t<div class=\"modal__content\">\n\t\t\t\t<h3>{{ t('dashboard', 'Edit widgets') }}</h3>\n\t\t\t\t<ol class=\"panels\">\n\t\t\t\t\t<li v-for=\"status in sortedAllStatuses\" :key=\"status\" :class=\"'panel-' + status\">\n\t\t\t\t\t\t<input :id=\"'status-checkbox-' + status\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isStatusActive(status)\"\n\t\t\t\t\t\t\t@input=\"updateStatusCheckbox(status, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'status-checkbox-' + status\">\n\t\t\t\t\t\t\t<div :class=\"statusInfo[status].icon\" role=\"img\" />\n\t\t\t\t\t\t\t{{ statusInfo[status].text }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</ol>\n\t\t\t\t<Draggable v-model=\"layout\"\n\t\t\t\t\tclass=\"panels\"\n\t\t\t\t\ttag=\"ol\"\n\t\t\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\t\t\thandle=\".draggable\"\n\t\t\t\t\t@end=\"saveLayout\">\n\t\t\t\t\t<li v-for=\"panel in sortedPanels\" :key=\"panel.id\" :class=\"'panel-' + panel.id\">\n\t\t\t\t\t\t<input :id=\"'panel-checkbox-' + panel.id\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isActive(panel)\"\n\t\t\t\t\t\t\t@input=\"updateCheckbox(panel, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'panel-checkbox-' + panel.id\" :class=\"{ draggable: isActive(panel) }\">\n\t\t\t\t\t\t\t<div :class=\"panel.iconClass\" role=\"img\" />\n\t\t\t\t\t\t\t{{ panel.title }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</Draggable>\n\n\t\t\t\t<a v-if=\"isAdmin\" :href=\"appStoreUrl\" class=\"button\">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>\n\n\t\t\t\t<h3>{{ t('dashboard', 'Weather service') }}</h3>\n\t\t\t\t<p>\n\t\t\t\t\t{{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}\n\t\t\t\t</p>\n\t\t\t\t<p class=\"credits--end\">\n\t\t\t\t\t<a href=\"https://api.met.no/doc/TermsOfService\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'Weather data from Met.no') }}</a>,\n\t\t\t\t\t<a href=\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'geocoding with Nominatim') }}</a>,\n\t\t\t\t\t<a href=\"https://www.opentopodata.org/#public-api\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'elevation data from OpenTopoData') }}</a>.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcModal>\n\t</div>\n</template>\n\n<script>\nimport { generateUrl, imagePath } from '@nextcloud/router'\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { loadState } from '@nextcloud/initial-state'\nimport axios from '@nextcloud/axios'\nimport NcButton from '@nextcloud/vue/dist/Components/NcButton'\nimport Draggable from 'vuedraggable'\nimport NcModal from '@nextcloud/vue/dist/Components/NcModal'\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\nimport Vue from 'vue'\n\nimport isMobile from './mixins/isMobile.js'\nimport { getBackgroundUrl } from './helpers/getBackgroundUrl.js'\n\nconst panels = loadState('dashboard', 'panels')\nconst firstRun = loadState('dashboard', 'firstRun')\n\nconst background = loadState('theming', 'background')\nconst backgroundVersion = loadState('theming', 'backgroundVersion')\nconst themingDefaultBackground = loadState('theming', 'themingDefaultBackground')\nconst shippedBackgroundList = loadState('theming', 'shippedBackgrounds')\n\nconst statusInfo = {\n\tweather: {\n\t\ttext: t('dashboard', 'Weather'),\n\t\ticon: 'icon-weather-status',\n\t},\n\tstatus: {\n\t\ttext: t('dashboard', 'Status'),\n\t\ticon: 'icon-user-status-online',\n\t},\n}\n\nexport default {\n\tname: 'DashboardApp',\n\tcomponents: {\n\t\tNcButton,\n\t\tDraggable,\n\t\tNcModal,\n\t\tPencil,\n\t},\n\tmixins: [\n\t\tisMobile,\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\tisAdmin: getCurrentUser().isAdmin,\n\t\t\ttimer: new Date(),\n\t\t\tregisteredStatus: [],\n\t\t\tcallbacks: {},\n\t\t\tcallbacksStatus: {},\n\t\t\tallCallbacksStatus: {},\n\t\t\tstatusInfo,\n\t\t\tenabledStatuses: loadState('dashboard', 'statuses'),\n\t\t\tpanels,\n\t\t\tfirstRun,\n\t\t\tdisplayName: getCurrentUser()?.displayName,\n\t\t\tuid: getCurrentUser()?.uid,\n\t\t\tlayout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),\n\t\t\tmodal: false,\n\t\t\tappStoreUrl: generateUrl('/settings/apps/dashboard'),\n\t\t\tstatuses: {},\n\t\t\tbackground,\n\t\t\tthemingDefaultBackground,\n\t\t}\n\t},\n\tcomputed: {\n\t\tbackgroundImage() {\n\t\t\treturn getBackgroundUrl(this.background, backgroundVersion, this.themingDefaultBackground)\n\t\t},\n\t\tbackgroundStyle() {\n\t\t\tif ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')\n\t\t\t\t|| this.background.match(/#[0-9A-Fa-f]{6}/g)) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tbackgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,\n\t\t\t}\n\t\t},\n\t\tgreeting() {\n\t\t\tconst time = this.timer.getHours()\n\n\t\t\t// Determine part of the day\n\t\t\tlet partOfDay\n\t\t\tif (time >= 22 || time < 5) {\n\t\t\t\tpartOfDay = 'night'\n\t\t\t} else if (time >= 18) {\n\t\t\t\tpartOfDay = 'evening'\n\t\t\t} else if (time >= 12) {\n\t\t\t\tpartOfDay = 'afternoon'\n\t\t\t} else {\n\t\t\t\tpartOfDay = 'morning'\n\t\t\t}\n\n\t\t\t// Define the greetings\n\t\t\tconst good = {\n\t\t\t\tmorning: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good morning'),\n\t\t\t\t\twithName: t('dashboard', 'Good morning, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tafternoon: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good afternoon'),\n\t\t\t\t\twithName: t('dashboard', 'Good afternoon, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tevening: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good evening'),\n\t\t\t\t\twithName: t('dashboard', 'Good evening, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tnight: {\n\t\t\t\t\t// Don't use \"Good night\" as it's not a greeting\n\t\t\t\t\tgeneric: t('dashboard', 'Hello'),\n\t\t\t\t\twithName: t('dashboard', 'Hello, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\t// Figure out which greeting to show\n\t\t\tconst shouldShowName = this.displayName && this.uid !== this.displayName\n\t\t\treturn { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }\n\t\t},\n\n\t\tisActive() {\n\t\t\treturn (panel) => this.layout.indexOf(panel.id) > -1\n\t\t},\n\t\tisStatusActive() {\n\t\t\treturn (status) => !(status in this.enabledStatuses) || this.enabledStatuses[status]\n\t\t},\n\n\t\tsortedAllStatuses() {\n\t\t\treturn Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)\n\t\t},\n\t\tsortedPanels() {\n\t\t\treturn Object.values(this.panels).sort((a, b) => {\n\t\t\t\tconst indexA = this.layout.indexOf(a.id)\n\t\t\t\tconst indexB = this.layout.indexOf(b.id)\n\t\t\t\tif (indexA === -1 || indexB === -1) {\n\t\t\t\t\treturn indexB - indexA || a.id - b.id\n\t\t\t\t}\n\t\t\t\treturn indexA - indexB || a.id - b.id\n\t\t\t})\n\t\t},\n\t\tsortedRegisteredStatus() {\n\t\t\treturn this.registeredStatus.slice().sort(this.sortStatuses)\n\t\t},\n\t},\n\n\twatch: {\n\t\tcallbacks() {\n\t\t\tthis.rerenderPanels()\n\t\t},\n\t\tcallbacksStatus() {\n\t\t\tfor (const app in this.callbacksStatus) {\n\t\t\t\tconst element = this.$refs['status-' + app]\n\t\t\t\tif (this.statuses[app] && this.statuses[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacksStatus[app](element[0])\n\t\t\t\t\tVue.set(this.statuses, app, { mounted: true })\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.updateGlobalStyles()\n\t\tthis.updateSkipLink()\n\t\twindow.addEventListener('scroll', this.handleScroll)\n\n\t\tsetInterval(() => {\n\t\t\tthis.timer = new Date()\n\t\t}, 30000)\n\n\t\tif (this.firstRun) {\n\t\t\twindow.addEventListener('scroll', this.disableFirstrunHint)\n\t\t}\n\t},\n\tdestroyed() {\n\t\twindow.removeEventListener('scroll', this.handleScroll)\n\t},\n\n\tmethods: {\n\t\tupdateGlobalStyles() {\n\t\t\t// Override primary-invert-if-bright and color-primary-text if background is set\n\t\t\tconst isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'\n\t\t\tif (isBackgroundBright) {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#000000')\n\t\t\t\t// document.body.removeAttribute('data-theme-dark')\n\t\t\t\t// document.body.setAttribute('data-theme-light', 'true')\n\t\t\t} else {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')\n\t\t\t\t// document.body.removeAttribute('data-theme-light')\n\t\t\t\t// document.body.setAttribute('data-theme-dark', 'true')\n\t\t\t}\n\n\t\t\tconst themeElements = [document.documentElement, document.querySelector('#header'), document.querySelector('body')]\n\t\t\tfor (const element of themeElements) {\n\t\t\t\tif (this.background === 'default') {\n\t\t\t\t\telement.style.setProperty('--image-main-background', `url('${imagePath('core', 'app-background.jpg')}')`)\n\t\t\t\t} else if (this.background.match(/#[0-9A-Fa-f]{6}/g)) {\n\t\t\t\t\telement.style.setProperty('--image-main-background', undefined)\n\t\t\t\t} else {\n\t\t\t\t\telement.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Method to register panels that will be called by the integrating apps\n\t\t *\n\t\t * @param {string} app The unique app id for the widget\n\t\t * @param {Function} callback The callback function to register a panel which gets the DOM element passed as parameter\n\t\t */\n\t\tregister(app, callback) {\n\t\t\tVue.set(this.callbacks, app, callback)\n\t\t},\n\t\tregisterStatus(app, callback) {\n\t\t\t// always save callbacks in case user enables the status later\n\t\t\tVue.set(this.allCallbacksStatus, app, callback)\n\t\t\t// register only if status is enabled or missing from config\n\t\t\tif (this.isStatusActive(app)) {\n\t\t\t\tthis.registeredStatus.push(app)\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.set(this.callbacksStatus, app, callback)\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\trerenderPanels() {\n\t\t\tfor (const app in this.callbacks) {\n\t\t\t\tconst element = this.$refs[app]\n\t\t\t\tif (this.layout.indexOf(app) === -1) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (this.panels[app] && this.panels[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacks[app](element[0], {\n\t\t\t\t\t\twidget: this.panels[app],\n\t\t\t\t\t})\n\t\t\t\t\tVue.set(this.panels[app], 'mounted', true)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsaveLayout() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/layout'), {\n\t\t\t\tlayout: this.layout.join(','),\n\t\t\t})\n\t\t},\n\t\tsaveStatuses() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/statuses'), {\n\t\t\t\tstatuses: JSON.stringify(this.enabledStatuses),\n\t\t\t})\n\t\t},\n\t\tshowModal() {\n\t\t\tthis.modal = true\n\t\t\tthis.firstRun = false\n\t\t},\n\t\tcloseModal() {\n\t\t\tthis.modal = false\n\t\t},\n\t\tupdateCheckbox(panel, currentValue) {\n\t\t\tconst index = this.layout.indexOf(panel.id)\n\t\t\tif (!currentValue && index > -1) {\n\t\t\t\tthis.layout.splice(index, 1)\n\n\t\t\t} else {\n\t\t\t\tthis.layout.push(panel.id)\n\t\t\t}\n\t\t\tVue.set(this.panels[panel.id], 'mounted', false)\n\t\t\tthis.saveLayout()\n\t\t\tthis.$nextTick(() => this.rerenderPanels())\n\t\t},\n\t\tdisableFirstrunHint() {\n\t\t\twindow.removeEventListener('scroll', this.disableFirstrunHint)\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.firstRun = false\n\t\t\t}, 1000)\n\t\t},\n\t\tupdateSkipLink() {\n\t\t\t// Make sure \"Skip to main content\" link points to the app content\n\t\t\tdocument.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')\n\t\t},\n\t\tupdateStatusCheckbox(app, checked) {\n\t\t\tif (checked) {\n\t\t\t\tthis.enableStatus(app)\n\t\t\t} else {\n\t\t\t\tthis.disableStatus(app)\n\t\t\t}\n\t\t},\n\t\tenableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = true\n\t\t\tthis.registerStatus(app, this.allCallbacksStatus[app])\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tdisableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = false\n\t\t\tconst i = this.registeredStatus.findIndex((s) => s === app)\n\t\t\tif (i !== -1) {\n\t\t\t\tthis.registeredStatus.splice(i, 1)\n\t\t\t\tVue.set(this.statuses, app, { mounted: false })\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.delete(this.callbacksStatus, app)\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tsortStatuses(a, b) {\n\t\t\tconst al = a.toLowerCase()\n\t\t\tconst bl = b.toLowerCase()\n\t\t\treturn al > bl\n\t\t\t\t? 1\n\t\t\t\t: al < bl\n\t\t\t\t\t? -1\n\t\t\t\t\t: 0\n\t\t},\n\t\thandleScroll() {\n\t\t\tif (window.scrollY > 70) {\n\t\t\t\tdocument.body.classList.add('dashboard--scrolled')\n\t\t\t} else {\n\t\t\t\tdocument.body.classList.remove('dashboard--scrolled')\n\t\t\t}\n\t\t},\n\t},\n}\n<\/script>\n\n<style lang=\"scss\" scoped>\n#app-dashboard {\n\twidth: 100%;\n\tmin-height: 100%;\n\tbackground-size: cover;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\tbackground-attachment: fixed;\n\n\t> h2 {\n\t\tcolor: var(--color-primary-text);\n\t\ttext-align: center;\n\t\tfont-size: 32px;\n\t\tline-height: 130%;\n\t\tpadding: 1rem 0;\n\t}\n}\n\n.panels {\n\twidth: auto;\n\tmargin: auto;\n\tmax-width: 1500px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tflex-wrap: wrap;\n}\n\n.panel, .panels > div {\n\twidth: 320px;\n\tmax-width: 100%;\n\tmargin: 16px;\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\tborder-radius: var(--border-radius-large);\n\n\t#body-user.theme--highcontrast & {\n\t\tborder: 2px solid var(--color-border);\n\t}\n\n\t&.sortable-ghost {\n\t\t opacity: 0.1;\n\t}\n\n\t& > .panel--header {\n\t\tdisplay: flex;\n\t\tz-index: 1;\n\t\ttop: 50px;\n\t\tpadding: 16px;\n\t\tcursor: grab;\n\n\t\t&, ::v-deep * {\n\t\t\t-webkit-touch-callout: none;\n\t\t\t-webkit-user-select: none;\n\t\t\t-khtml-user-select: none;\n\t\t\t-moz-user-select: none;\n\t\t\t-ms-user-select: none;\n\t\t\tuser-select: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tcursor: grabbing;\n\t\t}\n\n\t\ta {\n\t\t\tflex-grow: 1;\n\t\t}\n\n\t\t> h2 {\n\t\t\tdisplay: block;\n\t\t\talign-items: center;\n\t\t\tflex-grow: 1;\n\t\t\tmargin: 0;\n\t\t\tfont-size: 20px;\n\t\t\tline-height: 24px;\n\t\t\tfont-weight: bold;\n\t\t\tpadding: 16px 8px;\n\t\t\theight: 56px;\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: grab;\n\t\t\tdiv {\n\t\t\t\tbackground-size: 32px;\n\t\t\t\twidth: 32px;\n\t\t\t\theight: 32px;\n\t\t\t\tmargin-right: 16px;\n\t\t\t\tbackground-position: center;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .panel--content {\n\t\tmargin: 0 16px 16px 16px;\n\t\theight: 424px;\n\t\t// We specifically do not want scrollbars inside widgets\n\t\toverflow: visible;\n\t}\n\n\t// No need to extend height of widgets if only one column is shown\n\t@media only screen and (max-width: 709px) {\n\t\t& > .panel--content {\n\t\t\theight: auto;\n\t\t}\n\t}\n}\n\n.footer {\n\tdisplay: flex;\n\tjustify-content: center;\n\ttransition: bottom var(--animation-slow) ease-in-out;\n\tpadding: 1rem 0;\n}\n\n.edit-panels {\n\tdisplay: inline-block;\n\tmargin:auto;\n\tbackground-position: 16px center;\n\tpadding: 12px 16px;\n\tpadding-left: 36px;\n\tborder-radius: var(--border-radius-pill);\n\tmax-width: 200px;\n\topacity: 1;\n\ttext-align: center;\n}\n\n.button,\n.button-vue,\n.edit-panels,\n.statuses ::v-deep .action-item .action-item__menutoggle,\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\topacity: 1 !important;\n\n\t&:hover,\n\t&:focus,\n\t&:active {\n\t\tbackground-color: var(--color-background-hover)!important;\n\t}\n\t&:focus-visible {\n\t\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\n\t}\n}\n\n.modal__content {\n\tpadding: 32px 16px;\n\ttext-align: center;\n\n\tol {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tjustify-content: center;\n\t\tlist-style-type: none;\n\t\tpadding-bottom: 16px;\n\t}\n\tli {\n\t\tlabel {\n\t\t\tposition: relative;\n\t\t\tdisplay: block;\n\t\t\tpadding: 48px 16px 14px 16px;\n\t\t\tmargin: 8px;\n\t\t\twidth: 140px;\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t\tborder: 2px solid var(--color-main-background);\n\t\t\tborder-radius: var(--border-radius-large);\n\t\t\ttext-align: left;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\n\t\t\tdiv {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 16px;\n\t\t\t\twidth: 24px;\n\t\t\t\theight: 24px;\n\t\t\t\tbackground-size: 24px;\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\tborder-color: var(--color-primary);\n\t\t\t}\n\t\t}\n\n\t\t// Do not invert status icons\n\t\t&:not(.panel-status) label div {\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\n\t\tinput[type='checkbox'].checkbox + label:before {\n\t\t\tposition: absolute;\n\t\t\tright: 12px;\n\t\t\ttop: 16px;\n\t\t}\n\n\t\tinput:focus + label {\n\t\t\tborder-color: var(--color-primary);\n\t\t}\n\t}\n\n\th3 {\n\t\tfont-weight: bold;\n\n\t\t&:not(:first-of-type) {\n\t\t\tmargin-top: 64px;\n\t\t}\n\t}\n\n\t// Adjust design of 'Get more widgets' button\n\t.button {\n\t\tdisplay: inline-block;\n\t\tpadding: 10px 16px;\n\t\tmargin: 0;\n\t}\n\n\tp {\n\t\tmax-width: 650px;\n\t\tmargin: 0 auto;\n\n\t\ta:hover,\n\t\ta:focus {\n\t\t\tborder-bottom: 2px solid var(--color-border);\n\t\t}\n\t}\n\n\t.credits--end {\n\t\tpadding-bottom: 32px;\n\t\tcolor: var(--color-text-maxcontrast);\n\n\t\ta {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\t}\n}\n\n.flip-list-move {\n\ttransition: transform var(--animation-slow);\n}\n\n.statuses {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\tflex-wrap: wrap;\n\tmargin-bottom: 36px;\n\n\t& > div {\n\t\tmargin: 8px;\n\t}\n}\n</style>\n<style>\nhtml, body {\n\tbackground-attachment: fixed;\n}\n\n#body-user #header {\n\tposition: fixed;\n}\n\n#content {\n\toverflow: auto;\n\tposition: static !important;;\n}\n</style>\n"],sourceRoot:""}]),n.Z=r}},a={};function o(t){var n=a[t];if(void 0!==n)return n.exports;var i=a[t]={id:t,loaded:!1,exports:{}};return e[t].call(i.exports,i,i.exports,o),i.loaded=!0,i.exports}o.m=e,o.amdD=function(){throw new Error("define cannot be used indirect")},o.amdO={},n=[],o.O=function(t,e,a,i){if(!e){var r=1/0;for(c=0;c<n.length;c++){e=n[c][0],a=n[c][1],i=n[c][2];for(var s=!0,d=0;d<e.length;d++)(!1&i||r>=i)&&Object.keys(o.O).every((function(t){return o.O[t](e[d])}))?e.splice(d--,1):(s=!1,i<r&&(r=i));if(s){n.splice(c--,1);var l=a();void 0!==l&&(t=l)}}return t}i=i||0;for(var c=n.length;c>0&&n[c-1][2]>i;c--)n[c]=n[c-1];n[c]=[e,a,i]},o.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(n,{a:n}),n},o.d=function(t,n){for(var e in n)o.o(n,e)&&!o.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),o.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.nmd=function(t){return t.paths=[],t.children||(t.children=[]),t},o.j=4773,function(){o.b=document.baseURI||self.location.href;var t={4773:0};o.O.j=function(n){return 0===t[n]};var n=function(n,e){var a,i,r=e[0],s=e[1],d=e[2],l=0;if(r.some((function(n){return 0!==t[n]}))){for(a in s)o.o(s,a)&&(o.m[a]=s[a]);if(d)var c=d(o)}for(n&&n(e);l<r.length;l++)i=r[l],o.o(t,i)&&t[i]&&t[i][0](),t[i]=0;return o.O(c)},e=self.webpackChunknextcloud=self.webpackChunknextcloud||[];e.forEach(n.bind(null,0)),e.push=n.bind(null,e.push.bind(e))}(),o.nc=void 0;var i=o.O(void 0,[7874],(function(){return o(31853)}));i=o.O(i)}();
+//# sourceMappingURL=dashboard-main.js.map?v=c4ee8754e5b77ec4b538
\ No newline at end of file
-{"version":3,"file":"dashboard-main.js?v=cfaa13fca1577c385601","mappings":"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","sources":["webpack:///nextcloud/webpack/runtime/chunk loaded","webpack:///nextcloud/apps/dashboard/src/mixins/isMobile.js","webpack:///nextcloud/apps/dashboard/src/helpers/prefixWithBaseUrl.js","webpack:///nextcloud/apps/dashboard/src/helpers/getBackgroundUrl.js","webpack:///nextcloud/apps/dashboard/src/components/BackgroundSettings.vue","webpack:///nextcloud/apps/dashboard/src/components/BackgroundSettings.vue?vue&type=script&lang=js&","webpack://nextcloud/./apps/dashboard/src/components/BackgroundSettings.vue?fc0a","webpack://nextcloud/./apps/dashboard/src/components/BackgroundSettings.vue?20a7","webpack:///nextcloud/apps/dashboard/src/components/BackgroundSettings.vue?vue&type=template&id=77b70ba2&scoped=true&","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue?vue&type=script&lang=js&","webpack://nextcloud/./apps/dashboard/src/DashboardApp.vue?cac7","webpack://nextcloud/./apps/dashboard/src/DashboardApp.vue?8e53","webpack://nextcloud/./apps/dashboard/src/DashboardApp.vue?5685","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue?vue&type=template&id=28cc8d42&scoped=true&","webpack:///nextcloud/apps/dashboard/src/main.js","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue?vue&type=style&index=0&id=28cc8d42&lang=scss&scoped=true&","webpack:///nextcloud/apps/dashboard/src/components/BackgroundSettings.vue?vue&type=style&index=0&id=77b70ba2&scoped=true&lang=scss&","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue?vue&type=style&index=1&lang=css&","webpack:///nextcloud/webpack/bootstrap","webpack:///nextcloud/webpack/runtime/amd define","webpack:///nextcloud/webpack/runtime/amd options","webpack:///nextcloud/webpack/runtime/compat get default export","webpack:///nextcloud/webpack/runtime/define property getters","webpack:///nextcloud/webpack/runtime/global","webpack:///nextcloud/webpack/runtime/hasOwnProperty shorthand","webpack:///nextcloud/webpack/runtime/make namespace object","webpack:///nextcloud/webpack/runtime/node module decorator","webpack:///nextcloud/webpack/runtime/runtimeId","webpack:///nextcloud/webpack/runtime/jsonp chunk loading","webpack:///nextcloud/webpack/runtime/nonce","webpack:///nextcloud/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","/**\n * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n *\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tisMobile: this._isMobile(),\n\t\t}\n\t},\n\tbeforeMount() {\n\t\twindow.addEventListener('resize', this._onResize)\n\t},\n\tbeforeDestroy() {\n\t\twindow.removeEventListener('resize', this._onResize)\n\t},\n\tmethods: {\n\t\t_onResize() {\n\t\t\t// Update mobile mode\n\t\t\tthis.isMobile = this._isMobile()\n\t\t},\n\t\t_isMobile() {\n\t\t\t// check if content width is under 768px\n\t\t\treturn document.documentElement.clientWidth < 768\n\t\t},\n\t},\n}\n","/**\n * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n *\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport { generateFilePath } from '@nextcloud/router'\n\nexport default (url) => generateFilePath('dashboard', '', 'img/') + url\n","/**\n * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n *\n * @author Avior <florian.bouillon@delta-wings.net>\n * @author Julien Veyssier <eneiluj@posteo.net>\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport { generateUrl } from '@nextcloud/router'\nimport prefixWithBaseUrl from './prefixWithBaseUrl'\n\nexport default (background, time = 0, themingDefaultBackground = '') => {\n\tconst enabledThemes = window.OCA?.Theming?.enabledThemes || []\n\tconst isDarkTheme = (enabledThemes.length === 0 || enabledThemes[0] === 'default')\n\t\t? window.matchMedia('(prefers-color-scheme: dark)').matches\n\t\t: enabledThemes.join('').indexOf('dark') !== -1\n\n\tif (background === 'default') {\n\t\tif (themingDefaultBackground && themingDefaultBackground !== 'backgroundColor') {\n\t\t\treturn generateUrl('/apps/theming/image/background') + '?v=' + window.OCA.Theming.cacheBuster\n\t\t}\n\n\t\tif (isDarkTheme) {\n\t\t\treturn prefixWithBaseUrl('eduardo-neves-pedra-azul.jpg')\n\t\t}\n\n\t\treturn prefixWithBaseUrl('kamil-porembinski-clouds.jpg')\n\t} else if (background === 'custom') {\n\t\treturn generateUrl('/apps/dashboard/background') + '?v=' + time\n\t}\n\n\treturn prefixWithBaseUrl(background)\n}\n","<!--\n - @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n -\n - @author Julius Härtl <jus@bitgrid.net>\n -\n - @license GNU AGPL version 3 or any later version\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n\n<template>\n\t<div class=\"background-selector\">\n\t\t<button class=\"background filepicker\"\n\t\t\t:class=\"{ active: background === 'custom' }\"\n\t\t\ttabindex=\"0\"\n\t\t\t@click=\"pickFile\">\n\t\t\t{{ t('dashboard', 'Pick from Files') }}\n\t\t</button>\n\t\t<button class=\"background default\"\n\t\t\ttabindex=\"0\"\n\t\t\t:class=\"{ 'icon-loading': loading === 'default', active: background === 'default' }\"\n\t\t\t@click=\"setDefault\">\n\t\t\t{{ t('dashboard', 'Default image') }}\n\t\t</button>\n\t\t<button class=\"background color\"\n\t\t\t:class=\"{ active: background === 'custom' }\"\n\t\t\ttabindex=\"0\"\n\t\t\t@click=\"pickColor\">\n\t\t\t{{ t('dashboard', 'Plain background') }}\n\t\t</button>\n\t\t<button v-for=\"shippedBackground in shippedBackgrounds\"\n\t\t\t:key=\"shippedBackground.name\"\n\t\t\tv-tooltip=\"shippedBackground.details.attribution\"\n\t\t\t:class=\"{ 'icon-loading': loading === shippedBackground.name, active: background === shippedBackground.name }\"\n\t\t\ttabindex=\"0\"\n\t\t\tclass=\"background\"\n\t\t\t:style=\"{ 'background-image': 'url(' + shippedBackground.preview + ')' }\"\n\t\t\t@click=\"setShipped(shippedBackground.name)\" />\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { generateUrl } from '@nextcloud/router'\nimport { loadState } from '@nextcloud/initial-state'\nimport getBackgroundUrl from './../helpers/getBackgroundUrl'\nimport prefixWithBaseUrl from './../helpers/prefixWithBaseUrl'\nconst shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')\n\nexport default {\n\tname: 'BackgroundSettings',\n\tprops: {\n\t\tbackground: {\n\t\t\ttype: String,\n\t\t\tdefault: 'default',\n\t\t},\n\t\tthemingDefaultBackground: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tbackgroundImage: generateUrl('/apps/dashboard/background') + '?v=' + Date.now(),\n\t\t\tloading: false,\n\t\t}\n\t},\n\tcomputed: {\n\t\tshippedBackgrounds() {\n\t\t\treturn Object.keys(shippedBackgroundList).map((item) => {\n\t\t\t\treturn {\n\t\t\t\t\tname: item,\n\t\t\t\t\turl: prefixWithBaseUrl(item),\n\t\t\t\t\tpreview: prefixWithBaseUrl('previews/' + item),\n\t\t\t\t\tdetails: shippedBackgroundList[item],\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t},\n\tmethods: {\n\t\tasync update(data) {\n\t\t\tconst background = data.type === 'custom' || data.type === 'default' ? data.type : data.value\n\t\t\tthis.backgroundImage = getBackgroundUrl(background, data.version, this.themingDefaultBackground)\n\t\t\tif (data.type === 'color' || (data.type === 'default' && this.themingDefaultBackground === 'backgroundColor')) {\n\t\t\t\tthis.$emit('update:background', data)\n\t\t\t\tthis.loading = false\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst image = new Image()\n\t\t\timage.onload = () => {\n\t\t\t\tthis.$emit('update:background', data)\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t\timage.src = this.backgroundImage\n\t\t},\n\t\tasync setDefault() {\n\t\t\tthis.loading = 'default'\n\t\t\tconst result = await axios.post(generateUrl('/apps/dashboard/background/default'))\n\t\t\tthis.update(result.data)\n\t\t},\n\t\tasync setShipped(shipped) {\n\t\t\tthis.loading = shipped\n\t\t\tconst result = await axios.post(generateUrl('/apps/dashboard/background/shipped'), { value: shipped })\n\t\t\tthis.update(result.data)\n\t\t},\n\t\tasync setFile(path) {\n\t\t\tthis.loading = 'custom'\n\t\t\tconst result = await axios.post(generateUrl('/apps/dashboard/background/custom'), { value: path })\n\t\t\tthis.update(result.data)\n\t\t},\n\t\tasync pickColor() {\n\t\t\tthis.loading = 'color'\n\t\t\tconst color = OCA && OCA.Theming ? OCA.Theming.color : '#0082c9'\n\t\t\tconst result = await axios.post(generateUrl('/apps/dashboard/background/color'), { value: color })\n\t\t\tthis.update(result.data)\n\t\t},\n\t\tpickFile() {\n\t\t\twindow.OC.dialogs.filepicker(t('dashboard', 'Insert from {productName}', { productName: OC.theme.name }), (path, type) => {\n\t\t\t\tif (type === OC.dialogs.FILEPICKER_TYPE_CHOOSE) {\n\t\t\t\t\tthis.setFile(path)\n\t\t\t\t}\n\t\t\t}, false, ['image/png', 'image/gif', 'image/jpeg', 'image/svg'], true, OC.dialogs.FILEPICKER_TYPE_CHOOSE)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped lang=\"scss\">\n.background-selector {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tjustify-content: center;\n\n\t.background {\n\t\twidth: 176px;\n\t\theight: 96px;\n\t\tmargin: 8px;\n\t\tbackground-size: cover;\n\t\tbackground-position: center center;\n\t\ttext-align: center;\n\t\tborder-radius: var(--border-radius-large);\n\t\tborder: 2px solid var(--color-main-background);\n\t\toverflow: hidden;\n\n\t\t&.current {\n\t\t\tbackground-image: var(--color-background-dark);\n\t\t}\n\n\t\t&.filepicker, &.default, &.color {\n\t\t\tborder-color: var(--color-border);\n\t\t}\n\n\t\t&.color {\n\t\t\tbackground-color: var(--color-primary);\n\t\t\tcolor: var(--color-primary-text);\n\t\t}\n\n\t\t&.active,\n\t\t&:hover,\n\t\t&:focus {\n\t\t\tborder: 2px solid var(--color-primary);\n\t\t}\n\n\t\t&.active:not(.icon-loading):after {\n\t\t\tbackground-image: var(--icon-checkmark-white);\n\t\t\tbackground-repeat: no-repeat;\n\t\t\tbackground-position: center;\n\t\t\tbackground-size: 44px;\n\t\t\tcontent: '';\n\t\t\tdisplay: block;\n\t\t\theight: 100%;\n\t\t}\n\t}\n}\n</style>\n","import mod from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./BackgroundSettings.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./BackgroundSettings.vue?vue&type=script&lang=js&\"","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./BackgroundSettings.vue?vue&type=style&index=0&id=77b70ba2&scoped=true&lang=scss&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./BackgroundSettings.vue?vue&type=style&index=0&id=77b70ba2&scoped=true&lang=scss&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./BackgroundSettings.vue?vue&type=template&id=77b70ba2&scoped=true&\"\nimport script from \"./BackgroundSettings.vue?vue&type=script&lang=js&\"\nexport * from \"./BackgroundSettings.vue?vue&type=script&lang=js&\"\nimport style0 from \"./BackgroundSettings.vue?vue&type=style&index=0&id=77b70ba2&scoped=true&lang=scss&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"77b70ba2\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"background-selector\"},[_c('button',{staticClass:\"background filepicker\",class:{ active: _vm.background === 'custom' },attrs:{\"tabindex\":\"0\"},on:{\"click\":_vm.pickFile}},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('dashboard', 'Pick from Files'))+\"\\n\\t\")]),_vm._v(\" \"),_c('button',{staticClass:\"background default\",class:{ 'icon-loading': _vm.loading === 'default', active: _vm.background === 'default' },attrs:{\"tabindex\":\"0\"},on:{\"click\":_vm.setDefault}},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('dashboard', 'Default image'))+\"\\n\\t\")]),_vm._v(\" \"),_c('button',{staticClass:\"background color\",class:{ active: _vm.background === 'custom' },attrs:{\"tabindex\":\"0\"},on:{\"click\":_vm.pickColor}},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('dashboard', 'Plain background'))+\"\\n\\t\")]),_vm._v(\" \"),_vm._l((_vm.shippedBackgrounds),function(shippedBackground){return _c('button',{directives:[{name:\"tooltip\",rawName:\"v-tooltip\",value:(shippedBackground.details.attribution),expression:\"shippedBackground.details.attribution\"}],key:shippedBackground.name,staticClass:\"background\",class:{ 'icon-loading': _vm.loading === shippedBackground.name, active: _vm.background === shippedBackground.name },style:({ 'background-image': 'url(' + shippedBackground.preview + ')' }),attrs:{\"tabindex\":\"0\"},on:{\"click\":function($event){return _vm.setShipped(shippedBackground.name)}}})})],2)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","<template>\n\t<div id=\"app-dashboard\">\n\t\t<h2>{{ greeting.text }}</h2>\n\t\t<ul class=\"statuses\">\n\t\t\t<div v-for=\"status in sortedRegisteredStatus\"\n\t\t\t\t:id=\"'status-' + status\"\n\t\t\t\t:key=\"status\">\n\t\t\t\t<div :ref=\"'status-' + status\" />\n\t\t\t</div>\n\t\t</ul>\n\n\t\t<Draggable v-model=\"layout\"\n\t\t\tclass=\"panels\"\n\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\thandle=\".panel--header\"\n\t\t\t@end=\"saveLayout\">\n\t\t\t<div v-for=\"panelId in layout\" :key=\"panels[panelId].id\" class=\"panel\">\n\t\t\t\t<div class=\"panel--header\">\n\t\t\t\t\t<h2>\n\t\t\t\t\t\t<div :class=\"panels[panelId].iconClass\" role=\"img\" />\n\t\t\t\t\t\t{{ panels[panelId].title }}\n\t\t\t\t\t</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"panel--content\" :class=\"{ loading: !panels[panelId].mounted }\">\n\t\t\t\t\t<div :ref=\"panels[panelId].id\" :data-id=\"panels[panelId].id\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Draggable>\n\n\t\t<div class=\"footer\">\n\t\t\t<NcButton @click=\"showModal\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('dashboard', 'Customize') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcModal v-if=\"modal\" size=\"large\" @close=\"closeModal\">\n\t\t\t<div class=\"modal__content\">\n\t\t\t\t<h3>{{ t('dashboard', 'Edit widgets') }}</h3>\n\t\t\t\t<ol class=\"panels\">\n\t\t\t\t\t<li v-for=\"status in sortedAllStatuses\" :key=\"status\" :class=\"'panel-' + status\">\n\t\t\t\t\t\t<input :id=\"'status-checkbox-' + status\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isStatusActive(status)\"\n\t\t\t\t\t\t\t@input=\"updateStatusCheckbox(status, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'status-checkbox-' + status\">\n\t\t\t\t\t\t\t<div :class=\"statusInfo[status].icon\" role=\"img\" />\n\t\t\t\t\t\t\t{{ statusInfo[status].text }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</ol>\n\t\t\t\t<Draggable v-model=\"layout\"\n\t\t\t\t\tclass=\"panels\"\n\t\t\t\t\ttag=\"ol\"\n\t\t\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\t\t\thandle=\".draggable\"\n\t\t\t\t\t@end=\"saveLayout\">\n\t\t\t\t\t<li v-for=\"panel in sortedPanels\" :key=\"panel.id\" :class=\"'panel-' + panel.id\">\n\t\t\t\t\t\t<input :id=\"'panel-checkbox-' + panel.id\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isActive(panel)\"\n\t\t\t\t\t\t\t@input=\"updateCheckbox(panel, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'panel-checkbox-' + panel.id\" :class=\"{ draggable: isActive(panel) }\">\n\t\t\t\t\t\t\t<div :class=\"panel.iconClass\" role=\"img\" />\n\t\t\t\t\t\t\t{{ panel.title }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</Draggable>\n\n\t\t\t\t<a v-if=\"isAdmin\" :href=\"appStoreUrl\" class=\"button\">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>\n\n\t\t\t\t<h3>{{ t('dashboard', 'Change background image') }}</h3>\n\t\t\t\t<BackgroundSettings :background=\"background\"\n\t\t\t\t\t:theming-default-background=\"themingDefaultBackground\"\n\t\t\t\t\t@update:background=\"updateBackground\" />\n\n\t\t\t\t<h3>{{ t('dashboard', 'Weather service') }}</h3>\n\t\t\t\t<p>\n\t\t\t\t\t{{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}\n\t\t\t\t</p>\n\t\t\t\t<p class=\"credits--end\">\n\t\t\t\t\t<a href=\"https://api.met.no/doc/TermsOfService\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'Weather data from Met.no') }}</a>,\n\t\t\t\t\t<a href=\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'geocoding with Nominatim') }}</a>,\n\t\t\t\t\t<a href=\"https://www.opentopodata.org/#public-api\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'elevation data from OpenTopoData') }}</a>.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcModal>\n\t</div>\n</template>\n\n<script>\nimport { generateUrl } from '@nextcloud/router'\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { loadState } from '@nextcloud/initial-state'\nimport axios from '@nextcloud/axios'\nimport NcButton from '@nextcloud/vue/dist/Components/NcButton'\nimport Draggable from 'vuedraggable'\nimport NcModal from '@nextcloud/vue/dist/Components/NcModal'\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\nimport Vue from 'vue'\n\nimport isMobile from './mixins/isMobile'\nimport BackgroundSettings from './components/BackgroundSettings'\nimport getBackgroundUrl from './helpers/getBackgroundUrl'\n\nconst panels = loadState('dashboard', 'panels')\nconst firstRun = loadState('dashboard', 'firstRun')\nconst background = loadState('dashboard', 'background')\nconst themingDefaultBackground = loadState('dashboard', 'themingDefaultBackground')\nconst version = loadState('dashboard', 'version')\nconst shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')\n\nconst statusInfo = {\n\tweather: {\n\t\ttext: t('dashboard', 'Weather'),\n\t\ticon: 'icon-weather-status',\n\t},\n\tstatus: {\n\t\ttext: t('dashboard', 'Status'),\n\t\ticon: 'icon-user-status-online',\n\t},\n}\n\nexport default {\n\tname: 'DashboardApp',\n\tcomponents: {\n\t\tBackgroundSettings,\n\t\tNcButton,\n\t\tDraggable,\n\t\tNcModal,\n\t\tPencil,\n\t},\n\tmixins: [\n\t\tisMobile,\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\tisAdmin: getCurrentUser().isAdmin,\n\t\t\ttimer: new Date(),\n\t\t\tregisteredStatus: [],\n\t\t\tcallbacks: {},\n\t\t\tcallbacksStatus: {},\n\t\t\tallCallbacksStatus: {},\n\t\t\tstatusInfo,\n\t\t\tenabledStatuses: loadState('dashboard', 'statuses'),\n\t\t\tpanels,\n\t\t\tfirstRun,\n\t\t\tdisplayName: getCurrentUser()?.displayName,\n\t\t\tuid: getCurrentUser()?.uid,\n\t\t\tlayout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),\n\t\t\tmodal: false,\n\t\t\tappStoreUrl: generateUrl('/settings/apps/dashboard'),\n\t\t\tstatuses: {},\n\t\t\tbackground,\n\t\t\tthemingDefaultBackground,\n\t\t\tversion,\n\t\t}\n\t},\n\tcomputed: {\n\t\tbackgroundImage() {\n\t\t\treturn getBackgroundUrl(this.background, this.version, this.themingDefaultBackground)\n\t\t},\n\t\tbackgroundStyle() {\n\t\t\tif ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')\n\t\t\t\t|| this.background.match(/#[0-9A-Fa-f]{6}/g)) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tbackgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,\n\t\t\t}\n\t\t},\n\n\t\tgreeting() {\n\t\t\tconst time = this.timer.getHours()\n\n\t\t\t// Determine part of the day\n\t\t\tlet partOfDay\n\t\t\tif (time >= 22 || time < 5) {\n\t\t\t\tpartOfDay = 'night'\n\t\t\t} else if (time >= 18) {\n\t\t\t\tpartOfDay = 'evening'\n\t\t\t} else if (time >= 12) {\n\t\t\t\tpartOfDay = 'afternoon'\n\t\t\t} else {\n\t\t\t\tpartOfDay = 'morning'\n\t\t\t}\n\n\t\t\t// Define the greetings\n\t\t\tconst good = {\n\t\t\t\tmorning: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good morning'),\n\t\t\t\t\twithName: t('dashboard', 'Good morning, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tafternoon: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good afternoon'),\n\t\t\t\t\twithName: t('dashboard', 'Good afternoon, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tevening: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good evening'),\n\t\t\t\t\twithName: t('dashboard', 'Good evening, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tnight: {\n\t\t\t\t\t// Don't use \"Good night\" as it's not a greeting\n\t\t\t\t\tgeneric: t('dashboard', 'Hello'),\n\t\t\t\t\twithName: t('dashboard', 'Hello, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\t// Figure out which greeting to show\n\t\t\tconst shouldShowName = this.displayName && this.uid !== this.displayName\n\t\t\treturn { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }\n\t\t},\n\n\t\tisActive() {\n\t\t\treturn (panel) => this.layout.indexOf(panel.id) > -1\n\t\t},\n\t\tisStatusActive() {\n\t\t\treturn (status) => !(status in this.enabledStatuses) || this.enabledStatuses[status]\n\t\t},\n\n\t\tsortedAllStatuses() {\n\t\t\treturn Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)\n\t\t},\n\t\tsortedPanels() {\n\t\t\treturn Object.values(this.panels).sort((a, b) => {\n\t\t\t\tconst indexA = this.layout.indexOf(a.id)\n\t\t\t\tconst indexB = this.layout.indexOf(b.id)\n\t\t\t\tif (indexA === -1 || indexB === -1) {\n\t\t\t\t\treturn indexB - indexA || a.id - b.id\n\t\t\t\t}\n\t\t\t\treturn indexA - indexB || a.id - b.id\n\t\t\t})\n\t\t},\n\t\tsortedRegisteredStatus() {\n\t\t\treturn this.registeredStatus.slice().sort(this.sortStatuses)\n\t\t},\n\t},\n\n\twatch: {\n\t\tcallbacks() {\n\t\t\tthis.rerenderPanels()\n\t\t},\n\t\tcallbacksStatus() {\n\t\t\tfor (const app in this.callbacksStatus) {\n\t\t\t\tconst element = this.$refs['status-' + app]\n\t\t\t\tif (this.statuses[app] && this.statuses[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacksStatus[app](element[0])\n\t\t\t\t\tVue.set(this.statuses, app, { mounted: true })\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.updateGlobalStyles()\n\t\tthis.updateSkipLink()\n\t\twindow.addEventListener('scroll', this.handleScroll)\n\n\t\tsetInterval(() => {\n\t\t\tthis.timer = new Date()\n\t\t}, 30000)\n\n\t\tif (this.firstRun) {\n\t\t\twindow.addEventListener('scroll', this.disableFirstrunHint)\n\t\t}\n\t},\n\tdestroyed() {\n\t\twindow.removeEventListener('scroll', this.handleScroll)\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Method to register panels that will be called by the integrating apps\n\t\t *\n\t\t * @param {string} app The unique app id for the widget\n\t\t * @param {Function} callback The callback function to register a panel which gets the DOM element passed as parameter\n\t\t */\n\t\tregister(app, callback) {\n\t\t\tVue.set(this.callbacks, app, callback)\n\t\t},\n\t\tregisterStatus(app, callback) {\n\t\t\t// always save callbacks in case user enables the status later\n\t\t\tVue.set(this.allCallbacksStatus, app, callback)\n\t\t\t// register only if status is enabled or missing from config\n\t\t\tif (this.isStatusActive(app)) {\n\t\t\t\tthis.registeredStatus.push(app)\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.set(this.callbacksStatus, app, callback)\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\trerenderPanels() {\n\t\t\tfor (const app in this.callbacks) {\n\t\t\t\tconst element = this.$refs[app]\n\t\t\t\tif (this.layout.indexOf(app) === -1) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (this.panels[app] && this.panels[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacks[app](element[0], {\n\t\t\t\t\t\twidget: this.panels[app],\n\t\t\t\t\t})\n\t\t\t\t\tVue.set(this.panels[app], 'mounted', true)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsaveLayout() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/layout'), {\n\t\t\t\tlayout: this.layout.join(','),\n\t\t\t})\n\t\t},\n\t\tsaveStatuses() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/statuses'), {\n\t\t\t\tstatuses: JSON.stringify(this.enabledStatuses),\n\t\t\t})\n\t\t},\n\t\tshowModal() {\n\t\t\tthis.modal = true\n\t\t\tthis.firstRun = false\n\t\t},\n\t\tcloseModal() {\n\t\t\tthis.modal = false\n\t\t},\n\t\tupdateCheckbox(panel, currentValue) {\n\t\t\tconst index = this.layout.indexOf(panel.id)\n\t\t\tif (!currentValue && index > -1) {\n\t\t\t\tthis.layout.splice(index, 1)\n\n\t\t\t} else {\n\t\t\t\tthis.layout.push(panel.id)\n\t\t\t}\n\t\t\tVue.set(this.panels[panel.id], 'mounted', false)\n\t\t\tthis.saveLayout()\n\t\t\tthis.$nextTick(() => this.rerenderPanels())\n\t\t},\n\t\tdisableFirstrunHint() {\n\t\t\twindow.removeEventListener('scroll', this.disableFirstrunHint)\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.firstRun = false\n\t\t\t}, 1000)\n\t\t},\n\t\tupdateBackground(data) {\n\t\t\tthis.background = data.type === 'custom' || data.type === 'default' ? data.type : data.value\n\t\t\tthis.version = data.version\n\t\t\tthis.updateGlobalStyles()\n\t\t},\n\t\tupdateGlobalStyles() {\n\t\t\t// Override primary-invert-if-bright and color-primary-text if background is set\n\t\t\tconst isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'\n\t\t\tif (isBackgroundBright) {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#000000')\n\t\t\t\t// document.body.removeAttribute('data-theme-dark')\n\t\t\t\t// document.body.setAttribute('data-theme-light', 'true')\n\t\t\t} else {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')\n\t\t\t\t// document.body.removeAttribute('data-theme-light')\n\t\t\t\t// document.body.setAttribute('data-theme-dark', 'true')\n\t\t\t}\n\n\t\t\tdocument.documentElement.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t\tdocument.querySelector('#header').style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t\tdocument.querySelector('body').style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t},\n\t\tupdateSkipLink() {\n\t\t\t// Make sure \"Skip to main content\" link points to the app content\n\t\t\tdocument.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')\n\t\t},\n\t\tupdateStatusCheckbox(app, checked) {\n\t\t\tif (checked) {\n\t\t\t\tthis.enableStatus(app)\n\t\t\t} else {\n\t\t\t\tthis.disableStatus(app)\n\t\t\t}\n\t\t},\n\t\tenableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = true\n\t\t\tthis.registerStatus(app, this.allCallbacksStatus[app])\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tdisableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = false\n\t\t\tconst i = this.registeredStatus.findIndex((s) => s === app)\n\t\t\tif (i !== -1) {\n\t\t\t\tthis.registeredStatus.splice(i, 1)\n\t\t\t\tVue.set(this.statuses, app, { mounted: false })\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.delete(this.callbacksStatus, app)\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tsortStatuses(a, b) {\n\t\t\tconst al = a.toLowerCase()\n\t\t\tconst bl = b.toLowerCase()\n\t\t\treturn al > bl\n\t\t\t\t? 1\n\t\t\t\t: al < bl\n\t\t\t\t\t? -1\n\t\t\t\t\t: 0\n\t\t},\n\t\thandleScroll() {\n\t\t\tif (window.scrollY > 70) {\n\t\t\t\tdocument.body.classList.add('dashboard--scrolled')\n\t\t\t} else {\n\t\t\t\tdocument.body.classList.remove('dashboard--scrolled')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n#app-dashboard {\n\twidth: 100%;\n\tmin-height: 100%;\n\tbackground-size: cover;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\tbackground-attachment: fixed;\n\n\t> h2 {\n\t\tcolor: var(--color-primary-text);\n\t\ttext-align: center;\n\t\tfont-size: 32px;\n\t\tline-height: 130%;\n\t\tpadding: 1rem 0;\n\t}\n}\n\n.panels {\n\twidth: auto;\n\tmargin: auto;\n\tmax-width: 1500px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tflex-wrap: wrap;\n}\n\n.panel, .panels > div {\n\twidth: 320px;\n\tmax-width: 100%;\n\tmargin: 16px;\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\tborder-radius: var(--border-radius-large);\n\n\t#body-user.theme--highcontrast & {\n\t\tborder: 2px solid var(--color-border);\n\t}\n\n\t&.sortable-ghost {\n\t\t opacity: 0.1;\n\t}\n\n\t& > .panel--header {\n\t\tdisplay: flex;\n\t\tz-index: 1;\n\t\ttop: 50px;\n\t\tpadding: 16px;\n\t\tcursor: grab;\n\n\t\t&, ::v-deep * {\n\t\t\t-webkit-touch-callout: none;\n\t\t\t-webkit-user-select: none;\n\t\t\t-khtml-user-select: none;\n\t\t\t-moz-user-select: none;\n\t\t\t-ms-user-select: none;\n\t\t\tuser-select: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tcursor: grabbing;\n\t\t}\n\n\t\ta {\n\t\t\tflex-grow: 1;\n\t\t}\n\n\t\t> h2 {\n\t\t\tdisplay: block;\n\t\t\talign-items: center;\n\t\t\tflex-grow: 1;\n\t\t\tmargin: 0;\n\t\t\tfont-size: 20px;\n\t\t\tline-height: 24px;\n\t\t\tfont-weight: bold;\n\t\t\tpadding: 16px 8px;\n\t\t\theight: 56px;\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: grab;\n\t\t\tdiv {\n\t\t\t\tbackground-size: 32px;\n\t\t\t\twidth: 32px;\n\t\t\t\theight: 32px;\n\t\t\t\tmargin-right: 16px;\n\t\t\t\tbackground-position: center;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .panel--content {\n\t\tmargin: 0 16px 16px 16px;\n\t\theight: 424px;\n\t\t// We specifically do not want scrollbars inside widgets\n\t\toverflow: visible;\n\t}\n\n\t// No need to extend height of widgets if only one column is shown\n\t@media only screen and (max-width: 709px) {\n\t\t& > .panel--content {\n\t\t\theight: auto;\n\t\t}\n\t}\n}\n\n.footer {\n\tdisplay: flex;\n\tjustify-content: center;\n\ttransition: bottom var(--animation-slow) ease-in-out;\n\tpadding: 1rem 0;\n}\n\n.edit-panels {\n\tdisplay: inline-block;\n\tmargin:auto;\n\tbackground-position: 16px center;\n\tpadding: 12px 16px;\n\tpadding-left: 36px;\n\tborder-radius: var(--border-radius-pill);\n\tmax-width: 200px;\n\topacity: 1;\n\ttext-align: center;\n}\n\n.button,\n.button-vue,\n.edit-panels,\n.statuses ::v-deep .action-item .action-item__menutoggle,\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\topacity: 1 !important;\n\n\t&:hover,\n\t&:focus,\n\t&:active {\n\t\tbackground-color: var(--color-background-hover)!important;\n\t}\n\t&:focus-visible {\n\t\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\n\t}\n}\n\n.modal__content {\n\tpadding: 32px 16px;\n\ttext-align: center;\n\n\tol {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tjustify-content: center;\n\t\tlist-style-type: none;\n\t\tpadding-bottom: 16px;\n\t}\n\tli {\n\t\tlabel {\n\t\t\tposition: relative;\n\t\t\tdisplay: block;\n\t\t\tpadding: 48px 16px 14px 16px;\n\t\t\tmargin: 8px;\n\t\t\twidth: 140px;\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t\tborder: 2px solid var(--color-main-background);\n\t\t\tborder-radius: var(--border-radius-large);\n\t\t\ttext-align: left;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\n\t\t\tdiv {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 16px;\n\t\t\t\twidth: 24px;\n\t\t\t\theight: 24px;\n\t\t\t\tbackground-size: 24px;\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\tborder-color: var(--color-primary);\n\t\t\t}\n\t\t}\n\n\t\t// Do not invert status icons\n\t\t&:not(.panel-status) label div {\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\n\t\tinput[type='checkbox'].checkbox + label:before {\n\t\t\tposition: absolute;\n\t\t\tright: 12px;\n\t\t\ttop: 16px;\n\t\t}\n\n\t\tinput:focus + label {\n\t\t\tborder-color: var(--color-primary);\n\t\t}\n\t}\n\n\th3 {\n\t\tfont-weight: bold;\n\n\t\t&:not(:first-of-type) {\n\t\t\tmargin-top: 64px;\n\t\t}\n\t}\n\n\t// Adjust design of 'Get more widgets' button\n\t.button {\n\t\tdisplay: inline-block;\n\t\tpadding: 10px 16px;\n\t\tmargin: 0;\n\t}\n\n\tp {\n\t\tmax-width: 650px;\n\t\tmargin: 0 auto;\n\n\t\ta:hover,\n\t\ta:focus {\n\t\t\tborder-bottom: 2px solid var(--color-border);\n\t\t}\n\t}\n\n\t.credits--end {\n\t\tpadding-bottom: 32px;\n\t\tcolor: var(--color-text-maxcontrast);\n\n\t\ta {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\t}\n}\n\n.flip-list-move {\n\ttransition: transform var(--animation-slow);\n}\n\n.statuses {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\tflex-wrap: wrap;\n\tmargin-bottom: 36px;\n\n\t& > div {\n\t\tmargin: 8px;\n\t}\n}\n</style>\n<style>\nhtml, body {\n\tbackground-attachment: fixed;\n}\n\n#body-user #header {\n\tposition: fixed;\n}\n\n#content {\n\toverflow: auto;\n\tposition: static !important;;\n}\n</style>\n","import mod from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=script&lang=js&\"","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/sass-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=style&index=0&id=28cc8d42&lang=scss&scoped=true&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/sass-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=style&index=0&id=28cc8d42&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=style&index=1&lang=css&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=style&index=1&lang=css&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./DashboardApp.vue?vue&type=template&id=28cc8d42&scoped=true&\"\nimport script from \"./DashboardApp.vue?vue&type=script&lang=js&\"\nexport * from \"./DashboardApp.vue?vue&type=script&lang=js&\"\nimport style0 from \"./DashboardApp.vue?vue&type=style&index=0&id=28cc8d42&lang=scss&scoped=true&\"\nimport style1 from \"./DashboardApp.vue?vue&type=style&index=1&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"28cc8d42\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{attrs:{\"id\":\"app-dashboard\"}},[_c('h2',[_vm._v(_vm._s(_vm.greeting.text))]),_vm._v(\" \"),_c('ul',{staticClass:\"statuses\"},_vm._l((_vm.sortedRegisteredStatus),function(status){return _c('div',{key:status,attrs:{\"id\":'status-' + status}},[_c('div',{ref:'status-' + status,refInFor:true})])}),0),_vm._v(\" \"),_c('Draggable',_vm._b({staticClass:\"panels\",attrs:{\"handle\":\".panel--header\"},on:{\"end\":_vm.saveLayout},model:{value:(_vm.layout),callback:function ($$v) {_vm.layout=$$v},expression:\"layout\"}},'Draggable',{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3},false),_vm._l((_vm.layout),function(panelId){return _c('div',{key:_vm.panels[panelId].id,staticClass:\"panel\"},[_c('div',{staticClass:\"panel--header\"},[_c('h2',[_c('div',{class:_vm.panels[panelId].iconClass,attrs:{\"role\":\"img\"}}),_vm._v(\"\\n\\t\\t\\t\\t\\t\"+_vm._s(_vm.panels[panelId].title)+\"\\n\\t\\t\\t\\t\")])]),_vm._v(\" \"),_c('div',{staticClass:\"panel--content\",class:{ loading: !_vm.panels[panelId].mounted }},[_c('div',{ref:_vm.panels[panelId].id,refInFor:true,attrs:{\"data-id\":_vm.panels[panelId].id}})])])}),0),_vm._v(\" \"),_c('div',{staticClass:\"footer\"},[_c('NcButton',{on:{\"click\":_vm.showModal},scopedSlots:_vm._u([{key:\"icon\",fn:function(){return [_c('Pencil',{attrs:{\"size\":20}})]},proxy:true}])},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.t('dashboard', 'Customize'))+\"\\n\\t\\t\")])],1),_vm._v(\" \"),(_vm.modal)?_c('NcModal',{attrs:{\"size\":\"large\"},on:{\"close\":_vm.closeModal}},[_c('div',{staticClass:\"modal__content\"},[_c('h3',[_vm._v(_vm._s(_vm.t('dashboard', 'Edit widgets')))]),_vm._v(\" \"),_c('ol',{staticClass:\"panels\"},_vm._l((_vm.sortedAllStatuses),function(status){return _c('li',{key:status,class:'panel-' + status},[_c('input',{staticClass:\"checkbox\",attrs:{\"id\":'status-checkbox-' + status,\"type\":\"checkbox\"},domProps:{\"checked\":_vm.isStatusActive(status)},on:{\"input\":function($event){return _vm.updateStatusCheckbox(status, $event.target.checked)}}}),_vm._v(\" \"),_c('label',{attrs:{\"for\":'status-checkbox-' + status}},[_c('div',{class:_vm.statusInfo[status].icon,attrs:{\"role\":\"img\"}}),_vm._v(\"\\n\\t\\t\\t\\t\\t\\t\"+_vm._s(_vm.statusInfo[status].text)+\"\\n\\t\\t\\t\\t\\t\")])])}),0),_vm._v(\" \"),_c('Draggable',_vm._b({staticClass:\"panels\",attrs:{\"tag\":\"ol\",\"handle\":\".draggable\"},on:{\"end\":_vm.saveLayout},model:{value:(_vm.layout),callback:function ($$v) {_vm.layout=$$v},expression:\"layout\"}},'Draggable',{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3},false),_vm._l((_vm.sortedPanels),function(panel){return _c('li',{key:panel.id,class:'panel-' + panel.id},[_c('input',{staticClass:\"checkbox\",attrs:{\"id\":'panel-checkbox-' + panel.id,\"type\":\"checkbox\"},domProps:{\"checked\":_vm.isActive(panel)},on:{\"input\":function($event){return _vm.updateCheckbox(panel, $event.target.checked)}}}),_vm._v(\" \"),_c('label',{class:{ draggable: _vm.isActive(panel) },attrs:{\"for\":'panel-checkbox-' + panel.id}},[_c('div',{class:panel.iconClass,attrs:{\"role\":\"img\"}}),_vm._v(\"\\n\\t\\t\\t\\t\\t\\t\"+_vm._s(panel.title)+\"\\n\\t\\t\\t\\t\\t\")])])}),0),_vm._v(\" \"),(_vm.isAdmin)?_c('a',{staticClass:\"button\",attrs:{\"href\":_vm.appStoreUrl}},[_vm._v(_vm._s(_vm.t('dashboard', 'Get more widgets from the App Store')))]):_vm._e(),_vm._v(\" \"),_c('h3',[_vm._v(_vm._s(_vm.t('dashboard', 'Change background image')))]),_vm._v(\" \"),_c('BackgroundSettings',{attrs:{\"background\":_vm.background,\"theming-default-background\":_vm.themingDefaultBackground},on:{\"update:background\":_vm.updateBackground}}),_vm._v(\" \"),_c('h3',[_vm._v(_vm._s(_vm.t('dashboard', 'Weather service')))]),_vm._v(\" \"),_c('p',[_vm._v(\"\\n\\t\\t\\t\\t\"+_vm._s(_vm.t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.'))+\"\\n\\t\\t\\t\")]),_vm._v(\" \"),_c('p',{staticClass:\"credits--end\"},[_c('a',{attrs:{\"href\":\"https://api.met.no/doc/TermsOfService\",\"target\":\"_blank\",\"rel\":\"noopener\"}},[_vm._v(_vm._s(_vm.t('dashboard', 'Weather data from Met.no')))]),_vm._v(\",\\n\\t\\t\\t\\t\"),_c('a',{attrs:{\"href\":\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\",\"target\":\"_blank\",\"rel\":\"noopener\"}},[_vm._v(_vm._s(_vm.t('dashboard', 'geocoding with Nominatim')))]),_vm._v(\",\\n\\t\\t\\t\\t\"),_c('a',{attrs:{\"href\":\"https://www.opentopodata.org/#public-api\",\"target\":\"_blank\",\"rel\":\"noopener\"}},[_vm._v(_vm._s(_vm.t('dashboard', 'elevation data from OpenTopoData')))]),_vm._v(\".\\n\\t\\t\\t\")])],1)]):_vm._e()],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/**\n * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>\n *\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport Vue from 'vue'\nimport DashboardApp from './DashboardApp.vue'\nimport { translate as t } from '@nextcloud/l10n'\nimport VTooltip from '@nextcloud/vue/dist/Directives/Tooltip'\nimport { getRequestToken } from '@nextcloud/auth'\n\n// eslint-disable-next-line camelcase\n__webpack_nonce__ = btoa(getRequestToken())\n\nVue.directive('Tooltip', VTooltip)\n\nVue.prototype.t = t\n\n// FIXME workaround to make the sidebar work\nif (!window.OCA.Files) {\n\twindow.OCA.Files = {}\n}\n\nObject.assign(window.OCA.Files, { App: { fileList: { filesClient: OC.Files.getClient() } } }, window.OCA.Files)\n\nconst Dashboard = Vue.extend(DashboardApp)\nconst Instance = new Dashboard({}).$mount('#app-content-vue')\n\nwindow.OCA.Dashboard = {\n\tregister: (app, callback) => Instance.register(app, callback),\n\tregisterStatus: (app, callback) => Instance.registerStatus(app, callback),\n}\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"#app-dashboard[data-v-28cc8d42]{width:100%;min-height:100%;background-size:cover;background-position:center center;background-repeat:no-repeat;background-attachment:fixed}#app-dashboard>h2[data-v-28cc8d42]{color:var(--color-primary-text);text-align:center;font-size:32px;line-height:130%;padding:1rem 0}.panels[data-v-28cc8d42]{width:auto;margin:auto;max-width:1500px;display:flex;justify-content:center;flex-direction:row;align-items:flex-start;flex-wrap:wrap}.panel[data-v-28cc8d42],.panels>div[data-v-28cc8d42]{width:320px;max-width:100%;margin:16px;background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);border-radius:var(--border-radius-large)}#body-user.theme--highcontrast .panel[data-v-28cc8d42],#body-user.theme--highcontrast .panels>div[data-v-28cc8d42]{border:2px solid var(--color-border)}.panel.sortable-ghost[data-v-28cc8d42],.panels>div.sortable-ghost[data-v-28cc8d42]{opacity:.1}.panel>.panel--header[data-v-28cc8d42],.panels>div>.panel--header[data-v-28cc8d42]{display:flex;z-index:1;top:50px;padding:16px;cursor:grab}.panel>.panel--header[data-v-28cc8d42],.panel>.panel--header[data-v-28cc8d42] *,.panels>div>.panel--header[data-v-28cc8d42],.panels>div>.panel--header[data-v-28cc8d42] *{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.panel>.panel--header[data-v-28cc8d42]:active,.panels>div>.panel--header[data-v-28cc8d42]:active{cursor:grabbing}.panel>.panel--header a[data-v-28cc8d42],.panels>div>.panel--header a[data-v-28cc8d42]{flex-grow:1}.panel>.panel--header>h2[data-v-28cc8d42],.panels>div>.panel--header>h2[data-v-28cc8d42]{display:block;align-items:center;flex-grow:1;margin:0;font-size:20px;line-height:24px;font-weight:bold;padding:16px 8px;height:56px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:grab}.panel>.panel--header>h2 div[data-v-28cc8d42],.panels>div>.panel--header>h2 div[data-v-28cc8d42]{background-size:32px;width:32px;height:32px;margin-right:16px;background-position:center;float:left}.panel>.panel--content[data-v-28cc8d42],.panels>div>.panel--content[data-v-28cc8d42]{margin:0 16px 16px 16px;height:424px;overflow:visible}@media only screen and (max-width: 709px){.panel>.panel--content[data-v-28cc8d42],.panels>div>.panel--content[data-v-28cc8d42]{height:auto}}.footer[data-v-28cc8d42]{display:flex;justify-content:center;transition:bottom var(--animation-slow) ease-in-out;padding:1rem 0}.edit-panels[data-v-28cc8d42]{display:inline-block;margin:auto;background-position:16px center;padding:12px 16px;padding-left:36px;border-radius:var(--border-radius-pill);max-width:200px;opacity:1;text-align:center}.button[data-v-28cc8d42],.button-vue[data-v-28cc8d42],.edit-panels[data-v-28cc8d42],.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle{background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);opacity:1 !important}.button[data-v-28cc8d42]:hover,.button[data-v-28cc8d42]:focus,.button[data-v-28cc8d42]:active,.button-vue[data-v-28cc8d42]:hover,.button-vue[data-v-28cc8d42]:focus,.button-vue[data-v-28cc8d42]:active,.edit-panels[data-v-28cc8d42]:hover,.edit-panels[data-v-28cc8d42]:focus,.edit-panels[data-v-28cc8d42]:active,.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle:hover,.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle:focus,.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle:active,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle:hover,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle:focus,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle:active{background-color:var(--color-background-hover) !important}.button[data-v-28cc8d42]:focus-visible,.button-vue[data-v-28cc8d42]:focus-visible,.edit-panels[data-v-28cc8d42]:focus-visible,.statuses[data-v-28cc8d42] .action-item .action-item__menutoggle:focus-visible,.statuses[data-v-28cc8d42] .action-item.action-item--open .action-item__menutoggle:focus-visible{box-shadow:0 0 0 2px var(--color-main-text) !important}.modal__content[data-v-28cc8d42]{padding:32px 16px;text-align:center}.modal__content ol[data-v-28cc8d42]{display:flex;flex-direction:row;justify-content:center;list-style-type:none;padding-bottom:16px}.modal__content li label[data-v-28cc8d42]{position:relative;display:block;padding:48px 16px 14px 16px;margin:8px;width:140px;background-color:var(--color-background-hover);border:2px solid var(--color-main-background);border-radius:var(--border-radius-large);text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.modal__content li label div[data-v-28cc8d42]{position:absolute;top:16px;width:24px;height:24px;background-size:24px}.modal__content li label[data-v-28cc8d42]:hover{border-color:var(--color-primary)}.modal__content li:not(.panel-status) label div[data-v-28cc8d42]{filter:var(--background-invert-if-dark)}.modal__content li input[type=checkbox].checkbox+label[data-v-28cc8d42]:before{position:absolute;right:12px;top:16px}.modal__content li input:focus+label[data-v-28cc8d42]{border-color:var(--color-primary)}.modal__content h3[data-v-28cc8d42]{font-weight:bold}.modal__content h3[data-v-28cc8d42]:not(:first-of-type){margin-top:64px}.modal__content .button[data-v-28cc8d42]{display:inline-block;padding:10px 16px;margin:0}.modal__content p[data-v-28cc8d42]{max-width:650px;margin:0 auto}.modal__content p a[data-v-28cc8d42]:hover,.modal__content p a[data-v-28cc8d42]:focus{border-bottom:2px solid var(--color-border)}.modal__content .credits--end[data-v-28cc8d42]{padding-bottom:32px;color:var(--color-text-maxcontrast)}.modal__content .credits--end a[data-v-28cc8d42]{color:var(--color-text-maxcontrast)}.flip-list-move[data-v-28cc8d42]{transition:transform var(--animation-slow)}.statuses[data-v-28cc8d42]{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap;margin-bottom:36px}.statuses>div[data-v-28cc8d42]{margin:8px}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/dashboard/src/DashboardApp.vue\"],\"names\":[],\"mappings\":\"AA6aA,gCACC,UAAA,CACA,eAAA,CACA,qBAAA,CACA,iCAAA,CACA,2BAAA,CACA,2BAAA,CAEA,mCACC,+BAAA,CACA,iBAAA,CACA,cAAA,CACA,gBAAA,CACA,cAAA,CAIF,yBACC,UAAA,CACA,WAAA,CACA,gBAAA,CACA,YAAA,CACA,sBAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CAGD,qDACC,WAAA,CACA,cAAA,CACA,WAAA,CACA,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,wCAAA,CAEA,mHACC,oCAAA,CAGD,mFACE,UAAA,CAGF,mFACC,YAAA,CACA,SAAA,CACA,QAAA,CACA,YAAA,CACA,WAAA,CAEA,4KACC,0BAAA,CACA,wBAAA,CACA,uBAAA,CACA,qBAAA,CACA,oBAAA,CACA,gBAAA,CAGD,iGACC,eAAA,CAGD,uFACC,WAAA,CAGD,yFACC,aAAA,CACA,kBAAA,CACA,WAAA,CACA,QAAA,CACA,cAAA,CACA,gBAAA,CACA,gBAAA,CACA,gBAAA,CACA,WAAA,CACA,kBAAA,CACA,eAAA,CACA,sBAAA,CACA,WAAA,CACA,iGACC,oBAAA,CACA,UAAA,CACA,WAAA,CACA,iBAAA,CACA,0BAAA,CACA,UAAA,CAKH,qFACC,uBAAA,CACA,YAAA,CAEA,gBAAA,CAID,0CACC,qFACC,WAAA,CAAA,CAKH,yBACC,YAAA,CACA,sBAAA,CACA,mDAAA,CACA,cAAA,CAGD,8BACC,oBAAA,CACA,WAAA,CACA,+BAAA,CACA,iBAAA,CACA,iBAAA,CACA,uCAAA,CACA,eAAA,CACA,SAAA,CACA,iBAAA,CAGD,0OAKC,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,oBAAA,CAEA,6xBAGC,yDAAA,CAED,gTACC,sDAAA,CAIF,iCACC,iBAAA,CACA,iBAAA,CAEA,oCACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,oBAAA,CACA,mBAAA,CAGA,0CACC,iBAAA,CACA,aAAA,CACA,2BAAA,CACA,UAAA,CACA,WAAA,CACA,8CAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CACA,eAAA,CACA,sBAAA,CACA,kBAAA,CAEA,8CACC,iBAAA,CACA,QAAA,CACA,UAAA,CACA,WAAA,CACA,oBAAA,CAGD,gDACC,iCAAA,CAKF,iEACC,uCAAA,CAGD,+EACC,iBAAA,CACA,UAAA,CACA,QAAA,CAGD,sDACC,iCAAA,CAIF,oCACC,gBAAA,CAEA,wDACC,eAAA,CAKF,yCACC,oBAAA,CACA,iBAAA,CACA,QAAA,CAGD,mCACC,eAAA,CACA,aAAA,CAEA,sFAEC,2CAAA,CAIF,+CACC,mBAAA,CACA,mCAAA,CAEA,iDACC,mCAAA,CAKH,iCACC,0CAAA,CAGD,2BACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACA,kBAAA,CAEA,+BACC,UAAA\",\"sourcesContent\":[\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n#app-dashboard {\\n\\twidth: 100%;\\n\\tmin-height: 100%;\\n\\tbackground-size: cover;\\n\\tbackground-position: center center;\\n\\tbackground-repeat: no-repeat;\\n\\tbackground-attachment: fixed;\\n\\n\\t> h2 {\\n\\t\\tcolor: var(--color-primary-text);\\n\\t\\ttext-align: center;\\n\\t\\tfont-size: 32px;\\n\\t\\tline-height: 130%;\\n\\t\\tpadding: 1rem 0;\\n\\t}\\n}\\n\\n.panels {\\n\\twidth: auto;\\n\\tmargin: auto;\\n\\tmax-width: 1500px;\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n\\tflex-direction: row;\\n\\talign-items: flex-start;\\n\\tflex-wrap: wrap;\\n}\\n\\n.panel, .panels > div {\\n\\twidth: 320px;\\n\\tmax-width: 100%;\\n\\tmargin: 16px;\\n\\tbackground-color: var(--color-main-background-blur);\\n\\t-webkit-backdrop-filter: var(--filter-background-blur);\\n\\tbackdrop-filter: var(--filter-background-blur);\\n\\tborder-radius: var(--border-radius-large);\\n\\n\\t#body-user.theme--highcontrast & {\\n\\t\\tborder: 2px solid var(--color-border);\\n\\t}\\n\\n\\t&.sortable-ghost {\\n\\t\\t opacity: 0.1;\\n\\t}\\n\\n\\t& > .panel--header {\\n\\t\\tdisplay: flex;\\n\\t\\tz-index: 1;\\n\\t\\ttop: 50px;\\n\\t\\tpadding: 16px;\\n\\t\\tcursor: grab;\\n\\n\\t\\t&, ::v-deep * {\\n\\t\\t\\t-webkit-touch-callout: none;\\n\\t\\t\\t-webkit-user-select: none;\\n\\t\\t\\t-khtml-user-select: none;\\n\\t\\t\\t-moz-user-select: none;\\n\\t\\t\\t-ms-user-select: none;\\n\\t\\t\\tuser-select: none;\\n\\t\\t}\\n\\n\\t\\t&:active {\\n\\t\\t\\tcursor: grabbing;\\n\\t\\t}\\n\\n\\t\\ta {\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t}\\n\\n\\t\\t> h2 {\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\talign-items: center;\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t\\tmargin: 0;\\n\\t\\t\\tfont-size: 20px;\\n\\t\\t\\tline-height: 24px;\\n\\t\\t\\tfont-weight: bold;\\n\\t\\t\\tpadding: 16px 8px;\\n\\t\\t\\theight: 56px;\\n\\t\\t\\twhite-space: nowrap;\\n\\t\\t\\toverflow: hidden;\\n\\t\\t\\ttext-overflow: ellipsis;\\n\\t\\t\\tcursor: grab;\\n\\t\\t\\tdiv {\\n\\t\\t\\t\\tbackground-size: 32px;\\n\\t\\t\\t\\twidth: 32px;\\n\\t\\t\\t\\theight: 32px;\\n\\t\\t\\t\\tmargin-right: 16px;\\n\\t\\t\\t\\tbackground-position: center;\\n\\t\\t\\t\\tfloat: left;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\n\\t& > .panel--content {\\n\\t\\tmargin: 0 16px 16px 16px;\\n\\t\\theight: 424px;\\n\\t\\t// We specifically do not want scrollbars inside widgets\\n\\t\\toverflow: visible;\\n\\t}\\n\\n\\t// No need to extend height of widgets if only one column is shown\\n\\t@media only screen and (max-width: 709px) {\\n\\t\\t& > .panel--content {\\n\\t\\t\\theight: auto;\\n\\t\\t}\\n\\t}\\n}\\n\\n.footer {\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n\\ttransition: bottom var(--animation-slow) ease-in-out;\\n\\tpadding: 1rem 0;\\n}\\n\\n.edit-panels {\\n\\tdisplay: inline-block;\\n\\tmargin:auto;\\n\\tbackground-position: 16px center;\\n\\tpadding: 12px 16px;\\n\\tpadding-left: 36px;\\n\\tborder-radius: var(--border-radius-pill);\\n\\tmax-width: 200px;\\n\\topacity: 1;\\n\\ttext-align: center;\\n}\\n\\n.button,\\n.button-vue,\\n.edit-panels,\\n.statuses ::v-deep .action-item .action-item__menutoggle,\\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\\n\\tbackground-color: var(--color-main-background-blur);\\n\\t-webkit-backdrop-filter: var(--filter-background-blur);\\n\\tbackdrop-filter: var(--filter-background-blur);\\n\\topacity: 1 !important;\\n\\n\\t&:hover,\\n\\t&:focus,\\n\\t&:active {\\n\\t\\tbackground-color: var(--color-background-hover)!important;\\n\\t}\\n\\t&:focus-visible {\\n\\t\\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\\n\\t}\\n}\\n\\n.modal__content {\\n\\tpadding: 32px 16px;\\n\\ttext-align: center;\\n\\n\\tol {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-direction: row;\\n\\t\\tjustify-content: center;\\n\\t\\tlist-style-type: none;\\n\\t\\tpadding-bottom: 16px;\\n\\t}\\n\\tli {\\n\\t\\tlabel {\\n\\t\\t\\tposition: relative;\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\tpadding: 48px 16px 14px 16px;\\n\\t\\t\\tmargin: 8px;\\n\\t\\t\\twidth: 140px;\\n\\t\\t\\tbackground-color: var(--color-background-hover);\\n\\t\\t\\tborder: 2px solid var(--color-main-background);\\n\\t\\t\\tborder-radius: var(--border-radius-large);\\n\\t\\t\\ttext-align: left;\\n\\t\\t\\toverflow: hidden;\\n\\t\\t\\ttext-overflow: ellipsis;\\n\\t\\t\\twhite-space: nowrap;\\n\\n\\t\\t\\tdiv {\\n\\t\\t\\t\\tposition: absolute;\\n\\t\\t\\t\\ttop: 16px;\\n\\t\\t\\t\\twidth: 24px;\\n\\t\\t\\t\\theight: 24px;\\n\\t\\t\\t\\tbackground-size: 24px;\\n\\t\\t\\t}\\n\\n\\t\\t\\t&:hover {\\n\\t\\t\\t\\tborder-color: var(--color-primary);\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\t// Do not invert status icons\\n\\t\\t&:not(.panel-status) label div {\\n\\t\\t\\tfilter: var(--background-invert-if-dark);\\n\\t\\t}\\n\\n\\t\\tinput[type='checkbox'].checkbox + label:before {\\n\\t\\t\\tposition: absolute;\\n\\t\\t\\tright: 12px;\\n\\t\\t\\ttop: 16px;\\n\\t\\t}\\n\\n\\t\\tinput:focus + label {\\n\\t\\t\\tborder-color: var(--color-primary);\\n\\t\\t}\\n\\t}\\n\\n\\th3 {\\n\\t\\tfont-weight: bold;\\n\\n\\t\\t&:not(:first-of-type) {\\n\\t\\t\\tmargin-top: 64px;\\n\\t\\t}\\n\\t}\\n\\n\\t// Adjust design of 'Get more widgets' button\\n\\t.button {\\n\\t\\tdisplay: inline-block;\\n\\t\\tpadding: 10px 16px;\\n\\t\\tmargin: 0;\\n\\t}\\n\\n\\tp {\\n\\t\\tmax-width: 650px;\\n\\t\\tmargin: 0 auto;\\n\\n\\t\\ta:hover,\\n\\t\\ta:focus {\\n\\t\\t\\tborder-bottom: 2px solid var(--color-border);\\n\\t\\t}\\n\\t}\\n\\n\\t.credits--end {\\n\\t\\tpadding-bottom: 32px;\\n\\t\\tcolor: var(--color-text-maxcontrast);\\n\\n\\t\\ta {\\n\\t\\t\\tcolor: var(--color-text-maxcontrast);\\n\\t\\t}\\n\\t}\\n}\\n\\n.flip-list-move {\\n\\ttransition: transform var(--animation-slow);\\n}\\n\\n.statuses {\\n\\tdisplay: flex;\\n\\tflex-direction: row;\\n\\tjustify-content: center;\\n\\tflex-wrap: wrap;\\n\\tmargin-bottom: 36px;\\n\\n\\t& > div {\\n\\t\\tmargin: 8px;\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".background-selector[data-v-77b70ba2]{display:flex;flex-wrap:wrap;justify-content:center}.background-selector .background[data-v-77b70ba2]{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}.background-selector .background.current[data-v-77b70ba2]{background-image:var(--color-background-dark)}.background-selector .background.filepicker[data-v-77b70ba2],.background-selector .background.default[data-v-77b70ba2],.background-selector .background.color[data-v-77b70ba2]{border-color:var(--color-border)}.background-selector .background.color[data-v-77b70ba2]{background-color:var(--color-primary);color:var(--color-primary-text)}.background-selector .background.active[data-v-77b70ba2],.background-selector .background[data-v-77b70ba2]:hover,.background-selector .background[data-v-77b70ba2]:focus{border:2px solid var(--color-primary)}.background-selector .background.active[data-v-77b70ba2]:not(.icon-loading):after{background-image:var(--icon-checkmark-white);background-repeat:no-repeat;background-position:center;background-size:44px;content:\\\"\\\";display:block;height:100%}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/dashboard/src/components/BackgroundSettings.vue\"],\"names\":[],\"mappings\":\"AA4IA,sCACC,YAAA,CACA,cAAA,CACA,sBAAA,CAEA,kDACC,WAAA,CACA,WAAA,CACA,UAAA,CACA,qBAAA,CACA,iCAAA,CACA,iBAAA,CACA,wCAAA,CACA,6CAAA,CACA,eAAA,CAEA,0DACC,6CAAA,CAGD,+KACC,gCAAA,CAGD,wDACC,qCAAA,CACA,+BAAA,CAGD,yKAGC,qCAAA,CAGD,kFACC,4CAAA,CACA,2BAAA,CACA,0BAAA,CACA,oBAAA,CACA,UAAA,CACA,aAAA,CACA,WAAA\",\"sourcesContent\":[\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n.background-selector {\\n\\tdisplay: flex;\\n\\tflex-wrap: wrap;\\n\\tjustify-content: center;\\n\\n\\t.background {\\n\\t\\twidth: 176px;\\n\\t\\theight: 96px;\\n\\t\\tmargin: 8px;\\n\\t\\tbackground-size: cover;\\n\\t\\tbackground-position: center center;\\n\\t\\ttext-align: center;\\n\\t\\tborder-radius: var(--border-radius-large);\\n\\t\\tborder: 2px solid var(--color-main-background);\\n\\t\\toverflow: hidden;\\n\\n\\t\\t&.current {\\n\\t\\t\\tbackground-image: var(--color-background-dark);\\n\\t\\t}\\n\\n\\t\\t&.filepicker, &.default, &.color {\\n\\t\\t\\tborder-color: var(--color-border);\\n\\t\\t}\\n\\n\\t\\t&.color {\\n\\t\\t\\tbackground-color: var(--color-primary);\\n\\t\\t\\tcolor: var(--color-primary-text);\\n\\t\\t}\\n\\n\\t\\t&.active,\\n\\t\\t&:hover,\\n\\t\\t&:focus {\\n\\t\\t\\tborder: 2px solid var(--color-primary);\\n\\t\\t}\\n\\n\\t\\t&.active:not(.icon-loading):after {\\n\\t\\t\\tbackground-image: var(--icon-checkmark-white);\\n\\t\\t\\tbackground-repeat: no-repeat;\\n\\t\\t\\tbackground-position: center;\\n\\t\\t\\tbackground-size: 44px;\\n\\t\\t\\tcontent: '';\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\theight: 100%;\\n\\t\\t}\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"\\nhtml, body {\\n\\tbackground-attachment: fixed;\\n}\\n#body-user #header {\\n\\tposition: fixed;\\n}\\n#content {\\n\\toverflow: auto;\\n\\tposition: static !important;\\n}\\n\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/dashboard/src/DashboardApp.vue\"],\"names\":[],\"mappings\":\";AA4qBA;CACA,4BAAA;AACA;AAEA;CACA,eAAA;AACA;AAEA;CACA,cAAA;CACA,2BAAA;AACA\",\"sourcesContent\":[\"<template>\\n\\t<div id=\\\"app-dashboard\\\">\\n\\t\\t<h2>{{ greeting.text }}</h2>\\n\\t\\t<ul class=\\\"statuses\\\">\\n\\t\\t\\t<div v-for=\\\"status in sortedRegisteredStatus\\\"\\n\\t\\t\\t\\t:id=\\\"'status-' + status\\\"\\n\\t\\t\\t\\t:key=\\\"status\\\">\\n\\t\\t\\t\\t<div :ref=\\\"'status-' + status\\\" />\\n\\t\\t\\t</div>\\n\\t\\t</ul>\\n\\n\\t\\t<Draggable v-model=\\\"layout\\\"\\n\\t\\t\\tclass=\\\"panels\\\"\\n\\t\\t\\tv-bind=\\\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\\\"\\n\\t\\t\\thandle=\\\".panel--header\\\"\\n\\t\\t\\t@end=\\\"saveLayout\\\">\\n\\t\\t\\t<div v-for=\\\"panelId in layout\\\" :key=\\\"panels[panelId].id\\\" class=\\\"panel\\\">\\n\\t\\t\\t\\t<div class=\\\"panel--header\\\">\\n\\t\\t\\t\\t\\t<h2>\\n\\t\\t\\t\\t\\t\\t<div :class=\\\"panels[panelId].iconClass\\\" role=\\\"img\\\" />\\n\\t\\t\\t\\t\\t\\t{{ panels[panelId].title }}\\n\\t\\t\\t\\t\\t</h2>\\n\\t\\t\\t\\t</div>\\n\\t\\t\\t\\t<div class=\\\"panel--content\\\" :class=\\\"{ loading: !panels[panelId].mounted }\\\">\\n\\t\\t\\t\\t\\t<div :ref=\\\"panels[panelId].id\\\" :data-id=\\\"panels[panelId].id\\\" />\\n\\t\\t\\t\\t</div>\\n\\t\\t\\t</div>\\n\\t\\t</Draggable>\\n\\n\\t\\t<div class=\\\"footer\\\">\\n\\t\\t\\t<NcButton @click=\\\"showModal\\\">\\n\\t\\t\\t\\t<template #icon>\\n\\t\\t\\t\\t\\t<Pencil :size=\\\"20\\\" />\\n\\t\\t\\t\\t</template>\\n\\t\\t\\t\\t{{ t('dashboard', 'Customize') }}\\n\\t\\t\\t</NcButton>\\n\\t\\t</div>\\n\\n\\t\\t<NcModal v-if=\\\"modal\\\" size=\\\"large\\\" @close=\\\"closeModal\\\">\\n\\t\\t\\t<div class=\\\"modal__content\\\">\\n\\t\\t\\t\\t<h3>{{ t('dashboard', 'Edit widgets') }}</h3>\\n\\t\\t\\t\\t<ol class=\\\"panels\\\">\\n\\t\\t\\t\\t\\t<li v-for=\\\"status in sortedAllStatuses\\\" :key=\\\"status\\\" :class=\\\"'panel-' + status\\\">\\n\\t\\t\\t\\t\\t\\t<input :id=\\\"'status-checkbox-' + status\\\"\\n\\t\\t\\t\\t\\t\\t\\ttype=\\\"checkbox\\\"\\n\\t\\t\\t\\t\\t\\t\\tclass=\\\"checkbox\\\"\\n\\t\\t\\t\\t\\t\\t\\t:checked=\\\"isStatusActive(status)\\\"\\n\\t\\t\\t\\t\\t\\t\\t@input=\\\"updateStatusCheckbox(status, $event.target.checked)\\\">\\n\\t\\t\\t\\t\\t\\t<label :for=\\\"'status-checkbox-' + status\\\">\\n\\t\\t\\t\\t\\t\\t\\t<div :class=\\\"statusInfo[status].icon\\\" role=\\\"img\\\" />\\n\\t\\t\\t\\t\\t\\t\\t{{ statusInfo[status].text }}\\n\\t\\t\\t\\t\\t\\t</label>\\n\\t\\t\\t\\t\\t</li>\\n\\t\\t\\t\\t</ol>\\n\\t\\t\\t\\t<Draggable v-model=\\\"layout\\\"\\n\\t\\t\\t\\t\\tclass=\\\"panels\\\"\\n\\t\\t\\t\\t\\ttag=\\\"ol\\\"\\n\\t\\t\\t\\t\\tv-bind=\\\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\\\"\\n\\t\\t\\t\\t\\thandle=\\\".draggable\\\"\\n\\t\\t\\t\\t\\t@end=\\\"saveLayout\\\">\\n\\t\\t\\t\\t\\t<li v-for=\\\"panel in sortedPanels\\\" :key=\\\"panel.id\\\" :class=\\\"'panel-' + panel.id\\\">\\n\\t\\t\\t\\t\\t\\t<input :id=\\\"'panel-checkbox-' + panel.id\\\"\\n\\t\\t\\t\\t\\t\\t\\ttype=\\\"checkbox\\\"\\n\\t\\t\\t\\t\\t\\t\\tclass=\\\"checkbox\\\"\\n\\t\\t\\t\\t\\t\\t\\t:checked=\\\"isActive(panel)\\\"\\n\\t\\t\\t\\t\\t\\t\\t@input=\\\"updateCheckbox(panel, $event.target.checked)\\\">\\n\\t\\t\\t\\t\\t\\t<label :for=\\\"'panel-checkbox-' + panel.id\\\" :class=\\\"{ draggable: isActive(panel) }\\\">\\n\\t\\t\\t\\t\\t\\t\\t<div :class=\\\"panel.iconClass\\\" role=\\\"img\\\" />\\n\\t\\t\\t\\t\\t\\t\\t{{ panel.title }}\\n\\t\\t\\t\\t\\t\\t</label>\\n\\t\\t\\t\\t\\t</li>\\n\\t\\t\\t\\t</Draggable>\\n\\n\\t\\t\\t\\t<a v-if=\\\"isAdmin\\\" :href=\\\"appStoreUrl\\\" class=\\\"button\\\">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>\\n\\n\\t\\t\\t\\t<h3>{{ t('dashboard', 'Change background image') }}</h3>\\n\\t\\t\\t\\t<BackgroundSettings :background=\\\"background\\\"\\n\\t\\t\\t\\t\\t:theming-default-background=\\\"themingDefaultBackground\\\"\\n\\t\\t\\t\\t\\t@update:background=\\\"updateBackground\\\" />\\n\\n\\t\\t\\t\\t<h3>{{ t('dashboard', 'Weather service') }}</h3>\\n\\t\\t\\t\\t<p>\\n\\t\\t\\t\\t\\t{{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}\\n\\t\\t\\t\\t</p>\\n\\t\\t\\t\\t<p class=\\\"credits--end\\\">\\n\\t\\t\\t\\t\\t<a href=\\\"https://api.met.no/doc/TermsOfService\\\" target=\\\"_blank\\\" rel=\\\"noopener\\\">{{ t('dashboard', 'Weather data from Met.no') }}</a>,\\n\\t\\t\\t\\t\\t<a href=\\\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\\\" target=\\\"_blank\\\" rel=\\\"noopener\\\">{{ t('dashboard', 'geocoding with Nominatim') }}</a>,\\n\\t\\t\\t\\t\\t<a href=\\\"https://www.opentopodata.org/#public-api\\\" target=\\\"_blank\\\" rel=\\\"noopener\\\">{{ t('dashboard', 'elevation data from OpenTopoData') }}</a>.\\n\\t\\t\\t\\t</p>\\n\\t\\t\\t</div>\\n\\t\\t</NcModal>\\n\\t</div>\\n</template>\\n\\n<script>\\nimport { generateUrl } from '@nextcloud/router'\\nimport { getCurrentUser } from '@nextcloud/auth'\\nimport { loadState } from '@nextcloud/initial-state'\\nimport axios from '@nextcloud/axios'\\nimport NcButton from '@nextcloud/vue/dist/Components/NcButton'\\nimport Draggable from 'vuedraggable'\\nimport NcModal from '@nextcloud/vue/dist/Components/NcModal'\\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\\nimport Vue from 'vue'\\n\\nimport isMobile from './mixins/isMobile'\\nimport BackgroundSettings from './components/BackgroundSettings'\\nimport getBackgroundUrl from './helpers/getBackgroundUrl'\\n\\nconst panels = loadState('dashboard', 'panels')\\nconst firstRun = loadState('dashboard', 'firstRun')\\nconst background = loadState('dashboard', 'background')\\nconst themingDefaultBackground = loadState('dashboard', 'themingDefaultBackground')\\nconst version = loadState('dashboard', 'version')\\nconst shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')\\n\\nconst statusInfo = {\\n\\tweather: {\\n\\t\\ttext: t('dashboard', 'Weather'),\\n\\t\\ticon: 'icon-weather-status',\\n\\t},\\n\\tstatus: {\\n\\t\\ttext: t('dashboard', 'Status'),\\n\\t\\ticon: 'icon-user-status-online',\\n\\t},\\n}\\n\\nexport default {\\n\\tname: 'DashboardApp',\\n\\tcomponents: {\\n\\t\\tBackgroundSettings,\\n\\t\\tNcButton,\\n\\t\\tDraggable,\\n\\t\\tNcModal,\\n\\t\\tPencil,\\n\\t},\\n\\tmixins: [\\n\\t\\tisMobile,\\n\\t],\\n\\n\\tdata() {\\n\\t\\treturn {\\n\\t\\t\\tisAdmin: getCurrentUser().isAdmin,\\n\\t\\t\\ttimer: new Date(),\\n\\t\\t\\tregisteredStatus: [],\\n\\t\\t\\tcallbacks: {},\\n\\t\\t\\tcallbacksStatus: {},\\n\\t\\t\\tallCallbacksStatus: {},\\n\\t\\t\\tstatusInfo,\\n\\t\\t\\tenabledStatuses: loadState('dashboard', 'statuses'),\\n\\t\\t\\tpanels,\\n\\t\\t\\tfirstRun,\\n\\t\\t\\tdisplayName: getCurrentUser()?.displayName,\\n\\t\\t\\tuid: getCurrentUser()?.uid,\\n\\t\\t\\tlayout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),\\n\\t\\t\\tmodal: false,\\n\\t\\t\\tappStoreUrl: generateUrl('/settings/apps/dashboard'),\\n\\t\\t\\tstatuses: {},\\n\\t\\t\\tbackground,\\n\\t\\t\\tthemingDefaultBackground,\\n\\t\\t\\tversion,\\n\\t\\t}\\n\\t},\\n\\tcomputed: {\\n\\t\\tbackgroundImage() {\\n\\t\\t\\treturn getBackgroundUrl(this.background, this.version, this.themingDefaultBackground)\\n\\t\\t},\\n\\t\\tbackgroundStyle() {\\n\\t\\t\\tif ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')\\n\\t\\t\\t\\t|| this.background.match(/#[0-9A-Fa-f]{6}/g)) {\\n\\t\\t\\t\\treturn null\\n\\t\\t\\t}\\n\\n\\t\\t\\treturn {\\n\\t\\t\\t\\tbackgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,\\n\\t\\t\\t}\\n\\t\\t},\\n\\n\\t\\tgreeting() {\\n\\t\\t\\tconst time = this.timer.getHours()\\n\\n\\t\\t\\t// Determine part of the day\\n\\t\\t\\tlet partOfDay\\n\\t\\t\\tif (time >= 22 || time < 5) {\\n\\t\\t\\t\\tpartOfDay = 'night'\\n\\t\\t\\t} else if (time >= 18) {\\n\\t\\t\\t\\tpartOfDay = 'evening'\\n\\t\\t\\t} else if (time >= 12) {\\n\\t\\t\\t\\tpartOfDay = 'afternoon'\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tpartOfDay = 'morning'\\n\\t\\t\\t}\\n\\n\\t\\t\\t// Define the greetings\\n\\t\\t\\tconst good = {\\n\\t\\t\\t\\tmorning: {\\n\\t\\t\\t\\t\\tgeneric: t('dashboard', 'Good morning'),\\n\\t\\t\\t\\t\\twithName: t('dashboard', 'Good morning, {name}', { name: this.displayName }, undefined, { escape: false }),\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tafternoon: {\\n\\t\\t\\t\\t\\tgeneric: t('dashboard', 'Good afternoon'),\\n\\t\\t\\t\\t\\twithName: t('dashboard', 'Good afternoon, {name}', { name: this.displayName }, undefined, { escape: false }),\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tevening: {\\n\\t\\t\\t\\t\\tgeneric: t('dashboard', 'Good evening'),\\n\\t\\t\\t\\t\\twithName: t('dashboard', 'Good evening, {name}', { name: this.displayName }, undefined, { escape: false }),\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tnight: {\\n\\t\\t\\t\\t\\t// Don't use \\\"Good night\\\" as it's not a greeting\\n\\t\\t\\t\\t\\tgeneric: t('dashboard', 'Hello'),\\n\\t\\t\\t\\t\\twithName: t('dashboard', 'Hello, {name}', { name: this.displayName }, undefined, { escape: false }),\\n\\t\\t\\t\\t},\\n\\t\\t\\t}\\n\\n\\t\\t\\t// Figure out which greeting to show\\n\\t\\t\\tconst shouldShowName = this.displayName && this.uid !== this.displayName\\n\\t\\t\\treturn { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }\\n\\t\\t},\\n\\n\\t\\tisActive() {\\n\\t\\t\\treturn (panel) => this.layout.indexOf(panel.id) > -1\\n\\t\\t},\\n\\t\\tisStatusActive() {\\n\\t\\t\\treturn (status) => !(status in this.enabledStatuses) || this.enabledStatuses[status]\\n\\t\\t},\\n\\n\\t\\tsortedAllStatuses() {\\n\\t\\t\\treturn Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)\\n\\t\\t},\\n\\t\\tsortedPanels() {\\n\\t\\t\\treturn Object.values(this.panels).sort((a, b) => {\\n\\t\\t\\t\\tconst indexA = this.layout.indexOf(a.id)\\n\\t\\t\\t\\tconst indexB = this.layout.indexOf(b.id)\\n\\t\\t\\t\\tif (indexA === -1 || indexB === -1) {\\n\\t\\t\\t\\t\\treturn indexB - indexA || a.id - b.id\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn indexA - indexB || a.id - b.id\\n\\t\\t\\t})\\n\\t\\t},\\n\\t\\tsortedRegisteredStatus() {\\n\\t\\t\\treturn this.registeredStatus.slice().sort(this.sortStatuses)\\n\\t\\t},\\n\\t},\\n\\n\\twatch: {\\n\\t\\tcallbacks() {\\n\\t\\t\\tthis.rerenderPanels()\\n\\t\\t},\\n\\t\\tcallbacksStatus() {\\n\\t\\t\\tfor (const app in this.callbacksStatus) {\\n\\t\\t\\t\\tconst element = this.$refs['status-' + app]\\n\\t\\t\\t\\tif (this.statuses[app] && this.statuses[app].mounted) {\\n\\t\\t\\t\\t\\tcontinue\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\tthis.callbacksStatus[app](element[0])\\n\\t\\t\\t\\t\\tVue.set(this.statuses, app, { mounted: true })\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t},\\n\\t},\\n\\n\\tmounted() {\\n\\t\\tthis.updateGlobalStyles()\\n\\t\\tthis.updateSkipLink()\\n\\t\\twindow.addEventListener('scroll', this.handleScroll)\\n\\n\\t\\tsetInterval(() => {\\n\\t\\t\\tthis.timer = new Date()\\n\\t\\t}, 30000)\\n\\n\\t\\tif (this.firstRun) {\\n\\t\\t\\twindow.addEventListener('scroll', this.disableFirstrunHint)\\n\\t\\t}\\n\\t},\\n\\tdestroyed() {\\n\\t\\twindow.removeEventListener('scroll', this.handleScroll)\\n\\t},\\n\\n\\tmethods: {\\n\\t\\t/**\\n\\t\\t * Method to register panels that will be called by the integrating apps\\n\\t\\t *\\n\\t\\t * @param {string} app The unique app id for the widget\\n\\t\\t * @param {Function} callback The callback function to register a panel which gets the DOM element passed as parameter\\n\\t\\t */\\n\\t\\tregister(app, callback) {\\n\\t\\t\\tVue.set(this.callbacks, app, callback)\\n\\t\\t},\\n\\t\\tregisterStatus(app, callback) {\\n\\t\\t\\t// always save callbacks in case user enables the status later\\n\\t\\t\\tVue.set(this.allCallbacksStatus, app, callback)\\n\\t\\t\\t// register only if status is enabled or missing from config\\n\\t\\t\\tif (this.isStatusActive(app)) {\\n\\t\\t\\t\\tthis.registeredStatus.push(app)\\n\\t\\t\\t\\tthis.$nextTick(() => {\\n\\t\\t\\t\\t\\tVue.set(this.callbacksStatus, app, callback)\\n\\t\\t\\t\\t})\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\trerenderPanels() {\\n\\t\\t\\tfor (const app in this.callbacks) {\\n\\t\\t\\t\\tconst element = this.$refs[app]\\n\\t\\t\\t\\tif (this.layout.indexOf(app) === -1) {\\n\\t\\t\\t\\t\\tcontinue\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.panels[app] && this.panels[app].mounted) {\\n\\t\\t\\t\\t\\tcontinue\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\tthis.callbacks[app](element[0], {\\n\\t\\t\\t\\t\\t\\twidget: this.panels[app],\\n\\t\\t\\t\\t\\t})\\n\\t\\t\\t\\t\\tVue.set(this.panels[app], 'mounted', true)\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\tsaveLayout() {\\n\\t\\t\\taxios.post(generateUrl('/apps/dashboard/layout'), {\\n\\t\\t\\t\\tlayout: this.layout.join(','),\\n\\t\\t\\t})\\n\\t\\t},\\n\\t\\tsaveStatuses() {\\n\\t\\t\\taxios.post(generateUrl('/apps/dashboard/statuses'), {\\n\\t\\t\\t\\tstatuses: JSON.stringify(this.enabledStatuses),\\n\\t\\t\\t})\\n\\t\\t},\\n\\t\\tshowModal() {\\n\\t\\t\\tthis.modal = true\\n\\t\\t\\tthis.firstRun = false\\n\\t\\t},\\n\\t\\tcloseModal() {\\n\\t\\t\\tthis.modal = false\\n\\t\\t},\\n\\t\\tupdateCheckbox(panel, currentValue) {\\n\\t\\t\\tconst index = this.layout.indexOf(panel.id)\\n\\t\\t\\tif (!currentValue && index > -1) {\\n\\t\\t\\t\\tthis.layout.splice(index, 1)\\n\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.layout.push(panel.id)\\n\\t\\t\\t}\\n\\t\\t\\tVue.set(this.panels[panel.id], 'mounted', false)\\n\\t\\t\\tthis.saveLayout()\\n\\t\\t\\tthis.$nextTick(() => this.rerenderPanels())\\n\\t\\t},\\n\\t\\tdisableFirstrunHint() {\\n\\t\\t\\twindow.removeEventListener('scroll', this.disableFirstrunHint)\\n\\t\\t\\tsetTimeout(() => {\\n\\t\\t\\t\\tthis.firstRun = false\\n\\t\\t\\t}, 1000)\\n\\t\\t},\\n\\t\\tupdateBackground(data) {\\n\\t\\t\\tthis.background = data.type === 'custom' || data.type === 'default' ? data.type : data.value\\n\\t\\t\\tthis.version = data.version\\n\\t\\t\\tthis.updateGlobalStyles()\\n\\t\\t},\\n\\t\\tupdateGlobalStyles() {\\n\\t\\t\\t// Override primary-invert-if-bright and color-primary-text if background is set\\n\\t\\t\\tconst isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'\\n\\t\\t\\tif (isBackgroundBright) {\\n\\t\\t\\t\\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')\\n\\t\\t\\t\\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#000000')\\n\\t\\t\\t\\t// document.body.removeAttribute('data-theme-dark')\\n\\t\\t\\t\\t// document.body.setAttribute('data-theme-light', 'true')\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')\\n\\t\\t\\t\\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')\\n\\t\\t\\t\\t// document.body.removeAttribute('data-theme-light')\\n\\t\\t\\t\\t// document.body.setAttribute('data-theme-dark', 'true')\\n\\t\\t\\t}\\n\\n\\t\\t\\tdocument.documentElement.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\\n\\t\\t\\tdocument.querySelector('#header').style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\\n\\t\\t\\tdocument.querySelector('body').style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\\n\\t\\t},\\n\\t\\tupdateSkipLink() {\\n\\t\\t\\t// Make sure \\\"Skip to main content\\\" link points to the app content\\n\\t\\t\\tdocument.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')\\n\\t\\t},\\n\\t\\tupdateStatusCheckbox(app, checked) {\\n\\t\\t\\tif (checked) {\\n\\t\\t\\t\\tthis.enableStatus(app)\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.disableStatus(app)\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\tenableStatus(app) {\\n\\t\\t\\tthis.enabledStatuses[app] = true\\n\\t\\t\\tthis.registerStatus(app, this.allCallbacksStatus[app])\\n\\t\\t\\tthis.saveStatuses()\\n\\t\\t},\\n\\t\\tdisableStatus(app) {\\n\\t\\t\\tthis.enabledStatuses[app] = false\\n\\t\\t\\tconst i = this.registeredStatus.findIndex((s) => s === app)\\n\\t\\t\\tif (i !== -1) {\\n\\t\\t\\t\\tthis.registeredStatus.splice(i, 1)\\n\\t\\t\\t\\tVue.set(this.statuses, app, { mounted: false })\\n\\t\\t\\t\\tthis.$nextTick(() => {\\n\\t\\t\\t\\t\\tVue.delete(this.callbacksStatus, app)\\n\\t\\t\\t\\t})\\n\\t\\t\\t}\\n\\t\\t\\tthis.saveStatuses()\\n\\t\\t},\\n\\t\\tsortStatuses(a, b) {\\n\\t\\t\\tconst al = a.toLowerCase()\\n\\t\\t\\tconst bl = b.toLowerCase()\\n\\t\\t\\treturn al > bl\\n\\t\\t\\t\\t? 1\\n\\t\\t\\t\\t: al < bl\\n\\t\\t\\t\\t\\t? -1\\n\\t\\t\\t\\t\\t: 0\\n\\t\\t},\\n\\t\\thandleScroll() {\\n\\t\\t\\tif (window.scrollY > 70) {\\n\\t\\t\\t\\tdocument.body.classList.add('dashboard--scrolled')\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdocument.body.classList.remove('dashboard--scrolled')\\n\\t\\t\\t}\\n\\t\\t},\\n\\t},\\n}\\n</script>\\n\\n<style lang=\\\"scss\\\" scoped>\\n#app-dashboard {\\n\\twidth: 100%;\\n\\tmin-height: 100%;\\n\\tbackground-size: cover;\\n\\tbackground-position: center center;\\n\\tbackground-repeat: no-repeat;\\n\\tbackground-attachment: fixed;\\n\\n\\t> h2 {\\n\\t\\tcolor: var(--color-primary-text);\\n\\t\\ttext-align: center;\\n\\t\\tfont-size: 32px;\\n\\t\\tline-height: 130%;\\n\\t\\tpadding: 1rem 0;\\n\\t}\\n}\\n\\n.panels {\\n\\twidth: auto;\\n\\tmargin: auto;\\n\\tmax-width: 1500px;\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n\\tflex-direction: row;\\n\\talign-items: flex-start;\\n\\tflex-wrap: wrap;\\n}\\n\\n.panel, .panels > div {\\n\\twidth: 320px;\\n\\tmax-width: 100%;\\n\\tmargin: 16px;\\n\\tbackground-color: var(--color-main-background-blur);\\n\\t-webkit-backdrop-filter: var(--filter-background-blur);\\n\\tbackdrop-filter: var(--filter-background-blur);\\n\\tborder-radius: var(--border-radius-large);\\n\\n\\t#body-user.theme--highcontrast & {\\n\\t\\tborder: 2px solid var(--color-border);\\n\\t}\\n\\n\\t&.sortable-ghost {\\n\\t\\t opacity: 0.1;\\n\\t}\\n\\n\\t& > .panel--header {\\n\\t\\tdisplay: flex;\\n\\t\\tz-index: 1;\\n\\t\\ttop: 50px;\\n\\t\\tpadding: 16px;\\n\\t\\tcursor: grab;\\n\\n\\t\\t&, ::v-deep * {\\n\\t\\t\\t-webkit-touch-callout: none;\\n\\t\\t\\t-webkit-user-select: none;\\n\\t\\t\\t-khtml-user-select: none;\\n\\t\\t\\t-moz-user-select: none;\\n\\t\\t\\t-ms-user-select: none;\\n\\t\\t\\tuser-select: none;\\n\\t\\t}\\n\\n\\t\\t&:active {\\n\\t\\t\\tcursor: grabbing;\\n\\t\\t}\\n\\n\\t\\ta {\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t}\\n\\n\\t\\t> h2 {\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\talign-items: center;\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t\\tmargin: 0;\\n\\t\\t\\tfont-size: 20px;\\n\\t\\t\\tline-height: 24px;\\n\\t\\t\\tfont-weight: bold;\\n\\t\\t\\tpadding: 16px 8px;\\n\\t\\t\\theight: 56px;\\n\\t\\t\\twhite-space: nowrap;\\n\\t\\t\\toverflow: hidden;\\n\\t\\t\\ttext-overflow: ellipsis;\\n\\t\\t\\tcursor: grab;\\n\\t\\t\\tdiv {\\n\\t\\t\\t\\tbackground-size: 32px;\\n\\t\\t\\t\\twidth: 32px;\\n\\t\\t\\t\\theight: 32px;\\n\\t\\t\\t\\tmargin-right: 16px;\\n\\t\\t\\t\\tbackground-position: center;\\n\\t\\t\\t\\tfloat: left;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\n\\t& > .panel--content {\\n\\t\\tmargin: 0 16px 16px 16px;\\n\\t\\theight: 424px;\\n\\t\\t// We specifically do not want scrollbars inside widgets\\n\\t\\toverflow: visible;\\n\\t}\\n\\n\\t// No need to extend height of widgets if only one column is shown\\n\\t@media only screen and (max-width: 709px) {\\n\\t\\t& > .panel--content {\\n\\t\\t\\theight: auto;\\n\\t\\t}\\n\\t}\\n}\\n\\n.footer {\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n\\ttransition: bottom var(--animation-slow) ease-in-out;\\n\\tpadding: 1rem 0;\\n}\\n\\n.edit-panels {\\n\\tdisplay: inline-block;\\n\\tmargin:auto;\\n\\tbackground-position: 16px center;\\n\\tpadding: 12px 16px;\\n\\tpadding-left: 36px;\\n\\tborder-radius: var(--border-radius-pill);\\n\\tmax-width: 200px;\\n\\topacity: 1;\\n\\ttext-align: center;\\n}\\n\\n.button,\\n.button-vue,\\n.edit-panels,\\n.statuses ::v-deep .action-item .action-item__menutoggle,\\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\\n\\tbackground-color: var(--color-main-background-blur);\\n\\t-webkit-backdrop-filter: var(--filter-background-blur);\\n\\tbackdrop-filter: var(--filter-background-blur);\\n\\topacity: 1 !important;\\n\\n\\t&:hover,\\n\\t&:focus,\\n\\t&:active {\\n\\t\\tbackground-color: var(--color-background-hover)!important;\\n\\t}\\n\\t&:focus-visible {\\n\\t\\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\\n\\t}\\n}\\n\\n.modal__content {\\n\\tpadding: 32px 16px;\\n\\ttext-align: center;\\n\\n\\tol {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-direction: row;\\n\\t\\tjustify-content: center;\\n\\t\\tlist-style-type: none;\\n\\t\\tpadding-bottom: 16px;\\n\\t}\\n\\tli {\\n\\t\\tlabel {\\n\\t\\t\\tposition: relative;\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\tpadding: 48px 16px 14px 16px;\\n\\t\\t\\tmargin: 8px;\\n\\t\\t\\twidth: 140px;\\n\\t\\t\\tbackground-color: var(--color-background-hover);\\n\\t\\t\\tborder: 2px solid var(--color-main-background);\\n\\t\\t\\tborder-radius: var(--border-radius-large);\\n\\t\\t\\ttext-align: left;\\n\\t\\t\\toverflow: hidden;\\n\\t\\t\\ttext-overflow: ellipsis;\\n\\t\\t\\twhite-space: nowrap;\\n\\n\\t\\t\\tdiv {\\n\\t\\t\\t\\tposition: absolute;\\n\\t\\t\\t\\ttop: 16px;\\n\\t\\t\\t\\twidth: 24px;\\n\\t\\t\\t\\theight: 24px;\\n\\t\\t\\t\\tbackground-size: 24px;\\n\\t\\t\\t}\\n\\n\\t\\t\\t&:hover {\\n\\t\\t\\t\\tborder-color: var(--color-primary);\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\t// Do not invert status icons\\n\\t\\t&:not(.panel-status) label div {\\n\\t\\t\\tfilter: var(--background-invert-if-dark);\\n\\t\\t}\\n\\n\\t\\tinput[type='checkbox'].checkbox + label:before {\\n\\t\\t\\tposition: absolute;\\n\\t\\t\\tright: 12px;\\n\\t\\t\\ttop: 16px;\\n\\t\\t}\\n\\n\\t\\tinput:focus + label {\\n\\t\\t\\tborder-color: var(--color-primary);\\n\\t\\t}\\n\\t}\\n\\n\\th3 {\\n\\t\\tfont-weight: bold;\\n\\n\\t\\t&:not(:first-of-type) {\\n\\t\\t\\tmargin-top: 64px;\\n\\t\\t}\\n\\t}\\n\\n\\t// Adjust design of 'Get more widgets' button\\n\\t.button {\\n\\t\\tdisplay: inline-block;\\n\\t\\tpadding: 10px 16px;\\n\\t\\tmargin: 0;\\n\\t}\\n\\n\\tp {\\n\\t\\tmax-width: 650px;\\n\\t\\tmargin: 0 auto;\\n\\n\\t\\ta:hover,\\n\\t\\ta:focus {\\n\\t\\t\\tborder-bottom: 2px solid var(--color-border);\\n\\t\\t}\\n\\t}\\n\\n\\t.credits--end {\\n\\t\\tpadding-bottom: 32px;\\n\\t\\tcolor: var(--color-text-maxcontrast);\\n\\n\\t\\ta {\\n\\t\\t\\tcolor: var(--color-text-maxcontrast);\\n\\t\\t}\\n\\t}\\n}\\n\\n.flip-list-move {\\n\\ttransition: transform var(--animation-slow);\\n}\\n\\n.statuses {\\n\\tdisplay: flex;\\n\\tflex-direction: row;\\n\\tjustify-content: center;\\n\\tflex-wrap: wrap;\\n\\tmargin-bottom: 36px;\\n\\n\\t& > div {\\n\\t\\tmargin: 8px;\\n\\t}\\n}\\n</style>\\n<style>\\nhtml, body {\\n\\tbackground-attachment: fixed;\\n}\\n\\n#body-user #header {\\n\\tposition: fixed;\\n}\\n\\n#content {\\n\\toverflow: auto;\\n\\tposition: static !important;;\\n}\\n</style>\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdD = function () {\n\tthrow new Error('define cannot be used indirect');\n};","__webpack_require__.amdO = {};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 4773;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t4773: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknextcloud\"] = self[\"webpackChunknextcloud\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [7874], function() { return __webpack_require__(18719); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","data","isMobile","this","_isMobile","beforeMount","window","addEventListener","_onResize","beforeDestroy","removeEventListener","methods","document","documentElement","clientWidth","url","generateFilePath","background","time","themingDefaultBackground","enabledThemes","OCA","Theming","isDarkTheme","length","matchMedia","matches","join","indexOf","generateUrl","cacheBuster","prefixWithBaseUrl","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","_vm","_h","$createElement","_c","_self","staticClass","class","active","attrs","on","pickFile","_v","_s","t","loading","setDefault","pickColor","_l","shippedBackground","directives","name","rawName","value","details","expression","key","style","preview","$event","setShipped","greeting","text","status","ref","refInFor","_b","saveLayout","model","callback","$$v","layout","swapThreshold","delay","delayOnTouchOnly","touchStartThreshold","panelId","panels","id","iconClass","title","mounted","showModal","scopedSlots","_u","fn","proxy","closeModal","domProps","isStatusActive","updateStatusCheckbox","target","checked","statusInfo","icon","panel","isActive","updateCheckbox","draggable","appStoreUrl","_e","updateBackground","__webpack_nonce__","btoa","getRequestToken","Vue","VTooltip","Files","Object","assign","App","fileList","filesClient","OC","getClient","Instance","DashboardApp","$mount","Dashboard","register","app","registerStatus","___CSS_LOADER_EXPORT___","push","module","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","loaded","__webpack_modules__","call","m","amdD","Error","amdO","O","result","chunkIds","priority","notFulfilled","Infinity","i","fulfilled","j","keys","every","splice","r","n","getter","__esModule","d","a","definition","o","defineProperty","enumerable","get","g","globalThis","Function","e","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","nmd","paths","children","b","baseURI","self","location","href","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","forEach","bind","nc","__webpack_exports__"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"file":"dashboard-main.js?v=c4ee8754e5b77ec4b538","mappings":"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","sources":["webpack:///nextcloud/webpack/runtime/chunk loaded","webpack:///nextcloud/apps/dashboard/src/mixins/isMobile.js","webpack:///nextcloud/apps/dashboard/src/helpers/prefixWithBaseUrl.js","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue","webpack:///nextcloud/apps/dashboard/src/helpers/getBackgroundUrl.js","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue?vue&type=script&lang=js&","webpack://nextcloud/./apps/dashboard/src/DashboardApp.vue?76d0","webpack://nextcloud/./apps/dashboard/src/DashboardApp.vue?8e53","webpack://nextcloud/./apps/dashboard/src/DashboardApp.vue?5685","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue?vue&type=template&id=55a1daf8&scoped=true&","webpack:///nextcloud/apps/dashboard/src/main.js","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue?vue&type=style&index=0&id=55a1daf8&lang=scss&scoped=true&","webpack:///nextcloud/apps/dashboard/src/DashboardApp.vue?vue&type=style&index=1&lang=css&","webpack:///nextcloud/webpack/bootstrap","webpack:///nextcloud/webpack/runtime/amd define","webpack:///nextcloud/webpack/runtime/amd options","webpack:///nextcloud/webpack/runtime/compat get default export","webpack:///nextcloud/webpack/runtime/define property getters","webpack:///nextcloud/webpack/runtime/global","webpack:///nextcloud/webpack/runtime/hasOwnProperty shorthand","webpack:///nextcloud/webpack/runtime/make namespace object","webpack:///nextcloud/webpack/runtime/node module decorator","webpack:///nextcloud/webpack/runtime/runtimeId","webpack:///nextcloud/webpack/runtime/jsonp chunk loading","webpack:///nextcloud/webpack/runtime/nonce","webpack:///nextcloud/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","/**\n * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n *\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tisMobile: this._isMobile(),\n\t\t}\n\t},\n\tbeforeMount() {\n\t\twindow.addEventListener('resize', this._onResize)\n\t},\n\tbeforeDestroy() {\n\t\twindow.removeEventListener('resize', this._onResize)\n\t},\n\tmethods: {\n\t\t_onResize() {\n\t\t\t// Update mobile mode\n\t\t\tthis.isMobile = this._isMobile()\n\t\t},\n\t\t_isMobile() {\n\t\t\t// check if content width is under 768px\n\t\t\treturn document.documentElement.clientWidth < 768\n\t\t},\n\t},\n}\n","/**\n * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n *\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport { generateFilePath } from '@nextcloud/router'\n\nexport const prefixWithBaseUrl = (url) => generateFilePath('theming', '', 'img/background/') + url\n","<template>\n\t<div id=\"app-dashboard\">\n\t\t<h2>{{ greeting.text }}</h2>\n\t\t<ul class=\"statuses\">\n\t\t\t<div v-for=\"status in sortedRegisteredStatus\"\n\t\t\t\t:id=\"'status-' + status\"\n\t\t\t\t:key=\"status\">\n\t\t\t\t<div :ref=\"'status-' + status\" />\n\t\t\t</div>\n\t\t</ul>\n\n\t\t<Draggable v-model=\"layout\"\n\t\t\tclass=\"panels\"\n\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\thandle=\".panel--header\"\n\t\t\t@end=\"saveLayout\">\n\t\t\t<div v-for=\"panelId in layout\" :key=\"panels[panelId].id\" class=\"panel\">\n\t\t\t\t<div class=\"panel--header\">\n\t\t\t\t\t<h2>\n\t\t\t\t\t\t<div :class=\"panels[panelId].iconClass\" role=\"img\" />\n\t\t\t\t\t\t{{ panels[panelId].title }}\n\t\t\t\t\t</h2>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"panel--content\" :class=\"{ loading: !panels[panelId].mounted }\">\n\t\t\t\t\t<div :ref=\"panels[panelId].id\" :data-id=\"panels[panelId].id\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Draggable>\n\n\t\t<div class=\"footer\">\n\t\t\t<NcButton @click=\"showModal\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('dashboard', 'Customize') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcModal v-if=\"modal\" size=\"large\" @close=\"closeModal\">\n\t\t\t<div class=\"modal__content\">\n\t\t\t\t<h3>{{ t('dashboard', 'Edit widgets') }}</h3>\n\t\t\t\t<ol class=\"panels\">\n\t\t\t\t\t<li v-for=\"status in sortedAllStatuses\" :key=\"status\" :class=\"'panel-' + status\">\n\t\t\t\t\t\t<input :id=\"'status-checkbox-' + status\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isStatusActive(status)\"\n\t\t\t\t\t\t\t@input=\"updateStatusCheckbox(status, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'status-checkbox-' + status\">\n\t\t\t\t\t\t\t<div :class=\"statusInfo[status].icon\" role=\"img\" />\n\t\t\t\t\t\t\t{{ statusInfo[status].text }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</ol>\n\t\t\t\t<Draggable v-model=\"layout\"\n\t\t\t\t\tclass=\"panels\"\n\t\t\t\t\ttag=\"ol\"\n\t\t\t\t\tv-bind=\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\"\n\t\t\t\t\thandle=\".draggable\"\n\t\t\t\t\t@end=\"saveLayout\">\n\t\t\t\t\t<li v-for=\"panel in sortedPanels\" :key=\"panel.id\" :class=\"'panel-' + panel.id\">\n\t\t\t\t\t\t<input :id=\"'panel-checkbox-' + panel.id\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"checkbox\"\n\t\t\t\t\t\t\t:checked=\"isActive(panel)\"\n\t\t\t\t\t\t\t@input=\"updateCheckbox(panel, $event.target.checked)\">\n\t\t\t\t\t\t<label :for=\"'panel-checkbox-' + panel.id\" :class=\"{ draggable: isActive(panel) }\">\n\t\t\t\t\t\t\t<div :class=\"panel.iconClass\" role=\"img\" />\n\t\t\t\t\t\t\t{{ panel.title }}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t</Draggable>\n\n\t\t\t\t<a v-if=\"isAdmin\" :href=\"appStoreUrl\" class=\"button\">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>\n\n\t\t\t\t<h3>{{ t('dashboard', 'Weather service') }}</h3>\n\t\t\t\t<p>\n\t\t\t\t\t{{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}\n\t\t\t\t</p>\n\t\t\t\t<p class=\"credits--end\">\n\t\t\t\t\t<a href=\"https://api.met.no/doc/TermsOfService\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'Weather data from Met.no') }}</a>,\n\t\t\t\t\t<a href=\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'geocoding with Nominatim') }}</a>,\n\t\t\t\t\t<a href=\"https://www.opentopodata.org/#public-api\" target=\"_blank\" rel=\"noopener\">{{ t('dashboard', 'elevation data from OpenTopoData') }}</a>.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcModal>\n\t</div>\n</template>\n\n<script>\nimport { generateUrl, imagePath } from '@nextcloud/router'\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { loadState } from '@nextcloud/initial-state'\nimport axios from '@nextcloud/axios'\nimport NcButton from '@nextcloud/vue/dist/Components/NcButton'\nimport Draggable from 'vuedraggable'\nimport NcModal from '@nextcloud/vue/dist/Components/NcModal'\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\nimport Vue from 'vue'\n\nimport isMobile from './mixins/isMobile.js'\nimport { getBackgroundUrl } from './helpers/getBackgroundUrl.js'\n\nconst panels = loadState('dashboard', 'panels')\nconst firstRun = loadState('dashboard', 'firstRun')\n\nconst background = loadState('theming', 'background')\nconst backgroundVersion = loadState('theming', 'backgroundVersion')\nconst themingDefaultBackground = loadState('theming', 'themingDefaultBackground')\nconst shippedBackgroundList = loadState('theming', 'shippedBackgrounds')\n\nconst statusInfo = {\n\tweather: {\n\t\ttext: t('dashboard', 'Weather'),\n\t\ticon: 'icon-weather-status',\n\t},\n\tstatus: {\n\t\ttext: t('dashboard', 'Status'),\n\t\ticon: 'icon-user-status-online',\n\t},\n}\n\nexport default {\n\tname: 'DashboardApp',\n\tcomponents: {\n\t\tNcButton,\n\t\tDraggable,\n\t\tNcModal,\n\t\tPencil,\n\t},\n\tmixins: [\n\t\tisMobile,\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\tisAdmin: getCurrentUser().isAdmin,\n\t\t\ttimer: new Date(),\n\t\t\tregisteredStatus: [],\n\t\t\tcallbacks: {},\n\t\t\tcallbacksStatus: {},\n\t\t\tallCallbacksStatus: {},\n\t\t\tstatusInfo,\n\t\t\tenabledStatuses: loadState('dashboard', 'statuses'),\n\t\t\tpanels,\n\t\t\tfirstRun,\n\t\t\tdisplayName: getCurrentUser()?.displayName,\n\t\t\tuid: getCurrentUser()?.uid,\n\t\t\tlayout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),\n\t\t\tmodal: false,\n\t\t\tappStoreUrl: generateUrl('/settings/apps/dashboard'),\n\t\t\tstatuses: {},\n\t\t\tbackground,\n\t\t\tthemingDefaultBackground,\n\t\t}\n\t},\n\tcomputed: {\n\t\tbackgroundImage() {\n\t\t\treturn getBackgroundUrl(this.background, backgroundVersion, this.themingDefaultBackground)\n\t\t},\n\t\tbackgroundStyle() {\n\t\t\tif ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')\n\t\t\t\t|| this.background.match(/#[0-9A-Fa-f]{6}/g)) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tbackgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,\n\t\t\t}\n\t\t},\n\t\tgreeting() {\n\t\t\tconst time = this.timer.getHours()\n\n\t\t\t// Determine part of the day\n\t\t\tlet partOfDay\n\t\t\tif (time >= 22 || time < 5) {\n\t\t\t\tpartOfDay = 'night'\n\t\t\t} else if (time >= 18) {\n\t\t\t\tpartOfDay = 'evening'\n\t\t\t} else if (time >= 12) {\n\t\t\t\tpartOfDay = 'afternoon'\n\t\t\t} else {\n\t\t\t\tpartOfDay = 'morning'\n\t\t\t}\n\n\t\t\t// Define the greetings\n\t\t\tconst good = {\n\t\t\t\tmorning: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good morning'),\n\t\t\t\t\twithName: t('dashboard', 'Good morning, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tafternoon: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good afternoon'),\n\t\t\t\t\twithName: t('dashboard', 'Good afternoon, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tevening: {\n\t\t\t\t\tgeneric: t('dashboard', 'Good evening'),\n\t\t\t\t\twithName: t('dashboard', 'Good evening, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t\tnight: {\n\t\t\t\t\t// Don't use \"Good night\" as it's not a greeting\n\t\t\t\t\tgeneric: t('dashboard', 'Hello'),\n\t\t\t\t\twithName: t('dashboard', 'Hello, {name}', { name: this.displayName }, undefined, { escape: false }),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\t// Figure out which greeting to show\n\t\t\tconst shouldShowName = this.displayName && this.uid !== this.displayName\n\t\t\treturn { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }\n\t\t},\n\n\t\tisActive() {\n\t\t\treturn (panel) => this.layout.indexOf(panel.id) > -1\n\t\t},\n\t\tisStatusActive() {\n\t\t\treturn (status) => !(status in this.enabledStatuses) || this.enabledStatuses[status]\n\t\t},\n\n\t\tsortedAllStatuses() {\n\t\t\treturn Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)\n\t\t},\n\t\tsortedPanels() {\n\t\t\treturn Object.values(this.panels).sort((a, b) => {\n\t\t\t\tconst indexA = this.layout.indexOf(a.id)\n\t\t\t\tconst indexB = this.layout.indexOf(b.id)\n\t\t\t\tif (indexA === -1 || indexB === -1) {\n\t\t\t\t\treturn indexB - indexA || a.id - b.id\n\t\t\t\t}\n\t\t\t\treturn indexA - indexB || a.id - b.id\n\t\t\t})\n\t\t},\n\t\tsortedRegisteredStatus() {\n\t\t\treturn this.registeredStatus.slice().sort(this.sortStatuses)\n\t\t},\n\t},\n\n\twatch: {\n\t\tcallbacks() {\n\t\t\tthis.rerenderPanels()\n\t\t},\n\t\tcallbacksStatus() {\n\t\t\tfor (const app in this.callbacksStatus) {\n\t\t\t\tconst element = this.$refs['status-' + app]\n\t\t\t\tif (this.statuses[app] && this.statuses[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacksStatus[app](element[0])\n\t\t\t\t\tVue.set(this.statuses, app, { mounted: true })\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.updateGlobalStyles()\n\t\tthis.updateSkipLink()\n\t\twindow.addEventListener('scroll', this.handleScroll)\n\n\t\tsetInterval(() => {\n\t\t\tthis.timer = new Date()\n\t\t}, 30000)\n\n\t\tif (this.firstRun) {\n\t\t\twindow.addEventListener('scroll', this.disableFirstrunHint)\n\t\t}\n\t},\n\tdestroyed() {\n\t\twindow.removeEventListener('scroll', this.handleScroll)\n\t},\n\n\tmethods: {\n\t\tupdateGlobalStyles() {\n\t\t\t// Override primary-invert-if-bright and color-primary-text if background is set\n\t\t\tconst isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'\n\t\t\tif (isBackgroundBright) {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#000000')\n\t\t\t\t// document.body.removeAttribute('data-theme-dark')\n\t\t\t\t// document.body.setAttribute('data-theme-light', 'true')\n\t\t\t} else {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')\n\t\t\t\t// document.body.removeAttribute('data-theme-light')\n\t\t\t\t// document.body.setAttribute('data-theme-dark', 'true')\n\t\t\t}\n\n\t\t\tconst themeElements = [document.documentElement, document.querySelector('#header'), document.querySelector('body')]\n\t\t\tfor (const element of themeElements) {\n\t\t\t\tif (this.background === 'default') {\n\t\t\t\t\telement.style.setProperty('--image-main-background', `url('${imagePath('core', 'app-background.jpg')}')`)\n\t\t\t\t} else if (this.background.match(/#[0-9A-Fa-f]{6}/g)) {\n\t\t\t\t\telement.style.setProperty('--image-main-background', undefined)\n\t\t\t\t} else {\n\t\t\t\t\telement.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Method to register panels that will be called by the integrating apps\n\t\t *\n\t\t * @param {string} app The unique app id for the widget\n\t\t * @param {Function} callback The callback function to register a panel which gets the DOM element passed as parameter\n\t\t */\n\t\tregister(app, callback) {\n\t\t\tVue.set(this.callbacks, app, callback)\n\t\t},\n\t\tregisterStatus(app, callback) {\n\t\t\t// always save callbacks in case user enables the status later\n\t\t\tVue.set(this.allCallbacksStatus, app, callback)\n\t\t\t// register only if status is enabled or missing from config\n\t\t\tif (this.isStatusActive(app)) {\n\t\t\t\tthis.registeredStatus.push(app)\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.set(this.callbacksStatus, app, callback)\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\trerenderPanels() {\n\t\t\tfor (const app in this.callbacks) {\n\t\t\t\tconst element = this.$refs[app]\n\t\t\t\tif (this.layout.indexOf(app) === -1) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (this.panels[app] && this.panels[app].mounted) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\tthis.callbacks[app](element[0], {\n\t\t\t\t\t\twidget: this.panels[app],\n\t\t\t\t\t})\n\t\t\t\t\tVue.set(this.panels[app], 'mounted', true)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsaveLayout() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/layout'), {\n\t\t\t\tlayout: this.layout.join(','),\n\t\t\t})\n\t\t},\n\t\tsaveStatuses() {\n\t\t\taxios.post(generateUrl('/apps/dashboard/statuses'), {\n\t\t\t\tstatuses: JSON.stringify(this.enabledStatuses),\n\t\t\t})\n\t\t},\n\t\tshowModal() {\n\t\t\tthis.modal = true\n\t\t\tthis.firstRun = false\n\t\t},\n\t\tcloseModal() {\n\t\t\tthis.modal = false\n\t\t},\n\t\tupdateCheckbox(panel, currentValue) {\n\t\t\tconst index = this.layout.indexOf(panel.id)\n\t\t\tif (!currentValue && index > -1) {\n\t\t\t\tthis.layout.splice(index, 1)\n\n\t\t\t} else {\n\t\t\t\tthis.layout.push(panel.id)\n\t\t\t}\n\t\t\tVue.set(this.panels[panel.id], 'mounted', false)\n\t\t\tthis.saveLayout()\n\t\t\tthis.$nextTick(() => this.rerenderPanels())\n\t\t},\n\t\tdisableFirstrunHint() {\n\t\t\twindow.removeEventListener('scroll', this.disableFirstrunHint)\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.firstRun = false\n\t\t\t}, 1000)\n\t\t},\n\t\tupdateSkipLink() {\n\t\t\t// Make sure \"Skip to main content\" link points to the app content\n\t\t\tdocument.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')\n\t\t},\n\t\tupdateStatusCheckbox(app, checked) {\n\t\t\tif (checked) {\n\t\t\t\tthis.enableStatus(app)\n\t\t\t} else {\n\t\t\t\tthis.disableStatus(app)\n\t\t\t}\n\t\t},\n\t\tenableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = true\n\t\t\tthis.registerStatus(app, this.allCallbacksStatus[app])\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tdisableStatus(app) {\n\t\t\tthis.enabledStatuses[app] = false\n\t\t\tconst i = this.registeredStatus.findIndex((s) => s === app)\n\t\t\tif (i !== -1) {\n\t\t\t\tthis.registeredStatus.splice(i, 1)\n\t\t\t\tVue.set(this.statuses, app, { mounted: false })\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tVue.delete(this.callbacksStatus, app)\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.saveStatuses()\n\t\t},\n\t\tsortStatuses(a, b) {\n\t\t\tconst al = a.toLowerCase()\n\t\t\tconst bl = b.toLowerCase()\n\t\t\treturn al > bl\n\t\t\t\t? 1\n\t\t\t\t: al < bl\n\t\t\t\t\t? -1\n\t\t\t\t\t: 0\n\t\t},\n\t\thandleScroll() {\n\t\t\tif (window.scrollY > 70) {\n\t\t\t\tdocument.body.classList.add('dashboard--scrolled')\n\t\t\t} else {\n\t\t\t\tdocument.body.classList.remove('dashboard--scrolled')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n#app-dashboard {\n\twidth: 100%;\n\tmin-height: 100%;\n\tbackground-size: cover;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\tbackground-attachment: fixed;\n\n\t> h2 {\n\t\tcolor: var(--color-primary-text);\n\t\ttext-align: center;\n\t\tfont-size: 32px;\n\t\tline-height: 130%;\n\t\tpadding: 1rem 0;\n\t}\n}\n\n.panels {\n\twidth: auto;\n\tmargin: auto;\n\tmax-width: 1500px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tflex-wrap: wrap;\n}\n\n.panel, .panels > div {\n\twidth: 320px;\n\tmax-width: 100%;\n\tmargin: 16px;\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\tborder-radius: var(--border-radius-large);\n\n\t#body-user.theme--highcontrast & {\n\t\tborder: 2px solid var(--color-border);\n\t}\n\n\t&.sortable-ghost {\n\t\t opacity: 0.1;\n\t}\n\n\t& > .panel--header {\n\t\tdisplay: flex;\n\t\tz-index: 1;\n\t\ttop: 50px;\n\t\tpadding: 16px;\n\t\tcursor: grab;\n\n\t\t&, ::v-deep * {\n\t\t\t-webkit-touch-callout: none;\n\t\t\t-webkit-user-select: none;\n\t\t\t-khtml-user-select: none;\n\t\t\t-moz-user-select: none;\n\t\t\t-ms-user-select: none;\n\t\t\tuser-select: none;\n\t\t}\n\n\t\t&:active {\n\t\t\tcursor: grabbing;\n\t\t}\n\n\t\ta {\n\t\t\tflex-grow: 1;\n\t\t}\n\n\t\t> h2 {\n\t\t\tdisplay: block;\n\t\t\talign-items: center;\n\t\t\tflex-grow: 1;\n\t\t\tmargin: 0;\n\t\t\tfont-size: 20px;\n\t\t\tline-height: 24px;\n\t\t\tfont-weight: bold;\n\t\t\tpadding: 16px 8px;\n\t\t\theight: 56px;\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\tcursor: grab;\n\t\t\tdiv {\n\t\t\t\tbackground-size: 32px;\n\t\t\t\twidth: 32px;\n\t\t\t\theight: 32px;\n\t\t\t\tmargin-right: 16px;\n\t\t\t\tbackground-position: center;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t}\n\t}\n\n\t& > .panel--content {\n\t\tmargin: 0 16px 16px 16px;\n\t\theight: 424px;\n\t\t// We specifically do not want scrollbars inside widgets\n\t\toverflow: visible;\n\t}\n\n\t// No need to extend height of widgets if only one column is shown\n\t@media only screen and (max-width: 709px) {\n\t\t& > .panel--content {\n\t\t\theight: auto;\n\t\t}\n\t}\n}\n\n.footer {\n\tdisplay: flex;\n\tjustify-content: center;\n\ttransition: bottom var(--animation-slow) ease-in-out;\n\tpadding: 1rem 0;\n}\n\n.edit-panels {\n\tdisplay: inline-block;\n\tmargin:auto;\n\tbackground-position: 16px center;\n\tpadding: 12px 16px;\n\tpadding-left: 36px;\n\tborder-radius: var(--border-radius-pill);\n\tmax-width: 200px;\n\topacity: 1;\n\ttext-align: center;\n}\n\n.button,\n.button-vue,\n.edit-panels,\n.statuses ::v-deep .action-item .action-item__menutoggle,\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\n\tbackground-color: var(--color-main-background-blur);\n\t-webkit-backdrop-filter: var(--filter-background-blur);\n\tbackdrop-filter: var(--filter-background-blur);\n\topacity: 1 !important;\n\n\t&:hover,\n\t&:focus,\n\t&:active {\n\t\tbackground-color: var(--color-background-hover)!important;\n\t}\n\t&:focus-visible {\n\t\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\n\t}\n}\n\n.modal__content {\n\tpadding: 32px 16px;\n\ttext-align: center;\n\n\tol {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tjustify-content: center;\n\t\tlist-style-type: none;\n\t\tpadding-bottom: 16px;\n\t}\n\tli {\n\t\tlabel {\n\t\t\tposition: relative;\n\t\t\tdisplay: block;\n\t\t\tpadding: 48px 16px 14px 16px;\n\t\t\tmargin: 8px;\n\t\t\twidth: 140px;\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t\tborder: 2px solid var(--color-main-background);\n\t\t\tborder-radius: var(--border-radius-large);\n\t\t\ttext-align: left;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t\twhite-space: nowrap;\n\n\t\t\tdiv {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 16px;\n\t\t\t\twidth: 24px;\n\t\t\t\theight: 24px;\n\t\t\t\tbackground-size: 24px;\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\tborder-color: var(--color-primary);\n\t\t\t}\n\t\t}\n\n\t\t// Do not invert status icons\n\t\t&:not(.panel-status) label div {\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\n\t\tinput[type='checkbox'].checkbox + label:before {\n\t\t\tposition: absolute;\n\t\t\tright: 12px;\n\t\t\ttop: 16px;\n\t\t}\n\n\t\tinput:focus + label {\n\t\t\tborder-color: var(--color-primary);\n\t\t}\n\t}\n\n\th3 {\n\t\tfont-weight: bold;\n\n\t\t&:not(:first-of-type) {\n\t\t\tmargin-top: 64px;\n\t\t}\n\t}\n\n\t// Adjust design of 'Get more widgets' button\n\t.button {\n\t\tdisplay: inline-block;\n\t\tpadding: 10px 16px;\n\t\tmargin: 0;\n\t}\n\n\tp {\n\t\tmax-width: 650px;\n\t\tmargin: 0 auto;\n\n\t\ta:hover,\n\t\ta:focus {\n\t\t\tborder-bottom: 2px solid var(--color-border);\n\t\t}\n\t}\n\n\t.credits--end {\n\t\tpadding-bottom: 32px;\n\t\tcolor: var(--color-text-maxcontrast);\n\n\t\ta {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\t}\n}\n\n.flip-list-move {\n\ttransition: transform var(--animation-slow);\n}\n\n.statuses {\n\tdisplay: flex;\n\tflex-direction: row;\n\tjustify-content: center;\n\tflex-wrap: wrap;\n\tmargin-bottom: 36px;\n\n\t& > div {\n\t\tmargin: 8px;\n\t}\n}\n</style>\n<style>\nhtml, body {\n\tbackground-attachment: fixed;\n}\n\n#body-user #header {\n\tposition: fixed;\n}\n\n#content {\n\toverflow: auto;\n\tposition: static !important;;\n}\n</style>\n","/**\n * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n *\n * @author Avior <florian.bouillon@delta-wings.net>\n * @author Julien Veyssier <eneiluj@posteo.net>\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport { generateUrl } from '@nextcloud/router'\nimport { prefixWithBaseUrl } from './prefixWithBaseUrl.js'\n\nexport const getBackgroundUrl = (background, time = 0, themingDefaultBackground = '') => {\n\tconst enabledThemes = window.OCA?.Theming?.enabledThemes || []\n\tconst isDarkTheme = (enabledThemes.length === 0 || enabledThemes[0] === 'default')\n\t\t? window.matchMedia('(prefers-color-scheme: dark)').matches\n\t\t: enabledThemes.join('').indexOf('dark') !== -1\n\n\tif (background === 'default') {\n\t\tif (themingDefaultBackground && themingDefaultBackground !== 'backgroundColor') {\n\t\t\treturn generateUrl('/apps/theming/image/background') + '?v=' + window.OCA.Theming.cacheBuster\n\t\t}\n\n\t\tif (isDarkTheme) {\n\t\t\treturn prefixWithBaseUrl('eduardo-neves-pedra-azul.jpg')\n\t\t}\n\n\t\treturn prefixWithBaseUrl('kamil-porembinski-clouds.jpg')\n\t} else if (background === 'custom') {\n\t\treturn generateUrl('/apps/theming/background') + '?v=' + time\n\t}\n\n\treturn prefixWithBaseUrl(background)\n}\n","import mod from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=script&lang=js&\"","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/sass-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=style&index=0&id=55a1daf8&lang=scss&scoped=true&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/sass-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=style&index=0&id=55a1daf8&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=style&index=1&lang=css&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./DashboardApp.vue?vue&type=style&index=1&lang=css&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./DashboardApp.vue?vue&type=template&id=55a1daf8&scoped=true&\"\nimport script from \"./DashboardApp.vue?vue&type=script&lang=js&\"\nexport * from \"./DashboardApp.vue?vue&type=script&lang=js&\"\nimport style0 from \"./DashboardApp.vue?vue&type=style&index=0&id=55a1daf8&lang=scss&scoped=true&\"\nimport style1 from \"./DashboardApp.vue?vue&type=style&index=1&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"55a1daf8\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{attrs:{\"id\":\"app-dashboard\"}},[_c('h2',[_vm._v(_vm._s(_vm.greeting.text))]),_vm._v(\" \"),_c('ul',{staticClass:\"statuses\"},_vm._l((_vm.sortedRegisteredStatus),function(status){return _c('div',{key:status,attrs:{\"id\":'status-' + status}},[_c('div',{ref:'status-' + status,refInFor:true})])}),0),_vm._v(\" \"),_c('Draggable',_vm._b({staticClass:\"panels\",attrs:{\"handle\":\".panel--header\"},on:{\"end\":_vm.saveLayout},model:{value:(_vm.layout),callback:function ($$v) {_vm.layout=$$v},expression:\"layout\"}},'Draggable',{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3},false),_vm._l((_vm.layout),function(panelId){return _c('div',{key:_vm.panels[panelId].id,staticClass:\"panel\"},[_c('div',{staticClass:\"panel--header\"},[_c('h2',[_c('div',{class:_vm.panels[panelId].iconClass,attrs:{\"role\":\"img\"}}),_vm._v(\"\\n\\t\\t\\t\\t\\t\"+_vm._s(_vm.panels[panelId].title)+\"\\n\\t\\t\\t\\t\")])]),_vm._v(\" \"),_c('div',{staticClass:\"panel--content\",class:{ loading: !_vm.panels[panelId].mounted }},[_c('div',{ref:_vm.panels[panelId].id,refInFor:true,attrs:{\"data-id\":_vm.panels[panelId].id}})])])}),0),_vm._v(\" \"),_c('div',{staticClass:\"footer\"},[_c('NcButton',{on:{\"click\":_vm.showModal},scopedSlots:_vm._u([{key:\"icon\",fn:function(){return [_c('Pencil',{attrs:{\"size\":20}})]},proxy:true}])},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.t('dashboard', 'Customize'))+\"\\n\\t\\t\")])],1),_vm._v(\" \"),(_vm.modal)?_c('NcModal',{attrs:{\"size\":\"large\"},on:{\"close\":_vm.closeModal}},[_c('div',{staticClass:\"modal__content\"},[_c('h3',[_vm._v(_vm._s(_vm.t('dashboard', 'Edit widgets')))]),_vm._v(\" \"),_c('ol',{staticClass:\"panels\"},_vm._l((_vm.sortedAllStatuses),function(status){return _c('li',{key:status,class:'panel-' + status},[_c('input',{staticClass:\"checkbox\",attrs:{\"id\":'status-checkbox-' + status,\"type\":\"checkbox\"},domProps:{\"checked\":_vm.isStatusActive(status)},on:{\"input\":function($event){return _vm.updateStatusCheckbox(status, $event.target.checked)}}}),_vm._v(\" \"),_c('label',{attrs:{\"for\":'status-checkbox-' + status}},[_c('div',{class:_vm.statusInfo[status].icon,attrs:{\"role\":\"img\"}}),_vm._v(\"\\n\\t\\t\\t\\t\\t\\t\"+_vm._s(_vm.statusInfo[status].text)+\"\\n\\t\\t\\t\\t\\t\")])])}),0),_vm._v(\" \"),_c('Draggable',_vm._b({staticClass:\"panels\",attrs:{\"tag\":\"ol\",\"handle\":\".draggable\"},on:{\"end\":_vm.saveLayout},model:{value:(_vm.layout),callback:function ($$v) {_vm.layout=$$v},expression:\"layout\"}},'Draggable',{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3},false),_vm._l((_vm.sortedPanels),function(panel){return _c('li',{key:panel.id,class:'panel-' + panel.id},[_c('input',{staticClass:\"checkbox\",attrs:{\"id\":'panel-checkbox-' + panel.id,\"type\":\"checkbox\"},domProps:{\"checked\":_vm.isActive(panel)},on:{\"input\":function($event){return _vm.updateCheckbox(panel, $event.target.checked)}}}),_vm._v(\" \"),_c('label',{class:{ draggable: _vm.isActive(panel) },attrs:{\"for\":'panel-checkbox-' + panel.id}},[_c('div',{class:panel.iconClass,attrs:{\"role\":\"img\"}}),_vm._v(\"\\n\\t\\t\\t\\t\\t\\t\"+_vm._s(panel.title)+\"\\n\\t\\t\\t\\t\\t\")])])}),0),_vm._v(\" \"),(_vm.isAdmin)?_c('a',{staticClass:\"button\",attrs:{\"href\":_vm.appStoreUrl}},[_vm._v(_vm._s(_vm.t('dashboard', 'Get more widgets from the App Store')))]):_vm._e(),_vm._v(\" \"),_c('h3',[_vm._v(_vm._s(_vm.t('dashboard', 'Weather service')))]),_vm._v(\" \"),_c('p',[_vm._v(\"\\n\\t\\t\\t\\t\"+_vm._s(_vm.t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.'))+\"\\n\\t\\t\\t\")]),_vm._v(\" \"),_c('p',{staticClass:\"credits--end\"},[_c('a',{attrs:{\"href\":\"https://api.met.no/doc/TermsOfService\",\"target\":\"_blank\",\"rel\":\"noopener\"}},[_vm._v(_vm._s(_vm.t('dashboard', 'Weather data from Met.no')))]),_vm._v(\",\\n\\t\\t\\t\\t\"),_c('a',{attrs:{\"href\":\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\",\"target\":\"_blank\",\"rel\":\"noopener\"}},[_vm._v(_vm._s(_vm.t('dashboard', 'geocoding with Nominatim')))]),_vm._v(\",\\n\\t\\t\\t\\t\"),_c('a',{attrs:{\"href\":\"https://www.opentopodata.org/#public-api\",\"target\":\"_blank\",\"rel\":\"noopener\"}},[_vm._v(_vm._s(_vm.t('dashboard', 'elevation data from OpenTopoData')))]),_vm._v(\".\\n\\t\\t\\t\")])],1)]):_vm._e()],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/**\n * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>\n *\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport Vue from 'vue'\nimport DashboardApp from './DashboardApp.vue'\nimport { translate as t } from '@nextcloud/l10n'\nimport VTooltip from '@nextcloud/vue/dist/Directives/Tooltip'\nimport { getRequestToken } from '@nextcloud/auth'\n\n// eslint-disable-next-line camelcase\n__webpack_nonce__ = btoa(getRequestToken())\n\nVue.directive('Tooltip', VTooltip)\n\nVue.prototype.t = t\n\n// FIXME workaround to make the sidebar work\nif (!window.OCA.Files) {\n\twindow.OCA.Files = {}\n}\n\nObject.assign(window.OCA.Files, { App: { fileList: { filesClient: OC.Files.getClient() } } }, window.OCA.Files)\n\nconst Dashboard = Vue.extend(DashboardApp)\nconst Instance = new Dashboard({}).$mount('#app-content-vue')\n\nwindow.OCA.Dashboard = {\n\tregister: (app, callback) => Instance.register(app, callback),\n\tregisterStatus: (app, callback) => Instance.registerStatus(app, callback),\n}\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"#app-dashboard[data-v-55a1daf8]{width:100%;min-height:100%;background-size:cover;background-position:center center;background-repeat:no-repeat;background-attachment:fixed}#app-dashboard>h2[data-v-55a1daf8]{color:var(--color-primary-text);text-align:center;font-size:32px;line-height:130%;padding:1rem 0}.panels[data-v-55a1daf8]{width:auto;margin:auto;max-width:1500px;display:flex;justify-content:center;flex-direction:row;align-items:flex-start;flex-wrap:wrap}.panel[data-v-55a1daf8],.panels>div[data-v-55a1daf8]{width:320px;max-width:100%;margin:16px;background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);border-radius:var(--border-radius-large)}#body-user.theme--highcontrast .panel[data-v-55a1daf8],#body-user.theme--highcontrast .panels>div[data-v-55a1daf8]{border:2px solid var(--color-border)}.panel.sortable-ghost[data-v-55a1daf8],.panels>div.sortable-ghost[data-v-55a1daf8]{opacity:.1}.panel>.panel--header[data-v-55a1daf8],.panels>div>.panel--header[data-v-55a1daf8]{display:flex;z-index:1;top:50px;padding:16px;cursor:grab}.panel>.panel--header[data-v-55a1daf8],.panel>.panel--header[data-v-55a1daf8] *,.panels>div>.panel--header[data-v-55a1daf8],.panels>div>.panel--header[data-v-55a1daf8] *{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.panel>.panel--header[data-v-55a1daf8]:active,.panels>div>.panel--header[data-v-55a1daf8]:active{cursor:grabbing}.panel>.panel--header a[data-v-55a1daf8],.panels>div>.panel--header a[data-v-55a1daf8]{flex-grow:1}.panel>.panel--header>h2[data-v-55a1daf8],.panels>div>.panel--header>h2[data-v-55a1daf8]{display:block;align-items:center;flex-grow:1;margin:0;font-size:20px;line-height:24px;font-weight:bold;padding:16px 8px;height:56px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:grab}.panel>.panel--header>h2 div[data-v-55a1daf8],.panels>div>.panel--header>h2 div[data-v-55a1daf8]{background-size:32px;width:32px;height:32px;margin-right:16px;background-position:center;float:left}.panel>.panel--content[data-v-55a1daf8],.panels>div>.panel--content[data-v-55a1daf8]{margin:0 16px 16px 16px;height:424px;overflow:visible}@media only screen and (max-width: 709px){.panel>.panel--content[data-v-55a1daf8],.panels>div>.panel--content[data-v-55a1daf8]{height:auto}}.footer[data-v-55a1daf8]{display:flex;justify-content:center;transition:bottom var(--animation-slow) ease-in-out;padding:1rem 0}.edit-panels[data-v-55a1daf8]{display:inline-block;margin:auto;background-position:16px center;padding:12px 16px;padding-left:36px;border-radius:var(--border-radius-pill);max-width:200px;opacity:1;text-align:center}.button[data-v-55a1daf8],.button-vue[data-v-55a1daf8],.edit-panels[data-v-55a1daf8],.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle{background-color:var(--color-main-background-blur);-webkit-backdrop-filter:var(--filter-background-blur);backdrop-filter:var(--filter-background-blur);opacity:1 !important}.button[data-v-55a1daf8]:hover,.button[data-v-55a1daf8]:focus,.button[data-v-55a1daf8]:active,.button-vue[data-v-55a1daf8]:hover,.button-vue[data-v-55a1daf8]:focus,.button-vue[data-v-55a1daf8]:active,.edit-panels[data-v-55a1daf8]:hover,.edit-panels[data-v-55a1daf8]:focus,.edit-panels[data-v-55a1daf8]:active,.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle:hover,.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle:focus,.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle:active,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle:hover,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle:focus,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle:active{background-color:var(--color-background-hover) !important}.button[data-v-55a1daf8]:focus-visible,.button-vue[data-v-55a1daf8]:focus-visible,.edit-panels[data-v-55a1daf8]:focus-visible,.statuses[data-v-55a1daf8] .action-item .action-item__menutoggle:focus-visible,.statuses[data-v-55a1daf8] .action-item.action-item--open .action-item__menutoggle:focus-visible{box-shadow:0 0 0 2px var(--color-main-text) !important}.modal__content[data-v-55a1daf8]{padding:32px 16px;text-align:center}.modal__content ol[data-v-55a1daf8]{display:flex;flex-direction:row;justify-content:center;list-style-type:none;padding-bottom:16px}.modal__content li label[data-v-55a1daf8]{position:relative;display:block;padding:48px 16px 14px 16px;margin:8px;width:140px;background-color:var(--color-background-hover);border:2px solid var(--color-main-background);border-radius:var(--border-radius-large);text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.modal__content li label div[data-v-55a1daf8]{position:absolute;top:16px;width:24px;height:24px;background-size:24px}.modal__content li label[data-v-55a1daf8]:hover{border-color:var(--color-primary)}.modal__content li:not(.panel-status) label div[data-v-55a1daf8]{filter:var(--background-invert-if-dark)}.modal__content li input[type=checkbox].checkbox+label[data-v-55a1daf8]:before{position:absolute;right:12px;top:16px}.modal__content li input:focus+label[data-v-55a1daf8]{border-color:var(--color-primary)}.modal__content h3[data-v-55a1daf8]{font-weight:bold}.modal__content h3[data-v-55a1daf8]:not(:first-of-type){margin-top:64px}.modal__content .button[data-v-55a1daf8]{display:inline-block;padding:10px 16px;margin:0}.modal__content p[data-v-55a1daf8]{max-width:650px;margin:0 auto}.modal__content p a[data-v-55a1daf8]:hover,.modal__content p a[data-v-55a1daf8]:focus{border-bottom:2px solid var(--color-border)}.modal__content .credits--end[data-v-55a1daf8]{padding-bottom:32px;color:var(--color-text-maxcontrast)}.modal__content .credits--end a[data-v-55a1daf8]{color:var(--color-text-maxcontrast)}.flip-list-move[data-v-55a1daf8]{transition:transform var(--animation-slow)}.statuses[data-v-55a1daf8]{display:flex;flex-direction:row;justify-content:center;flex-wrap:wrap;margin-bottom:36px}.statuses>div[data-v-55a1daf8]{margin:8px}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/dashboard/src/DashboardApp.vue\"],\"names\":[],\"mappings\":\"AAuaA,gCACC,UAAA,CACA,eAAA,CACA,qBAAA,CACA,iCAAA,CACA,2BAAA,CACA,2BAAA,CAEA,mCACC,+BAAA,CACA,iBAAA,CACA,cAAA,CACA,gBAAA,CACA,cAAA,CAIF,yBACC,UAAA,CACA,WAAA,CACA,gBAAA,CACA,YAAA,CACA,sBAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CAGD,qDACC,WAAA,CACA,cAAA,CACA,WAAA,CACA,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,wCAAA,CAEA,mHACC,oCAAA,CAGD,mFACE,UAAA,CAGF,mFACC,YAAA,CACA,SAAA,CACA,QAAA,CACA,YAAA,CACA,WAAA,CAEA,4KACC,0BAAA,CACA,wBAAA,CACA,uBAAA,CACA,qBAAA,CACA,oBAAA,CACA,gBAAA,CAGD,iGACC,eAAA,CAGD,uFACC,WAAA,CAGD,yFACC,aAAA,CACA,kBAAA,CACA,WAAA,CACA,QAAA,CACA,cAAA,CACA,gBAAA,CACA,gBAAA,CACA,gBAAA,CACA,WAAA,CACA,kBAAA,CACA,eAAA,CACA,sBAAA,CACA,WAAA,CACA,iGACC,oBAAA,CACA,UAAA,CACA,WAAA,CACA,iBAAA,CACA,0BAAA,CACA,UAAA,CAKH,qFACC,uBAAA,CACA,YAAA,CAEA,gBAAA,CAID,0CACC,qFACC,WAAA,CAAA,CAKH,yBACC,YAAA,CACA,sBAAA,CACA,mDAAA,CACA,cAAA,CAGD,8BACC,oBAAA,CACA,WAAA,CACA,+BAAA,CACA,iBAAA,CACA,iBAAA,CACA,uCAAA,CACA,eAAA,CACA,SAAA,CACA,iBAAA,CAGD,0OAKC,kDAAA,CACA,qDAAA,CACA,6CAAA,CACA,oBAAA,CAEA,6xBAGC,yDAAA,CAED,gTACC,sDAAA,CAIF,iCACC,iBAAA,CACA,iBAAA,CAEA,oCACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,oBAAA,CACA,mBAAA,CAGA,0CACC,iBAAA,CACA,aAAA,CACA,2BAAA,CACA,UAAA,CACA,WAAA,CACA,8CAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CACA,eAAA,CACA,sBAAA,CACA,kBAAA,CAEA,8CACC,iBAAA,CACA,QAAA,CACA,UAAA,CACA,WAAA,CACA,oBAAA,CAGD,gDACC,iCAAA,CAKF,iEACC,uCAAA,CAGD,+EACC,iBAAA,CACA,UAAA,CACA,QAAA,CAGD,sDACC,iCAAA,CAIF,oCACC,gBAAA,CAEA,wDACC,eAAA,CAKF,yCACC,oBAAA,CACA,iBAAA,CACA,QAAA,CAGD,mCACC,eAAA,CACA,aAAA,CAEA,sFAEC,2CAAA,CAIF,+CACC,mBAAA,CACA,mCAAA,CAEA,iDACC,mCAAA,CAKH,iCACC,0CAAA,CAGD,2BACC,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACA,kBAAA,CAEA,+BACC,UAAA\",\"sourcesContent\":[\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n#app-dashboard {\\n\\twidth: 100%;\\n\\tmin-height: 100%;\\n\\tbackground-size: cover;\\n\\tbackground-position: center center;\\n\\tbackground-repeat: no-repeat;\\n\\tbackground-attachment: fixed;\\n\\n\\t> h2 {\\n\\t\\tcolor: var(--color-primary-text);\\n\\t\\ttext-align: center;\\n\\t\\tfont-size: 32px;\\n\\t\\tline-height: 130%;\\n\\t\\tpadding: 1rem 0;\\n\\t}\\n}\\n\\n.panels {\\n\\twidth: auto;\\n\\tmargin: auto;\\n\\tmax-width: 1500px;\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n\\tflex-direction: row;\\n\\talign-items: flex-start;\\n\\tflex-wrap: wrap;\\n}\\n\\n.panel, .panels > div {\\n\\twidth: 320px;\\n\\tmax-width: 100%;\\n\\tmargin: 16px;\\n\\tbackground-color: var(--color-main-background-blur);\\n\\t-webkit-backdrop-filter: var(--filter-background-blur);\\n\\tbackdrop-filter: var(--filter-background-blur);\\n\\tborder-radius: var(--border-radius-large);\\n\\n\\t#body-user.theme--highcontrast & {\\n\\t\\tborder: 2px solid var(--color-border);\\n\\t}\\n\\n\\t&.sortable-ghost {\\n\\t\\t opacity: 0.1;\\n\\t}\\n\\n\\t& > .panel--header {\\n\\t\\tdisplay: flex;\\n\\t\\tz-index: 1;\\n\\t\\ttop: 50px;\\n\\t\\tpadding: 16px;\\n\\t\\tcursor: grab;\\n\\n\\t\\t&, ::v-deep * {\\n\\t\\t\\t-webkit-touch-callout: none;\\n\\t\\t\\t-webkit-user-select: none;\\n\\t\\t\\t-khtml-user-select: none;\\n\\t\\t\\t-moz-user-select: none;\\n\\t\\t\\t-ms-user-select: none;\\n\\t\\t\\tuser-select: none;\\n\\t\\t}\\n\\n\\t\\t&:active {\\n\\t\\t\\tcursor: grabbing;\\n\\t\\t}\\n\\n\\t\\ta {\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t}\\n\\n\\t\\t> h2 {\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\talign-items: center;\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t\\tmargin: 0;\\n\\t\\t\\tfont-size: 20px;\\n\\t\\t\\tline-height: 24px;\\n\\t\\t\\tfont-weight: bold;\\n\\t\\t\\tpadding: 16px 8px;\\n\\t\\t\\theight: 56px;\\n\\t\\t\\twhite-space: nowrap;\\n\\t\\t\\toverflow: hidden;\\n\\t\\t\\ttext-overflow: ellipsis;\\n\\t\\t\\tcursor: grab;\\n\\t\\t\\tdiv {\\n\\t\\t\\t\\tbackground-size: 32px;\\n\\t\\t\\t\\twidth: 32px;\\n\\t\\t\\t\\theight: 32px;\\n\\t\\t\\t\\tmargin-right: 16px;\\n\\t\\t\\t\\tbackground-position: center;\\n\\t\\t\\t\\tfloat: left;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\n\\t& > .panel--content {\\n\\t\\tmargin: 0 16px 16px 16px;\\n\\t\\theight: 424px;\\n\\t\\t// We specifically do not want scrollbars inside widgets\\n\\t\\toverflow: visible;\\n\\t}\\n\\n\\t// No need to extend height of widgets if only one column is shown\\n\\t@media only screen and (max-width: 709px) {\\n\\t\\t& > .panel--content {\\n\\t\\t\\theight: auto;\\n\\t\\t}\\n\\t}\\n}\\n\\n.footer {\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n\\ttransition: bottom var(--animation-slow) ease-in-out;\\n\\tpadding: 1rem 0;\\n}\\n\\n.edit-panels {\\n\\tdisplay: inline-block;\\n\\tmargin:auto;\\n\\tbackground-position: 16px center;\\n\\tpadding: 12px 16px;\\n\\tpadding-left: 36px;\\n\\tborder-radius: var(--border-radius-pill);\\n\\tmax-width: 200px;\\n\\topacity: 1;\\n\\ttext-align: center;\\n}\\n\\n.button,\\n.button-vue,\\n.edit-panels,\\n.statuses ::v-deep .action-item .action-item__menutoggle,\\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\\n\\tbackground-color: var(--color-main-background-blur);\\n\\t-webkit-backdrop-filter: var(--filter-background-blur);\\n\\tbackdrop-filter: var(--filter-background-blur);\\n\\topacity: 1 !important;\\n\\n\\t&:hover,\\n\\t&:focus,\\n\\t&:active {\\n\\t\\tbackground-color: var(--color-background-hover)!important;\\n\\t}\\n\\t&:focus-visible {\\n\\t\\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\\n\\t}\\n}\\n\\n.modal__content {\\n\\tpadding: 32px 16px;\\n\\ttext-align: center;\\n\\n\\tol {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-direction: row;\\n\\t\\tjustify-content: center;\\n\\t\\tlist-style-type: none;\\n\\t\\tpadding-bottom: 16px;\\n\\t}\\n\\tli {\\n\\t\\tlabel {\\n\\t\\t\\tposition: relative;\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\tpadding: 48px 16px 14px 16px;\\n\\t\\t\\tmargin: 8px;\\n\\t\\t\\twidth: 140px;\\n\\t\\t\\tbackground-color: var(--color-background-hover);\\n\\t\\t\\tborder: 2px solid var(--color-main-background);\\n\\t\\t\\tborder-radius: var(--border-radius-large);\\n\\t\\t\\ttext-align: left;\\n\\t\\t\\toverflow: hidden;\\n\\t\\t\\ttext-overflow: ellipsis;\\n\\t\\t\\twhite-space: nowrap;\\n\\n\\t\\t\\tdiv {\\n\\t\\t\\t\\tposition: absolute;\\n\\t\\t\\t\\ttop: 16px;\\n\\t\\t\\t\\twidth: 24px;\\n\\t\\t\\t\\theight: 24px;\\n\\t\\t\\t\\tbackground-size: 24px;\\n\\t\\t\\t}\\n\\n\\t\\t\\t&:hover {\\n\\t\\t\\t\\tborder-color: var(--color-primary);\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\t// Do not invert status icons\\n\\t\\t&:not(.panel-status) label div {\\n\\t\\t\\tfilter: var(--background-invert-if-dark);\\n\\t\\t}\\n\\n\\t\\tinput[type='checkbox'].checkbox + label:before {\\n\\t\\t\\tposition: absolute;\\n\\t\\t\\tright: 12px;\\n\\t\\t\\ttop: 16px;\\n\\t\\t}\\n\\n\\t\\tinput:focus + label {\\n\\t\\t\\tborder-color: var(--color-primary);\\n\\t\\t}\\n\\t}\\n\\n\\th3 {\\n\\t\\tfont-weight: bold;\\n\\n\\t\\t&:not(:first-of-type) {\\n\\t\\t\\tmargin-top: 64px;\\n\\t\\t}\\n\\t}\\n\\n\\t// Adjust design of 'Get more widgets' button\\n\\t.button {\\n\\t\\tdisplay: inline-block;\\n\\t\\tpadding: 10px 16px;\\n\\t\\tmargin: 0;\\n\\t}\\n\\n\\tp {\\n\\t\\tmax-width: 650px;\\n\\t\\tmargin: 0 auto;\\n\\n\\t\\ta:hover,\\n\\t\\ta:focus {\\n\\t\\t\\tborder-bottom: 2px solid var(--color-border);\\n\\t\\t}\\n\\t}\\n\\n\\t.credits--end {\\n\\t\\tpadding-bottom: 32px;\\n\\t\\tcolor: var(--color-text-maxcontrast);\\n\\n\\t\\ta {\\n\\t\\t\\tcolor: var(--color-text-maxcontrast);\\n\\t\\t}\\n\\t}\\n}\\n\\n.flip-list-move {\\n\\ttransition: transform var(--animation-slow);\\n}\\n\\n.statuses {\\n\\tdisplay: flex;\\n\\tflex-direction: row;\\n\\tjustify-content: center;\\n\\tflex-wrap: wrap;\\n\\tmargin-bottom: 36px;\\n\\n\\t& > div {\\n\\t\\tmargin: 8px;\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"\\nhtml, body {\\n\\tbackground-attachment: fixed;\\n}\\n#body-user #header {\\n\\tposition: fixed;\\n}\\n#content {\\n\\toverflow: auto;\\n\\tposition: static !important;\\n}\\n\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/dashboard/src/DashboardApp.vue\"],\"names\":[],\"mappings\":\";AAsqBA;CACA,4BAAA;AACA;AAEA;CACA,eAAA;AACA;AAEA;CACA,cAAA;CACA,2BAAA;AACA\",\"sourcesContent\":[\"<template>\\n\\t<div id=\\\"app-dashboard\\\">\\n\\t\\t<h2>{{ greeting.text }}</h2>\\n\\t\\t<ul class=\\\"statuses\\\">\\n\\t\\t\\t<div v-for=\\\"status in sortedRegisteredStatus\\\"\\n\\t\\t\\t\\t:id=\\\"'status-' + status\\\"\\n\\t\\t\\t\\t:key=\\\"status\\\">\\n\\t\\t\\t\\t<div :ref=\\\"'status-' + status\\\" />\\n\\t\\t\\t</div>\\n\\t\\t</ul>\\n\\n\\t\\t<Draggable v-model=\\\"layout\\\"\\n\\t\\t\\tclass=\\\"panels\\\"\\n\\t\\t\\tv-bind=\\\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\\\"\\n\\t\\t\\thandle=\\\".panel--header\\\"\\n\\t\\t\\t@end=\\\"saveLayout\\\">\\n\\t\\t\\t<div v-for=\\\"panelId in layout\\\" :key=\\\"panels[panelId].id\\\" class=\\\"panel\\\">\\n\\t\\t\\t\\t<div class=\\\"panel--header\\\">\\n\\t\\t\\t\\t\\t<h2>\\n\\t\\t\\t\\t\\t\\t<div :class=\\\"panels[panelId].iconClass\\\" role=\\\"img\\\" />\\n\\t\\t\\t\\t\\t\\t{{ panels[panelId].title }}\\n\\t\\t\\t\\t\\t</h2>\\n\\t\\t\\t\\t</div>\\n\\t\\t\\t\\t<div class=\\\"panel--content\\\" :class=\\\"{ loading: !panels[panelId].mounted }\\\">\\n\\t\\t\\t\\t\\t<div :ref=\\\"panels[panelId].id\\\" :data-id=\\\"panels[panelId].id\\\" />\\n\\t\\t\\t\\t</div>\\n\\t\\t\\t</div>\\n\\t\\t</Draggable>\\n\\n\\t\\t<div class=\\\"footer\\\">\\n\\t\\t\\t<NcButton @click=\\\"showModal\\\">\\n\\t\\t\\t\\t<template #icon>\\n\\t\\t\\t\\t\\t<Pencil :size=\\\"20\\\" />\\n\\t\\t\\t\\t</template>\\n\\t\\t\\t\\t{{ t('dashboard', 'Customize') }}\\n\\t\\t\\t</NcButton>\\n\\t\\t</div>\\n\\n\\t\\t<NcModal v-if=\\\"modal\\\" size=\\\"large\\\" @close=\\\"closeModal\\\">\\n\\t\\t\\t<div class=\\\"modal__content\\\">\\n\\t\\t\\t\\t<h3>{{ t('dashboard', 'Edit widgets') }}</h3>\\n\\t\\t\\t\\t<ol class=\\\"panels\\\">\\n\\t\\t\\t\\t\\t<li v-for=\\\"status in sortedAllStatuses\\\" :key=\\\"status\\\" :class=\\\"'panel-' + status\\\">\\n\\t\\t\\t\\t\\t\\t<input :id=\\\"'status-checkbox-' + status\\\"\\n\\t\\t\\t\\t\\t\\t\\ttype=\\\"checkbox\\\"\\n\\t\\t\\t\\t\\t\\t\\tclass=\\\"checkbox\\\"\\n\\t\\t\\t\\t\\t\\t\\t:checked=\\\"isStatusActive(status)\\\"\\n\\t\\t\\t\\t\\t\\t\\t@input=\\\"updateStatusCheckbox(status, $event.target.checked)\\\">\\n\\t\\t\\t\\t\\t\\t<label :for=\\\"'status-checkbox-' + status\\\">\\n\\t\\t\\t\\t\\t\\t\\t<div :class=\\\"statusInfo[status].icon\\\" role=\\\"img\\\" />\\n\\t\\t\\t\\t\\t\\t\\t{{ statusInfo[status].text }}\\n\\t\\t\\t\\t\\t\\t</label>\\n\\t\\t\\t\\t\\t</li>\\n\\t\\t\\t\\t</ol>\\n\\t\\t\\t\\t<Draggable v-model=\\\"layout\\\"\\n\\t\\t\\t\\t\\tclass=\\\"panels\\\"\\n\\t\\t\\t\\t\\ttag=\\\"ol\\\"\\n\\t\\t\\t\\t\\tv-bind=\\\"{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}\\\"\\n\\t\\t\\t\\t\\thandle=\\\".draggable\\\"\\n\\t\\t\\t\\t\\t@end=\\\"saveLayout\\\">\\n\\t\\t\\t\\t\\t<li v-for=\\\"panel in sortedPanels\\\" :key=\\\"panel.id\\\" :class=\\\"'panel-' + panel.id\\\">\\n\\t\\t\\t\\t\\t\\t<input :id=\\\"'panel-checkbox-' + panel.id\\\"\\n\\t\\t\\t\\t\\t\\t\\ttype=\\\"checkbox\\\"\\n\\t\\t\\t\\t\\t\\t\\tclass=\\\"checkbox\\\"\\n\\t\\t\\t\\t\\t\\t\\t:checked=\\\"isActive(panel)\\\"\\n\\t\\t\\t\\t\\t\\t\\t@input=\\\"updateCheckbox(panel, $event.target.checked)\\\">\\n\\t\\t\\t\\t\\t\\t<label :for=\\\"'panel-checkbox-' + panel.id\\\" :class=\\\"{ draggable: isActive(panel) }\\\">\\n\\t\\t\\t\\t\\t\\t\\t<div :class=\\\"panel.iconClass\\\" role=\\\"img\\\" />\\n\\t\\t\\t\\t\\t\\t\\t{{ panel.title }}\\n\\t\\t\\t\\t\\t\\t</label>\\n\\t\\t\\t\\t\\t</li>\\n\\t\\t\\t\\t</Draggable>\\n\\n\\t\\t\\t\\t<a v-if=\\\"isAdmin\\\" :href=\\\"appStoreUrl\\\" class=\\\"button\\\">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>\\n\\n\\t\\t\\t\\t<h3>{{ t('dashboard', 'Weather service') }}</h3>\\n\\t\\t\\t\\t<p>\\n\\t\\t\\t\\t\\t{{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}\\n\\t\\t\\t\\t</p>\\n\\t\\t\\t\\t<p class=\\\"credits--end\\\">\\n\\t\\t\\t\\t\\t<a href=\\\"https://api.met.no/doc/TermsOfService\\\" target=\\\"_blank\\\" rel=\\\"noopener\\\">{{ t('dashboard', 'Weather data from Met.no') }}</a>,\\n\\t\\t\\t\\t\\t<a href=\\\"https://wiki.osmfoundation.org/wiki/Privacy_Policy\\\" target=\\\"_blank\\\" rel=\\\"noopener\\\">{{ t('dashboard', 'geocoding with Nominatim') }}</a>,\\n\\t\\t\\t\\t\\t<a href=\\\"https://www.opentopodata.org/#public-api\\\" target=\\\"_blank\\\" rel=\\\"noopener\\\">{{ t('dashboard', 'elevation data from OpenTopoData') }}</a>.\\n\\t\\t\\t\\t</p>\\n\\t\\t\\t</div>\\n\\t\\t</NcModal>\\n\\t</div>\\n</template>\\n\\n<script>\\nimport { generateUrl, imagePath } from '@nextcloud/router'\\nimport { getCurrentUser } from '@nextcloud/auth'\\nimport { loadState } from '@nextcloud/initial-state'\\nimport axios from '@nextcloud/axios'\\nimport NcButton from '@nextcloud/vue/dist/Components/NcButton'\\nimport Draggable from 'vuedraggable'\\nimport NcModal from '@nextcloud/vue/dist/Components/NcModal'\\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\\nimport Vue from 'vue'\\n\\nimport isMobile from './mixins/isMobile.js'\\nimport { getBackgroundUrl } from './helpers/getBackgroundUrl.js'\\n\\nconst panels = loadState('dashboard', 'panels')\\nconst firstRun = loadState('dashboard', 'firstRun')\\n\\nconst background = loadState('theming', 'background')\\nconst backgroundVersion = loadState('theming', 'backgroundVersion')\\nconst themingDefaultBackground = loadState('theming', 'themingDefaultBackground')\\nconst shippedBackgroundList = loadState('theming', 'shippedBackgrounds')\\n\\nconst statusInfo = {\\n\\tweather: {\\n\\t\\ttext: t('dashboard', 'Weather'),\\n\\t\\ticon: 'icon-weather-status',\\n\\t},\\n\\tstatus: {\\n\\t\\ttext: t('dashboard', 'Status'),\\n\\t\\ticon: 'icon-user-status-online',\\n\\t},\\n}\\n\\nexport default {\\n\\tname: 'DashboardApp',\\n\\tcomponents: {\\n\\t\\tNcButton,\\n\\t\\tDraggable,\\n\\t\\tNcModal,\\n\\t\\tPencil,\\n\\t},\\n\\tmixins: [\\n\\t\\tisMobile,\\n\\t],\\n\\n\\tdata() {\\n\\t\\treturn {\\n\\t\\t\\tisAdmin: getCurrentUser().isAdmin,\\n\\t\\t\\ttimer: new Date(),\\n\\t\\t\\tregisteredStatus: [],\\n\\t\\t\\tcallbacks: {},\\n\\t\\t\\tcallbacksStatus: {},\\n\\t\\t\\tallCallbacksStatus: {},\\n\\t\\t\\tstatusInfo,\\n\\t\\t\\tenabledStatuses: loadState('dashboard', 'statuses'),\\n\\t\\t\\tpanels,\\n\\t\\t\\tfirstRun,\\n\\t\\t\\tdisplayName: getCurrentUser()?.displayName,\\n\\t\\t\\tuid: getCurrentUser()?.uid,\\n\\t\\t\\tlayout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),\\n\\t\\t\\tmodal: false,\\n\\t\\t\\tappStoreUrl: generateUrl('/settings/apps/dashboard'),\\n\\t\\t\\tstatuses: {},\\n\\t\\t\\tbackground,\\n\\t\\t\\tthemingDefaultBackground,\\n\\t\\t}\\n\\t},\\n\\tcomputed: {\\n\\t\\tbackgroundImage() {\\n\\t\\t\\treturn getBackgroundUrl(this.background, backgroundVersion, this.themingDefaultBackground)\\n\\t\\t},\\n\\t\\tbackgroundStyle() {\\n\\t\\t\\tif ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')\\n\\t\\t\\t\\t|| this.background.match(/#[0-9A-Fa-f]{6}/g)) {\\n\\t\\t\\t\\treturn null\\n\\t\\t\\t}\\n\\n\\t\\t\\treturn {\\n\\t\\t\\t\\tbackgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\tgreeting() {\\n\\t\\t\\tconst time = this.timer.getHours()\\n\\n\\t\\t\\t// Determine part of the day\\n\\t\\t\\tlet partOfDay\\n\\t\\t\\tif (time >= 22 || time < 5) {\\n\\t\\t\\t\\tpartOfDay = 'night'\\n\\t\\t\\t} else if (time >= 18) {\\n\\t\\t\\t\\tpartOfDay = 'evening'\\n\\t\\t\\t} else if (time >= 12) {\\n\\t\\t\\t\\tpartOfDay = 'afternoon'\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tpartOfDay = 'morning'\\n\\t\\t\\t}\\n\\n\\t\\t\\t// Define the greetings\\n\\t\\t\\tconst good = {\\n\\t\\t\\t\\tmorning: {\\n\\t\\t\\t\\t\\tgeneric: t('dashboard', 'Good morning'),\\n\\t\\t\\t\\t\\twithName: t('dashboard', 'Good morning, {name}', { name: this.displayName }, undefined, { escape: false }),\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tafternoon: {\\n\\t\\t\\t\\t\\tgeneric: t('dashboard', 'Good afternoon'),\\n\\t\\t\\t\\t\\twithName: t('dashboard', 'Good afternoon, {name}', { name: this.displayName }, undefined, { escape: false }),\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tevening: {\\n\\t\\t\\t\\t\\tgeneric: t('dashboard', 'Good evening'),\\n\\t\\t\\t\\t\\twithName: t('dashboard', 'Good evening, {name}', { name: this.displayName }, undefined, { escape: false }),\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tnight: {\\n\\t\\t\\t\\t\\t// Don't use \\\"Good night\\\" as it's not a greeting\\n\\t\\t\\t\\t\\tgeneric: t('dashboard', 'Hello'),\\n\\t\\t\\t\\t\\twithName: t('dashboard', 'Hello, {name}', { name: this.displayName }, undefined, { escape: false }),\\n\\t\\t\\t\\t},\\n\\t\\t\\t}\\n\\n\\t\\t\\t// Figure out which greeting to show\\n\\t\\t\\tconst shouldShowName = this.displayName && this.uid !== this.displayName\\n\\t\\t\\treturn { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }\\n\\t\\t},\\n\\n\\t\\tisActive() {\\n\\t\\t\\treturn (panel) => this.layout.indexOf(panel.id) > -1\\n\\t\\t},\\n\\t\\tisStatusActive() {\\n\\t\\t\\treturn (status) => !(status in this.enabledStatuses) || this.enabledStatuses[status]\\n\\t\\t},\\n\\n\\t\\tsortedAllStatuses() {\\n\\t\\t\\treturn Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)\\n\\t\\t},\\n\\t\\tsortedPanels() {\\n\\t\\t\\treturn Object.values(this.panels).sort((a, b) => {\\n\\t\\t\\t\\tconst indexA = this.layout.indexOf(a.id)\\n\\t\\t\\t\\tconst indexB = this.layout.indexOf(b.id)\\n\\t\\t\\t\\tif (indexA === -1 || indexB === -1) {\\n\\t\\t\\t\\t\\treturn indexB - indexA || a.id - b.id\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn indexA - indexB || a.id - b.id\\n\\t\\t\\t})\\n\\t\\t},\\n\\t\\tsortedRegisteredStatus() {\\n\\t\\t\\treturn this.registeredStatus.slice().sort(this.sortStatuses)\\n\\t\\t},\\n\\t},\\n\\n\\twatch: {\\n\\t\\tcallbacks() {\\n\\t\\t\\tthis.rerenderPanels()\\n\\t\\t},\\n\\t\\tcallbacksStatus() {\\n\\t\\t\\tfor (const app in this.callbacksStatus) {\\n\\t\\t\\t\\tconst element = this.$refs['status-' + app]\\n\\t\\t\\t\\tif (this.statuses[app] && this.statuses[app].mounted) {\\n\\t\\t\\t\\t\\tcontinue\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\tthis.callbacksStatus[app](element[0])\\n\\t\\t\\t\\t\\tVue.set(this.statuses, app, { mounted: true })\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t},\\n\\t},\\n\\n\\tmounted() {\\n\\t\\tthis.updateGlobalStyles()\\n\\t\\tthis.updateSkipLink()\\n\\t\\twindow.addEventListener('scroll', this.handleScroll)\\n\\n\\t\\tsetInterval(() => {\\n\\t\\t\\tthis.timer = new Date()\\n\\t\\t}, 30000)\\n\\n\\t\\tif (this.firstRun) {\\n\\t\\t\\twindow.addEventListener('scroll', this.disableFirstrunHint)\\n\\t\\t}\\n\\t},\\n\\tdestroyed() {\\n\\t\\twindow.removeEventListener('scroll', this.handleScroll)\\n\\t},\\n\\n\\tmethods: {\\n\\t\\tupdateGlobalStyles() {\\n\\t\\t\\t// Override primary-invert-if-bright and color-primary-text if background is set\\n\\t\\t\\tconst isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'\\n\\t\\t\\tif (isBackgroundBright) {\\n\\t\\t\\t\\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')\\n\\t\\t\\t\\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#000000')\\n\\t\\t\\t\\t// document.body.removeAttribute('data-theme-dark')\\n\\t\\t\\t\\t// document.body.setAttribute('data-theme-light', 'true')\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')\\n\\t\\t\\t\\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')\\n\\t\\t\\t\\t// document.body.removeAttribute('data-theme-light')\\n\\t\\t\\t\\t// document.body.setAttribute('data-theme-dark', 'true')\\n\\t\\t\\t}\\n\\n\\t\\t\\tconst themeElements = [document.documentElement, document.querySelector('#header'), document.querySelector('body')]\\n\\t\\t\\tfor (const element of themeElements) {\\n\\t\\t\\t\\tif (this.background === 'default') {\\n\\t\\t\\t\\t\\telement.style.setProperty('--image-main-background', `url('${imagePath('core', 'app-background.jpg')}')`)\\n\\t\\t\\t\\t} else if (this.background.match(/#[0-9A-Fa-f]{6}/g)) {\\n\\t\\t\\t\\t\\telement.style.setProperty('--image-main-background', undefined)\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\telement.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\t/**\\n\\t\\t * Method to register panels that will be called by the integrating apps\\n\\t\\t *\\n\\t\\t * @param {string} app The unique app id for the widget\\n\\t\\t * @param {Function} callback The callback function to register a panel which gets the DOM element passed as parameter\\n\\t\\t */\\n\\t\\tregister(app, callback) {\\n\\t\\t\\tVue.set(this.callbacks, app, callback)\\n\\t\\t},\\n\\t\\tregisterStatus(app, callback) {\\n\\t\\t\\t// always save callbacks in case user enables the status later\\n\\t\\t\\tVue.set(this.allCallbacksStatus, app, callback)\\n\\t\\t\\t// register only if status is enabled or missing from config\\n\\t\\t\\tif (this.isStatusActive(app)) {\\n\\t\\t\\t\\tthis.registeredStatus.push(app)\\n\\t\\t\\t\\tthis.$nextTick(() => {\\n\\t\\t\\t\\t\\tVue.set(this.callbacksStatus, app, callback)\\n\\t\\t\\t\\t})\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\trerenderPanels() {\\n\\t\\t\\tfor (const app in this.callbacks) {\\n\\t\\t\\t\\tconst element = this.$refs[app]\\n\\t\\t\\t\\tif (this.layout.indexOf(app) === -1) {\\n\\t\\t\\t\\t\\tcontinue\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.panels[app] && this.panels[app].mounted) {\\n\\t\\t\\t\\t\\tcontinue\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\tthis.callbacks[app](element[0], {\\n\\t\\t\\t\\t\\t\\twidget: this.panels[app],\\n\\t\\t\\t\\t\\t})\\n\\t\\t\\t\\t\\tVue.set(this.panels[app], 'mounted', true)\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconsole.error('Failed to register panel in the frontend as no backend data was provided for ' + app)\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\tsaveLayout() {\\n\\t\\t\\taxios.post(generateUrl('/apps/dashboard/layout'), {\\n\\t\\t\\t\\tlayout: this.layout.join(','),\\n\\t\\t\\t})\\n\\t\\t},\\n\\t\\tsaveStatuses() {\\n\\t\\t\\taxios.post(generateUrl('/apps/dashboard/statuses'), {\\n\\t\\t\\t\\tstatuses: JSON.stringify(this.enabledStatuses),\\n\\t\\t\\t})\\n\\t\\t},\\n\\t\\tshowModal() {\\n\\t\\t\\tthis.modal = true\\n\\t\\t\\tthis.firstRun = false\\n\\t\\t},\\n\\t\\tcloseModal() {\\n\\t\\t\\tthis.modal = false\\n\\t\\t},\\n\\t\\tupdateCheckbox(panel, currentValue) {\\n\\t\\t\\tconst index = this.layout.indexOf(panel.id)\\n\\t\\t\\tif (!currentValue && index > -1) {\\n\\t\\t\\t\\tthis.layout.splice(index, 1)\\n\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.layout.push(panel.id)\\n\\t\\t\\t}\\n\\t\\t\\tVue.set(this.panels[panel.id], 'mounted', false)\\n\\t\\t\\tthis.saveLayout()\\n\\t\\t\\tthis.$nextTick(() => this.rerenderPanels())\\n\\t\\t},\\n\\t\\tdisableFirstrunHint() {\\n\\t\\t\\twindow.removeEventListener('scroll', this.disableFirstrunHint)\\n\\t\\t\\tsetTimeout(() => {\\n\\t\\t\\t\\tthis.firstRun = false\\n\\t\\t\\t}, 1000)\\n\\t\\t},\\n\\t\\tupdateSkipLink() {\\n\\t\\t\\t// Make sure \\\"Skip to main content\\\" link points to the app content\\n\\t\\t\\tdocument.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')\\n\\t\\t},\\n\\t\\tupdateStatusCheckbox(app, checked) {\\n\\t\\t\\tif (checked) {\\n\\t\\t\\t\\tthis.enableStatus(app)\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.disableStatus(app)\\n\\t\\t\\t}\\n\\t\\t},\\n\\t\\tenableStatus(app) {\\n\\t\\t\\tthis.enabledStatuses[app] = true\\n\\t\\t\\tthis.registerStatus(app, this.allCallbacksStatus[app])\\n\\t\\t\\tthis.saveStatuses()\\n\\t\\t},\\n\\t\\tdisableStatus(app) {\\n\\t\\t\\tthis.enabledStatuses[app] = false\\n\\t\\t\\tconst i = this.registeredStatus.findIndex((s) => s === app)\\n\\t\\t\\tif (i !== -1) {\\n\\t\\t\\t\\tthis.registeredStatus.splice(i, 1)\\n\\t\\t\\t\\tVue.set(this.statuses, app, { mounted: false })\\n\\t\\t\\t\\tthis.$nextTick(() => {\\n\\t\\t\\t\\t\\tVue.delete(this.callbacksStatus, app)\\n\\t\\t\\t\\t})\\n\\t\\t\\t}\\n\\t\\t\\tthis.saveStatuses()\\n\\t\\t},\\n\\t\\tsortStatuses(a, b) {\\n\\t\\t\\tconst al = a.toLowerCase()\\n\\t\\t\\tconst bl = b.toLowerCase()\\n\\t\\t\\treturn al > bl\\n\\t\\t\\t\\t? 1\\n\\t\\t\\t\\t: al < bl\\n\\t\\t\\t\\t\\t? -1\\n\\t\\t\\t\\t\\t: 0\\n\\t\\t},\\n\\t\\thandleScroll() {\\n\\t\\t\\tif (window.scrollY > 70) {\\n\\t\\t\\t\\tdocument.body.classList.add('dashboard--scrolled')\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdocument.body.classList.remove('dashboard--scrolled')\\n\\t\\t\\t}\\n\\t\\t},\\n\\t},\\n}\\n</script>\\n\\n<style lang=\\\"scss\\\" scoped>\\n#app-dashboard {\\n\\twidth: 100%;\\n\\tmin-height: 100%;\\n\\tbackground-size: cover;\\n\\tbackground-position: center center;\\n\\tbackground-repeat: no-repeat;\\n\\tbackground-attachment: fixed;\\n\\n\\t> h2 {\\n\\t\\tcolor: var(--color-primary-text);\\n\\t\\ttext-align: center;\\n\\t\\tfont-size: 32px;\\n\\t\\tline-height: 130%;\\n\\t\\tpadding: 1rem 0;\\n\\t}\\n}\\n\\n.panels {\\n\\twidth: auto;\\n\\tmargin: auto;\\n\\tmax-width: 1500px;\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n\\tflex-direction: row;\\n\\talign-items: flex-start;\\n\\tflex-wrap: wrap;\\n}\\n\\n.panel, .panels > div {\\n\\twidth: 320px;\\n\\tmax-width: 100%;\\n\\tmargin: 16px;\\n\\tbackground-color: var(--color-main-background-blur);\\n\\t-webkit-backdrop-filter: var(--filter-background-blur);\\n\\tbackdrop-filter: var(--filter-background-blur);\\n\\tborder-radius: var(--border-radius-large);\\n\\n\\t#body-user.theme--highcontrast & {\\n\\t\\tborder: 2px solid var(--color-border);\\n\\t}\\n\\n\\t&.sortable-ghost {\\n\\t\\t opacity: 0.1;\\n\\t}\\n\\n\\t& > .panel--header {\\n\\t\\tdisplay: flex;\\n\\t\\tz-index: 1;\\n\\t\\ttop: 50px;\\n\\t\\tpadding: 16px;\\n\\t\\tcursor: grab;\\n\\n\\t\\t&, ::v-deep * {\\n\\t\\t\\t-webkit-touch-callout: none;\\n\\t\\t\\t-webkit-user-select: none;\\n\\t\\t\\t-khtml-user-select: none;\\n\\t\\t\\t-moz-user-select: none;\\n\\t\\t\\t-ms-user-select: none;\\n\\t\\t\\tuser-select: none;\\n\\t\\t}\\n\\n\\t\\t&:active {\\n\\t\\t\\tcursor: grabbing;\\n\\t\\t}\\n\\n\\t\\ta {\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t}\\n\\n\\t\\t> h2 {\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\talign-items: center;\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t\\tmargin: 0;\\n\\t\\t\\tfont-size: 20px;\\n\\t\\t\\tline-height: 24px;\\n\\t\\t\\tfont-weight: bold;\\n\\t\\t\\tpadding: 16px 8px;\\n\\t\\t\\theight: 56px;\\n\\t\\t\\twhite-space: nowrap;\\n\\t\\t\\toverflow: hidden;\\n\\t\\t\\ttext-overflow: ellipsis;\\n\\t\\t\\tcursor: grab;\\n\\t\\t\\tdiv {\\n\\t\\t\\t\\tbackground-size: 32px;\\n\\t\\t\\t\\twidth: 32px;\\n\\t\\t\\t\\theight: 32px;\\n\\t\\t\\t\\tmargin-right: 16px;\\n\\t\\t\\t\\tbackground-position: center;\\n\\t\\t\\t\\tfloat: left;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\n\\t& > .panel--content {\\n\\t\\tmargin: 0 16px 16px 16px;\\n\\t\\theight: 424px;\\n\\t\\t// We specifically do not want scrollbars inside widgets\\n\\t\\toverflow: visible;\\n\\t}\\n\\n\\t// No need to extend height of widgets if only one column is shown\\n\\t@media only screen and (max-width: 709px) {\\n\\t\\t& > .panel--content {\\n\\t\\t\\theight: auto;\\n\\t\\t}\\n\\t}\\n}\\n\\n.footer {\\n\\tdisplay: flex;\\n\\tjustify-content: center;\\n\\ttransition: bottom var(--animation-slow) ease-in-out;\\n\\tpadding: 1rem 0;\\n}\\n\\n.edit-panels {\\n\\tdisplay: inline-block;\\n\\tmargin:auto;\\n\\tbackground-position: 16px center;\\n\\tpadding: 12px 16px;\\n\\tpadding-left: 36px;\\n\\tborder-radius: var(--border-radius-pill);\\n\\tmax-width: 200px;\\n\\topacity: 1;\\n\\ttext-align: center;\\n}\\n\\n.button,\\n.button-vue,\\n.edit-panels,\\n.statuses ::v-deep .action-item .action-item__menutoggle,\\n.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {\\n\\tbackground-color: var(--color-main-background-blur);\\n\\t-webkit-backdrop-filter: var(--filter-background-blur);\\n\\tbackdrop-filter: var(--filter-background-blur);\\n\\topacity: 1 !important;\\n\\n\\t&:hover,\\n\\t&:focus,\\n\\t&:active {\\n\\t\\tbackground-color: var(--color-background-hover)!important;\\n\\t}\\n\\t&:focus-visible {\\n\\t\\tbox-shadow: 0 0 0 2px var(--color-main-text) !important;\\n\\t}\\n}\\n\\n.modal__content {\\n\\tpadding: 32px 16px;\\n\\ttext-align: center;\\n\\n\\tol {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-direction: row;\\n\\t\\tjustify-content: center;\\n\\t\\tlist-style-type: none;\\n\\t\\tpadding-bottom: 16px;\\n\\t}\\n\\tli {\\n\\t\\tlabel {\\n\\t\\t\\tposition: relative;\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\tpadding: 48px 16px 14px 16px;\\n\\t\\t\\tmargin: 8px;\\n\\t\\t\\twidth: 140px;\\n\\t\\t\\tbackground-color: var(--color-background-hover);\\n\\t\\t\\tborder: 2px solid var(--color-main-background);\\n\\t\\t\\tborder-radius: var(--border-radius-large);\\n\\t\\t\\ttext-align: left;\\n\\t\\t\\toverflow: hidden;\\n\\t\\t\\ttext-overflow: ellipsis;\\n\\t\\t\\twhite-space: nowrap;\\n\\n\\t\\t\\tdiv {\\n\\t\\t\\t\\tposition: absolute;\\n\\t\\t\\t\\ttop: 16px;\\n\\t\\t\\t\\twidth: 24px;\\n\\t\\t\\t\\theight: 24px;\\n\\t\\t\\t\\tbackground-size: 24px;\\n\\t\\t\\t}\\n\\n\\t\\t\\t&:hover {\\n\\t\\t\\t\\tborder-color: var(--color-primary);\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\t// Do not invert status icons\\n\\t\\t&:not(.panel-status) label div {\\n\\t\\t\\tfilter: var(--background-invert-if-dark);\\n\\t\\t}\\n\\n\\t\\tinput[type='checkbox'].checkbox + label:before {\\n\\t\\t\\tposition: absolute;\\n\\t\\t\\tright: 12px;\\n\\t\\t\\ttop: 16px;\\n\\t\\t}\\n\\n\\t\\tinput:focus + label {\\n\\t\\t\\tborder-color: var(--color-primary);\\n\\t\\t}\\n\\t}\\n\\n\\th3 {\\n\\t\\tfont-weight: bold;\\n\\n\\t\\t&:not(:first-of-type) {\\n\\t\\t\\tmargin-top: 64px;\\n\\t\\t}\\n\\t}\\n\\n\\t// Adjust design of 'Get more widgets' button\\n\\t.button {\\n\\t\\tdisplay: inline-block;\\n\\t\\tpadding: 10px 16px;\\n\\t\\tmargin: 0;\\n\\t}\\n\\n\\tp {\\n\\t\\tmax-width: 650px;\\n\\t\\tmargin: 0 auto;\\n\\n\\t\\ta:hover,\\n\\t\\ta:focus {\\n\\t\\t\\tborder-bottom: 2px solid var(--color-border);\\n\\t\\t}\\n\\t}\\n\\n\\t.credits--end {\\n\\t\\tpadding-bottom: 32px;\\n\\t\\tcolor: var(--color-text-maxcontrast);\\n\\n\\t\\ta {\\n\\t\\t\\tcolor: var(--color-text-maxcontrast);\\n\\t\\t}\\n\\t}\\n}\\n\\n.flip-list-move {\\n\\ttransition: transform var(--animation-slow);\\n}\\n\\n.statuses {\\n\\tdisplay: flex;\\n\\tflex-direction: row;\\n\\tjustify-content: center;\\n\\tflex-wrap: wrap;\\n\\tmargin-bottom: 36px;\\n\\n\\t& > div {\\n\\t\\tmargin: 8px;\\n\\t}\\n}\\n</style>\\n<style>\\nhtml, body {\\n\\tbackground-attachment: fixed;\\n}\\n\\n#body-user #header {\\n\\tposition: fixed;\\n}\\n\\n#content {\\n\\toverflow: auto;\\n\\tposition: static !important;;\\n}\\n</style>\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdD = function () {\n\tthrow new Error('define cannot be used indirect');\n};","__webpack_require__.amdO = {};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 4773;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t4773: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknextcloud\"] = self[\"webpackChunknextcloud\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [7874], function() { return __webpack_require__(31853); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","data","isMobile","this","_isMobile","beforeMount","window","addEventListener","_onResize","beforeDestroy","removeEventListener","methods","document","documentElement","clientWidth","prefixWithBaseUrl","url","generateFilePath","background","time","themingDefaultBackground","enabledThemes","OCA","Theming","isDarkTheme","length","matchMedia","matches","join","indexOf","generateUrl","cacheBuster","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","_vm","_h","$createElement","_c","_self","attrs","_v","_s","greeting","text","staticClass","_l","status","key","ref","refInFor","_b","on","saveLayout","model","value","callback","$$v","layout","expression","swapThreshold","delay","delayOnTouchOnly","touchStartThreshold","panelId","panels","id","class","iconClass","title","loading","mounted","showModal","scopedSlots","_u","fn","proxy","t","closeModal","domProps","isStatusActive","$event","updateStatusCheckbox","target","checked","statusInfo","icon","panel","isActive","updateCheckbox","draggable","appStoreUrl","_e","__webpack_nonce__","btoa","getRequestToken","Vue","VTooltip","Files","Object","assign","App","fileList","filesClient","OC","getClient","Instance","DashboardApp","$mount","Dashboard","register","app","registerStatus","___CSS_LOADER_EXPORT___","push","module","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","loaded","__webpack_modules__","call","m","amdD","Error","amdO","O","result","chunkIds","priority","notFulfilled","Infinity","i","fulfilled","j","keys","every","splice","r","n","getter","__esModule","d","a","definition","o","defineProperty","enumerable","get","g","globalThis","Function","e","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","nmd","paths","children","b","baseURI","self","location","href","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","forEach","bind","nc","__webpack_exports__"],"sourceRoot":""}
\ No newline at end of file
/*! For license information please see theming-theming-settings.js.LICENSE.txt */
-!function(){"use strict";var n,e={58739:function(n,e,i){var r=i(20144),a=i(79753),o=i(16453),s=i(4820),c=i(13299),l=i.n(c),d=i(20571),u={name:"ItemPreview",components:{NcCheckboxRadioSwitch:i.n(d)()},props:{enforced:{type:Boolean,default:!1},selected:{type:Boolean,default:!1},theme:{type:Object,required:!0},type:{type:String,default:""},unique:{type:Boolean,default:!1}},computed:{switchType:function(){return this.unique?"switch":"radio"},name:function(){return this.unique?null:this.type},img:function(){return(0,a.generateFilePath)("theming","img",this.theme.id+".jpg")},checked:{get:function(){return this.selected},set:function(n){console.debug("Changed theme",this.theme.id,n),this.unique?this.$emit("change",{enabled:!0===n,id:this.theme.id}):this.$emit("change",{enabled:!0,id:this.theme.id})}}},methods:{onToggle:function(){"radio"!==this.switchType?this.checked=!this.checked:this.checked=!0}}},h=i(93379),m=i.n(h),p=i(7795),A=i.n(p),f=i(90569),g=i.n(f),v=i(3565),b=i.n(v),C=i(19216),w=i.n(C),y=i(44589),_=i.n(y),x=i(83005),k={};k.styleTagTransform=_(),k.setAttributes=b(),k.insert=g().bind(null,"head"),k.domAPI=A(),k.insertStyleElement=w(),m()(x.Z,k),x.Z&&x.Z.locals&&x.Z.locals;var T=i(51900),B=(0,T.Z)(u,(function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{staticClass:"theming__preview",class:"theming__preview--"+n.theme.id},[t("div",{staticClass:"theming__preview-image",style:{backgroundImage:"url("+n.img+")"},on:{click:n.onToggle}}),n._v(" "),t("div",{staticClass:"theming__preview-description"},[t("h3",[n._v(n._s(n.theme.title))]),n._v(" "),t("p",[n._v(n._s(n.theme.description))]),n._v(" "),n.enforced?t("span",{staticClass:"theming__preview-warning",attrs:{role:"note"}},[n._v("\n\t\t\t"+n._s(n.t("theming","Theme selection is enforced"))+"\n\t\t")]):n._e(),n._v(" "),t("NcCheckboxRadioSwitch",{staticClass:"theming__preview-toggle",attrs:{checked:n.checked,disabled:n.enforced,name:n.name,type:n.switchType},on:{"update:checked":function(e){n.checked=e}}},[n._v("\n\t\t\t"+n._s(n.theme.enableLabel)+"\n\t\t")])],1)])}),[],!1,null,"37ca8ab2",null).exports;function I(n,e,t,i,r,a,o){try{var s=n[a](o),c=s.value}catch(n){return void t(n)}s.done?e(c):Promise.resolve(c).then(i,r)}function E(n){return function(n){if(Array.isArray(n))return O(n)}(n)||function(n){if("undefined"!=typeof Symbol&&null!=n[Symbol.iterator]||null!=n["@@iterator"])return Array.from(n)}(n)||function(n,e){if(n){if("string"==typeof n)return O(n,e);var t=Object.prototype.toString.call(n).slice(8,-1);return"Object"===t&&n.constructor&&(t=n.constructor.name),"Map"===t||"Set"===t?Array.from(n):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?O(n,e):void 0}}(n)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function O(n,e){(null==e||e>n.length)&&(e=n.length);for(var t=0,i=new Array(e);t<e;t++)i[t]=n[t];return i}var P=(0,o.loadState)("theming","themes",[]),S=(0,o.loadState)("theming","enforceTheme","");console.debug("Available themes",P);var j={name:"UserThemes",components:{ItemPreview:B,NcSettingsSection:l()},data:function(){return{availableThemes:P,enforceTheme:S}},computed:{themes:function(){return this.availableThemes.filter((function(n){return 1===n.type}))},fonts:function(){return this.availableThemes.filter((function(n){return 2===n.type}))},selectedTheme:function(){return this.themes.find((function(n){return!0===n.enabled}))||this.themes[0]},description:function(){return t("theming","Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {guidelines}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level.").replace("{guidelines}",this.guidelinesLink).replace("{linkend}","</a>")},guidelinesLink:function(){return'<a target="_blank" href="https://www.w3.org/WAI/standards-guidelines/wcag/" rel="noreferrer nofollow">'},descriptionDetail:function(){return t("theming","If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!").replace("{issuetracker}",this.issuetrackerLink).replace("{designteam}",this.designteamLink).replace(/\{linkend\}/g,"</a>")},issuetrackerLink:function(){return'<a target="_blank" href="https://github.com/nextcloud/server/issues/" rel="noreferrer nofollow">'},designteamLink:function(){return'<a target="_blank" href="https://nextcloud.com/design" rel="noreferrer nofollow">'}},methods:{changeTheme:function(n){var e=n.enabled,t=n.id;this.themes.forEach((function(n){n.id===t&&e?n.enabled=!0:n.enabled=!1})),this.updateBodyAttributes(),this.selectItem(e,t)},changeFont:function(n){var e=n.enabled,t=n.id;this.fonts.forEach((function(n){n.id===t&&e?n.enabled=!0:n.enabled=!1})),this.updateBodyAttributes(),this.selectItem(e,t)},updateBodyAttributes:function(){var n=this.themes.filter((function(n){return!0===n.enabled})).map((function(n){return n.id})),e=this.fonts.filter((function(n){return!0===n.enabled})).map((function(n){return n.id}));this.themes.forEach((function(n){document.body.toggleAttribute("data-theme-".concat(n.id),n.enabled)})),this.fonts.forEach((function(n){document.body.toggleAttribute("data-theme-".concat(n.id),n.enabled)})),document.body.setAttribute("data-themes",[].concat(E(n),E(e)).join(","))},selectItem:function(n,e){return(i=regeneratorRuntime.mark((function i(){return regeneratorRuntime.wrap((function(i){for(;;)switch(i.prev=i.next){case 0:if(i.prev=0,!n){i.next=6;break}return i.next=4,(0,s.default)({url:(0,a.generateOcsUrl)("apps/theming/api/v1/theme/{themeId}/enable",{themeId:e}),method:"PUT"});case 4:i.next=8;break;case 6:return i.next=8,(0,s.default)({url:(0,a.generateOcsUrl)("apps/theming/api/v1/theme/{themeId}",{themeId:e}),method:"DELETE"});case 8:i.next=14;break;case 10:i.prev=10,i.t0=i.catch(0),console.error(i.t0,i.t0.response),OC.Notification.showTemporary(t("theming",i.t0.response.data.ocs.meta.message+". Unable to apply the setting."));case 14:case"end":return i.stop()}}),i,null,[[0,10]])})),function(){var n=this,e=arguments;return new Promise((function(t,r){var a=i.apply(n,e);function o(n){I(a,t,r,o,s,"next",n)}function s(n){I(a,t,r,o,s,"throw",n)}o(void 0)}))})();var i}}},Z=j,q=i(65699),L={};L.styleTagTransform=_(),L.setAttributes=b(),L.insert=g().bind(null,"head"),L.domAPI=A(),L.insertStyleElement=w(),m()(q.Z,L),q.Z&&q.Z.locals&&q.Z.locals;var D=(0,T.Z)(Z,(function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("NcSettingsSection",{staticClass:"theming",attrs:{title:n.t("themes","Appearance and accessibility")}},[t("p",{domProps:{innerHTML:n._s(n.description)}}),n._v(" "),t("p",{domProps:{innerHTML:n._s(n.descriptionDetail)}}),n._v(" "),t("div",{staticClass:"theming__preview-list"},n._l(n.themes,(function(e){return t("ItemPreview",{key:e.id,attrs:{enforced:e.id===n.enforceTheme,selected:n.selectedTheme.id===e.id,theme:e,unique:1===n.themes.length,type:"theme"},on:{change:n.changeTheme}})})),1),n._v(" "),t("div",{staticClass:"theming__preview-list"},n._l(n.fonts,(function(e){return t("ItemPreview",{key:e.id,attrs:{selected:e.enabled,theme:e,unique:1===n.fonts.length,type:"font"},on:{change:n.changeFont}})})),1)])}),[],!1,null,"015ac8e0",null).exports;r.ZP.prototype.OC=OC,r.ZP.prototype.t=t,(new(r.ZP.extend(D))).$mount("#theming")},65699:function(n,e,t){var i=t(87537),r=t.n(i),a=t(23645),o=t.n(a)()(r());o.push([n.id,".theming p[data-v-015ac8e0]{max-width:800px}.theming[data-v-015ac8e0] a{font-weight:bold}.theming[data-v-015ac8e0] a:hover,.theming[data-v-015ac8e0] a:focus{text-decoration:underline}.theming__preview-list[data-v-015ac8e0]{--gap: 30px;display:grid;margin-top:var(--gap);column-gap:var(--gap);row-gap:var(--gap);grid-template-columns:1fr 1fr}@media(max-width: 1440px){.theming__preview-list[data-v-015ac8e0]{display:flex;flex-direction:column}}","",{version:3,sources:["webpack://./apps/theming/src/UserThemes.vue"],names:[],mappings:"AA2KC,4BACC,eAAA,CAID,4BACC,gBAAA,CAEA,oEAEC,yBAAA,CAIF,wCACC,WAAA,CAEA,YAAA,CACA,qBAAA,CACA,qBAAA,CACA,kBAAA,CACA,6BAAA,CAIF,0BACC,wCACC,YAAA,CACA,qBAAA,CAAA",sourcesContent:["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.theming {\n\t// Limit width of settings sections for readability\n\tp {\n\t\tmax-width: 800px;\n\t}\n\n\t// Proper highlight for links and focus feedback\n\t&::v-deep a {\n\t\tfont-weight: bold;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\ttext-decoration: underline;\n\t\t}\n\t}\n\n\t&__preview-list {\n\t\t--gap: 30px;\n\n\t\tdisplay: grid;\n\t\tmargin-top: var(--gap);\n\t\tcolumn-gap: var(--gap);\n\t\trow-gap: var(--gap);\n\t\tgrid-template-columns: 1fr 1fr;\n\t}\n}\n\n@media (max-width: 1440px) {\n\t.theming__preview-list {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t}\n}\n\n"],sourceRoot:""}]),e.Z=o},83005:function(n,e,t){var i=t(87537),r=t.n(i),a=t(23645),o=t.n(a)()(r());o.push([n.id,".theming__preview[data-v-37ca8ab2]{--ratio: 16;position:relative;display:flex;justify-content:flex-start;max-width:800px}.theming__preview[data-v-37ca8ab2],.theming__preview *[data-v-37ca8ab2]{user-select:none}.theming__preview-image[data-v-37ca8ab2]{flex-basis:calc(16px*var(--ratio));flex-shrink:0;height:calc(10px*var(--ratio));margin-right:var(--gap);cursor:pointer;border-radius:var(--border-radius);background-repeat:no-repeat;background-position:top left;background-size:cover}.theming__preview-description[data-v-37ca8ab2]{display:flex;flex-direction:column}.theming__preview-description label[data-v-37ca8ab2]{padding:12px 0}.theming__preview--default[data-v-37ca8ab2]{grid-column:span 2}.theming__preview-warning[data-v-37ca8ab2]{color:var(--color-warning)}@media(max-width: 682.6666666667px){.theming__preview[data-v-37ca8ab2]{flex-direction:column}.theming__preview-image[data-v-37ca8ab2]{margin:0}}","",{version:3,sources:["webpack://./apps/theming/src/components/ItemPreview.vue"],names:[],mappings:"AAiGA,mCAEC,WAAA,CAEA,iBAAA,CACA,YAAA,CACA,0BAAA,CACA,eAAA,CAEA,wEAEC,gBAAA,CAGD,yCACC,kCAAA,CACA,aAAA,CACA,8BAAA,CACA,uBAAA,CACA,cAAA,CACA,kCAAA,CACA,2BAAA,CACA,4BAAA,CACA,qBAAA,CAGD,+CACC,YAAA,CACA,qBAAA,CAEA,qDACC,cAAA,CAIF,4CACC,kBAAA,CAGD,2CACC,0BAAA,CAIF,oCACC,mCACC,qBAAA,CAEA,yCACC,QAAA,CAAA",sourcesContent:["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.theming__preview {\n\t// We make previews on 16/10 screens\n\t--ratio: 16;\n\n\tposition: relative;\n\tdisplay: flex;\n\tjustify-content: flex-start;\n\tmax-width: 800px;\n\n\t&,\n\t* {\n\t\tuser-select: none;\n\t}\n\n\t&-image {\n\t\tflex-basis: calc(16px * var(--ratio));\n\t\tflex-shrink: 0;\n\t\theight: calc(10px * var(--ratio));\n\t\tmargin-right: var(--gap);\n\t\tcursor: pointer;\n\t\tborder-radius: var(--border-radius);\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-position: top left;\n\t\tbackground-size: cover;\n\t}\n\n\t&-description {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\n\t\tlabel {\n\t\t\tpadding: 12px 0;\n\t\t}\n\t}\n\n\t&--default {\n\t\tgrid-column: span 2;\n\t}\n\n\t&-warning {\n\t\tcolor: var(--color-warning);\n\t}\n}\n\n@media (max-width: (1024px / 1.5)) {\n\t.theming__preview {\n\t\tflex-direction: column;\n\n\t\t&-image {\n\t\t\tmargin: 0;\n\t\t}\n\t}\n}\n\n"],sourceRoot:""}]),e.Z=o}},i={};function r(n){var t=i[n];if(void 0!==t)return t.exports;var a=i[n]={id:n,loaded:!1,exports:{}};return e[n].call(a.exports,a,a.exports,r),a.loaded=!0,a.exports}r.m=e,r.amdD=function(){throw new Error("define cannot be used indirect")},r.amdO={},n=[],r.O=function(e,t,i,a){if(!t){var o=1/0;for(d=0;d<n.length;d++){t=n[d][0],i=n[d][1],a=n[d][2];for(var s=!0,c=0;c<t.length;c++)(!1&a||o>=a)&&Object.keys(r.O).every((function(n){return r.O[n](t[c])}))?t.splice(c--,1):(s=!1,a<o&&(o=a));if(s){n.splice(d--,1);var l=i();void 0!==l&&(e=l)}}return e}a=a||0;for(var d=n.length;d>0&&n[d-1][2]>a;d--)n[d]=n[d-1];n[d]=[t,i,a]},r.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(e,{a:e}),e},r.d=function(n,e){for(var t in e)r.o(e,t)&&!r.o(n,t)&&Object.defineProperty(n,t,{enumerable:!0,get:e[t]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),r.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},r.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},r.nmd=function(n){return n.paths=[],n.children||(n.children=[]),n},r.j=6755,function(){r.b=document.baseURI||self.location.href;var n={6755:0};r.O.j=function(e){return 0===n[e]};var e=function(e,t){var i,a,o=t[0],s=t[1],c=t[2],l=0;if(o.some((function(e){return 0!==n[e]}))){for(i in s)r.o(s,i)&&(r.m[i]=s[i]);if(c)var d=c(r)}for(e&&e(t);l<o.length;l++)a=o[l],r.o(n,a)&&n[a]&&n[a][0](),n[a]=0;return r.O(d)},t=self.webpackChunknextcloud=self.webpackChunknextcloud||[];t.forEach(e.bind(null,0)),t.push=e.bind(null,t.push.bind(t))}(),r.nc=void 0;var a=r.O(void 0,[7874],(function(){return r(58739)}));a=r.O(a)}();
-//# sourceMappingURL=theming-theming-settings.js.map?v=9d1dc5a13970c7e1a75c
\ No newline at end of file
+!function(){"use strict";var n,e={34198:function(n,e,r){var a=r(20144),o=r(79753),i=r(16453),c=r(4820),s=r(13299),d=r.n(s),u=r(15168),l=r.n(u),g=function(n){return(0,o.generateFilePath)("theming","","img/background/")+n},p=function(n){var e,t,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",i=(null===(e=window.OCA)||void 0===e||null===(t=e.Theming)||void 0===t?void 0:t.enabledThemes)||[],c=0===i.length||"default"===i[0]?window.matchMedia("(prefers-color-scheme: dark)").matches:-1!==i.join("").indexOf("dark");return"default"===n?a&&"backgroundColor"!==a?(0,o.generateUrl)("/apps/theming/image/background")+"?v="+window.OCA.Theming.cacheBuster:g(c?"eduardo-neves-pedra-azul.jpg":"kamil-porembinski-clouds.jpg"):"custom"===n?(0,o.generateUrl)("/apps/theming/background")+"?v="+r:g(n)};function m(n,e,t,r,a,o,i){try{var c=n[o](i),s=c.value}catch(n){return void t(n)}c.done?e(s):Promise.resolve(s).then(r,a)}function h(n){return function(){var e=this,t=arguments;return new Promise((function(r,a){var o=n.apply(e,t);function i(n){m(o,r,a,i,c,"next",n)}function c(n){m(o,r,a,i,c,"throw",n)}i(void 0)}))}}var A=(0,i.loadState)("theming","shippedBackgrounds"),f={name:"BackgroundSettings",directives:{Tooltip:l()},props:{background:{type:String,default:"default"},themingDefaultBackground:{type:String,default:""}},data:function(){return{backgroundImage:(0,o.generateUrl)("/apps/theming/background")+"?v="+Date.now(),loading:!1}},computed:{shippedBackgrounds:function(){return Object.keys(A).map((function(n){return{name:n,url:g(n),preview:g("preview/"+n),details:A[n]}}))}},methods:{update:function(n){var e=this;return h(regeneratorRuntime.mark((function t(){var r,a;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(r="custom"===n.type||"default"===n.type?n.type:n.value,e.backgroundImage=p(r,n.version,e.themingDefaultBackground),"color"!==n.type&&("default"!==n.type||"backgroundColor"!==e.themingDefaultBackground)){t.next=6;break}return e.$emit("update:background",n),e.loading=!1,t.abrupt("return");case 6:(a=new Image).onload=function(){e.$emit("update:background",n),e.loading=!1},a.src=e.backgroundImage;case 9:case"end":return t.stop()}}),t)})))()},setDefault:function(){var n=this;return h(regeneratorRuntime.mark((function e(){var t;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n.loading="default",e.next=3,c.default.post((0,o.generateUrl)("/apps/theming/background/default"));case 3:t=e.sent,n.update(t.data);case 5:case"end":return e.stop()}}),e)})))()},setShipped:function(n){var e=this;return h(regeneratorRuntime.mark((function t(){var r;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return e.loading=n,t.next=3,c.default.post((0,o.generateUrl)("/apps/theming/background/shipped"),{value:n});case 3:r=t.sent,e.update(r.data);case 5:case"end":return t.stop()}}),t)})))()},setFile:function(n){var e=this;return h(regeneratorRuntime.mark((function t(){var r;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return e.loading="custom",t.next=3,c.default.post((0,o.generateUrl)("/apps/theming/background/custom"),{value:n});case 3:r=t.sent,e.update(r.data);case 5:case"end":return t.stop()}}),t)})))()},pickColor:function(){var n=this;return h(regeneratorRuntime.mark((function e(){var t,r;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n.loading="color",t=OCA&&OCA.Theming?OCA.Theming.color:"#0082c9",e.next=4,c.default.post((0,o.generateUrl)("/apps/theming/background/color"),{value:t});case 4:r=e.sent,n.update(r.data);case 6:case"end":return e.stop()}}),e)})))()},pickFile:function(){var n=this;window.OC.dialogs.filepicker(t("theming","Insert from {productName}",{productName:OC.theme.name}),(function(e,t){t===OC.dialogs.FILEPICKER_TYPE_CHOOSE&&n.setFile(e)}),!1,["image/png","image/gif","image/jpeg","image/svg"],!0,OC.dialogs.FILEPICKER_TYPE_CHOOSE)}}},v=f,b=r(93379),k=r.n(b),C=r(7795),y=r.n(C),w=r(90569),x=r.n(w),_=r(3565),B=r.n(_),S=r(19216),T=r.n(S),I=r(44589),P=r.n(I),E=r(33470),O={};O.styleTagTransform=P(),O.setAttributes=B(),O.insert=x().bind(null,"head"),O.domAPI=y(),O.insertStyleElement=T(),k()(E.Z,O),E.Z&&E.Z.locals&&E.Z.locals;var D=r(51900),j=(0,D.Z)(v,(function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{staticClass:"background-selector"},[t("button",{staticClass:"background filepicker",class:{active:"custom"===n.background},attrs:{tabindex:"0"},on:{click:n.pickFile}},[n._v("\n\t\t"+n._s(n.t("theming","Pick from Files"))+"\n\t")]),n._v(" "),t("button",{staticClass:"background default",class:{"icon-loading":"default"===n.loading,active:"default"===n.background},attrs:{tabindex:"0"},on:{click:n.setDefault}},[n._v("\n\t\t"+n._s(n.t("theming","Default image"))+"\n\t")]),n._v(" "),t("button",{staticClass:"background color",class:{active:"custom"===n.background},attrs:{tabindex:"0"},on:{click:n.pickColor}},[n._v("\n\t\t"+n._s(n.t("theming","Plain background"))+"\n\t")]),n._v(" "),n._l(n.shippedBackgrounds,(function(e){return t("button",{directives:[{name:"tooltip",rawName:"v-tooltip",value:e.details.attribution,expression:"shippedBackground.details.attribution"}],key:e.name,staticClass:"background",class:{"icon-loading":n.loading===e.name,active:n.background===e.name},style:{"background-image":"url("+e.preview+")"},attrs:{tabindex:"0"},on:{click:function(t){return n.setShipped(e.name)}}})}))],2)}),[],!1,null,"50307d02",null).exports,q=r(20571),Z={name:"ItemPreview",components:{NcCheckboxRadioSwitch:r.n(q)()},props:{enforced:{type:Boolean,default:!1},selected:{type:Boolean,default:!1},theme:{type:Object,required:!0},type:{type:String,default:""},unique:{type:Boolean,default:!1}},computed:{switchType:function(){return this.unique?"switch":"radio"},name:function(){return this.unique?null:this.type},img:function(){return(0,o.generateFilePath)("theming","img",this.theme.id+".jpg")},checked:{get:function(){return this.selected},set:function(n){console.debug("Changed theme",this.theme.id,n),this.unique?this.$emit("change",{enabled:!0===n,id:this.theme.id}):this.$emit("change",{enabled:!0,id:this.theme.id})}}},methods:{onToggle:function(){"radio"!==this.switchType?this.checked=!this.checked:this.checked=!0}}},R=r(83005),F={};F.styleTagTransform=P(),F.setAttributes=B(),F.insert=x().bind(null,"head"),F.domAPI=y(),F.insertStyleElement=T(),k()(R.Z,F),R.Z&&R.Z.locals&&R.Z.locals;var U=(0,D.Z)(Z,(function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{staticClass:"theming__preview",class:"theming__preview--"+n.theme.id},[t("div",{staticClass:"theming__preview-image",style:{backgroundImage:"url("+n.img+")"},on:{click:n.onToggle}}),n._v(" "),t("div",{staticClass:"theming__preview-description"},[t("h3",[n._v(n._s(n.theme.title))]),n._v(" "),t("p",[n._v(n._s(n.theme.description))]),n._v(" "),n.enforced?t("span",{staticClass:"theming__preview-warning",attrs:{role:"note"}},[n._v("\n\t\t\t"+n._s(n.t("theming","Theme selection is enforced"))+"\n\t\t")]):n._e(),n._v(" "),t("NcCheckboxRadioSwitch",{staticClass:"theming__preview-toggle",attrs:{checked:n.checked,disabled:n.enforced,name:n.name,type:n.switchType},on:{"update:checked":function(e){n.checked=e}}},[n._v("\n\t\t\t"+n._s(n.theme.enableLabel)+"\n\t\t")])],1)])}),[],!1,null,"37ca8ab2",null).exports;function G(n,e,t,r,a,o,i){try{var c=n[o](i),s=c.value}catch(n){return void t(n)}c.done?e(s):Promise.resolve(s).then(r,a)}function L(n){return function(n){if(Array.isArray(n))return W(n)}(n)||function(n){if("undefined"!=typeof Symbol&&null!=n[Symbol.iterator]||null!=n["@@iterator"])return Array.from(n)}(n)||function(n,e){if(n){if("string"==typeof n)return W(n,e);var t=Object.prototype.toString.call(n).slice(8,-1);return"Object"===t&&n.constructor&&(t=n.constructor.name),"Map"===t||"Set"===t?Array.from(n):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?W(n,e):void 0}}(n)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function W(n,e){(null==e||e>n.length)&&(e=n.length);for(var t=0,r=new Array(e);t<e;t++)r[t]=n[t];return r}var N=(0,i.loadState)("theming","themes",[]),$=(0,i.loadState)("theming","enforceTheme",""),z=(0,i.loadState)("theming","background"),M=(0,i.loadState)("theming","backgroundVersion"),Y=(0,i.loadState)("theming","themingDefaultBackground"),K=(0,i.loadState)("theming","shippedBackgrounds");console.debug("Available themes",N);var H={name:"UserThemes",components:{ItemPreview:U,NcSettingsSection:d(),BackgroundSettings:j},data:function(){return{availableThemes:N,enforceTheme:$,background:z,themingDefaultBackground:Y}},computed:{backgroundImage:function(){return p(this.background,M,this.themingDefaultBackground)},backgroundStyle:function(){return"default"===this.background&&"backgroundColor"===this.themingDefaultBackground||this.background.match(/#[0-9A-Fa-f]{6}/g)?null:{backgroundImage:"default"===this.background?"var(--image-main-background)":"url('".concat(this.backgroundImage,"')")}},themes:function(){return this.availableThemes.filter((function(n){return 1===n.type}))},fonts:function(){return this.availableThemes.filter((function(n){return 2===n.type}))},selectedTheme:function(){return this.themes.find((function(n){return!0===n.enabled}))||this.themes[0]},description:function(){return t("theming","Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {guidelines}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level.").replace("{guidelines}",this.guidelinesLink).replace("{linkend}","</a>")},guidelinesLink:function(){return'<a target="_blank" href="https://www.w3.org/WAI/standards-guidelines/wcag/" rel="noreferrer nofollow">'},descriptionDetail:function(){return t("theming","If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!").replace("{issuetracker}",this.issuetrackerLink).replace("{designteam}",this.designteamLink).replace(/\{linkend\}/g,"</a>")},issuetrackerLink:function(){return'<a target="_blank" href="https://github.com/nextcloud/server/issues/" rel="noreferrer nofollow">'},designteamLink:function(){return'<a target="_blank" href="https://nextcloud.com/design" rel="noreferrer nofollow">'}},mounted:function(){this.updateGlobalStyles()},methods:{updateBackground:function(n){this.background="custom"===n.type||"default"===n.type?n.type:n.value,this.updateGlobalStyles()},updateGlobalStyles:function(){var n;"dark"===(null===(n=K[this.background])||void 0===n?void 0:n.theming)?(document.querySelector("#header").style.setProperty("--primary-invert-if-bright","invert(100%)"),document.querySelector("#header").style.setProperty("--color-primary-text","#000000")):(document.querySelector("#header").style.setProperty("--primary-invert-if-bright","no"),document.querySelector("#header").style.setProperty("--color-primary-text","#ffffff"));for(var e=0,t=[document.documentElement,document.querySelector("#header"),document.querySelector("body")];e<t.length;e++){var r=t[e];"default"===this.background?r.style.setProperty("--image-main-background","url('".concat((0,o.imagePath)("core","app-background.jpg"),"')")):this.background.match(/#[0-9A-Fa-f]{6}/g)?r.style.setProperty("--image-main-background",void 0):r.style.setProperty("--image-main-background",this.backgroundStyle.backgroundImage)}},changeTheme:function(n){var e=n.enabled,t=n.id;this.themes.forEach((function(n){n.id===t&&e?n.enabled=!0:n.enabled=!1})),this.updateBodyAttributes(),this.selectItem(e,t)},changeFont:function(n){var e=n.enabled,t=n.id;this.fonts.forEach((function(n){n.id===t&&e?n.enabled=!0:n.enabled=!1})),this.updateBodyAttributes(),this.selectItem(e,t)},updateBodyAttributes:function(){var n=this.themes.filter((function(n){return!0===n.enabled})).map((function(n){return n.id})),e=this.fonts.filter((function(n){return!0===n.enabled})).map((function(n){return n.id}));this.themes.forEach((function(n){document.body.toggleAttribute("data-theme-".concat(n.id),n.enabled)})),this.fonts.forEach((function(n){document.body.toggleAttribute("data-theme-".concat(n.id),n.enabled)})),document.body.setAttribute("data-themes",[].concat(L(n),L(e)).join(","))},selectItem:function(n,e){return(r=regeneratorRuntime.mark((function r(){return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:if(r.prev=0,!n){r.next=6;break}return r.next=4,(0,c.default)({url:(0,o.generateOcsUrl)("apps/theming/api/v1/theme/{themeId}/enable",{themeId:e}),method:"PUT"});case 4:r.next=8;break;case 6:return r.next=8,(0,c.default)({url:(0,o.generateOcsUrl)("apps/theming/api/v1/theme/{themeId}",{themeId:e}),method:"DELETE"});case 8:r.next=14;break;case 10:r.prev=10,r.t0=r.catch(0),console.error(r.t0,r.t0.response),OC.Notification.showTemporary(t("theming",r.t0.response.data.ocs.meta.message+". Unable to apply the setting."));case 14:case"end":return r.stop()}}),r,null,[[0,10]])})),function(){var n=this,e=arguments;return new Promise((function(t,a){var o=r.apply(n,e);function i(n){G(o,t,a,i,c,"next",n)}function c(n){G(o,t,a,i,c,"throw",n)}i(void 0)}))})();var r}}},Q=H,J=r(28871),V={};V.styleTagTransform=P(),V.setAttributes=B(),V.insert=x().bind(null,"head"),V.domAPI=y(),V.insertStyleElement=T(),k()(J.Z,V),J.Z&&J.Z.locals&&J.Z.locals;var X=(0,D.Z)(Q,(function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("section",[t("NcSettingsSection",{staticClass:"theming",attrs:{title:n.t("theming","Appearance and accessibility")}},[t("p",{domProps:{innerHTML:n._s(n.description)}}),n._v(" "),t("p",{domProps:{innerHTML:n._s(n.descriptionDetail)}}),n._v(" "),t("div",{staticClass:"theming__preview-list"},n._l(n.themes,(function(e){return t("ItemPreview",{key:e.id,attrs:{enforced:e.id===n.enforceTheme,selected:n.selectedTheme.id===e.id,theme:e,unique:1===n.themes.length,type:"theme"},on:{change:n.changeTheme}})})),1),n._v(" "),t("div",{staticClass:"theming__preview-list"},n._l(n.fonts,(function(e){return t("ItemPreview",{key:e.id,attrs:{selected:e.enabled,theme:e,unique:1===n.fonts.length,type:"font"},on:{change:n.changeFont}})})),1)]),n._v(" "),t("NcSettingsSection",{staticClass:"background",attrs:{title:n.t("theming","Background")}},[t("p",[n._v(n._s(n.t("theming","Set a custom background")))]),n._v(" "),t("BackgroundSettings",{staticClass:"background__grid",attrs:{background:n.background,"theming-default-background":n.themingDefaultBackground},on:{"update:background":n.updateBackground}})],1)],1)}),[],!1,null,"5654fc60",null).exports;a.ZP.prototype.OC=OC,a.ZP.prototype.t=t,(new(a.ZP.extend(X))).$mount("#theming")},28871:function(n,e,t){var r=t(87537),a=t.n(r),o=t(23645),i=t.n(o)()(a());i.push([n.id,".theming p[data-v-5654fc60]{max-width:800px}.theming[data-v-5654fc60] a{font-weight:bold}.theming[data-v-5654fc60] a:hover,.theming[data-v-5654fc60] a:focus{text-decoration:underline}.theming__preview-list[data-v-5654fc60]{--gap: 30px;display:grid;margin-top:var(--gap);column-gap:var(--gap);row-gap:var(--gap);grid-template-columns:1fr 1fr}.background__grid[data-v-5654fc60]{margin-top:30px}@media(max-width: 1440px){.theming__preview-list[data-v-5654fc60]{display:flex;flex-direction:column}}","",{version:3,sources:["webpack://./apps/theming/src/UserThemes.vue"],names:[],mappings:"AAqQC,4BACC,eAAA,CAID,4BACC,gBAAA,CAEA,oEAEC,yBAAA,CAIF,wCACC,WAAA,CAEA,YAAA,CACA,qBAAA,CACA,qBAAA,CACA,kBAAA,CACA,6BAAA,CAKD,mCACC,eAAA,CAIF,0BACC,wCACC,YAAA,CACA,qBAAA,CAAA",sourcesContent:["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.theming {\n\t// Limit width of settings sections for readability\n\tp {\n\t\tmax-width: 800px;\n\t}\n\n\t// Proper highlight for links and focus feedback\n\t&::v-deep a {\n\t\tfont-weight: bold;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\ttext-decoration: underline;\n\t\t}\n\t}\n\n\t&__preview-list {\n\t\t--gap: 30px;\n\n\t\tdisplay: grid;\n\t\tmargin-top: var(--gap);\n\t\tcolumn-gap: var(--gap);\n\t\trow-gap: var(--gap);\n\t\tgrid-template-columns: 1fr 1fr;\n\t}\n}\n\n.background {\n\t&__grid {\n\t\tmargin-top: 30px;\n\t}\n}\n\n@media (max-width: 1440px) {\n\t.theming__preview-list {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t}\n}\n"],sourceRoot:""}]),e.Z=i},33470:function(n,e,t){var r=t(87537),a=t.n(r),o=t(23645),i=t.n(o)()(a());i.push([n.id,'.background-selector[data-v-50307d02]{display:flex;flex-wrap:wrap;justify-content:center}.background-selector .background[data-v-50307d02]{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}.background-selector .background.current[data-v-50307d02]{background-image:var(--color-background-dark)}.background-selector .background.filepicker[data-v-50307d02],.background-selector .background.default[data-v-50307d02],.background-selector .background.color[data-v-50307d02]{border-color:var(--color-border)}.background-selector .background.color[data-v-50307d02]{background-color:var(--color-primary);color:var(--color-primary-text)}.background-selector .background.active[data-v-50307d02],.background-selector .background[data-v-50307d02]:hover,.background-selector .background[data-v-50307d02]:focus{border:2px solid var(--color-primary)}.background-selector .background.active[data-v-50307d02]:not(.icon-loading):after{background-image:var(--icon-checkmark-white);background-repeat:no-repeat;background-position:center;background-size:44px;content:"";display:block;height:100%}',"",{version:3,sources:["webpack://./apps/theming/src/components/BackgroundSettings.vue"],names:[],mappings:"AAoJA,sCACC,YAAA,CACA,cAAA,CACA,sBAAA,CAEA,kDACC,WAAA,CACA,WAAA,CACA,UAAA,CACA,qBAAA,CACA,iCAAA,CACA,iBAAA,CACA,wCAAA,CACA,6CAAA,CACA,eAAA,CAEA,0DACC,6CAAA,CAGD,+KACC,gCAAA,CAGD,wDACC,qCAAA,CACA,+BAAA,CAGD,yKAGC,qCAAA,CAGD,kFACC,4CAAA,CACA,2BAAA,CACA,0BAAA,CACA,oBAAA,CACA,UAAA,CACA,aAAA,CACA,WAAA",sourcesContent:["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.background-selector {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tjustify-content: center;\n\n\t.background {\n\t\twidth: 176px;\n\t\theight: 96px;\n\t\tmargin: 8px;\n\t\tbackground-size: cover;\n\t\tbackground-position: center center;\n\t\ttext-align: center;\n\t\tborder-radius: var(--border-radius-large);\n\t\tborder: 2px solid var(--color-main-background);\n\t\toverflow: hidden;\n\n\t\t&.current {\n\t\t\tbackground-image: var(--color-background-dark);\n\t\t}\n\n\t\t&.filepicker, &.default, &.color {\n\t\t\tborder-color: var(--color-border);\n\t\t}\n\n\t\t&.color {\n\t\t\tbackground-color: var(--color-primary);\n\t\t\tcolor: var(--color-primary-text);\n\t\t}\n\n\t\t&.active,\n\t\t&:hover,\n\t\t&:focus {\n\t\t\tborder: 2px solid var(--color-primary);\n\t\t}\n\n\t\t&.active:not(.icon-loading):after {\n\t\t\tbackground-image: var(--icon-checkmark-white);\n\t\t\tbackground-repeat: no-repeat;\n\t\t\tbackground-position: center;\n\t\t\tbackground-size: 44px;\n\t\t\tcontent: '';\n\t\t\tdisplay: block;\n\t\t\theight: 100%;\n\t\t}\n\t}\n}\n"],sourceRoot:""}]),e.Z=i},83005:function(n,e,t){var r=t(87537),a=t.n(r),o=t(23645),i=t.n(o)()(a());i.push([n.id,".theming__preview[data-v-37ca8ab2]{--ratio: 16;position:relative;display:flex;justify-content:flex-start;max-width:800px}.theming__preview[data-v-37ca8ab2],.theming__preview *[data-v-37ca8ab2]{user-select:none}.theming__preview-image[data-v-37ca8ab2]{flex-basis:calc(16px*var(--ratio));flex-shrink:0;height:calc(10px*var(--ratio));margin-right:var(--gap);cursor:pointer;border-radius:var(--border-radius);background-repeat:no-repeat;background-position:top left;background-size:cover}.theming__preview-description[data-v-37ca8ab2]{display:flex;flex-direction:column}.theming__preview-description label[data-v-37ca8ab2]{padding:12px 0}.theming__preview--default[data-v-37ca8ab2]{grid-column:span 2}.theming__preview-warning[data-v-37ca8ab2]{color:var(--color-warning)}@media(max-width: 682.6666666667px){.theming__preview[data-v-37ca8ab2]{flex-direction:column}.theming__preview-image[data-v-37ca8ab2]{margin:0}}","",{version:3,sources:["webpack://./apps/theming/src/components/ItemPreview.vue"],names:[],mappings:"AAiGA,mCAEC,WAAA,CAEA,iBAAA,CACA,YAAA,CACA,0BAAA,CACA,eAAA,CAEA,wEAEC,gBAAA,CAGD,yCACC,kCAAA,CACA,aAAA,CACA,8BAAA,CACA,uBAAA,CACA,cAAA,CACA,kCAAA,CACA,2BAAA,CACA,4BAAA,CACA,qBAAA,CAGD,+CACC,YAAA,CACA,qBAAA,CAEA,qDACC,cAAA,CAIF,4CACC,kBAAA,CAGD,2CACC,0BAAA,CAIF,oCACC,mCACC,qBAAA,CAEA,yCACC,QAAA,CAAA",sourcesContent:["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.theming__preview {\n\t// We make previews on 16/10 screens\n\t--ratio: 16;\n\n\tposition: relative;\n\tdisplay: flex;\n\tjustify-content: flex-start;\n\tmax-width: 800px;\n\n\t&,\n\t* {\n\t\tuser-select: none;\n\t}\n\n\t&-image {\n\t\tflex-basis: calc(16px * var(--ratio));\n\t\tflex-shrink: 0;\n\t\theight: calc(10px * var(--ratio));\n\t\tmargin-right: var(--gap);\n\t\tcursor: pointer;\n\t\tborder-radius: var(--border-radius);\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-position: top left;\n\t\tbackground-size: cover;\n\t}\n\n\t&-description {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\n\t\tlabel {\n\t\t\tpadding: 12px 0;\n\t\t}\n\t}\n\n\t&--default {\n\t\tgrid-column: span 2;\n\t}\n\n\t&-warning {\n\t\tcolor: var(--color-warning);\n\t}\n}\n\n@media (max-width: (1024px / 1.5)) {\n\t.theming__preview {\n\t\tflex-direction: column;\n\n\t\t&-image {\n\t\t\tmargin: 0;\n\t\t}\n\t}\n}\n\n"],sourceRoot:""}]),e.Z=i}},r={};function a(n){var t=r[n];if(void 0!==t)return t.exports;var o=r[n]={id:n,loaded:!1,exports:{}};return e[n].call(o.exports,o,o.exports,a),o.loaded=!0,o.exports}a.m=e,a.amdD=function(){throw new Error("define cannot be used indirect")},a.amdO={},n=[],a.O=function(e,t,r,o){if(!t){var i=1/0;for(u=0;u<n.length;u++){t=n[u][0],r=n[u][1],o=n[u][2];for(var c=!0,s=0;s<t.length;s++)(!1&o||i>=o)&&Object.keys(a.O).every((function(n){return a.O[n](t[s])}))?t.splice(s--,1):(c=!1,o<i&&(i=o));if(c){n.splice(u--,1);var d=r();void 0!==d&&(e=d)}}return e}o=o||0;for(var u=n.length;u>0&&n[u-1][2]>o;u--)n[u]=n[u-1];n[u]=[t,r,o]},a.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return a.d(e,{a:e}),e},a.d=function(n,e){for(var t in e)a.o(e,t)&&!a.o(n,t)&&Object.defineProperty(n,t,{enumerable:!0,get:e[t]})},a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),a.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},a.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},a.nmd=function(n){return n.paths=[],n.children||(n.children=[]),n},a.j=6755,function(){a.b=document.baseURI||self.location.href;var n={6755:0};a.O.j=function(e){return 0===n[e]};var e=function(e,t){var r,o,i=t[0],c=t[1],s=t[2],d=0;if(i.some((function(e){return 0!==n[e]}))){for(r in c)a.o(c,r)&&(a.m[r]=c[r]);if(s)var u=s(a)}for(e&&e(t);d<i.length;d++)o=i[d],a.o(n,o)&&n[o]&&n[o][0](),n[o]=0;return a.O(u)},t=self.webpackChunknextcloud=self.webpackChunknextcloud||[];t.forEach(e.bind(null,0)),t.push=e.bind(null,t.push.bind(t))}(),a.nc=void 0;var o=a.O(void 0,[7874],(function(){return a(34198)}));o=a.O(o)}();
+//# sourceMappingURL=theming-theming-settings.js.map?v=1f53bcf4598d8f0407d7
\ No newline at end of file
-{"version":3,"file":"theming-theming-settings.js?v=9d1dc5a13970c7e1a75c","mappings":";6BAAIA,yGCAoL,ECwBxL,CACA,mBACA,YACA,gCAEA,OACA,UACA,aACA,YAEA,UACA,aACA,YAEA,OACA,YACA,aAEA,MACA,YACA,YAEA,QACA,aACA,aAGA,UACA,WADA,WAEA,qCAGA,KALA,WAMA,mCAGA,IATA,WAUA,oEAGA,SACA,IADA,WAEA,sBAEA,IAJA,SAIA,GACA,+CAGA,YAMA,uDALA,sDAUA,SACA,SADA,WAEA,0BAMA,2BALA,oJC3EIC,EAAU,GAEdA,EAAQC,kBAAoB,IAC5BD,EAAQE,cAAgB,IAElBF,EAAQG,OAAS,SAAc,KAAM,QAE3CH,EAAQI,OAAS,IACjBJ,EAAQK,mBAAqB,IAEhB,IAAI,IAASL,GAKJ,KAAW,YAAiB,WALlD,eCFA,GAXgB,OACd,GCTW,WAAa,IAAIM,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,YAAY,mBAAmBC,MAAM,qBAAuBP,EAAIQ,MAAMC,IAAI,CAACL,EAAG,MAAM,CAACE,YAAY,yBAAyBI,MAAM,CAAGC,gBAAiB,OAASX,EAAIY,IAAM,KAAOC,GAAG,CAAC,MAAQb,EAAIc,YAAYd,EAAIe,GAAG,KAAKX,EAAG,MAAM,CAACE,YAAY,gCAAgC,CAACF,EAAG,KAAK,CAACJ,EAAIe,GAAGf,EAAIgB,GAAGhB,EAAIQ,MAAMS,UAAUjB,EAAIe,GAAG,KAAKX,EAAG,IAAI,CAACJ,EAAIe,GAAGf,EAAIgB,GAAGhB,EAAIQ,MAAMU,gBAAgBlB,EAAIe,GAAG,KAAMf,EAAY,SAAEI,EAAG,OAAO,CAACE,YAAY,2BAA2Ba,MAAM,CAAC,KAAO,SAAS,CAACnB,EAAIe,GAAG,WAAWf,EAAIgB,GAAGhB,EAAIoB,EAAE,UAAW,gCAAgC,YAAYpB,EAAIqB,KAAKrB,EAAIe,GAAG,KAAKX,EAAG,wBAAwB,CAACE,YAAY,0BAA0Ba,MAAM,CAAC,QAAUnB,EAAIsB,QAAQ,SAAWtB,EAAIuB,SAAS,KAAOvB,EAAIwB,KAAK,KAAOxB,EAAIyB,YAAYZ,GAAG,CAAC,iBAAiB,SAASa,GAAQ1B,EAAIsB,QAAQI,KAAU,CAAC1B,EAAIe,GAAG,WAAWf,EAAIgB,GAAGhB,EAAIQ,MAAMmB,aAAa,aAAa,OACh7B,IDWpB,EACA,KACA,WACA,MAI8B,i3BEiBhC,6CACA,+CAEAC,QAAQC,MAAM,mBAAoBC,GAElC,OACA,kBACA,YACA,cACA,uBAGA,KAPA,WAQA,OACA,kBACA,iBAIA,UACA,OADA,WAEA,sEAEA,MAJA,WAKA,sEAIA,cATA,WAUA,8EAGA,YAbA,WAeA,SACA,UACA,sUAEA,4CACA,6BAEA,eAtBA,WAuBA,gHAEA,kBAzBA,WA0BA,SACA,UACA,wLAEA,gDACA,4CACA,gCAEA,iBAlCA,WAmCA,0GAEA,eArCA,WAsCA,4FAGA,SACA,YADA,YACA,uBAEA,iCACA,YACA,aAGA,gBAGA,4BACA,sBAEA,WAdA,YAcA,uBAEA,gCACA,YACA,aAGA,gBAGA,4BACA,sBAGA,qBA5BA,WA6BA,8FACA,yFAEA,iCACA,uEAEA,gCACA,uEAGA,0EAUA,WAjDA,SAiDA,iJAEA,EAFA,iCAGA,cACA,mFACA,eALA,8CAQA,cACA,4EACA,kBAVA,yDAeA,kCACA,iHAhBA,mPCjJiL,eCW7K,EAAU,GAEd,EAAQnC,kBAAoB,IAC5B,EAAQC,cAAgB,IAElB,EAAQC,OAAS,SAAc,KAAM,QAE3C,EAAQC,OAAS,IACjB,EAAQC,mBAAqB,IAEhB,IAAI,IAAS,GAKJ,KAAW,YAAiB,WALlD,ICFA,GAXgB,OACd,GCTW,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,oBAAoB,CAACE,YAAY,UAAUa,MAAM,CAAC,MAAQnB,EAAIoB,EAAE,SAAU,kCAAkC,CAAChB,EAAG,IAAI,CAAC2B,SAAS,CAAC,UAAY/B,EAAIgB,GAAGhB,EAAIkB,gBAAgBlB,EAAIe,GAAG,KAAKX,EAAG,IAAI,CAAC2B,SAAS,CAAC,UAAY/B,EAAIgB,GAAGhB,EAAIgC,sBAAsBhC,EAAIe,GAAG,KAAKX,EAAG,MAAM,CAACE,YAAY,yBAAyBN,EAAIiC,GAAIjC,EAAU,QAAE,SAASQ,GAAO,OAAOJ,EAAG,cAAc,CAAC8B,IAAI1B,EAAMC,GAAGU,MAAM,CAAC,SAAWX,EAAMC,KAAOT,EAAImC,aAAa,SAAWnC,EAAIoC,cAAc3B,KAAOD,EAAMC,GAAG,MAAQD,EAAM,OAA+B,IAAtBR,EAAIqC,OAAOC,OAAa,KAAO,SAASzB,GAAG,CAAC,OAASb,EAAIuC,kBAAiB,GAAGvC,EAAIe,GAAG,KAAKX,EAAG,MAAM,CAACE,YAAY,yBAAyBN,EAAIiC,GAAIjC,EAAS,OAAE,SAASQ,GAAO,OAAOJ,EAAG,cAAc,CAAC8B,IAAI1B,EAAMC,GAAGU,MAAM,CAAC,SAAWX,EAAMgC,QAAQ,MAAQhC,EAAM,OAA8B,IAArBR,EAAIyC,MAAMH,OAAa,KAAO,QAAQzB,GAAG,CAAC,OAASb,EAAI0C,iBAAgB,OACt4B,IDWpB,EACA,KACA,WACA,MAI8B,QEOhCC,EAAAA,GAAAA,UAAAA,GAAmBC,GACnBD,EAAAA,GAAAA,UAAAA,EAAkBvB,GAGF,IADHuB,EAAAA,GAAAA,OAAWE,KAEhBC,OAAO,sEC5BXC,QAA0B,GAA4B,KAE1DA,EAAwBC,KAAK,CAACC,EAAOxC,GAAI,8bAA+b,GAAG,CAAC,QAAU,EAAE,QAAU,CAAC,+CAA+C,MAAQ,GAAG,SAAW,iKAAiK,eAAiB,CAAC,g6BAAg6B,WAAa,MAExqD,gECJIsC,QAA0B,GAA4B,KAE1DA,EAAwBC,KAAK,CAACC,EAAOxC,GAAI,k5BAAm5B,GAAG,CAAC,QAAU,EAAE,QAAU,CAAC,2DAA2D,MAAQ,GAAG,SAAW,8SAA8S,eAAiB,CAAC,olCAAolC,WAAa,MAEz8E,QCNIyC,EAA2B,GAG/B,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaE,QAGrB,IAAIN,EAASC,EAAyBE,GAAY,CACjD3C,GAAI2C,EACJI,QAAQ,EACRD,QAAS,IAUV,OANAE,EAAoBL,GAAUM,KAAKT,EAAOM,QAASN,EAAQA,EAAOM,QAASJ,GAG3EF,EAAOO,QAAS,EAGTP,EAAOM,QAIfJ,EAAoBQ,EAAIF,EC5BxBN,EAAoBS,KAAO,WAC1B,MAAM,IAAIC,MAAM,mCCDjBV,EAAoBW,KAAO,GhBAvBrE,EAAW,GACf0D,EAAoBY,EAAI,SAASC,EAAQC,EAAUC,EAAIC,GACtD,IAAGF,EAAH,CAMA,IAAIG,EAAeC,EAAAA,EACnB,IAASC,EAAI,EAAGA,EAAI7E,EAAS6C,OAAQgC,IAAK,CACrCL,EAAWxE,EAAS6E,GAAG,GACvBJ,EAAKzE,EAAS6E,GAAG,GACjBH,EAAW1E,EAAS6E,GAAG,GAE3B,IAJA,IAGIC,GAAY,EACPC,EAAI,EAAGA,EAAIP,EAAS3B,OAAQkC,MACpB,EAAXL,GAAsBC,GAAgBD,IAAaM,OAAOC,KAAKvB,EAAoBY,GAAGY,OAAM,SAASzC,GAAO,OAAOiB,EAAoBY,EAAE7B,GAAK+B,EAASO,OAC3JP,EAASW,OAAOJ,IAAK,IAErBD,GAAY,EACTJ,EAAWC,IAAcA,EAAeD,IAG7C,GAAGI,EAAW,CACb9E,EAASmF,OAAON,IAAK,GACrB,IAAIO,EAAIX,SACEZ,IAANuB,IAAiBb,EAASa,IAGhC,OAAOb,EAzBNG,EAAWA,GAAY,EACvB,IAAI,IAAIG,EAAI7E,EAAS6C,OAAQgC,EAAI,GAAK7E,EAAS6E,EAAI,GAAG,GAAKH,EAAUG,IAAK7E,EAAS6E,GAAK7E,EAAS6E,EAAI,GACrG7E,EAAS6E,GAAK,CAACL,EAAUC,EAAIC,IiBJ/BhB,EAAoB2B,EAAI,SAAS7B,GAChC,IAAI8B,EAAS9B,GAAUA,EAAO+B,WAC7B,WAAa,OAAO/B,EAAgB,SACpC,WAAa,OAAOA,GAErB,OADAE,EAAoB8B,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,GCLR5B,EAAoB8B,EAAI,SAAS1B,EAAS4B,GACzC,IAAI,IAAIjD,KAAOiD,EACXhC,EAAoBiC,EAAED,EAAYjD,KAASiB,EAAoBiC,EAAE7B,EAASrB,IAC5EuC,OAAOY,eAAe9B,EAASrB,EAAK,CAAEoD,YAAY,EAAMC,IAAKJ,EAAWjD,MCJ3EiB,EAAoBqC,EAAI,WACvB,GAA0B,iBAAfC,WAAyB,OAAOA,WAC3C,IACC,OAAOxF,MAAQ,IAAIyF,SAAS,cAAb,GACd,MAAOC,GACR,GAAsB,iBAAXC,OAAqB,OAAOA,QALjB,GCAxBzC,EAAoBiC,EAAI,SAASS,EAAKC,GAAQ,OAAOrB,OAAOsB,UAAUC,eAAetC,KAAKmC,EAAKC,ICC/F3C,EAAoB0B,EAAI,SAAStB,GACX,oBAAX0C,QAA0BA,OAAOC,aAC1CzB,OAAOY,eAAe9B,EAAS0C,OAAOC,YAAa,CAAEC,MAAO,WAE7D1B,OAAOY,eAAe9B,EAAS,aAAc,CAAE4C,OAAO,KCLvDhD,EAAoBiD,IAAM,SAASnD,GAGlC,OAFAA,EAAOoD,MAAQ,GACVpD,EAAOqD,WAAUrD,EAAOqD,SAAW,IACjCrD,GCHRE,EAAoBqB,EAAI,gBCAxBrB,EAAoBoD,EAAIC,SAASC,SAAWC,KAAKC,SAASC,KAK1D,IAAIC,EAAkB,CACrB,KAAM,GAaP1D,EAAoBY,EAAES,EAAI,SAASsC,GAAW,OAAoC,IAA7BD,EAAgBC,IAGrE,IAAIC,EAAuB,SAASC,EAA4BC,GAC/D,IAKI7D,EAAU0D,EALV7C,EAAWgD,EAAK,GAChBC,EAAcD,EAAK,GACnBE,EAAUF,EAAK,GAGI3C,EAAI,EAC3B,GAAGL,EAASmD,MAAK,SAAS3G,GAAM,OAA+B,IAAxBoG,EAAgBpG,MAAe,CACrE,IAAI2C,KAAY8D,EACZ/D,EAAoBiC,EAAE8B,EAAa9D,KACrCD,EAAoBQ,EAAEP,GAAY8D,EAAY9D,IAGhD,GAAG+D,EAAS,IAAInD,EAASmD,EAAQhE,GAGlC,IADG6D,GAA4BA,EAA2BC,GACrD3C,EAAIL,EAAS3B,OAAQgC,IACzBwC,EAAU7C,EAASK,GAChBnB,EAAoBiC,EAAEyB,EAAiBC,IAAYD,EAAgBC,IACrED,EAAgBC,GAAS,KAE1BD,EAAgBC,GAAW,EAE5B,OAAO3D,EAAoBY,EAAEC,IAG1BqD,EAAqBX,KAA4B,sBAAIA,KAA4B,uBAAK,GAC1FW,EAAmBC,QAAQP,EAAqBQ,KAAK,KAAM,IAC3DF,EAAmBrE,KAAO+D,EAAqBQ,KAAK,KAAMF,EAAmBrE,KAAKuE,KAAKF,OClDvFlE,EAAoBqE,QAAKlE,ECGzB,IAAImE,EAAsBtE,EAAoBY,OAAET,EAAW,CAAC,OAAO,WAAa,OAAOH,EAAoB,UAC3GsE,EAAsBtE,EAAoBY,EAAE0D","sources":["webpack:///nextcloud/webpack/runtime/chunk loaded","webpack:///nextcloud/apps/theming/src/components/ItemPreview.vue?vue&type=script&lang=js&","webpack:///nextcloud/apps/theming/src/components/ItemPreview.vue","webpack://nextcloud/./apps/theming/src/components/ItemPreview.vue?f1c6","webpack://nextcloud/./apps/theming/src/components/ItemPreview.vue?8797","webpack:///nextcloud/apps/theming/src/components/ItemPreview.vue?vue&type=template&id=37ca8ab2&scoped=true&","webpack:///nextcloud/apps/theming/src/UserThemes.vue","webpack:///nextcloud/apps/theming/src/UserThemes.vue?vue&type=script&lang=js&","webpack://nextcloud/./apps/theming/src/UserThemes.vue?8f1a","webpack://nextcloud/./apps/theming/src/UserThemes.vue?7eb2","webpack:///nextcloud/apps/theming/src/UserThemes.vue?vue&type=template&id=015ac8e0&scoped=true&","webpack:///nextcloud/apps/theming/src/settings.js","webpack:///nextcloud/apps/theming/src/UserThemes.vue?vue&type=style&index=0&id=015ac8e0&lang=scss&scoped=true&","webpack:///nextcloud/apps/theming/src/components/ItemPreview.vue?vue&type=style&index=0&id=37ca8ab2&lang=scss&scoped=true&","webpack:///nextcloud/webpack/bootstrap","webpack:///nextcloud/webpack/runtime/amd define","webpack:///nextcloud/webpack/runtime/amd options","webpack:///nextcloud/webpack/runtime/compat get default export","webpack:///nextcloud/webpack/runtime/define property getters","webpack:///nextcloud/webpack/runtime/global","webpack:///nextcloud/webpack/runtime/hasOwnProperty shorthand","webpack:///nextcloud/webpack/runtime/make namespace object","webpack:///nextcloud/webpack/runtime/node module decorator","webpack:///nextcloud/webpack/runtime/runtimeId","webpack:///nextcloud/webpack/runtime/jsonp chunk loading","webpack:///nextcloud/webpack/runtime/nonce","webpack:///nextcloud/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","import mod from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ItemPreview.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ItemPreview.vue?vue&type=script&lang=js&\"","<template>\n\t<div :class=\"'theming__preview--' + theme.id\" class=\"theming__preview\">\n\t\t<div class=\"theming__preview-image\" :style=\"{ backgroundImage: 'url(' + img + ')' }\" @click=\"onToggle\" />\n\t\t<div class=\"theming__preview-description\">\n\t\t\t<h3>{{ theme.title }}</h3>\n\t\t\t<p>{{ theme.description }}</p>\n\t\t\t<span v-if=\"enforced\" class=\"theming__preview-warning\" role=\"note\">\n\t\t\t\t{{ t('theming', 'Theme selection is enforced') }}\n\t\t\t</span>\n\t\t\t<NcCheckboxRadioSwitch class=\"theming__preview-toggle\"\n\t\t\t\t:checked.sync=\"checked\"\n\t\t\t\t:disabled=\"enforced\"\n\t\t\t\t:name=\"name\"\n\t\t\t\t:type=\"switchType\">\n\t\t\t\t{{ theme.enableLabel }}\n\t\t\t</NcCheckboxRadioSwitch>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { generateFilePath } from '@nextcloud/router'\nimport NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch'\n\nexport default {\n\tname: 'ItemPreview',\n\tcomponents: {\n\t\tNcCheckboxRadioSwitch,\n\t},\n\tprops: {\n\t\tenforced: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t\ttheme: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\t\ttype: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t\tunique: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tcomputed: {\n\t\tswitchType() {\n\t\t\treturn this.unique ? 'switch' : 'radio'\n\t\t},\n\n\t\tname() {\n\t\t\treturn !this.unique ? this.type : null\n\t\t},\n\n\t\timg() {\n\t\t\treturn generateFilePath('theming', 'img', this.theme.id + '.jpg')\n\t\t},\n\n\t\tchecked: {\n\t\t\tget() {\n\t\t\t\treturn this.selected\n\t\t\t},\n\t\t\tset(checked) {\n\t\t\t\tconsole.debug('Changed theme', this.theme.id, checked)\n\n\t\t\t\t// If this is a radio, we can only enable\n\t\t\t\tif (!this.unique) {\n\t\t\t\t\tthis.$emit('change', { enabled: true, id: this.theme.id })\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// If this is a switch, we can disable the theme\n\t\t\t\tthis.$emit('change', { enabled: checked === true, id: this.theme.id })\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tonToggle() {\n\t\t\tif (this.switchType === 'radio') {\n\t\t\t\tthis.checked = true\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Invert state\n\t\t\tthis.checked = !this.checked\n\t\t},\n\t},\n}\n</script>\n<style lang=\"scss\" scoped>\n.theming__preview {\n\t// We make previews on 16/10 screens\n\t--ratio: 16;\n\n\tposition: relative;\n\tdisplay: flex;\n\tjustify-content: flex-start;\n\tmax-width: 800px;\n\n\t&,\n\t* {\n\t\tuser-select: none;\n\t}\n\n\t&-image {\n\t\tflex-basis: calc(16px * var(--ratio));\n\t\tflex-shrink: 0;\n\t\theight: calc(10px * var(--ratio));\n\t\tmargin-right: var(--gap);\n\t\tcursor: pointer;\n\t\tborder-radius: var(--border-radius);\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-position: top left;\n\t\tbackground-size: cover;\n\t}\n\n\t&-description {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\n\t\tlabel {\n\t\t\tpadding: 12px 0;\n\t\t}\n\t}\n\n\t&--default {\n\t\tgrid-column: span 2;\n\t}\n\n\t&-warning {\n\t\tcolor: var(--color-warning);\n\t}\n}\n\n@media (max-width: (1024px / 1.5)) {\n\t.theming__preview {\n\t\tflex-direction: column;\n\n\t\t&-image {\n\t\t\tmargin: 0;\n\t\t}\n\t}\n}\n\n</style>\n","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ItemPreview.vue?vue&type=style&index=0&id=37ca8ab2&lang=scss&scoped=true&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ItemPreview.vue?vue&type=style&index=0&id=37ca8ab2&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./ItemPreview.vue?vue&type=template&id=37ca8ab2&scoped=true&\"\nimport script from \"./ItemPreview.vue?vue&type=script&lang=js&\"\nexport * from \"./ItemPreview.vue?vue&type=script&lang=js&\"\nimport style0 from \"./ItemPreview.vue?vue&type=style&index=0&id=37ca8ab2&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"37ca8ab2\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"theming__preview\",class:'theming__preview--' + _vm.theme.id},[_c('div',{staticClass:\"theming__preview-image\",style:({ backgroundImage: 'url(' + _vm.img + ')' }),on:{\"click\":_vm.onToggle}}),_vm._v(\" \"),_c('div',{staticClass:\"theming__preview-description\"},[_c('h3',[_vm._v(_vm._s(_vm.theme.title))]),_vm._v(\" \"),_c('p',[_vm._v(_vm._s(_vm.theme.description))]),_vm._v(\" \"),(_vm.enforced)?_c('span',{staticClass:\"theming__preview-warning\",attrs:{\"role\":\"note\"}},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.t('theming', 'Theme selection is enforced'))+\"\\n\\t\\t\")]):_vm._e(),_vm._v(\" \"),_c('NcCheckboxRadioSwitch',{staticClass:\"theming__preview-toggle\",attrs:{\"checked\":_vm.checked,\"disabled\":_vm.enforced,\"name\":_vm.name,\"type\":_vm.switchType},on:{\"update:checked\":function($event){_vm.checked=$event}}},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.theme.enableLabel)+\"\\n\\t\\t\")])],1)])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","<template>\n\t<NcSettingsSection class=\"theming\" :title=\"t('themes', 'Appearance and accessibility')\">\n\t\t<p v-html=\"description\" />\n\t\t<p v-html=\"descriptionDetail\" />\n\n\t\t<div class=\"theming__preview-list\">\n\t\t\t<ItemPreview v-for=\"theme in themes\"\n\t\t\t\t:key=\"theme.id\"\n\t\t\t\t:enforced=\"theme.id === enforceTheme\"\n\t\t\t\t:selected=\"selectedTheme.id === theme.id\"\n\t\t\t\t:theme=\"theme\"\n\t\t\t\t:unique=\"themes.length === 1\"\n\t\t\t\ttype=\"theme\"\n\t\t\t\t@change=\"changeTheme\" />\n\t\t</div>\n\n\t\t<div class=\"theming__preview-list\">\n\t\t\t<ItemPreview v-for=\"theme in fonts\"\n\t\t\t\t:key=\"theme.id\"\n\t\t\t\t:selected=\"theme.enabled\"\n\t\t\t\t:theme=\"theme\"\n\t\t\t\t:unique=\"fonts.length === 1\"\n\t\t\t\ttype=\"font\"\n\t\t\t\t@change=\"changeFont\" />\n\t\t</div>\n\t</NcSettingsSection>\n</template>\n\n<script>\nimport { generateOcsUrl } from '@nextcloud/router'\nimport { loadState } from '@nextcloud/initial-state'\nimport axios from '@nextcloud/axios'\nimport NcSettingsSection from '@nextcloud/vue/dist/Components/NcSettingsSection'\n\nimport ItemPreview from './components/ItemPreview'\n\nconst availableThemes = loadState('theming', 'themes', [])\nconst enforceTheme = loadState('theming', 'enforceTheme', '')\n\nconsole.debug('Available themes', availableThemes)\n\nexport default {\n\tname: 'UserThemes',\n\tcomponents: {\n\t\tItemPreview,\n\t\tNcSettingsSection,\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tavailableThemes,\n\t\t\tenforceTheme,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tthemes() {\n\t\t\treturn this.availableThemes.filter(theme => theme.type === 1)\n\t\t},\n\t\tfonts() {\n\t\t\treturn this.availableThemes.filter(theme => theme.type === 2)\n\t\t},\n\n\t\t// Selected theme, fallback on first (default) if none\n\t\tselectedTheme() {\n\t\t\treturn this.themes.find(theme => theme.enabled === true) || this.themes[0]\n\t\t},\n\n\t\tdescription() {\n\t\t\t// using the `t` replace method escape html, we have to do it manually :/\n\t\t\treturn t(\n\t\t\t\t'theming',\n\t\t\t\t'Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {guidelines}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level.'\n\t\t\t)\n\t\t\t\t.replace('{guidelines}', this.guidelinesLink)\n\t\t\t\t.replace('{linkend}', '</a>')\n\t\t},\n\t\tguidelinesLink() {\n\t\t\treturn '<a target=\"_blank\" href=\"https://www.w3.org/WAI/standards-guidelines/wcag/\" rel=\"noreferrer nofollow\">'\n\t\t},\n\t\tdescriptionDetail() {\n\t\t\treturn t(\n\t\t\t\t'theming',\n\t\t\t\t'If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!'\n\t\t\t)\n\t\t\t\t.replace('{issuetracker}', this.issuetrackerLink)\n\t\t\t\t.replace('{designteam}', this.designteamLink)\n\t\t\t\t.replace(/\\{linkend\\}/g, '</a>')\n\t\t},\n\t\tissuetrackerLink() {\n\t\t\treturn '<a target=\"_blank\" href=\"https://github.com/nextcloud/server/issues/\" rel=\"noreferrer nofollow\">'\n\t\t},\n\t\tdesignteamLink() {\n\t\t\treturn '<a target=\"_blank\" href=\"https://nextcloud.com/design\" rel=\"noreferrer nofollow\">'\n\t\t},\n\t},\n\tmethods: {\n\t\tchangeTheme({ enabled, id }) {\n\t\t\t// Reset selected and select new one\n\t\t\tthis.themes.forEach(theme => {\n\t\t\t\tif (theme.id === id && enabled) {\n\t\t\t\t\ttheme.enabled = true\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttheme.enabled = false\n\t\t\t})\n\n\t\t\tthis.updateBodyAttributes()\n\t\t\tthis.selectItem(enabled, id)\n\t\t},\n\t\tchangeFont({ enabled, id }) {\n\t\t\t// Reset selected and select new one\n\t\t\tthis.fonts.forEach(font => {\n\t\t\t\tif (font.id === id && enabled) {\n\t\t\t\t\tfont.enabled = true\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tfont.enabled = false\n\t\t\t})\n\n\t\t\tthis.updateBodyAttributes()\n\t\t\tthis.selectItem(enabled, id)\n\t\t},\n\n\t\tupdateBodyAttributes() {\n\t\t\tconst enabledThemesIDs = this.themes.filter(theme => theme.enabled === true).map(theme => theme.id)\n\t\t\tconst enabledFontsIDs = this.fonts.filter(font => font.enabled === true).map(font => font.id)\n\n\t\t\tthis.themes.forEach(theme => {\n\t\t\t\tdocument.body.toggleAttribute(`data-theme-${theme.id}`, theme.enabled)\n\t\t\t})\n\t\t\tthis.fonts.forEach(font => {\n\t\t\t\tdocument.body.toggleAttribute(`data-theme-${font.id}`, font.enabled)\n\t\t\t})\n\n\t\t\tdocument.body.setAttribute('data-themes', [...enabledThemesIDs, ...enabledFontsIDs].join(','))\n\t\t},\n\n\t\t/**\n\t\t * Commit a change and force reload css\n\t\t * Fetching the file again will trigger the server update\n\t\t *\n\t\t * @param {boolean} enabled the theme state\n\t\t * @param {string} themeId the theme ID to change\n\t\t */\n\t\tasync selectItem(enabled, themeId) {\n\t\t\ttry {\n\t\t\t\tif (enabled) {\n\t\t\t\t\tawait axios({\n\t\t\t\t\t\turl: generateOcsUrl('apps/theming/api/v1/theme/{themeId}/enable', { themeId }),\n\t\t\t\t\t\tmethod: 'PUT',\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tawait axios({\n\t\t\t\t\t\turl: generateOcsUrl('apps/theming/api/v1/theme/{themeId}', { themeId }),\n\t\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(err, err.response)\n\t\t\t\tOC.Notification.showTemporary(t('theming', err.response.data.ocs.meta.message + '. Unable to apply the setting.'))\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.theming {\n\t// Limit width of settings sections for readability\n\tp {\n\t\tmax-width: 800px;\n\t}\n\n\t// Proper highlight for links and focus feedback\n\t&::v-deep a {\n\t\tfont-weight: bold;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\ttext-decoration: underline;\n\t\t}\n\t}\n\n\t&__preview-list {\n\t\t--gap: 30px;\n\n\t\tdisplay: grid;\n\t\tmargin-top: var(--gap);\n\t\tcolumn-gap: var(--gap);\n\t\trow-gap: var(--gap);\n\t\tgrid-template-columns: 1fr 1fr;\n\t}\n}\n\n@media (max-width: 1440px) {\n\t.theming__preview-list {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t}\n}\n\n</style>\n","import mod from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserThemes.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserThemes.vue?vue&type=script&lang=js&\"","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/sass-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserThemes.vue?vue&type=style&index=0&id=015ac8e0&lang=scss&scoped=true&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/sass-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserThemes.vue?vue&type=style&index=0&id=015ac8e0&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./UserThemes.vue?vue&type=template&id=015ac8e0&scoped=true&\"\nimport script from \"./UserThemes.vue?vue&type=script&lang=js&\"\nexport * from \"./UserThemes.vue?vue&type=script&lang=js&\"\nimport style0 from \"./UserThemes.vue?vue&type=style&index=0&id=015ac8e0&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"015ac8e0\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('NcSettingsSection',{staticClass:\"theming\",attrs:{\"title\":_vm.t('themes', 'Appearance and accessibility')}},[_c('p',{domProps:{\"innerHTML\":_vm._s(_vm.description)}}),_vm._v(\" \"),_c('p',{domProps:{\"innerHTML\":_vm._s(_vm.descriptionDetail)}}),_vm._v(\" \"),_c('div',{staticClass:\"theming__preview-list\"},_vm._l((_vm.themes),function(theme){return _c('ItemPreview',{key:theme.id,attrs:{\"enforced\":theme.id === _vm.enforceTheme,\"selected\":_vm.selectedTheme.id === theme.id,\"theme\":theme,\"unique\":_vm.themes.length === 1,\"type\":\"theme\"},on:{\"change\":_vm.changeTheme}})}),1),_vm._v(\" \"),_c('div',{staticClass:\"theming__preview-list\"},_vm._l((_vm.fonts),function(theme){return _c('ItemPreview',{key:theme.id,attrs:{\"selected\":theme.enabled,\"theme\":theme,\"unique\":_vm.fonts.length === 1,\"type\":\"font\"},on:{\"change\":_vm.changeFont}})}),1)])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/**\n * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>\n *\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport Vue from 'vue'\nimport App from './UserThemes.vue'\n\n// bind to window\nVue.prototype.OC = OC\nVue.prototype.t = t\n\nconst View = Vue.extend(App)\nconst theming = new View()\ntheming.$mount('#theming')\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".theming p[data-v-015ac8e0]{max-width:800px}.theming[data-v-015ac8e0] a{font-weight:bold}.theming[data-v-015ac8e0] a:hover,.theming[data-v-015ac8e0] a:focus{text-decoration:underline}.theming__preview-list[data-v-015ac8e0]{--gap: 30px;display:grid;margin-top:var(--gap);column-gap:var(--gap);row-gap:var(--gap);grid-template-columns:1fr 1fr}@media(max-width: 1440px){.theming__preview-list[data-v-015ac8e0]{display:flex;flex-direction:column}}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/theming/src/UserThemes.vue\"],\"names\":[],\"mappings\":\"AA2KC,4BACC,eAAA,CAID,4BACC,gBAAA,CAEA,oEAEC,yBAAA,CAIF,wCACC,WAAA,CAEA,YAAA,CACA,qBAAA,CACA,qBAAA,CACA,kBAAA,CACA,6BAAA,CAIF,0BACC,wCACC,YAAA,CACA,qBAAA,CAAA\",\"sourcesContent\":[\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n.theming {\\n\\t// Limit width of settings sections for readability\\n\\tp {\\n\\t\\tmax-width: 800px;\\n\\t}\\n\\n\\t// Proper highlight for links and focus feedback\\n\\t&::v-deep a {\\n\\t\\tfont-weight: bold;\\n\\n\\t\\t&:hover,\\n\\t\\t&:focus {\\n\\t\\t\\ttext-decoration: underline;\\n\\t\\t}\\n\\t}\\n\\n\\t&__preview-list {\\n\\t\\t--gap: 30px;\\n\\n\\t\\tdisplay: grid;\\n\\t\\tmargin-top: var(--gap);\\n\\t\\tcolumn-gap: var(--gap);\\n\\t\\trow-gap: var(--gap);\\n\\t\\tgrid-template-columns: 1fr 1fr;\\n\\t}\\n}\\n\\n@media (max-width: 1440px) {\\n\\t.theming__preview-list {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-direction: column;\\n\\t}\\n}\\n\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".theming__preview[data-v-37ca8ab2]{--ratio: 16;position:relative;display:flex;justify-content:flex-start;max-width:800px}.theming__preview[data-v-37ca8ab2],.theming__preview *[data-v-37ca8ab2]{user-select:none}.theming__preview-image[data-v-37ca8ab2]{flex-basis:calc(16px*var(--ratio));flex-shrink:0;height:calc(10px*var(--ratio));margin-right:var(--gap);cursor:pointer;border-radius:var(--border-radius);background-repeat:no-repeat;background-position:top left;background-size:cover}.theming__preview-description[data-v-37ca8ab2]{display:flex;flex-direction:column}.theming__preview-description label[data-v-37ca8ab2]{padding:12px 0}.theming__preview--default[data-v-37ca8ab2]{grid-column:span 2}.theming__preview-warning[data-v-37ca8ab2]{color:var(--color-warning)}@media(max-width: 682.6666666667px){.theming__preview[data-v-37ca8ab2]{flex-direction:column}.theming__preview-image[data-v-37ca8ab2]{margin:0}}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/theming/src/components/ItemPreview.vue\"],\"names\":[],\"mappings\":\"AAiGA,mCAEC,WAAA,CAEA,iBAAA,CACA,YAAA,CACA,0BAAA,CACA,eAAA,CAEA,wEAEC,gBAAA,CAGD,yCACC,kCAAA,CACA,aAAA,CACA,8BAAA,CACA,uBAAA,CACA,cAAA,CACA,kCAAA,CACA,2BAAA,CACA,4BAAA,CACA,qBAAA,CAGD,+CACC,YAAA,CACA,qBAAA,CAEA,qDACC,cAAA,CAIF,4CACC,kBAAA,CAGD,2CACC,0BAAA,CAIF,oCACC,mCACC,qBAAA,CAEA,yCACC,QAAA,CAAA\",\"sourcesContent\":[\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n.theming__preview {\\n\\t// We make previews on 16/10 screens\\n\\t--ratio: 16;\\n\\n\\tposition: relative;\\n\\tdisplay: flex;\\n\\tjustify-content: flex-start;\\n\\tmax-width: 800px;\\n\\n\\t&,\\n\\t* {\\n\\t\\tuser-select: none;\\n\\t}\\n\\n\\t&-image {\\n\\t\\tflex-basis: calc(16px * var(--ratio));\\n\\t\\tflex-shrink: 0;\\n\\t\\theight: calc(10px * var(--ratio));\\n\\t\\tmargin-right: var(--gap);\\n\\t\\tcursor: pointer;\\n\\t\\tborder-radius: var(--border-radius);\\n\\t\\tbackground-repeat: no-repeat;\\n\\t\\tbackground-position: top left;\\n\\t\\tbackground-size: cover;\\n\\t}\\n\\n\\t&-description {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-direction: column;\\n\\n\\t\\tlabel {\\n\\t\\t\\tpadding: 12px 0;\\n\\t\\t}\\n\\t}\\n\\n\\t&--default {\\n\\t\\tgrid-column: span 2;\\n\\t}\\n\\n\\t&-warning {\\n\\t\\tcolor: var(--color-warning);\\n\\t}\\n}\\n\\n@media (max-width: (1024px / 1.5)) {\\n\\t.theming__preview {\\n\\t\\tflex-direction: column;\\n\\n\\t\\t&-image {\\n\\t\\t\\tmargin: 0;\\n\\t\\t}\\n\\t}\\n}\\n\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdD = function () {\n\tthrow new Error('define cannot be used indirect');\n};","__webpack_require__.amdO = {};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 6755;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t6755: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknextcloud\"] = self[\"webpackChunknextcloud\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [7874], function() { return __webpack_require__(58739); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","_vm","this","_h","$createElement","_c","_self","staticClass","class","theme","id","style","backgroundImage","img","on","onToggle","_v","_s","title","description","attrs","t","_e","checked","enforced","name","switchType","$event","enableLabel","console","debug","availableThemes","domProps","descriptionDetail","_l","key","enforceTheme","selectedTheme","themes","length","changeTheme","enabled","fonts","changeFont","Vue","OC","App","$mount","___CSS_LOADER_EXPORT___","push","module","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","loaded","__webpack_modules__","call","m","amdD","Error","amdO","O","result","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","Object","keys","every","splice","r","n","getter","__esModule","d","a","definition","o","defineProperty","enumerable","get","g","globalThis","Function","e","window","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","value","nmd","paths","children","b","document","baseURI","self","location","href","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","data","moreModules","runtime","some","chunkLoadingGlobal","forEach","bind","nc","__webpack_exports__"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"file":"theming-theming-settings.js?v=1f53bcf4598d8f0407d7","mappings":"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","sources":["webpack:///nextcloud/webpack/runtime/chunk loaded","webpack:///nextcloud/apps/theming/src/helpers/prefixWithBaseUrl.js","webpack:///nextcloud/apps/theming/src/helpers/getBackgroundUrl.js","webpack:///nextcloud/apps/theming/src/components/BackgroundSettings.vue","webpack:///nextcloud/apps/theming/src/components/BackgroundSettings.vue?vue&type=script&lang=js&","webpack://nextcloud/./apps/theming/src/components/BackgroundSettings.vue?4447","webpack://nextcloud/./apps/theming/src/components/BackgroundSettings.vue?65db","webpack:///nextcloud/apps/theming/src/components/BackgroundSettings.vue?vue&type=template&id=50307d02&scoped=true&","webpack:///nextcloud/apps/theming/src/components/ItemPreview.vue?vue&type=script&lang=js&","webpack:///nextcloud/apps/theming/src/components/ItemPreview.vue","webpack://nextcloud/./apps/theming/src/components/ItemPreview.vue?f1c6","webpack://nextcloud/./apps/theming/src/components/ItemPreview.vue?8797","webpack:///nextcloud/apps/theming/src/components/ItemPreview.vue?vue&type=template&id=37ca8ab2&scoped=true&","webpack:///nextcloud/apps/theming/src/UserThemes.vue","webpack:///nextcloud/apps/theming/src/UserThemes.vue?vue&type=script&lang=js&","webpack://nextcloud/./apps/theming/src/UserThemes.vue?9bd2","webpack://nextcloud/./apps/theming/src/UserThemes.vue?7eb2","webpack:///nextcloud/apps/theming/src/UserThemes.vue?vue&type=template&id=5654fc60&scoped=true&","webpack:///nextcloud/apps/theming/src/settings.js","webpack:///nextcloud/apps/theming/src/UserThemes.vue?vue&type=style&index=0&id=5654fc60&lang=scss&scoped=true&","webpack:///nextcloud/apps/theming/src/components/BackgroundSettings.vue?vue&type=style&index=0&id=50307d02&scoped=true&lang=scss&","webpack:///nextcloud/apps/theming/src/components/ItemPreview.vue?vue&type=style&index=0&id=37ca8ab2&lang=scss&scoped=true&","webpack:///nextcloud/webpack/bootstrap","webpack:///nextcloud/webpack/runtime/amd define","webpack:///nextcloud/webpack/runtime/amd options","webpack:///nextcloud/webpack/runtime/compat get default export","webpack:///nextcloud/webpack/runtime/define property getters","webpack:///nextcloud/webpack/runtime/global","webpack:///nextcloud/webpack/runtime/hasOwnProperty shorthand","webpack:///nextcloud/webpack/runtime/make namespace object","webpack:///nextcloud/webpack/runtime/node module decorator","webpack:///nextcloud/webpack/runtime/runtimeId","webpack:///nextcloud/webpack/runtime/jsonp chunk loading","webpack:///nextcloud/webpack/runtime/nonce","webpack:///nextcloud/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","/**\n * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n *\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\n// FIXME hoist this into a package? The same logic is used in `apps/dashboard/src/helpers/prefixWithBaseUrl.js`\n\nimport { generateFilePath } from '@nextcloud/router'\n\nexport const prefixWithBaseUrl = (url) => generateFilePath('theming', '', 'img/background/') + url\n","/**\n * @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n *\n * @author Avior <florian.bouillon@delta-wings.net>\n * @author Julien Veyssier <eneiluj@posteo.net>\n * @author Julius Härtl <jus@bitgrid.net>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\n// FIXME hoist this into a package? The same logic is used in `apps/dashboard/src/helpers/getBackgroundUrl.js`\n\nimport { generateUrl } from '@nextcloud/router'\nimport { prefixWithBaseUrl } from './prefixWithBaseUrl.js'\n\nexport const getBackgroundUrl = (background, time = 0, themingDefaultBackground = '') => {\n\tconst enabledThemes = window.OCA?.Theming?.enabledThemes || []\n\tconst isDarkTheme = (enabledThemes.length === 0 || enabledThemes[0] === 'default')\n\t\t? window.matchMedia('(prefers-color-scheme: dark)').matches\n\t\t: enabledThemes.join('').indexOf('dark') !== -1\n\n\tif (background === 'default') {\n\t\tif (themingDefaultBackground && themingDefaultBackground !== 'backgroundColor') {\n\t\t\treturn generateUrl('/apps/theming/image/background') + '?v=' + window.OCA.Theming.cacheBuster\n\t\t}\n\n\t\tif (isDarkTheme) {\n\t\t\treturn prefixWithBaseUrl('eduardo-neves-pedra-azul.jpg')\n\t\t}\n\n\t\treturn prefixWithBaseUrl('kamil-porembinski-clouds.jpg')\n\t} else if (background === 'custom') {\n\t\treturn generateUrl('/apps/theming/background') + '?v=' + time\n\t}\n\n\treturn prefixWithBaseUrl(background)\n}\n","<!--\n - @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n - @copyright Copyright (c) 2022 Greta Doci <gretadoci@gmail.com>\n -\n - @author Julius Härtl <jus@bitgrid.net>\n - @author Greta Doci <gretadoci@gmail.com>\n - @author Christopher Ng <chrng8@gmail.com>\n -\n - @license GNU AGPL version 3 or any later version\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n\n<template>\n\t<div class=\"background-selector\">\n\t\t<button class=\"background filepicker\"\n\t\t\t:class=\"{ active: background === 'custom' }\"\n\t\t\ttabindex=\"0\"\n\t\t\t@click=\"pickFile\">\n\t\t\t{{ t('theming', 'Pick from Files') }}\n\t\t</button>\n\t\t<button class=\"background default\"\n\t\t\ttabindex=\"0\"\n\t\t\t:class=\"{ 'icon-loading': loading === 'default', active: background === 'default' }\"\n\t\t\t@click=\"setDefault\">\n\t\t\t{{ t('theming', 'Default image') }}\n\t\t</button>\n\t\t<button class=\"background color\"\n\t\t\t:class=\"{ active: background === 'custom' }\"\n\t\t\ttabindex=\"0\"\n\t\t\t@click=\"pickColor\">\n\t\t\t{{ t('theming', 'Plain background') }}\n\t\t</button>\n\t\t<button v-for=\"shippedBackground in shippedBackgrounds\"\n\t\t\t:key=\"shippedBackground.name\"\n\t\t\tv-tooltip=\"shippedBackground.details.attribution\"\n\t\t\t:class=\"{ 'icon-loading': loading === shippedBackground.name, active: background === shippedBackground.name }\"\n\t\t\ttabindex=\"0\"\n\t\t\tclass=\"background\"\n\t\t\t:style=\"{ 'background-image': 'url(' + shippedBackground.preview + ')' }\"\n\t\t\t@click=\"setShipped(shippedBackground.name)\" />\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'\nimport { generateUrl } from '@nextcloud/router'\nimport { loadState } from '@nextcloud/initial-state'\nimport { getBackgroundUrl } from '../helpers/getBackgroundUrl.js'\nimport { prefixWithBaseUrl } from '../helpers/prefixWithBaseUrl.js'\n\nconst shippedBackgroundList = loadState('theming', 'shippedBackgrounds')\n\nexport default {\n\tname: 'BackgroundSettings',\n\tdirectives: {\n\t\tTooltip,\n\t},\n\tprops: {\n\t\tbackground: {\n\t\t\ttype: String,\n\t\t\tdefault: 'default',\n\t\t},\n\t\tthemingDefaultBackground: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tbackgroundImage: generateUrl('/apps/theming/background') + '?v=' + Date.now(),\n\t\t\tloading: false,\n\t\t}\n\t},\n\tcomputed: {\n\t\tshippedBackgrounds() {\n\t\t\treturn Object.keys(shippedBackgroundList).map(fileName => {\n\t\t\t\treturn {\n\t\t\t\t\tname: fileName,\n\t\t\t\t\turl: prefixWithBaseUrl(fileName),\n\t\t\t\t\tpreview: prefixWithBaseUrl('preview/' + fileName),\n\t\t\t\t\tdetails: shippedBackgroundList[fileName],\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t},\n\tmethods: {\n\t\tasync update(data) {\n\t\t\tconst background = data.type === 'custom' || data.type === 'default' ? data.type : data.value\n\t\t\tthis.backgroundImage = getBackgroundUrl(background, data.version, this.themingDefaultBackground)\n\t\t\tif (data.type === 'color' || (data.type === 'default' && this.themingDefaultBackground === 'backgroundColor')) {\n\t\t\t\tthis.$emit('update:background', data)\n\t\t\t\tthis.loading = false\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst image = new Image()\n\t\t\timage.onload = () => {\n\t\t\t\tthis.$emit('update:background', data)\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t\timage.src = this.backgroundImage\n\t\t},\n\t\tasync setDefault() {\n\t\t\tthis.loading = 'default'\n\t\t\tconst result = await axios.post(generateUrl('/apps/theming/background/default'))\n\t\t\tthis.update(result.data)\n\t\t},\n\t\tasync setShipped(shipped) {\n\t\t\tthis.loading = shipped\n\t\t\tconst result = await axios.post(generateUrl('/apps/theming/background/shipped'), { value: shipped })\n\t\t\tthis.update(result.data)\n\t\t},\n\t\tasync setFile(path) {\n\t\t\tthis.loading = 'custom'\n\t\t\tconst result = await axios.post(generateUrl('/apps/theming/background/custom'), { value: path })\n\t\t\tthis.update(result.data)\n\t\t},\n\t\tasync pickColor() {\n\t\t\tthis.loading = 'color'\n\t\t\tconst color = OCA && OCA.Theming ? OCA.Theming.color : '#0082c9'\n\t\t\tconst result = await axios.post(generateUrl('/apps/theming/background/color'), { value: color })\n\t\t\tthis.update(result.data)\n\t\t},\n\t\tpickFile() {\n\t\t\twindow.OC.dialogs.filepicker(t('theming', 'Insert from {productName}', { productName: OC.theme.name }), (path, type) => {\n\t\t\t\tif (type === OC.dialogs.FILEPICKER_TYPE_CHOOSE) {\n\t\t\t\t\tthis.setFile(path)\n\t\t\t\t}\n\t\t\t}, false, ['image/png', 'image/gif', 'image/jpeg', 'image/svg'], true, OC.dialogs.FILEPICKER_TYPE_CHOOSE)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped lang=\"scss\">\n.background-selector {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tjustify-content: center;\n\n\t.background {\n\t\twidth: 176px;\n\t\theight: 96px;\n\t\tmargin: 8px;\n\t\tbackground-size: cover;\n\t\tbackground-position: center center;\n\t\ttext-align: center;\n\t\tborder-radius: var(--border-radius-large);\n\t\tborder: 2px solid var(--color-main-background);\n\t\toverflow: hidden;\n\n\t\t&.current {\n\t\t\tbackground-image: var(--color-background-dark);\n\t\t}\n\n\t\t&.filepicker, &.default, &.color {\n\t\t\tborder-color: var(--color-border);\n\t\t}\n\n\t\t&.color {\n\t\t\tbackground-color: var(--color-primary);\n\t\t\tcolor: var(--color-primary-text);\n\t\t}\n\n\t\t&.active,\n\t\t&:hover,\n\t\t&:focus {\n\t\t\tborder: 2px solid var(--color-primary);\n\t\t}\n\n\t\t&.active:not(.icon-loading):after {\n\t\t\tbackground-image: var(--icon-checkmark-white);\n\t\t\tbackground-repeat: no-repeat;\n\t\t\tbackground-position: center;\n\t\t\tbackground-size: 44px;\n\t\t\tcontent: '';\n\t\t\tdisplay: block;\n\t\t\theight: 100%;\n\t\t}\n\t}\n}\n</style>\n","import mod from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./BackgroundSettings.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./BackgroundSettings.vue?vue&type=script&lang=js&\"","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./BackgroundSettings.vue?vue&type=style&index=0&id=50307d02&scoped=true&lang=scss&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./BackgroundSettings.vue?vue&type=style&index=0&id=50307d02&scoped=true&lang=scss&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./BackgroundSettings.vue?vue&type=template&id=50307d02&scoped=true&\"\nimport script from \"./BackgroundSettings.vue?vue&type=script&lang=js&\"\nexport * from \"./BackgroundSettings.vue?vue&type=script&lang=js&\"\nimport style0 from \"./BackgroundSettings.vue?vue&type=style&index=0&id=50307d02&scoped=true&lang=scss&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"50307d02\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"background-selector\"},[_c('button',{staticClass:\"background filepicker\",class:{ active: _vm.background === 'custom' },attrs:{\"tabindex\":\"0\"},on:{\"click\":_vm.pickFile}},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('theming', 'Pick from Files'))+\"\\n\\t\")]),_vm._v(\" \"),_c('button',{staticClass:\"background default\",class:{ 'icon-loading': _vm.loading === 'default', active: _vm.background === 'default' },attrs:{\"tabindex\":\"0\"},on:{\"click\":_vm.setDefault}},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('theming', 'Default image'))+\"\\n\\t\")]),_vm._v(\" \"),_c('button',{staticClass:\"background color\",class:{ active: _vm.background === 'custom' },attrs:{\"tabindex\":\"0\"},on:{\"click\":_vm.pickColor}},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('theming', 'Plain background'))+\"\\n\\t\")]),_vm._v(\" \"),_vm._l((_vm.shippedBackgrounds),function(shippedBackground){return _c('button',{directives:[{name:\"tooltip\",rawName:\"v-tooltip\",value:(shippedBackground.details.attribution),expression:\"shippedBackground.details.attribution\"}],key:shippedBackground.name,staticClass:\"background\",class:{ 'icon-loading': _vm.loading === shippedBackground.name, active: _vm.background === shippedBackground.name },style:({ 'background-image': 'url(' + shippedBackground.preview + ')' }),attrs:{\"tabindex\":\"0\"},on:{\"click\":function($event){return _vm.setShipped(shippedBackground.name)}}})})],2)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ItemPreview.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ItemPreview.vue?vue&type=script&lang=js&\"","<template>\n\t<div :class=\"'theming__preview--' + theme.id\" class=\"theming__preview\">\n\t\t<div class=\"theming__preview-image\" :style=\"{ backgroundImage: 'url(' + img + ')' }\" @click=\"onToggle\" />\n\t\t<div class=\"theming__preview-description\">\n\t\t\t<h3>{{ theme.title }}</h3>\n\t\t\t<p>{{ theme.description }}</p>\n\t\t\t<span v-if=\"enforced\" class=\"theming__preview-warning\" role=\"note\">\n\t\t\t\t{{ t('theming', 'Theme selection is enforced') }}\n\t\t\t</span>\n\t\t\t<NcCheckboxRadioSwitch class=\"theming__preview-toggle\"\n\t\t\t\t:checked.sync=\"checked\"\n\t\t\t\t:disabled=\"enforced\"\n\t\t\t\t:name=\"name\"\n\t\t\t\t:type=\"switchType\">\n\t\t\t\t{{ theme.enableLabel }}\n\t\t\t</NcCheckboxRadioSwitch>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { generateFilePath } from '@nextcloud/router'\nimport NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch'\n\nexport default {\n\tname: 'ItemPreview',\n\tcomponents: {\n\t\tNcCheckboxRadioSwitch,\n\t},\n\tprops: {\n\t\tenforced: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t\ttheme: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\t\ttype: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t\tunique: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\tcomputed: {\n\t\tswitchType() {\n\t\t\treturn this.unique ? 'switch' : 'radio'\n\t\t},\n\n\t\tname() {\n\t\t\treturn !this.unique ? this.type : null\n\t\t},\n\n\t\timg() {\n\t\t\treturn generateFilePath('theming', 'img', this.theme.id + '.jpg')\n\t\t},\n\n\t\tchecked: {\n\t\t\tget() {\n\t\t\t\treturn this.selected\n\t\t\t},\n\t\t\tset(checked) {\n\t\t\t\tconsole.debug('Changed theme', this.theme.id, checked)\n\n\t\t\t\t// If this is a radio, we can only enable\n\t\t\t\tif (!this.unique) {\n\t\t\t\t\tthis.$emit('change', { enabled: true, id: this.theme.id })\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// If this is a switch, we can disable the theme\n\t\t\t\tthis.$emit('change', { enabled: checked === true, id: this.theme.id })\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tonToggle() {\n\t\t\tif (this.switchType === 'radio') {\n\t\t\t\tthis.checked = true\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Invert state\n\t\t\tthis.checked = !this.checked\n\t\t},\n\t},\n}\n</script>\n<style lang=\"scss\" scoped>\n.theming__preview {\n\t// We make previews on 16/10 screens\n\t--ratio: 16;\n\n\tposition: relative;\n\tdisplay: flex;\n\tjustify-content: flex-start;\n\tmax-width: 800px;\n\n\t&,\n\t* {\n\t\tuser-select: none;\n\t}\n\n\t&-image {\n\t\tflex-basis: calc(16px * var(--ratio));\n\t\tflex-shrink: 0;\n\t\theight: calc(10px * var(--ratio));\n\t\tmargin-right: var(--gap);\n\t\tcursor: pointer;\n\t\tborder-radius: var(--border-radius);\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-position: top left;\n\t\tbackground-size: cover;\n\t}\n\n\t&-description {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\n\t\tlabel {\n\t\t\tpadding: 12px 0;\n\t\t}\n\t}\n\n\t&--default {\n\t\tgrid-column: span 2;\n\t}\n\n\t&-warning {\n\t\tcolor: var(--color-warning);\n\t}\n}\n\n@media (max-width: (1024px / 1.5)) {\n\t.theming__preview {\n\t\tflex-direction: column;\n\n\t\t&-image {\n\t\t\tmargin: 0;\n\t\t}\n\t}\n}\n\n</style>\n","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ItemPreview.vue?vue&type=style&index=0&id=37ca8ab2&lang=scss&scoped=true&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./ItemPreview.vue?vue&type=style&index=0&id=37ca8ab2&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./ItemPreview.vue?vue&type=template&id=37ca8ab2&scoped=true&\"\nimport script from \"./ItemPreview.vue?vue&type=script&lang=js&\"\nexport * from \"./ItemPreview.vue?vue&type=script&lang=js&\"\nimport style0 from \"./ItemPreview.vue?vue&type=style&index=0&id=37ca8ab2&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"37ca8ab2\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"theming__preview\",class:'theming__preview--' + _vm.theme.id},[_c('div',{staticClass:\"theming__preview-image\",style:({ backgroundImage: 'url(' + _vm.img + ')' }),on:{\"click\":_vm.onToggle}}),_vm._v(\" \"),_c('div',{staticClass:\"theming__preview-description\"},[_c('h3',[_vm._v(_vm._s(_vm.theme.title))]),_vm._v(\" \"),_c('p',[_vm._v(_vm._s(_vm.theme.description))]),_vm._v(\" \"),(_vm.enforced)?_c('span',{staticClass:\"theming__preview-warning\",attrs:{\"role\":\"note\"}},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.t('theming', 'Theme selection is enforced'))+\"\\n\\t\\t\")]):_vm._e(),_vm._v(\" \"),_c('NcCheckboxRadioSwitch',{staticClass:\"theming__preview-toggle\",attrs:{\"checked\":_vm.checked,\"disabled\":_vm.enforced,\"name\":_vm.name,\"type\":_vm.switchType},on:{\"update:checked\":function($event){_vm.checked=$event}}},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.theme.enableLabel)+\"\\n\\t\\t\")])],1)])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","<!--\n - @copyright Copyright (c) 2020 Julius Härtl <jus@bitgrid.net>\n - @copyright Copyright (c) 2022 Greta Doci <gretadoci@gmail.com>\n -\n - @author Christopher Ng <chrng8@gmail.com>\n -\n - @license AGPL-3.0-or-later\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n-->\n\n<template>\n\t<section>\n\t\t<NcSettingsSection class=\"theming\" :title=\"t('theming', 'Appearance and accessibility')\">\n\t\t\t<p v-html=\"description\" />\n\t\t\t<p v-html=\"descriptionDetail\" />\n\n\t\t\t<div class=\"theming__preview-list\">\n\t\t\t\t<ItemPreview v-for=\"theme in themes\"\n\t\t\t\t\t:key=\"theme.id\"\n\t\t\t\t\t:enforced=\"theme.id === enforceTheme\"\n\t\t\t\t\t:selected=\"selectedTheme.id === theme.id\"\n\t\t\t\t\t:theme=\"theme\"\n\t\t\t\t\t:unique=\"themes.length === 1\"\n\t\t\t\t\ttype=\"theme\"\n\t\t\t\t\t@change=\"changeTheme\" />\n\t\t\t</div>\n\n\t\t\t<div class=\"theming__preview-list\">\n\t\t\t\t<ItemPreview v-for=\"theme in fonts\"\n\t\t\t\t\t:key=\"theme.id\"\n\t\t\t\t\t:selected=\"theme.enabled\"\n\t\t\t\t\t:theme=\"theme\"\n\t\t\t\t\t:unique=\"fonts.length === 1\"\n\t\t\t\t\ttype=\"font\"\n\t\t\t\t\t@change=\"changeFont\" />\n\t\t\t</div>\n\t\t</NcSettingsSection>\n\t\t<NcSettingsSection :title=\"t('theming', 'Background')\"\n\t\t\tclass=\"background\">\n\t\t\t<p>{{ t('theming', 'Set a custom background') }}</p>\n\t\t\t<BackgroundSettings class=\"background__grid\"\n\t\t\t\t:background=\"background\"\n\t\t\t\t:theming-default-background=\"themingDefaultBackground\"\n\t\t\t\t@update:background=\"updateBackground\" />\n\t\t</NcSettingsSection>\n\t</section>\n</template>\n\n<script>\nimport { generateOcsUrl, imagePath } from '@nextcloud/router'\nimport { loadState } from '@nextcloud/initial-state'\nimport axios from '@nextcloud/axios'\nimport NcSettingsSection from '@nextcloud/vue/dist/Components/NcSettingsSection'\n\nimport BackgroundSettings from './components/BackgroundSettings.vue'\nimport ItemPreview from './components/ItemPreview.vue'\n\nimport { getBackgroundUrl } from '../src/helpers/getBackgroundUrl.js'\n\nconst availableThemes = loadState('theming', 'themes', [])\nconst enforceTheme = loadState('theming', 'enforceTheme', '')\n\nconst background = loadState('theming', 'background')\nconst backgroundVersion = loadState('theming', 'backgroundVersion')\nconst themingDefaultBackground = loadState('theming', 'themingDefaultBackground')\nconst shippedBackgroundList = loadState('theming', 'shippedBackgrounds')\n\nconsole.debug('Available themes', availableThemes)\n\nexport default {\n\tname: 'UserThemes',\n\tcomponents: {\n\t\tItemPreview,\n\t\tNcSettingsSection,\n\t\tBackgroundSettings,\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tavailableThemes,\n\t\t\tenforceTheme,\n\t\t\tbackground,\n\t\t\tthemingDefaultBackground,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tbackgroundImage() {\n\t\t\treturn getBackgroundUrl(this.background, backgroundVersion, this.themingDefaultBackground)\n\t\t},\n\t\tbackgroundStyle() {\n\t\t\tif ((this.background === 'default' && this.themingDefaultBackground === 'backgroundColor')\n\t\t\t\t|| this.background.match(/#[0-9A-Fa-f]{6}/g)) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tbackgroundImage: this.background === 'default' ? 'var(--image-main-background)' : `url('${this.backgroundImage}')`,\n\t\t\t}\n\t\t},\n\t\tthemes() {\n\t\t\treturn this.availableThemes.filter(theme => theme.type === 1)\n\t\t},\n\t\tfonts() {\n\t\t\treturn this.availableThemes.filter(theme => theme.type === 2)\n\t\t},\n\n\t\t// Selected theme, fallback on first (default) if none\n\t\tselectedTheme() {\n\t\t\treturn this.themes.find(theme => theme.enabled === true) || this.themes[0]\n\t\t},\n\n\t\tdescription() {\n\t\t\t// using the `t` replace method escape html, we have to do it manually :/\n\t\t\treturn t(\n\t\t\t\t'theming',\n\t\t\t\t'Universal access is very important to us. We follow web standards and check to make everything usable also without mouse, and assistive software such as screenreaders. We aim to be compliant with the {guidelines}Web Content Accessibility Guidelines{linkend} 2.1 on AA level, with the high contrast theme even on AAA level.'\n\t\t\t)\n\t\t\t\t.replace('{guidelines}', this.guidelinesLink)\n\t\t\t\t.replace('{linkend}', '</a>')\n\t\t},\n\t\tguidelinesLink() {\n\t\t\treturn '<a target=\"_blank\" href=\"https://www.w3.org/WAI/standards-guidelines/wcag/\" rel=\"noreferrer nofollow\">'\n\t\t},\n\t\tdescriptionDetail() {\n\t\t\treturn t(\n\t\t\t\t'theming',\n\t\t\t\t'If you find any issues, do not hesitate to report them on {issuetracker}our issue tracker{linkend}. And if you want to get involved, come join {designteam}our design team{linkend}!'\n\t\t\t)\n\t\t\t\t.replace('{issuetracker}', this.issuetrackerLink)\n\t\t\t\t.replace('{designteam}', this.designteamLink)\n\t\t\t\t.replace(/\\{linkend\\}/g, '</a>')\n\t\t},\n\t\tissuetrackerLink() {\n\t\t\treturn '<a target=\"_blank\" href=\"https://github.com/nextcloud/server/issues/\" rel=\"noreferrer nofollow\">'\n\t\t},\n\t\tdesignteamLink() {\n\t\t\treturn '<a target=\"_blank\" href=\"https://nextcloud.com/design\" rel=\"noreferrer nofollow\">'\n\t\t},\n\t},\n\tmounted() {\n\t\tthis.updateGlobalStyles()\n\t},\n\tmethods: {\n\t\tupdateBackground(data) {\n\t\t\tthis.background = (data.type === 'custom' || data.type === 'default') ? data.type : data.value\n\t\t\tthis.updateGlobalStyles()\n\t\t},\n\t\tupdateGlobalStyles() {\n\t\t\t// Override primary-invert-if-bright and color-primary-text if background is set\n\t\t\tconst isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'\n\t\t\tif (isBackgroundBright) {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#000000')\n\t\t\t\t// document.body.removeAttribute('data-theme-dark')\n\t\t\t\t// document.body.setAttribute('data-theme-light', 'true')\n\t\t\t} else {\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'no')\n\t\t\t\tdocument.querySelector('#header').style.setProperty('--color-primary-text', '#ffffff')\n\t\t\t\t// document.body.removeAttribute('data-theme-light')\n\t\t\t\t// document.body.setAttribute('data-theme-dark', 'true')\n\t\t\t}\n\n\t\t\tconst themeElements = [document.documentElement, document.querySelector('#header'), document.querySelector('body')]\n\t\t\tfor (const element of themeElements) {\n\t\t\t\tif (this.background === 'default') {\n\t\t\t\t\telement.style.setProperty('--image-main-background', `url('${imagePath('core', 'app-background.jpg')}')`)\n\t\t\t\t} else if (this.background.match(/#[0-9A-Fa-f]{6}/g)) {\n\t\t\t\t\telement.style.setProperty('--image-main-background', undefined)\n\t\t\t\t} else {\n\t\t\t\t\telement.style.setProperty('--image-main-background', this.backgroundStyle.backgroundImage)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tchangeTheme({ enabled, id }) {\n\t\t\t// Reset selected and select new one\n\t\t\tthis.themes.forEach(theme => {\n\t\t\t\tif (theme.id === id && enabled) {\n\t\t\t\t\ttheme.enabled = true\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\ttheme.enabled = false\n\t\t\t})\n\n\t\t\tthis.updateBodyAttributes()\n\t\t\tthis.selectItem(enabled, id)\n\t\t},\n\t\tchangeFont({ enabled, id }) {\n\t\t\t// Reset selected and select new one\n\t\t\tthis.fonts.forEach(font => {\n\t\t\t\tif (font.id === id && enabled) {\n\t\t\t\t\tfont.enabled = true\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tfont.enabled = false\n\t\t\t})\n\n\t\t\tthis.updateBodyAttributes()\n\t\t\tthis.selectItem(enabled, id)\n\t\t},\n\n\t\tupdateBodyAttributes() {\n\t\t\tconst enabledThemesIDs = this.themes.filter(theme => theme.enabled === true).map(theme => theme.id)\n\t\t\tconst enabledFontsIDs = this.fonts.filter(font => font.enabled === true).map(font => font.id)\n\n\t\t\tthis.themes.forEach(theme => {\n\t\t\t\tdocument.body.toggleAttribute(`data-theme-${theme.id}`, theme.enabled)\n\t\t\t})\n\t\t\tthis.fonts.forEach(font => {\n\t\t\t\tdocument.body.toggleAttribute(`data-theme-${font.id}`, font.enabled)\n\t\t\t})\n\n\t\t\tdocument.body.setAttribute('data-themes', [...enabledThemesIDs, ...enabledFontsIDs].join(','))\n\t\t},\n\n\t\t/**\n\t\t * Commit a change and force reload css\n\t\t * Fetching the file again will trigger the server update\n\t\t *\n\t\t * @param {boolean} enabled the theme state\n\t\t * @param {string} themeId the theme ID to change\n\t\t */\n\t\tasync selectItem(enabled, themeId) {\n\t\t\ttry {\n\t\t\t\tif (enabled) {\n\t\t\t\t\tawait axios({\n\t\t\t\t\t\turl: generateOcsUrl('apps/theming/api/v1/theme/{themeId}/enable', { themeId }),\n\t\t\t\t\t\tmethod: 'PUT',\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tawait axios({\n\t\t\t\t\t\turl: generateOcsUrl('apps/theming/api/v1/theme/{themeId}', { themeId }),\n\t\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(err, err.response)\n\t\t\t\tOC.Notification.showTemporary(t('theming', err.response.data.ocs.meta.message + '. Unable to apply the setting.'))\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.theming {\n\t// Limit width of settings sections for readability\n\tp {\n\t\tmax-width: 800px;\n\t}\n\n\t// Proper highlight for links and focus feedback\n\t&::v-deep a {\n\t\tfont-weight: bold;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\ttext-decoration: underline;\n\t\t}\n\t}\n\n\t&__preview-list {\n\t\t--gap: 30px;\n\n\t\tdisplay: grid;\n\t\tmargin-top: var(--gap);\n\t\tcolumn-gap: var(--gap);\n\t\trow-gap: var(--gap);\n\t\tgrid-template-columns: 1fr 1fr;\n\t}\n}\n\n.background {\n\t&__grid {\n\t\tmargin-top: 30px;\n\t}\n}\n\n@media (max-width: 1440px) {\n\t.theming__preview-list {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t}\n}\n</style>\n","import mod from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserThemes.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserThemes.vue?vue&type=script&lang=js&\"","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/sass-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserThemes.vue?vue&type=style&index=0&id=5654fc60&lang=scss&scoped=true&\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/sass-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./UserThemes.vue?vue&type=style&index=0&id=5654fc60&lang=scss&scoped=true&\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./UserThemes.vue?vue&type=template&id=5654fc60&scoped=true&\"\nimport script from \"./UserThemes.vue?vue&type=script&lang=js&\"\nexport * from \"./UserThemes.vue?vue&type=script&lang=js&\"\nimport style0 from \"./UserThemes.vue?vue&type=style&index=0&id=5654fc60&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"5654fc60\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('section',[_c('NcSettingsSection',{staticClass:\"theming\",attrs:{\"title\":_vm.t('theming', 'Appearance and accessibility')}},[_c('p',{domProps:{\"innerHTML\":_vm._s(_vm.description)}}),_vm._v(\" \"),_c('p',{domProps:{\"innerHTML\":_vm._s(_vm.descriptionDetail)}}),_vm._v(\" \"),_c('div',{staticClass:\"theming__preview-list\"},_vm._l((_vm.themes),function(theme){return _c('ItemPreview',{key:theme.id,attrs:{\"enforced\":theme.id === _vm.enforceTheme,\"selected\":_vm.selectedTheme.id === theme.id,\"theme\":theme,\"unique\":_vm.themes.length === 1,\"type\":\"theme\"},on:{\"change\":_vm.changeTheme}})}),1),_vm._v(\" \"),_c('div',{staticClass:\"theming__preview-list\"},_vm._l((_vm.fonts),function(theme){return _c('ItemPreview',{key:theme.id,attrs:{\"selected\":theme.enabled,\"theme\":theme,\"unique\":_vm.fonts.length === 1,\"type\":\"font\"},on:{\"change\":_vm.changeFont}})}),1)]),_vm._v(\" \"),_c('NcSettingsSection',{staticClass:\"background\",attrs:{\"title\":_vm.t('theming', 'Background')}},[_c('p',[_vm._v(_vm._s(_vm.t('theming', 'Set a custom background')))]),_vm._v(\" \"),_c('BackgroundSettings',{staticClass:\"background__grid\",attrs:{\"background\":_vm.background,\"theming-default-background\":_vm.themingDefaultBackground},on:{\"update:background\":_vm.updateBackground}})],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/**\n * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>\n *\n * @author John Molakvoæ <skjnldsv@protonmail.com>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport Vue from 'vue'\nimport App from './UserThemes.vue'\n\n// bind to window\nVue.prototype.OC = OC\nVue.prototype.t = t\n\nconst View = Vue.extend(App)\nconst theming = new View()\ntheming.$mount('#theming')\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".theming p[data-v-5654fc60]{max-width:800px}.theming[data-v-5654fc60] a{font-weight:bold}.theming[data-v-5654fc60] a:hover,.theming[data-v-5654fc60] a:focus{text-decoration:underline}.theming__preview-list[data-v-5654fc60]{--gap: 30px;display:grid;margin-top:var(--gap);column-gap:var(--gap);row-gap:var(--gap);grid-template-columns:1fr 1fr}.background__grid[data-v-5654fc60]{margin-top:30px}@media(max-width: 1440px){.theming__preview-list[data-v-5654fc60]{display:flex;flex-direction:column}}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/theming/src/UserThemes.vue\"],\"names\":[],\"mappings\":\"AAqQC,4BACC,eAAA,CAID,4BACC,gBAAA,CAEA,oEAEC,yBAAA,CAIF,wCACC,WAAA,CAEA,YAAA,CACA,qBAAA,CACA,qBAAA,CACA,kBAAA,CACA,6BAAA,CAKD,mCACC,eAAA,CAIF,0BACC,wCACC,YAAA,CACA,qBAAA,CAAA\",\"sourcesContent\":[\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n.theming {\\n\\t// Limit width of settings sections for readability\\n\\tp {\\n\\t\\tmax-width: 800px;\\n\\t}\\n\\n\\t// Proper highlight for links and focus feedback\\n\\t&::v-deep a {\\n\\t\\tfont-weight: bold;\\n\\n\\t\\t&:hover,\\n\\t\\t&:focus {\\n\\t\\t\\ttext-decoration: underline;\\n\\t\\t}\\n\\t}\\n\\n\\t&__preview-list {\\n\\t\\t--gap: 30px;\\n\\n\\t\\tdisplay: grid;\\n\\t\\tmargin-top: var(--gap);\\n\\t\\tcolumn-gap: var(--gap);\\n\\t\\trow-gap: var(--gap);\\n\\t\\tgrid-template-columns: 1fr 1fr;\\n\\t}\\n}\\n\\n.background {\\n\\t&__grid {\\n\\t\\tmargin-top: 30px;\\n\\t}\\n}\\n\\n@media (max-width: 1440px) {\\n\\t.theming__preview-list {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-direction: column;\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".background-selector[data-v-50307d02]{display:flex;flex-wrap:wrap;justify-content:center}.background-selector .background[data-v-50307d02]{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}.background-selector .background.current[data-v-50307d02]{background-image:var(--color-background-dark)}.background-selector .background.filepicker[data-v-50307d02],.background-selector .background.default[data-v-50307d02],.background-selector .background.color[data-v-50307d02]{border-color:var(--color-border)}.background-selector .background.color[data-v-50307d02]{background-color:var(--color-primary);color:var(--color-primary-text)}.background-selector .background.active[data-v-50307d02],.background-selector .background[data-v-50307d02]:hover,.background-selector .background[data-v-50307d02]:focus{border:2px solid var(--color-primary)}.background-selector .background.active[data-v-50307d02]:not(.icon-loading):after{background-image:var(--icon-checkmark-white);background-repeat:no-repeat;background-position:center;background-size:44px;content:\\\"\\\";display:block;height:100%}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/theming/src/components/BackgroundSettings.vue\"],\"names\":[],\"mappings\":\"AAoJA,sCACC,YAAA,CACA,cAAA,CACA,sBAAA,CAEA,kDACC,WAAA,CACA,WAAA,CACA,UAAA,CACA,qBAAA,CACA,iCAAA,CACA,iBAAA,CACA,wCAAA,CACA,6CAAA,CACA,eAAA,CAEA,0DACC,6CAAA,CAGD,+KACC,gCAAA,CAGD,wDACC,qCAAA,CACA,+BAAA,CAGD,yKAGC,qCAAA,CAGD,kFACC,4CAAA,CACA,2BAAA,CACA,0BAAA,CACA,oBAAA,CACA,UAAA,CACA,aAAA,CACA,WAAA\",\"sourcesContent\":[\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n.background-selector {\\n\\tdisplay: flex;\\n\\tflex-wrap: wrap;\\n\\tjustify-content: center;\\n\\n\\t.background {\\n\\t\\twidth: 176px;\\n\\t\\theight: 96px;\\n\\t\\tmargin: 8px;\\n\\t\\tbackground-size: cover;\\n\\t\\tbackground-position: center center;\\n\\t\\ttext-align: center;\\n\\t\\tborder-radius: var(--border-radius-large);\\n\\t\\tborder: 2px solid var(--color-main-background);\\n\\t\\toverflow: hidden;\\n\\n\\t\\t&.current {\\n\\t\\t\\tbackground-image: var(--color-background-dark);\\n\\t\\t}\\n\\n\\t\\t&.filepicker, &.default, &.color {\\n\\t\\t\\tborder-color: var(--color-border);\\n\\t\\t}\\n\\n\\t\\t&.color {\\n\\t\\t\\tbackground-color: var(--color-primary);\\n\\t\\t\\tcolor: var(--color-primary-text);\\n\\t\\t}\\n\\n\\t\\t&.active,\\n\\t\\t&:hover,\\n\\t\\t&:focus {\\n\\t\\t\\tborder: 2px solid var(--color-primary);\\n\\t\\t}\\n\\n\\t\\t&.active:not(.icon-loading):after {\\n\\t\\t\\tbackground-image: var(--icon-checkmark-white);\\n\\t\\t\\tbackground-repeat: no-repeat;\\n\\t\\t\\tbackground-position: center;\\n\\t\\t\\tbackground-size: 44px;\\n\\t\\t\\tcontent: '';\\n\\t\\t\\tdisplay: block;\\n\\t\\t\\theight: 100%;\\n\\t\\t}\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".theming__preview[data-v-37ca8ab2]{--ratio: 16;position:relative;display:flex;justify-content:flex-start;max-width:800px}.theming__preview[data-v-37ca8ab2],.theming__preview *[data-v-37ca8ab2]{user-select:none}.theming__preview-image[data-v-37ca8ab2]{flex-basis:calc(16px*var(--ratio));flex-shrink:0;height:calc(10px*var(--ratio));margin-right:var(--gap);cursor:pointer;border-radius:var(--border-radius);background-repeat:no-repeat;background-position:top left;background-size:cover}.theming__preview-description[data-v-37ca8ab2]{display:flex;flex-direction:column}.theming__preview-description label[data-v-37ca8ab2]{padding:12px 0}.theming__preview--default[data-v-37ca8ab2]{grid-column:span 2}.theming__preview-warning[data-v-37ca8ab2]{color:var(--color-warning)}@media(max-width: 682.6666666667px){.theming__preview[data-v-37ca8ab2]{flex-direction:column}.theming__preview-image[data-v-37ca8ab2]{margin:0}}\", \"\",{\"version\":3,\"sources\":[\"webpack://./apps/theming/src/components/ItemPreview.vue\"],\"names\":[],\"mappings\":\"AAiGA,mCAEC,WAAA,CAEA,iBAAA,CACA,YAAA,CACA,0BAAA,CACA,eAAA,CAEA,wEAEC,gBAAA,CAGD,yCACC,kCAAA,CACA,aAAA,CACA,8BAAA,CACA,uBAAA,CACA,cAAA,CACA,kCAAA,CACA,2BAAA,CACA,4BAAA,CACA,qBAAA,CAGD,+CACC,YAAA,CACA,qBAAA,CAEA,qDACC,cAAA,CAIF,4CACC,kBAAA,CAGD,2CACC,0BAAA,CAIF,oCACC,mCACC,qBAAA,CAEA,yCACC,QAAA,CAAA\",\"sourcesContent\":[\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n.theming__preview {\\n\\t// We make previews on 16/10 screens\\n\\t--ratio: 16;\\n\\n\\tposition: relative;\\n\\tdisplay: flex;\\n\\tjustify-content: flex-start;\\n\\tmax-width: 800px;\\n\\n\\t&,\\n\\t* {\\n\\t\\tuser-select: none;\\n\\t}\\n\\n\\t&-image {\\n\\t\\tflex-basis: calc(16px * var(--ratio));\\n\\t\\tflex-shrink: 0;\\n\\t\\theight: calc(10px * var(--ratio));\\n\\t\\tmargin-right: var(--gap);\\n\\t\\tcursor: pointer;\\n\\t\\tborder-radius: var(--border-radius);\\n\\t\\tbackground-repeat: no-repeat;\\n\\t\\tbackground-position: top left;\\n\\t\\tbackground-size: cover;\\n\\t}\\n\\n\\t&-description {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-direction: column;\\n\\n\\t\\tlabel {\\n\\t\\t\\tpadding: 12px 0;\\n\\t\\t}\\n\\t}\\n\\n\\t&--default {\\n\\t\\tgrid-column: span 2;\\n\\t}\\n\\n\\t&-warning {\\n\\t\\tcolor: var(--color-warning);\\n\\t}\\n}\\n\\n@media (max-width: (1024px / 1.5)) {\\n\\t.theming__preview {\\n\\t\\tflex-direction: column;\\n\\n\\t\\t&-image {\\n\\t\\t\\tmargin: 0;\\n\\t\\t}\\n\\t}\\n}\\n\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdD = function () {\n\tthrow new Error('define cannot be used indirect');\n};","__webpack_require__.amdO = {};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 6755;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t6755: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknextcloud\"] = self[\"webpackChunknextcloud\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [7874], function() { return __webpack_require__(34198); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","prefixWithBaseUrl","url","generateFilePath","getBackgroundUrl","background","time","themingDefaultBackground","enabledThemes","window","OCA","Theming","isDarkTheme","length","matchMedia","matches","join","indexOf","generateUrl","cacheBuster","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","_vm","this","_h","$createElement","_c","_self","staticClass","class","active","attrs","on","pickFile","_v","_s","t","loading","setDefault","pickColor","_l","shippedBackground","directives","name","rawName","value","details","expression","key","style","preview","$event","setShipped","theme","id","backgroundImage","img","onToggle","title","description","_e","checked","enforced","switchType","enableLabel","console","debug","availableThemes","domProps","descriptionDetail","enforceTheme","selectedTheme","themes","changeTheme","enabled","fonts","changeFont","updateBackground","Vue","OC","App","$mount","___CSS_LOADER_EXPORT___","push","module","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","loaded","__webpack_modules__","call","m","amdD","Error","amdO","O","result","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","Object","keys","every","splice","r","n","getter","__esModule","d","a","definition","o","defineProperty","enumerable","get","g","globalThis","Function","e","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","nmd","paths","children","b","document","baseURI","self","location","href","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","data","moreModules","runtime","some","chunkLoadingGlobal","forEach","bind","nc","__webpack_exports__"],"sourceRoot":""}
\ No newline at end of file