Refactor: re-design the settings page.
This commit is contained in:
parent
8e91eb4ac7
commit
1c5b4f344d
7 changed files with 253 additions and 200 deletions
|
|
@ -33,7 +33,7 @@ FRONTEND_ROUTES: list[str] = [
|
|||
"/logs/",
|
||||
"/conditions/",
|
||||
"/browser/",
|
||||
"/settings/",
|
||||
"/simple/",
|
||||
"/browser/{path:.*}",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -374,3 +374,7 @@ div.is-centered {
|
|||
padding: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.is-rounded-less {
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,39 @@
|
|||
<template>
|
||||
<main class="m-6">
|
||||
|
||||
<div>
|
||||
<template v-if="!simpleMode">
|
||||
<span class="title is-4">
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fas fa-cog" /></span>
|
||||
<p class="card-header-title">WebUI Settings</p>
|
||||
</span>
|
||||
</span>
|
||||
<span class="field is-horizontal" />
|
||||
</template>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Page View</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="modal" :class="{ 'is-active': isOpen }">
|
||||
<div class="modal-background" @click="emitter('close')" />
|
||||
<div class="modal-card"
|
||||
:class="{ 'slide-from-right': direction === 'right', 'slide-from-left': direction === 'left' }">
|
||||
<header class="modal-card-head is-rounded-less">
|
||||
<p class="modal-card-title">WebUI Settings</p>
|
||||
<button class="delete" @click="emitter('close')" aria-label="close" />
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<div class="box">
|
||||
<div class="field">
|
||||
<div class="control is-expanded has-icons-left">
|
||||
<label class="label">Page View</label>
|
||||
<div class="control">
|
||||
<input id="view_mode" type="checkbox" class="switch is-success" v-model="simpleMode">
|
||||
<label for="view_mode" class="is-unselectable">
|
||||
{{ simpleMode ? 'Simple View' : 'Regular View' }}
|
||||
</label>
|
||||
</div>
|
||||
<p class="help">
|
||||
<span class="icon"> <i class="fa-solid fa-info-circle" /></span>
|
||||
<span class="icon"><i class="fa-solid fa-info-circle" /></span>
|
||||
The simple view is ideal for non-technical users and mobile devices.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="field title is-4">
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fas fa-palette" /></span>
|
||||
<p class="card-header-title">Theming</p>
|
||||
</span>
|
||||
</span>
|
||||
<span class="field is-horizontal" />
|
||||
<div class="box">
|
||||
<p class="title is-5 mb-4">
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fas fa-palette" /></span>
|
||||
<span>Theming</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label">
|
||||
<label class="label">Color scheme</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<div class="field">
|
||||
<label class="label">Color scheme</label>
|
||||
<div class="control">
|
||||
<label for="auto" class="radio">
|
||||
<input id="auto" type="radio" v-model="selectedTheme" value="auto">
|
||||
|
|
@ -64,15 +52,9 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Show Background</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label">Show Background</label>
|
||||
<div class="control">
|
||||
<input id="random_bg" type="checkbox" class="switch is-success" v-model="bg_enable">
|
||||
<label for="random_bg" class="is-unselectable">
|
||||
|
|
@ -80,62 +62,42 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label"></label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<div class="field" v-if="bg_enable">
|
||||
<div class="control">
|
||||
<template v-if="bg_enable">
|
||||
<button @click="$emit('reload_bg')" class="has-text-link" :disabled="isLoading">
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fa"
|
||||
:class="{ 'fa-spin fa-spinner': isLoading, 'fa-file-image': !isLoading }" /></span>
|
||||
<span>Reload Background</span>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
<button @click="$emit('reload_bg')" class="button is-link is-light is-fullwidth" :disabled="isLoading">
|
||||
<span class="icon"><i class="fa"
|
||||
:class="{ 'fa-spin fa-spinner': isLoading, 'fa-file-image': !isLoading }" /></span>
|
||||
<span>Reload Background</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field" v-if="bg_enable">
|
||||
<label class="label">Background visibility</label>
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
<a class="button is-static">
|
||||
<code>{{ parseFloat(String(1.0 - bg_opacity)).toFixed(2) }}</code>
|
||||
</a>
|
||||
</div>
|
||||
<div class="control is-expanded">
|
||||
<input class="input" type="range" v-model="bg_opacity" min="0.50" max="1.00" step="0.05">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Background visibility</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field is-expanded">
|
||||
<a class="button is-static is-small">
|
||||
<code>{{ parseFloat(String(1.0 - bg_opacity)).toFixed(2) }}</code>
|
||||
</a>
|
||||
<div class="box">
|
||||
<p class="title is-5 mb-4">
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fas fa-home" /></span>
|
||||
<span>Dashboard</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div class="control">
|
||||
<input id="random_bg_opacity" style="width: 100%" type="range" v-model="bg_opacity" min="0.50" max="1.00"
|
||||
step="0.05">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="field title is-4">
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fas fa-home" /></span>
|
||||
<p class="card-header-title">Dashboard</p>
|
||||
</span>
|
||||
</span>
|
||||
<span class="field is-horizontal" />
|
||||
|
||||
<div class="field is-horizontal" v-if="!simpleMode">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">URL Separator</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<div class="field" v-if="!simpleMode">
|
||||
<label class="label">URL Separator</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select v-model="separator">
|
||||
|
|
@ -146,17 +108,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Show Thumbnails</label>
|
||||
</div>
|
||||
|
||||
<div class="field-body">
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<div class="field">
|
||||
<label class="label">Show Thumbnails</label>
|
||||
<div class="control">
|
||||
<input id="show_thumbnail" type="checkbox" class="switch is-success" v-model="show_thumbnail">
|
||||
<label for="show_thumbnail" class="is-unselectable">
|
||||
{{ show_thumbnail ? 'Yes' : 'No' }}
|
||||
|
|
@ -167,17 +122,10 @@
|
|||
Show videos thumbnail if available
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal" v-if="show_thumbnail">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Aspect Ratio</label>
|
||||
</div>
|
||||
|
||||
<div class="field-body">
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<div class="field" v-if="show_thumbnail">
|
||||
<label class="label">Aspect Ratio</label>
|
||||
<div class="control">
|
||||
<label for="ratio_16by9" class="radio">
|
||||
<input id="ratio_16by9" type="radio" v-model="thumbnail_ratio" value="is-16by9">
|
||||
<span> 16:9</span>
|
||||
|
|
@ -193,39 +141,27 @@
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span class="field title is-4">
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fas fa-bell" /></span>
|
||||
<p class="card-header-title">Notifications</p>
|
||||
</span>
|
||||
</span>
|
||||
<span class="field is-horizontal" />
|
||||
<div class="box">
|
||||
<p class="title is-5 mb-4">
|
||||
<span class="icon-text">
|
||||
<span class="icon"><i class="fas fa-bell" /></span>
|
||||
<span>Notifications</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Show notifications</label>
|
||||
</div>
|
||||
|
||||
<div class="field-body">
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<div class="field">
|
||||
<label class="label">Show notifications</label>
|
||||
<div class="control">
|
||||
<input id="allow_toasts" type="checkbox" class="switch is-success" v-model="allow_toasts">
|
||||
<label for="allow_toasts" class="is-unselectable">
|
||||
{{ allow_toasts ? 'Yes' : 'No' }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal" v-if="allow_toasts">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Notification target</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<div class="field" v-if="allow_toasts">
|
||||
<label class="label">Notification target</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select v-model="toast_target" @change="onNotificationTargetChange">
|
||||
|
|
@ -244,15 +180,9 @@
|
|||
</template>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal" v-if="allow_toasts && toast_target === 'toast'">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Notifications position</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<div class="field" v-if="allow_toasts && toast_target === 'toast'">
|
||||
<label class="label">Notifications position</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select v-model="toast_position">
|
||||
|
|
@ -266,17 +196,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal" v-if="allow_toasts && toast_target === 'toast'">
|
||||
<div class="field-label is-normal">
|
||||
<label class="label">Dismiss notification on click</label>
|
||||
</div>
|
||||
|
||||
<div class="field-body">
|
||||
<div class="control">
|
||||
<div class="field">
|
||||
<div class="field" v-if="allow_toasts && toast_target === 'toast'">
|
||||
<label class="label">Dismiss notification on click</label>
|
||||
<div class="control">
|
||||
<input id="dismiss_on_click" type="checkbox" class="switch is-success" v-model="toast_dismiss_on_click">
|
||||
<label for="dismiss_on_click" class="is-unselectable">
|
||||
{{ toast_dismiss_on_click ? 'Yes' : 'No' }}
|
||||
|
|
@ -284,22 +207,31 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import 'assets/css/bulma-switch.css'
|
||||
import { watch, onMounted, onBeforeUnmount, ref } from 'vue'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { POSITION } from 'vue-toastification'
|
||||
import { useConfigStore } from '~/stores/ConfigStore'
|
||||
import { useNotification } from '~/composables/useNotification'
|
||||
import type { notificationTarget } from '~/composables/useNotification'
|
||||
|
||||
defineProps<{ isLoading: boolean }>()
|
||||
const emitter = defineEmits<{ (e: 'reload_bg' | 'close'): void }>()
|
||||
const props = withDefaults(defineProps<{
|
||||
isOpen?: boolean
|
||||
direction?: 'left' | 'right'
|
||||
isLoading?: boolean
|
||||
}>(), {
|
||||
isOpen: false,
|
||||
direction: 'right',
|
||||
isLoading: false
|
||||
})
|
||||
|
||||
const emitter = defineEmits<{ (e: 'close' | 'reload_bg'): void }>()
|
||||
|
||||
const config = useConfigStore()
|
||||
const notification = useNotification()
|
||||
|
|
@ -317,14 +249,27 @@ const separator = useStorage<string>('url_separator', separators[0]?.value ?? ',
|
|||
const simpleMode = useStorage<boolean>('simple_mode', config.app.simple_mode || false)
|
||||
const isSecureContext = ref<boolean>(false)
|
||||
|
||||
const handleKeydown = (e: KeyboardEvent) => {
|
||||
if ('Escape' === e.key && props.isOpen) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
emitter('close')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
isSecureContext.value = window.isSecureContext
|
||||
await nextTick()
|
||||
|
||||
if ('browser' === toast_target.value && !isSecureContext.value) {
|
||||
toast_target.value = 'toast'
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', handleKeydown)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => document.removeEventListener('keydown', handleKeydown))
|
||||
|
||||
const onNotificationTargetChange = async (): Promise<void> => {
|
||||
if ('browser' === toast_target.value) {
|
||||
const permission = await notification.requestBrowserPermission()
|
||||
|
|
@ -335,5 +280,74 @@ const onNotificationTargetChange = async (): Promise<void> => {
|
|||
}
|
||||
}
|
||||
|
||||
watch(simpleMode, async () => emitter('close'))
|
||||
watch(() => props.isOpen, isOpen => {
|
||||
if (isOpen) {
|
||||
document.body.classList.add('settings-panel-open')
|
||||
} else {
|
||||
document.body.classList.remove('settings-panel-open')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-card.slide-from-right {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
margin: 0;
|
||||
width: 600px;
|
||||
max-width: 90vw;
|
||||
transition: transform 0.3s ease;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.modal.is-active .modal-card.slide-from-right {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.modal-card.slide-from-left {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
margin: 0;
|
||||
width: 600px;
|
||||
max-width: 90vw;
|
||||
transition: transform 0.3s ease;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.modal.is-active .modal-card.slide-from-left {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.modal-card-body {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
|
||||
.modal-card.slide-from-right,
|
||||
.modal-card.slide-from-left {
|
||||
width: 100vw;
|
||||
max-width: 100vw;
|
||||
}
|
||||
}
|
||||
|
||||
:global(body.settings-panel-open) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#main_container {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 769px) {
|
||||
:global(.settings-open #main_container) {
|
||||
transform: translateX(-300px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
<template>
|
||||
<div class="basic-wrapper">
|
||||
<div class="basic-wrapper" :class="{ 'settings-open': settingsOpen }">
|
||||
<div class="form-container" :class="{ 'is-centered': shouldCenterForm }">
|
||||
<section class="download-form box">
|
||||
<form class="download-form__body" autocomplete="off" @submit.prevent="addDownload">
|
||||
<label class="label" for="download-url">
|
||||
{{ greetingMessage }}
|
||||
<template v-if="!isMobile">{{ greetingMessage }}</template>
|
||||
<template v-else>What would you like to download?</template>
|
||||
<span class="is-pulled-right">
|
||||
<span class="icon is-pointer" :class="connectionStatusColor" @click="$emit('show_settings')"
|
||||
v-tooltip="'WebUI Settings'">
|
||||
|
|
@ -106,7 +107,9 @@
|
|||
</figure>
|
||||
<div class="media-content is-grid">
|
||||
<p class="title is-6 mb-0 queue-title">
|
||||
<NuxtLink target="_blank" :href="entry.item.url">{{ entry.item.title }}</NuxtLink>
|
||||
<NuxtLink target="_blank" :href="entry.item.url" v-tooltip="entry.item.title">
|
||||
{{ entry.item.title || 'Untitled' }}
|
||||
</NuxtLink>
|
||||
</p>
|
||||
<div class="field is-grouped is-unselectable">
|
||||
<div class="control">
|
||||
|
|
@ -205,7 +208,6 @@
|
|||
</div>
|
||||
<button class="modal-close is-large" aria-label="close" @click="closePlayer"></button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -225,10 +227,19 @@ import { ag, encodePath, formatTime, makeDownload, request, stripPath, ucFirst,
|
|||
|
||||
defineEmits<{ (e: 'show_settings'): void }>()
|
||||
|
||||
withDefaults(defineProps<{
|
||||
settingsOpen?: boolean
|
||||
}>(), {
|
||||
settingsOpen: false
|
||||
})
|
||||
|
||||
const configStore = useConfigStore()
|
||||
const stateStore = useStateStore()
|
||||
const socketStore = useSocketStore()
|
||||
const toast = useNotification()
|
||||
const dlFields = useStorage<Record<string, any>>('dl_fields', {})
|
||||
const show_thumbnail = useStorage<boolean>('show_thumbnail', true)
|
||||
const isMobile = useMediaQuery({ maxWidth: 1024 })
|
||||
|
||||
const { app, paused, presets } = storeToRefs(configStore)
|
||||
const { queue, history } = storeToRefs(stateStore)
|
||||
|
|
@ -241,12 +252,9 @@ const formUrl = ref<string>('')
|
|||
const formPreset = ref<{ preset: string }>({ preset: app.value.default_preset || '' })
|
||||
const addInProgress = ref<boolean>(false)
|
||||
const showExtras = ref<boolean>(false)
|
||||
const dlFields = useStorage<Record<string, any>>('dl_fields', {})
|
||||
const show_thumbnail = useStorage<boolean>('show_thumbnail', true)
|
||||
|
||||
const paginationInfo = computed(() => stateStore.getPagination())
|
||||
|
||||
const queueItems = computed<StoreItem[]>(() => Object.values(queue.value ?? {}).slice().sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0)))
|
||||
|
||||
const historyEntries = computed<StoreItem[]>(() => {
|
||||
const items = Object.values(history.value ?? {})
|
||||
return items.slice().sort((a, b) => new Date(b.datetime).getTime() - new Date(a.datetime).getTime())
|
||||
|
|
@ -654,6 +662,10 @@ onMounted(async () => {
|
|||
if (route.query?.simple !== undefined) {
|
||||
const simpleMode = useStorage<boolean>('simple_mode', configStore.app.simple_mode || false)
|
||||
simpleMode.value = ['true', '1', 'yes', 'on'].includes(route.query.simple as string)
|
||||
await nextTick()
|
||||
const url = new URL(window.location.href)
|
||||
url.searchParams.delete('simple')
|
||||
window.history.replaceState({}, '', url.toString())
|
||||
}
|
||||
|
||||
if (socketStore.isConnected && !paginationInfo.value.isLoaded) {
|
||||
|
|
@ -718,6 +730,17 @@ useIntersectionObserver(loadMoreTrigger, ([entry]) => {
|
|||
align-items: center;
|
||||
gap: 2.5rem;
|
||||
padding: 2rem 1rem 4rem;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.basic-wrapper.settings-open {
|
||||
transform: translateX(-300px);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.basic-wrapper.settings-open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.form-container {
|
||||
|
|
|
|||
|
|
@ -2,38 +2,16 @@
|
|||
|
||||
<template v-if="simpleMode">
|
||||
<Connection :status="socket.connectionStatus" @reconnect="() => socket.reconnect()" />
|
||||
<Simple @show_settings="() => show_settings = true" />
|
||||
<Simple @show_settings="() =>show_settings = true"
|
||||
:class="{ 'settings-open': show_settings }" />
|
||||
</template>
|
||||
|
||||
<template v-if="show_settings">
|
||||
<Modal @close="closeSettings()"
|
||||
:content-class="isMobile ? 'modal-content-max is-overflow-scroll ' : 'modal-content-max'">
|
||||
<div class="columns is-multiline" style="width:100%">
|
||||
<div class="column is-12">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">WebUI Settings</p>
|
||||
<span class="card-header-icon">
|
||||
<span class="icon"><i class="fas fa-cog" /></span>
|
||||
</span>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-12">
|
||||
<settings v-if="show_settings" :isLoading="loadingImage" @reload_bg="() => loadImage(true)"
|
||||
@close="closeSettings()" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
<SettingsPanel :isOpen="show_settings" :isLoading="loadingImage" @close="closeSettings()"
|
||||
@reload_bg="() => loadImage(true)" direction="right" />
|
||||
|
||||
<template v-if="!simpleMode">
|
||||
<Shutdown v-if="app_shutdown" />
|
||||
<div id="main_container" class="container" v-else>
|
||||
<div id="main_container" class="container" :class="{ 'settings-open': show_settings }" v-else>
|
||||
<NewVersion v-if="newVersionIsAvailable" />
|
||||
<Connection :status="socket.connectionStatus" @reconnect="() => socket.reconnect()" />
|
||||
<nav class="navbar is-mobile is-dark">
|
||||
|
|
@ -142,11 +120,11 @@
|
|||
</div>
|
||||
|
||||
<div class="navbar-item">
|
||||
<NuxtLink class="button is-dark " :class="{ 'has-tooltip-bottom mr-4': !isMobile }" to="/settings"
|
||||
@click.prevent="(e: MouseEvent) => changeRoute(e)">
|
||||
<button class="button is-dark " :class="{ 'has-tooltip-bottom mr-4': !isMobile }"
|
||||
@click="show_settings = !show_settings">
|
||||
<span class="icon"><i class="fas fa-cog" /></span>
|
||||
<span v-if="isMobile">WebUI Settings</span>
|
||||
</NuxtLink>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -226,7 +204,6 @@ import Simple from '~/components/Simple.vue'
|
|||
import Shutdown from '~/components/shutdown.vue'
|
||||
import Markdown from '~/components/Markdown.vue'
|
||||
import Connection from '~/components/Connection.vue'
|
||||
import Settings from "~/pages/settings.vue";
|
||||
|
||||
const Year = new Date().getFullYear()
|
||||
const selectedTheme = useStorage('theme', 'auto')
|
||||
|
|
@ -241,7 +218,6 @@ const isMobile = useMediaQuery({ maxWidth: 1024 })
|
|||
const app_shutdown = ref<boolean>(false)
|
||||
const simpleMode = useStorage<boolean>('simple_mode', config.app.simple_mode || false)
|
||||
const show_settings = ref(false)
|
||||
|
||||
const doc = ref<{ file: string }>({ file: '' })
|
||||
|
||||
const applyPreferredColorScheme = (scheme: string) => {
|
||||
|
|
@ -525,3 +501,23 @@ const connectionStatusColor = computed(() => {
|
|||
|
||||
const scrollToTop = () => document.getElementById('top')?.scrollIntoView({ behavior: 'smooth' });
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#main_container,
|
||||
.basic-wrapper {
|
||||
transition: transform 0.3s ease, margin-right 0.3s ease;
|
||||
}
|
||||
|
||||
#main_container.settings-open,
|
||||
.basic-wrapper.settings-open {
|
||||
transform: translateX(-300px);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
|
||||
#main_container.settings-open,
|
||||
.basic-wrapper.settings-open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -163,12 +163,16 @@ watch(() => route.query.tab, (newTab) => {
|
|||
activeTab.value = newTab as TabType
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
const route = useRoute()
|
||||
|
||||
if (route.query?.simple !== undefined) {
|
||||
const simpleMode = useStorage<boolean>('simple_mode', config.app.simple_mode || false)
|
||||
simpleMode.value = ['true', '1', 'yes', 'on'].includes(route.query.simple as string)
|
||||
await nextTick()
|
||||
const url = new URL(window.location.href)
|
||||
url.searchParams.delete('simple')
|
||||
window.history.replaceState({}, '', url.toString())
|
||||
}
|
||||
|
||||
activeTab.value = getInitialTab()
|
||||
|
|
|
|||
12
ui/app/pages/simple.vue
Normal file
12
ui/app/pages/simple.vue
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<template></template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useStorage } from '@vueuse/core'
|
||||
const simpleMode = useStorage<boolean>('simple_mode', true)
|
||||
|
||||
onMounted(async () => {
|
||||
simpleMode.value = true
|
||||
await nextTick()
|
||||
await navigateTo('/')
|
||||
})
|
||||
</script>
|
||||
Loading…
Reference in a new issue