minor ui updates/
This commit is contained in:
parent
53b7474069
commit
444e1458be
4 changed files with 84 additions and 22 deletions
|
|
@ -144,7 +144,7 @@ async def get_info(request: Request, cache: Cache, config: Config) -> Response:
|
|||
"ttl_left": data.get("_cached", {}).get("expires", time.time() + 300) - time.time(),
|
||||
"expires": data.get("_cached", {}).get("expires", time.time() + 300),
|
||||
}
|
||||
return web.Response(body=json.dumps(data, indent=4, default=str), status=web.HTTPOk.status_code)
|
||||
return web.json_response(body=json.dumps(data, indent=4, default=str), status=web.HTTPOk.status_code)
|
||||
|
||||
if ytdlp_proxy := config.get_ytdlp_args().get("proxy", None):
|
||||
opts = opts.add({"proxy": ytdlp_proxy})
|
||||
|
|
@ -203,7 +203,7 @@ async def get_info(request: Request, cache: Cache, config: Config) -> Response:
|
|||
|
||||
cache.set(key=key, value=data, ttl=300)
|
||||
|
||||
return web.Response(body=json.dumps(data, indent=4, default=str), status=web.HTTPOk.status_code)
|
||||
return web.json_response(body=json.dumps(data, indent=4, default=str), status=web.HTTPOk.status_code)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
LOG.error(f"Error encountered while getting video info for '{url}'. '{e!s}'.")
|
||||
|
|
|
|||
61
ui/app/composables/useMediaQuery.ts
Normal file
61
ui/app/composables/useMediaQuery.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { ref, onMounted, onBeforeUnmount, shallowReadonly, type Ref } from 'vue'
|
||||
|
||||
export interface MediaQueryOptions {
|
||||
/**
|
||||
* A custom media query string.
|
||||
* Example: "(max-width: 640px) or (hover: none)"
|
||||
* If provided, takes precedence over maxWidth.
|
||||
*/
|
||||
query?: string
|
||||
|
||||
/**
|
||||
* Max width in px considered true.
|
||||
* Ignored if `query` is provided. Default: 768.
|
||||
*/
|
||||
maxWidth?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Reactive state of a CSS media query.
|
||||
*/
|
||||
export function useMediaQuery(options: MediaQueryOptions = {}): Readonly<Ref<boolean>> {
|
||||
const query = options.query ?? `(max-width: ${options.maxWidth ?? 1024}px)`
|
||||
const matches = ref(false)
|
||||
|
||||
let mql: MediaQueryList | null = null
|
||||
let onChange: ((ev: MediaQueryListEvent) => void) | null = null
|
||||
|
||||
const setup = () => {
|
||||
if ('undefined' === typeof window || !window.matchMedia) {
|
||||
return
|
||||
}
|
||||
mql = window.matchMedia(query)
|
||||
matches.value = mql.matches
|
||||
|
||||
onChange = ev => { matches.value = ev.matches }
|
||||
if ('addEventListener' in mql) {
|
||||
mql.addEventListener('change', onChange as EventListener)
|
||||
return
|
||||
}
|
||||
|
||||
// @ts-expect-error legacy Safari
|
||||
mql.addListener(onChange)
|
||||
}
|
||||
|
||||
const teardown = () => {
|
||||
if (!mql || !onChange) return
|
||||
if ('removeEventListener' in mql) {
|
||||
mql.removeEventListener('change', onChange as EventListener)
|
||||
} else {
|
||||
// @ts-expect-error legacy Safari
|
||||
mql.removeListener(onChange)
|
||||
}
|
||||
mql = null
|
||||
onChange = null
|
||||
}
|
||||
|
||||
onMounted(setup)
|
||||
onBeforeUnmount(teardown)
|
||||
|
||||
return shallowReadonly(matches)
|
||||
}
|
||||
|
|
@ -75,27 +75,22 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="navbar-item is-hidden-mobile" v-if="false === config.app.is_native">
|
||||
<div class="navbar-item" v-if="false === config.app.is_native">
|
||||
<button class="button is-dark" @click="reloadPage">
|
||||
<span class="icon"><i class="fas fa-refresh" /></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="navbar-item is-hidden-tablet">
|
||||
<button class="button is-dark" @click="reloadPage">
|
||||
<span class="icon"><i class="fas fa-refresh" /></span>
|
||||
<span>Reload</span>
|
||||
<span v-if="isMobile">Reload</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<NotifyDropdown />
|
||||
|
||||
<div class="navbar-item is-hidden-mobile">
|
||||
<div class="navbar-item" v-if="!isMobile">
|
||||
<button class="button is-dark has-tooltip-bottom mr-4" v-tooltip.bottom="'WebUI Settings'"
|
||||
@click="show_settings = !show_settings">
|
||||
<span class="icon"><i class="fas fa-cog" /></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="navbar-item is-hidden-tablet">
|
||||
<div class="navbar-item" v-if="isMobile">
|
||||
<button class="button is-dark" @click="show_settings = !show_settings">
|
||||
<span class="icon"><i class="fas fa-cog" /></span>
|
||||
<span>WebUI Settings</span>
|
||||
|
|
@ -116,11 +111,11 @@
|
|||
<div class="column is-8-mobile">
|
||||
<div class="has-text-left" v-if="config.app?.app_version">
|
||||
© {{ Year }} - <NuxtLink href="https://github.com/ArabCoders/ytptube" target="_blank">YTPTube</NuxtLink>
|
||||
<span class="is-hidden-mobile has-tooltip"
|
||||
<span class="has-tooltip" v-if="!isMobile"
|
||||
v-tooltip="`Build Date: ${config.app?.app_build_date}, Branch: ${config.app?.app_branch}, commit: ${config.app?.app_commit_sha}`">
|
||||
({{ config?.app?.app_version || 'unknown' }})</span>
|
||||
- <NuxtLink target="_blank" href="https://github.com/yt-dlp/yt-dlp">yt-dlp</NuxtLink>
|
||||
<span class="is-hidden-mobile"> ({{ config?.app?.ytdlp_version || 'unknown' }})</span>
|
||||
<span v-if="!isMobile"> ({{ config?.app?.ytdlp_version || 'unknown' }})</span>
|
||||
- <NuxtLink to="/changelog">CHANGELOG</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -137,6 +132,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, readonly } from 'vue'
|
||||
import 'assets/css/bulma.css'
|
||||
import 'assets/css/style.css'
|
||||
import 'assets/css/all.css'
|
||||
|
|
@ -154,6 +150,7 @@ const loadingImage = ref(false)
|
|||
const bg_enable = useStorage('random_bg', true)
|
||||
const bg_opacity = useStorage('random_bg_opacity', 0.95)
|
||||
const showMenu = ref(false)
|
||||
const isMobile = useMediaQuery({ maxWidth: 1024 })
|
||||
|
||||
const applyPreferredColorScheme = (scheme: string) => {
|
||||
if (!scheme || scheme === 'auto') {
|
||||
|
|
|
|||
|
|
@ -20,26 +20,26 @@
|
|||
<p class="control">
|
||||
<button class="button is-danger is-light" @click="toggleFilter = !toggleFilter">
|
||||
<span class="icon"><i class="fas fa-filter" /></span>
|
||||
<span class="is-hidden-mobile">Filter</span>
|
||||
<span v-if="!isMobile">Filter</span>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
<p class="control" v-if="!config.app.basic_mode && false === config.app.basic_mode">
|
||||
<button class="button is-warning" @click="pauseDownload" v-if="false === config.paused">
|
||||
<span class="icon"><i class="fas fa-pause" /></span>
|
||||
<span class="is-hidden-mobile">Pause</span>
|
||||
<span v-if="!isMobile">Pause</span>
|
||||
</button>
|
||||
<button class="button is-danger" @click="socket.emit('resume', {})" v-else
|
||||
v-tooltip.bottom="'Resume downloading.'">
|
||||
<span class="icon"><i class="fas fa-play" /></span>
|
||||
<span class="is-hidden-mobile">Resume</span>
|
||||
<span v-if="!isMobile">Resume</span>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
<p class="control" v-if="!config.app.basic_mode && false === config.app.basic_mode">
|
||||
<button class="button is-primary has-tooltip-bottom" @click="config.showForm = !config.showForm">
|
||||
<span class="icon"><i class="fa-solid fa-plus" /></span>
|
||||
<span class="is-hidden-mobile">New Download</span>
|
||||
<span v-if="!isMobile">New Download</span>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
|
|
@ -48,13 +48,14 @@
|
|||
@click="() => changeDisplay()">
|
||||
<span class="icon"><i class="fa-solid"
|
||||
:class="{ 'fa-table': display_style === 'cards', 'fa-table-list': display_style === 'list' }" /></span>
|
||||
<span class="is-hidden-mobile">{{ display_style === 'cards' ? 'Cards' : 'List' }}</span>
|
||||
<span v-if="!isMobile">
|
||||
{{ display_style === 'cards' ? 'Cards' : 'List' }}
|
||||
</span>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-hidden-mobile">
|
||||
<div v-if="!isMobile">
|
||||
<span class="subtitle">
|
||||
Queued and completed downloads are displayed here.
|
||||
</span>
|
||||
|
|
@ -68,7 +69,7 @@
|
|||
<Queue @getInfo="(url: string, preset: string = '') => view_info(url, false, preset)" :thumbnails="show_thumbnail"
|
||||
:query="query" @getItemInfo="(id: string) => view_info(`/api/history/${id}`, true)" @clear_search="query = ''" />
|
||||
<History @getInfo="(url: string, preset: string = '') => view_info(url, false, preset)"
|
||||
@add_new="(item: item_request) => toNewDownload(item)" :query="query" :thumbnails="show_thumbnail"
|
||||
@add_new="(item: Partial<StoreItem>) => toNewDownload(item)" :query="query" :thumbnails="show_thumbnail"
|
||||
@getItemInfo="(id: string) => view_info(`/api/history/${id}`, true)" @clear_search="query = ''" />
|
||||
<GetInfo v-if="info_view.url" :link="info_view.url" :preset="info_view.preset" :useUrl="info_view.useUrl"
|
||||
@closeModel="close_info()" />
|
||||
|
|
@ -81,6 +82,7 @@
|
|||
<script setup lang="ts">
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import type { item_request } from '~/types/item'
|
||||
import type { StoreItem } from '~/types/store'
|
||||
|
||||
const config = useConfigStore()
|
||||
const stateStore = useStateStore()
|
||||
|
|
@ -106,6 +108,8 @@ const dialog_confirm = ref({
|
|||
options: [],
|
||||
})
|
||||
|
||||
const isMobile = useMediaQuery({ maxWidth: 1024 })
|
||||
|
||||
watch(toggleFilter, () => {
|
||||
if (!toggleFilter.value) {
|
||||
query.value = ''
|
||||
|
|
@ -170,7 +174,7 @@ watch(() => info_view.value.url, v => {
|
|||
|
||||
const changeDisplay = () => display_style.value = display_style.value === 'cards' ? 'list' : 'cards'
|
||||
|
||||
const toNewDownload = async (item: item_request) => {
|
||||
const toNewDownload = async (item: item_request | Partial<StoreItem>) => {
|
||||
if (!item) {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue