mirror of
https://github.com/jellyfin/jellyfin-vue.git
synced 2026-09-03 05:10:26 +03:00
feat(jApp): initial implementation
* JApp is the main wrapper that will set all the scripted CSS vars for the whole application. It will also handle all the theming. * Remove class-based approach in splashscreen and use CSS vars instead Signed-off-by: Fernando Fernández <ferferga@hotmail.com>
This commit is contained in:
+41
-36
@@ -1,40 +1,42 @@
|
||||
<template>
|
||||
<Backdrop />
|
||||
<VApp>
|
||||
<RouterView v-slot="{ Component, route }">
|
||||
<JTransition
|
||||
:name="route.meta.transition?.enter ?? defaultTransition"
|
||||
:mode="defaultTransitionMode"
|
||||
:disabled="!mounted"
|
||||
appear>
|
||||
<Suspense @resolve="apploaded = true">
|
||||
<div
|
||||
:key="route.meta.layout"
|
||||
class="uno-h-full j-transition">
|
||||
<component
|
||||
:is="getLayoutComponent(route.meta.layout)"
|
||||
:key="route.meta.layout">
|
||||
<JTransition
|
||||
:name="route.meta.transition?.enter ?? defaultTransition"
|
||||
:mode="defaultTransitionMode">
|
||||
<Suspense suspensible>
|
||||
<div
|
||||
:key="route.name ?? route.path"
|
||||
class="uno-h-full j-transition">
|
||||
<component
|
||||
:is="Component"
|
||||
:key="route.name ?? route.path" />
|
||||
</div>
|
||||
</Suspense>
|
||||
</JTransition>
|
||||
</component>
|
||||
</div>
|
||||
<template v-if="!apploaded" #fallback>
|
||||
<JSplashscreen />
|
||||
</template>
|
||||
</Suspense>
|
||||
</JTransition>
|
||||
</RouterView>
|
||||
<JApp>
|
||||
<RouterView v-slot="{ Component, route }">
|
||||
<JTransition
|
||||
:name="route.meta.transition?.enter ?? defaultTransition"
|
||||
:mode="defaultTransitionMode"
|
||||
:disabled="!mounted"
|
||||
appear>
|
||||
<Suspense @resolve="apploaded = true">
|
||||
<div
|
||||
:key="route.meta.layout"
|
||||
class="uno-h-full j-transition">
|
||||
<component
|
||||
:is="getLayoutComponent(route.meta.layout)"
|
||||
:key="route.meta.layout">
|
||||
<JTransition
|
||||
:name="route.meta.transition?.enter ?? defaultTransition"
|
||||
:mode="defaultTransitionMode">
|
||||
<Suspense suspensible>
|
||||
<div
|
||||
:key="route.name ?? route.path"
|
||||
class="uno-h-full j-transition">
|
||||
<component
|
||||
:is="Component"
|
||||
:key="route.name ?? route.path" />
|
||||
</div>
|
||||
</Suspense>
|
||||
</JTransition>
|
||||
</component>
|
||||
</div>
|
||||
<template v-if="!apploaded" #fallback>
|
||||
<JSplashscreen />
|
||||
</template>
|
||||
</Suspense>
|
||||
</JTransition>
|
||||
</RouterView>
|
||||
</JApp>
|
||||
<Snackbar />
|
||||
<ConfirmDialog />
|
||||
</VApp>
|
||||
@@ -57,11 +59,14 @@ const defaultTransition = 'slide-x-reverse';
|
||||
const defaultTransitionMode = 'out-in';
|
||||
|
||||
/**
|
||||
* When app is mounted, the classes we initialized in the pre-Vue splashscreen in body
|
||||
* are now useless and can break the page if not removed
|
||||
* When app is mounted, the classes and styles we initialized in the pre-Vue splashscreen in body
|
||||
* are now useless and can break the page if not removed.
|
||||
*
|
||||
* We set all the styles and vars in JApp, so we want a body with 0 styling attributes.
|
||||
*/
|
||||
onMounted(() => {
|
||||
document.body.removeAttribute('class');
|
||||
document.body.removeAttribute('style');
|
||||
mounted.value = true;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
* {
|
||||
font-family: "InterVariable", system-ui !important;
|
||||
cursor: var(--j-client-cursor);
|
||||
}
|
||||
|
||||
html {
|
||||
overscroll-behavior: none;
|
||||
color-scheme: light dark;
|
||||
}
|
||||
|
||||
html.no-forced-scrollbar {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
background-color: var(--j-background-color) !important;
|
||||
}
|
||||
|
||||
.j-splash > img {
|
||||
@@ -13,11 +14,3 @@
|
||||
height: 30% !important;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.j-splash.light {
|
||||
background-color: #f2f2f2 !important;
|
||||
}
|
||||
|
||||
.j-splash.dark {
|
||||
background-color: #111827 !important;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<Teleport to="head">
|
||||
<component is="style" data-jellyfin-css-vars>
|
||||
:root {
|
||||
<template v-if="isLoading">
|
||||
cursor: wait;
|
||||
</template>
|
||||
--j-background-color: rgb(var(--v-theme-background));
|
||||
}
|
||||
</component>
|
||||
</Teleport>
|
||||
<slot />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* TODO: Investigate or propose an RFC to allow style tags inside SFCs
|
||||
*/
|
||||
import { useLoading } from '@/composables/use-loading';
|
||||
|
||||
const { isLoading } = useLoading();
|
||||
</script>
|
||||
@@ -1,14 +1,7 @@
|
||||
import { computed, ref, watch, type ComputedRef } from 'vue';
|
||||
import { computed, shallowRef, type ComputedRef } from 'vue';
|
||||
|
||||
const requests = ref(0);
|
||||
const requests = shallowRef(0);
|
||||
const isLoading = computed(() => requests.value > 0);
|
||||
const cssVarKey = '--j-client-cursor';
|
||||
|
||||
watch(isLoading, () => {
|
||||
isLoading.value
|
||||
? window.document.documentElement.style.setProperty(cssVarKey, 'wait')
|
||||
: window.document.documentElement.style.removeProperty(cssVarKey);
|
||||
});
|
||||
|
||||
/**
|
||||
* Composable for triggering the linear progress that appears at the top of the page
|
||||
|
||||
@@ -15,14 +15,16 @@ const parsedStore = destr<ClientSettingsState>(store);
|
||||
const matchedDarkColorScheme = window.matchMedia(
|
||||
'(prefers-color-scheme: dark)'
|
||||
).matches;
|
||||
let classToApply: 'light' | 'dark' = matchedDarkColorScheme ? 'dark' : 'light';
|
||||
const darkColor = '#111827';
|
||||
const lightColor = '#f2f2f2';
|
||||
let colorToApply: typeof darkColor | typeof lightColor = matchedDarkColorScheme ? darkColor : lightColor;
|
||||
|
||||
if ('darkMode' in parsedStore) {
|
||||
const storeDarkMode = parsedStore.darkMode;
|
||||
|
||||
if (isBool(storeDarkMode)) {
|
||||
classToApply = parsedStore.darkMode === true ? 'dark' : 'light';
|
||||
colorToApply = parsedStore.darkMode === true ? darkColor : lightColor;
|
||||
}
|
||||
}
|
||||
|
||||
document.body.classList.add(classToApply);
|
||||
document.body.style.setProperty('--j-background-color', colorToApply);
|
||||
|
||||
+1
@@ -96,6 +96,7 @@ declare module 'vue' {
|
||||
ItemMenu: typeof import('./../../src/components/Item/ItemMenu.vue')['default']
|
||||
ItemsCarousel: typeof import('./../../src/components/Layout/Carousel/Item/ItemsCarousel.vue')['default']
|
||||
ItemsCarouselTitle: typeof import('./../../src/components/Layout/Carousel/Item/ItemsCarouselTitle.vue')['default']
|
||||
JApp: typeof import('./../../src/components/lib/JApp.vue')['default']
|
||||
JHover: typeof import('./../../src/components/lib/JHover.vue')['default']
|
||||
JImg: typeof import('./../../src/components/lib/JImg.vue')['default']
|
||||
JSafeHtml: typeof import('./../../src/components/lib/JSafeHtml.vue')['default']
|
||||
|
||||
Reference in New Issue
Block a user