+
{/if}
diff --git a/src/lib/components/ui/player/player.svelte b/src/lib/components/ui/player/player.svelte
index 47ed91b..f5e83a3 100644
--- a/src/lib/components/ui/player/player.svelte
+++ b/src/lib/components/ui/player/player.svelte
@@ -31,6 +31,7 @@
import EpisodesList from '$lib/components/EpisodesList.svelte'
import { episodes } from '$lib/modules/anizip'
import { page } from '$app/stores'
+ import { isPlaying } from '$lib/modules/idle'
export let mediaInfo: MediaInfo
export let files: TorrentFile[]
@@ -64,6 +65,8 @@
let paused = true
const cast = false
+ $: $isPlaying = !paused
+
$: buffering = readyState < 3
$: immersed = !buffering && !seeking && !paused && !ended && !$pictureInPictureElement
diff --git a/src/lib/components/ui/sidebar/sidebarlist.svelte b/src/lib/components/ui/sidebar/sidebarlist.svelte
index b67db9b..d21436f 100644
--- a/src/lib/components/ui/sidebar/sidebarlist.svelte
+++ b/src/lib/components/ui/sidebar/sidebarlist.svelte
@@ -10,12 +10,20 @@
import native from '$lib/modules/native'
import client from '$lib/modules/auth/client'
import * as Avatar from '$lib/components/ui/avatar'
+ import { lockedState, idleState, activityState } from '$lib/modules/idle'
+ import { page } from '$app/stores'
const auth = client.hasAuth
$: hasAuth = $auth
+
+ let visibilityState: DocumentVisibilityState
+
+ $: active = ($lockedState === 'locked' || visibilityState === 'hidden' || ($idleState === 'active' && $activityState === 'active')) && $page.route.id !== '/app/player'
+
+
@@ -38,7 +46,7 @@
diff --git a/src/lib/modules/idle.ts b/src/lib/modules/idle.ts
new file mode 100644
index 0000000..3b835ef
--- /dev/null
+++ b/src/lib/modules/idle.ts
@@ -0,0 +1,47 @@
+import { derived, readable } from 'svelte/store'
+import { writable } from 'simple-store-svelte'
+
+import { page } from '$app/stores'
+
+export const activityState = readable<'active' | 'inactive'>(document.hasFocus() ? 'active' : 'inactive', set => {
+ set(document.hasFocus() ? 'active' : 'inactive')
+ const ctrl = new AbortController()
+
+ window.addEventListener('pointermove', () => set('active'), { signal: ctrl.signal })
+ window.addEventListener('focus', () => set('active'), { signal: ctrl.signal })
+ window.addEventListener('blur', () => set('inactive'), { signal: ctrl.signal })
+
+ document.addEventListener('mouseenter', () => set('active'), { signal: ctrl.signal })
+ document.addEventListener('mouseleave', () => {
+ if (!document.hasFocus()) set('inactive')
+ }, { signal: ctrl.signal })
+
+ return () => ctrl.abort()
+})
+
+// @ts-expect-error non-standard API
+const idleDetector = new IdleDetector()
+idleDetector.start({
+ threshold: 60_000
+})
+
+export const idleState = readable<'active' | 'idle'>(idleDetector.userState, set => {
+ set(idleDetector.userState)
+ const ctrl = new AbortController()
+
+ idleDetector.addEventListener('change', () => set(idleDetector.userState), { signal: ctrl.signal })
+ window.addEventListener('pointermove', () => set('active'), { signal: ctrl.signal })
+
+ return () => ctrl.abort()
+})
+
+export const lockedState = readable<'locked' | 'unlocked'>(idleDetector.screenState, set => {
+ set(idleDetector.screenState)
+ const ctrl = new AbortController()
+
+ idleDetector.addEventListener('change', () => set(idleDetector.screenState), { signal: ctrl.signal })
+
+ return () => ctrl.abort()
+})
+
+export const isPlaying = writable(false)