perf: disable blur and increase native call time on underpowered devices

fix: doubleclick seekbar on androidTV
feat: player button for androidTV
This commit is contained in:
ThaUnknown 2025-07-14 17:08:23 +02:00
parent d8ada044ce
commit ee98dcb58b
No known key found for this signature in database
16 changed files with 42 additions and 17 deletions

View file

@ -1,6 +1,6 @@
{
"name": "ui",
"version": "6.4.36",
"version": "6.4.37",
"license": "BUSL-1.1",
"private": true,
"packageManager": "pnpm@9.14.4",

View file

@ -174,6 +174,7 @@
<div class='font-weight-bold text-2xl font-bold text-ellipsis text-nowrap overflow-hidden pb-2'>{$searchStore.media ? title($searchStore.media) : ''}</div>
<div class='flex items-center relative scale-parent'>
<Input
autofocus={false}
class='pl-9 bg-background select:bg-accent select:text-accent-foreground shadow-sm no-scale placeholder:opacity-50'
placeholder='Filter by text, or paste a magnet link or torrent file to specify a torrent manually'
bind:value={inputText} />

View file

@ -1 +1 @@
<svg name='logo' {...$$props} xml:space='preserve' viewBox='0 0 66.145833 66.145833'><path fill='currentColor' d='M.00000117 61.5156237V4.6302097l66.145831 37.041664v19.84375l-47.624995-26.72291v16.40416zm66.145831-30.42707-23.547916-13.229174 23.547916-13.22917Z' /></svg>
<svg name='logo' {...$$props} on:click xml:space='preserve' viewBox='0 0 66.145833 66.145833'><path fill='currentColor' d='M.00000117 61.5156237V4.6302097l66.145831 37.041664v19.84375l-47.624995-26.72291v16.40416zm66.145831-30.42707-23.547916-13.229174 23.547916-13.22917Z' /></svg>

Before

Width:  |  Height:  |  Size: 274 B

After

Width:  |  Height:  |  Size: 283 B

View file

@ -2,6 +2,7 @@
import { Dialog as DialogPrimitive } from 'bits-ui'
import { fade } from 'svelte/transition'
import { SUPPORTS } from '$lib/modules/settings'
import { cn } from '$lib/utils.js'
type $$Props = DialogPrimitive.OverlayProps
@ -17,6 +18,6 @@
<DialogPrimitive.Overlay
{transition}
{transitionConfig}
class={cn('custom-bg absolute inset-0 z-50 backdrop-blur-sm', className)}
class={cn('custom-bg absolute inset-0 z-50', !SUPPORTS.isUnderPowered && 'backdrop-blur-sm', className)}
{...$$restProps}
/>

View file

@ -1,6 +1,7 @@
<script lang='ts'>
import { Drawer as DrawerPrimitive } from 'vaul-svelte'
import { SUPPORTS } from '$lib/modules/settings'
import { cn } from '$lib/utils.js'
type $$Props = DrawerPrimitive.OverlayProps
@ -12,7 +13,7 @@
<DrawerPrimitive.Overlay
bind:el
class={cn('custom-bg fixed inset-0 z-50 backdrop-blur-sm', className)}
class={cn('custom-bg fixed inset-0 z-50', !SUPPORTS.isUnderPowered && 'backdrop-blur-sm', className)}
{...$$restProps}
>
<slot />

View file

@ -49,7 +49,7 @@
</script>
<div class='flex flex-col w-full relative h-full overflow-clip'>
<div class='space-y-0.5 p-3 md:p-10 mb:pb-0 pb-0'>
<div class='space-y-0.5 p-3 md:p-10 md:pb-0 pb-0'>
<h2 class='text-2xl font-bold'>Global App Chat</h2>
<p class='text-muted-foreground'>
Chat with other users of the app, share your thoughts, ask questions and have fun!

View file

@ -803,7 +803,7 @@
{/await}
{/if}
{#if stats}
<div class='absolute top-10 left-10 backdrop-blur-lg border-white/15 border bg-black/20 pointer-events-auto transition-opacity select:opacity-100 px-3 py-2 rounded'>
<div class='absolute top-10 left-10 border-white/15 border bg-black/60 pointer-events-auto transition-opacity select:opacity-100 px-3 py-2 rounded'>
<button class='absolute right-3 top-1' type='button' use:click={toggleStats}>×</button>
FPS: {stats.fps}<br />
Presented frames: {stats.presented}<br />
@ -816,7 +816,7 @@
Subtitle delay: {subtitleDelay} sec
</div>
{/if}
<Options {wrapper} bind:openSubs {video} {seekTo} {selectAudio} {selectVideo} {fullscreen} {chapters} {subtitles} {videoFiles} {selectFile} {pip} bind:playbackRate bind:subtitleDelay
<Options {wrapper} bind:openSubs {video} {seekTo} {selectAudio} {selectVideo} {fullscreen} {chapters} {subtitles} {videoFiles} {selectFile} {pip} bind:playbackRate bind:subtitleDelay id='player-options-button-top'
class='{$settings.minimalPlayerUI ? 'inline-flex' : 'mobile:inline-flex hidden'} p-3 w-12 h-12 absolute top-4 left-4 bg-black/20 pointer-events-auto transition-opacity select:opacity-100 {immersed && 'opacity-0'}' />
{#if fastForwarding}
<div class='absolute top-10 font-bold text-sm animate-[fade-in_.4s_ease] flex items-center leading-none bg-black/60 px-4 py-2 rounded-2xl'>x2 <FastForward class='ml-2' size='12' fill='currentColor' /></div>
@ -862,7 +862,7 @@
<div class='absolute w-full bottom-0 flex flex-col gradient px-6 py-3 transition-opacity select:opacity-100' class:opacity-0={immersed}>
<div class='flex justify-between gap-12 items-end'>
<div class='flex flex-col gap-2 text-left cursor-pointer'>
<a class='text-white text-lg font-normal leading-none line-clamp-1 hover:text-neutral-300 hover:underline' href='/app/anime/{mediaInfo.media.id}'>{mediaInfo.session.title}</a>
<a class='text-white text-lg font-normal leading-none line-clamp-1 hover:text-neutral-300 hover:underline' href='/app/anime/{mediaInfo.media.id}' data-up='#player-options-button-top'>{mediaInfo.session.title}</a>
<Sheet.Root portal={wrapper} bind:open={episodeListOpen}>
<Sheet.Trigger id='episode-list-button' class='text-[rgba(217,217,217,0.6)] hover:text-neutral-500 text-sm leading-none font-light line-clamp-1 text-left hover:underline'>{mediaInfo.session.description}</Sheet.Trigger>
<Sheet.Content class='w-full sm:w-[550px] p-3 sm:p-6 max-w-full sm:max-w-full h-full overflow-y-scroll flex flex-col pb-0 shrink-0 gap-0 bg-black justify-between'>

View file

@ -38,6 +38,7 @@
const dispatch = createEventDispatcher<{
seeking: null
seeked: null
dblclick: MouseEvent
}>()
// state
export let chapters: Chapter[] = []
@ -125,6 +126,15 @@
export let thumbnailer: Thumbnailer
$: seekIndex = Math.max(0, Math.floor(seekTime / thumbnailer.interval))
let lastDbl = 0
function customDoubleClick (e: MouseEvent) {
const now = Date.now()
if (now - lastDbl < 300) {
dispatch('dblclick', e)
}
lastDbl = now
}
</script>
<div class='w-full flex cursor-pointer relative group/seekbar touch-none !transform-none' class:!cursor-grab={seeking}
@ -132,8 +142,8 @@
id='player-seekbar'
data-down='#player-play-pause-button'
data-up='#episode-list-button'
on:dblclick
on:keydown
on:click={customDoubleClick}
bind:this={seekbar}
on:pointerdown={startSeeking}
on:pointerup={endSeeking}

View file

@ -2,6 +2,7 @@
import { Dialog as SheetPrimitive } from 'bits-ui'
import { fade } from 'svelte/transition'
import { SUPPORTS } from '$lib/modules/settings'
import { cn } from '$lib/utils.js'
type $$Props = SheetPrimitive.OverlayProps
@ -17,6 +18,6 @@
<SheetPrimitive.Overlay
{transition}
{transitionConfig}
class={cn('custom-bg absolute inset-0 z-50 backdrop-blur-sm', className)}
class={cn('custom-bg absolute inset-0 z-50', !SUPPORTS.isUnderPowered && 'backdrop-blur-sm', className)}
{...$$restProps}
/>

View file

@ -4,6 +4,7 @@
import House from 'lucide-svelte/icons/house'
import LogIn from 'lucide-svelte/icons/log-in'
import MessagesSquare from 'lucide-svelte/icons/messages-square'
import Play from 'lucide-svelte/icons/play'
import Search from 'lucide-svelte/icons/search'
import Settings from 'lucide-svelte/icons/settings'
import Users from 'lucide-svelte/icons/users'
@ -14,6 +15,7 @@
import SidebarButton from './SidebarButton.svelte'
import { goto } from '$app/navigation'
import { page } from '$app/stores'
import Logo from '$lib/components/icons/Logo.svelte'
import * as Avatar from '$lib/components/ui/avatar'
@ -39,7 +41,12 @@
<svelte:document bind:visibilityState />
<BannerImage class='absolute top-0 left-0 w-14 -z-10 hidden md:block' />
<Logo class={cn('mb-3 h-10 object-contain px-2.5 hidden md:block text-white ml-2', isMac && 'mt-3')} />
<Logo class={cn('mb-3 h-10 object-contain px-2.5 hidden md:block text-white ml-2 cursor-pointer', isMac && 'mt-3')} on:click={() => goto('/app/home/')} />
{#if SUPPORTS.isAndroidTV}
<SidebarButton href='/app/player/' class='hidden md:flex py-0'>
<Play size={16} />
</SidebarButton>
{/if}
<SidebarButton href='/app/home/'>
<House size={18} />
</SidebarButton>

View file

@ -2,5 +2,6 @@ export default {
isAndroid: typeof navigator !== 'undefined' && navigator.userAgent.includes('Android'),
isAndroidTV: typeof navigator !== 'undefined' && navigator.userAgent.includes('AndroidTV'),
// @ts-expect-error yeah
// 32 bit, <4GB of RAM, or any Android TV
isUnderPowered: typeof navigator !== 'undefined' && (navigator.platform === 'Linux armv8l' || navigator.deviceMemory < 4 || navigator.userAgent.includes('AndroidTV'))
}

View file

@ -3,6 +3,7 @@ import { get } from 'svelte/store'
import { persisted } from 'svelte-persisted-store'
import native from '../native'
import { SUPPORTS } from '../settings'
import { w2globby } from '../w2g/lobby'
import type { Media } from '../anilist'
@ -26,7 +27,7 @@ export const server = new class ServerClient {
active = writable<Promise<{ media: Media, id: string, episode: number, files: TorrentFile[] } | null>>()
downloaded = writable(this.cachedSet())
stats = this._timedSafeReadable(defaultTorrentInfo, native.torrentInfo, 200)
stats = this._timedSafeReadable(defaultTorrentInfo, native.torrentInfo, SUPPORTS.isUnderPowered ? 3000 : 200)
protocol = this._timedSafeReadable(defaultProtocolStatus, native.protocolStatus)
@ -36,7 +37,7 @@ export const server = new class ServerClient {
library = this._timedSafeReadable([], native.library, 120_000)
_timedSafeReadable<T> (defaultData: T, fn: (id: string) => Promise<T>, duration = 5000) {
_timedSafeReadable<T> (defaultData: T, fn: (id: string) => Promise<T>, duration = SUPPORTS.isUnderPowered ? 15000 : 5000) {
return readable<T>(defaultData, set => {
let listener = 0

View file

@ -47,4 +47,6 @@
<Online />
<slot />
</div>
<Backplate {root} />
{#if !SUPPORTS.isAndroid}
<Backplate {root} />
{/if}

View file

@ -47,7 +47,7 @@
}
</script>
<div class='space-y-6 p-3 md:p-10 mb:pb-0 pb-0 w-full h-full flex flex-col min-w-0'>
<div class='space-y-6 p-3 md:p-10 md:pb-0 pb-0 w-full h-full flex flex-col min-w-0'>
<div class='space-y-0.5'>
<h2 class='text-2xl font-bold'>{overview.title}</h2>
<p class='text-muted-foreground'>

View file

@ -38,7 +38,7 @@
]
</script>
<div class='space-y-6 p-3 md:p-10 mb:pb-0 pb-0 w-full h-full flex flex-col'>
<div class='space-y-6 p-3 md:p-10 md:pb-0 pb-0 w-full h-full flex flex-col'>
<div class='space-y-0.5'>
<h2 class='text-2xl font-bold'>Settings</h2>
<p class='text-muted-foreground'>

View file

@ -57,7 +57,7 @@
</script>
<div class='flex flex-col w-full relative h-full overflow-clip'>
<div class='space-y-0.5 p-3 md:p-10 mb:pb-0 pb-0'>
<div class='space-y-0.5 p-3 md:p-10 md:pb-0 pb-0'>
<h2 class='text-2xl font-bold'>Watch Together <span class='text-muted-foreground text-lg ml-4 font-semibold'>{$w2globby?.code}</span></h2>
<p class='text-muted-foreground'>
Watch videos together with friends in real-time. You can invite others to your lobby and chat while watching.