mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-04-20 14:12:06 +00:00
fix: touch support for miniplayer and fastforward
Some checks are pending
Check / check (push) Waiting to run
Some checks are pending
Check / check (push) Waiting to run
fix: mobile responsive UI for player episodelist, and settings pages
This commit is contained in:
parent
571efea41e
commit
f078ae8f19
19 changed files with 47 additions and 197 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ui",
|
||||
"version": "6.4.30",
|
||||
"version": "6.4.31",
|
||||
"license": "BUSL-1.1",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.14.4",
|
||||
|
|
@ -73,6 +73,7 @@
|
|||
"js-levenshtein": "^1.1.6",
|
||||
"lucide-svelte": "^0.511.0",
|
||||
"marked": "^15.0.11",
|
||||
"native": "github:hayase-app/native",
|
||||
"p2pt": "github:ThaUnknown/p2pt#modernise",
|
||||
"semver": "^7.7.2",
|
||||
"simple-store-svelte": "^1.0.6",
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ importers:
|
|||
marked:
|
||||
specifier: ^15.0.11
|
||||
version: 15.0.11
|
||||
native:
|
||||
specifier: github:hayase-app/native
|
||||
version: https://codeload.github.com/hayase-app/native/tar.gz/151ca360188ffd431143f1b9ba2f33ae0a87480b
|
||||
p2pt:
|
||||
specifier: github:ThaUnknown/p2pt#modernise
|
||||
version: https://codeload.github.com/ThaUnknown/p2pt/tar.gz/9ad7a56ed6ee43f5664ebad33b803702ee349316
|
||||
|
|
@ -1897,6 +1900,10 @@ packages:
|
|||
engines: {node: ^18 || >=20}
|
||||
hasBin: true
|
||||
|
||||
native@https://codeload.github.com/hayase-app/native/tar.gz/151ca360188ffd431143f1b9ba2f33ae0a87480b:
|
||||
resolution: {tarball: https://codeload.github.com/hayase-app/native/tar.gz/151ca360188ffd431143f1b9ba2f33ae0a87480b}
|
||||
version: 1.0.0
|
||||
|
||||
natural-compare@1.4.0:
|
||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||
|
||||
|
|
@ -4543,6 +4550,8 @@ snapshots:
|
|||
|
||||
nanoid@5.1.5: {}
|
||||
|
||||
native@https://codeload.github.com/hayase-app/native/tar.gz/151ca360188ffd431143f1b9ba2f33ae0a87480b: {}
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
no-case@3.0.4:
|
||||
|
|
|
|||
162
src/app.d.ts
vendored
162
src/app.d.ts
vendored
|
|
@ -1,16 +1,8 @@
|
|||
// See https://kit.svelte.dev/docs/types#app
|
||||
import type { SessionMetadata } from '$lib/components/ui/player/util'
|
||||
import type { Search } from '$lib/modules/anilist/queries'
|
||||
import type { VariablesOf } from 'gql.tada'
|
||||
import type { CompositionEventHandler } from 'svelte/elements'
|
||||
|
||||
// for information about these interfaces
|
||||
export interface AuthResponse {
|
||||
access_token: string
|
||||
expires_in: string // seconds
|
||||
token_type: 'Bearer'
|
||||
}
|
||||
|
||||
export interface Track {
|
||||
selected: boolean
|
||||
enabled: boolean
|
||||
|
|
@ -20,160 +12,6 @@ export interface Track {
|
|||
language: string
|
||||
}
|
||||
|
||||
export interface TorrentFile {
|
||||
name: string
|
||||
hash: string
|
||||
type: string
|
||||
size: number
|
||||
path: string
|
||||
url: string
|
||||
id: number
|
||||
}
|
||||
|
||||
export interface Attachment {
|
||||
filename: string
|
||||
mimetype: string
|
||||
id: number
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface TorrentInfo {
|
||||
name: string
|
||||
progress: number
|
||||
size: {
|
||||
total: number
|
||||
downloaded: number
|
||||
uploaded: number
|
||||
}
|
||||
speed: {
|
||||
down: number
|
||||
up: number
|
||||
}
|
||||
time: {
|
||||
remaining: number
|
||||
elapsed: number
|
||||
}
|
||||
peers: {
|
||||
seeders: number
|
||||
leechers: number
|
||||
wires: number
|
||||
}
|
||||
pieces: {
|
||||
total: number
|
||||
size: number
|
||||
}
|
||||
hash: string
|
||||
}
|
||||
|
||||
export interface PeerInfo {
|
||||
ip: string
|
||||
seeder: boolean
|
||||
client: string
|
||||
progress: number
|
||||
size: {
|
||||
downloaded: number
|
||||
uploaded: number
|
||||
}
|
||||
speed: {
|
||||
down: number
|
||||
up: number
|
||||
}
|
||||
flags: Array<'incoming' | 'outgoing' | 'utp' | 'encrypted'>
|
||||
time: number
|
||||
}
|
||||
|
||||
export interface FileInfo {
|
||||
name: string
|
||||
size: number
|
||||
progress: number
|
||||
selections: number
|
||||
}
|
||||
|
||||
export interface TorrentSettings {
|
||||
torrentPersist: boolean
|
||||
torrentDHT: boolean
|
||||
torrentStreamedDownload: boolean
|
||||
torrentSpeed: number
|
||||
maxConns: number
|
||||
torrentPort: number
|
||||
dhtPort: number
|
||||
torrentPeX: boolean
|
||||
}
|
||||
|
||||
export interface LibraryEntry {
|
||||
mediaID: number
|
||||
episode: number
|
||||
files: number
|
||||
hash: string
|
||||
progress: number
|
||||
date: number
|
||||
size: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface Native {
|
||||
authAL: (url: string) => Promise<AuthResponse>
|
||||
authMAL: (url: string) => Promise<{ code: string, state: string }>
|
||||
restart: () => Promise<void>
|
||||
openURL: (url: string) => Promise<void>
|
||||
share: Navigator['share']
|
||||
minimise: () => Promise<void>
|
||||
maximise: () => Promise<void>
|
||||
focus: () => Promise<void>
|
||||
close: () => Promise<void>
|
||||
selectPlayer: () => Promise<string>
|
||||
selectDownload: () => Promise<string>
|
||||
setAngle: (angle: string) => Promise<void>
|
||||
getLogs: () => Promise<string>
|
||||
getDeviceInfo: () => Promise<unknown>
|
||||
openUIDevtools: () => Promise<void>
|
||||
openTorrentDevtools: () => Promise<void>
|
||||
checkUpdate: () => Promise<void>
|
||||
updateAndRestart: () => Promise<void>
|
||||
updateReady: () => Promise<void>
|
||||
toggleDiscordDetails: (enabled: boolean) => Promise<void>
|
||||
setMediaSession: (metadata: SessionMetadata, mediaId: number) => Promise<void>
|
||||
setPositionState: (state?: MediaPositionState) => Promise<void>
|
||||
setPlayBackState: (paused: 'none' | 'paused' | 'playing') => Promise<void>
|
||||
setActionHandler: (action: MediaSessionAction | 'enterpictureinpicture', handler: MediaSessionActionHandler | null) => void
|
||||
checkAvailableSpace: (_?: unknown) => Promise<number>
|
||||
checkIncomingConnections: (port: number) => Promise<boolean>
|
||||
updatePeerCounts: (hashes: string[]) => Promise<Array<{ hash: string, complete: string, downloaded: string, incomplete: string }>>
|
||||
playTorrent: (id: string, mediaID: number, episode: number) => Promise<TorrentFile[]>
|
||||
library: () => Promise<LibraryEntry[]>
|
||||
attachments: (hash: string, id: number) => Promise<Attachment[]>
|
||||
tracks: (hash: string, id: number) => Promise<Array<{ number: string, language?: string, type: string, header?: string, name?: string }>>
|
||||
subtitles: (hash: string, id: number, cb: (subtitle: { text: string, time: number, duration: number }, trackNumber: number) => void) => Promise<void>
|
||||
errors: (cb: (error: Error) => void) => Promise<void>
|
||||
chapters: (hash: string, id: number) => Promise<Array<{ start: number, end: number, text: string }>>
|
||||
torrentInfo: (hash: string) => Promise<TorrentInfo>
|
||||
peerInfo: (hash: string) => Promise<PeerInfo[]>
|
||||
fileInfo: (hash: string) => Promise<FileInfo[]>
|
||||
protocolStatus: (hash: string) => Promise<{
|
||||
dht: boolean
|
||||
lsd: boolean
|
||||
pex: boolean
|
||||
nat: boolean
|
||||
forwarding: boolean
|
||||
persisting: boolean
|
||||
streaming: boolean
|
||||
}>
|
||||
setDOH: (dns: string) => Promise<void>
|
||||
cachedTorrents: () => Promise<string[]>
|
||||
downloadProgress: (percent: number) => Promise<void>
|
||||
updateSettings: (settings: TorrentSettings) => Promise<void>
|
||||
updateProgress: (cb: (progress: number) => void) => Promise<void>
|
||||
spawnPlayer: (url: string) => Promise<void>
|
||||
setHideToTray: (enabled: boolean) => Promise<void>
|
||||
transparency: (enabled: boolean) => Promise<void>
|
||||
setZoom: (scale: number) => Promise<void>
|
||||
isApp: boolean
|
||||
version: () => Promise<string>
|
||||
navigate: (cb: (data: { target: string, value: string | undefined }) => void) => Promise<void>
|
||||
defaultTransparency: () => boolean
|
||||
debug: (levels: string) => Promise<void>
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
namespace App {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
</script>
|
||||
|
||||
<div class='flex flex-col w-full relative h-full overflow-clip'>
|
||||
<div class='space-y-0.5 px-10 pt-10'>
|
||||
<div class='space-y-0.5 p-3 md:p-10 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!
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import type { ResolvedFile } from './resolver'
|
||||
import type { MediaInfo } from './util'
|
||||
import type { TorrentFile } from '../../../../app'
|
||||
import type { TorrentFile } from 'native'
|
||||
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
import Volume from './volume.svelte'
|
||||
|
||||
import type { ResolvedFile } from './resolver'
|
||||
import type { TorrentFile } from '../../../../app'
|
||||
import type { TorrentFile } from 'native'
|
||||
import type { SvelteMediaTimeRange } from 'svelte/elements'
|
||||
|
||||
import { beforeNavigate, goto } from '$app/navigation'
|
||||
|
|
@ -743,8 +743,8 @@
|
|||
|
||||
<svelte:document bind:fullscreenElement bind:visibilityState use:holdToFF={'key'} />
|
||||
|
||||
<div class='w-full h-full relative content-center bg-black overflow-clip text-left' class:fitWidth class:seeking class:pip={pictureInPictureElement} bind:this={wrapper} on:navigate={resetMove}>
|
||||
<video class='w-full h-full' preload='metadata' class:cursor-none={immersed} class:cursor-pointer={isMiniplayer} class:object-cover={fitWidth} class:opacity-0={$settings.playerDeband || seeking || pictureInPictureElement} class:absolute={$settings.playerDeband} class:top-0={$settings.playerDeband}
|
||||
<div class='w-full h-full relative content-center bg-black overflow-clip text-left touch-none' class:fitWidth class:seeking class:pip={pictureInPictureElement} bind:this={wrapper} on:navigate={resetMove}>
|
||||
<video class='w-full h-full touch-none' preload='metadata' class:cursor-none={immersed} class:cursor-pointer={isMiniplayer} class:object-cover={fitWidth} class:opacity-0={$settings.playerDeband || seeking || pictureInPictureElement} class:absolute={$settings.playerDeband} class:top-0={$settings.playerDeband}
|
||||
use:createSubtitles
|
||||
use:createDeband={$settings.playerDeband}
|
||||
use:holdToFF={'pointer'}
|
||||
|
|
@ -857,7 +857,7 @@
|
|||
<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>
|
||||
<Sheet.Root portal={wrapper}>
|
||||
<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-[550px] sm:max-w-full h-full overflow-y-scroll flex flex-col pb-0 shrink-0 gap-0 bg-black justify-between'>
|
||||
<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'>
|
||||
{#if mediaInfo.media}
|
||||
{#await Promise.all([episodes(mediaInfo.media.id), client.single(mediaInfo.media.id)]) then [eps, media]}
|
||||
{#if media.data?.Media}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import anitomyscript from 'anitomyscript'
|
||||
|
||||
import type { TorrentFile } from '$lib/../app'
|
||||
import type { MediaEdgeFrag } from '$lib/modules/anilist/queries'
|
||||
import type { AnitomyResult } from 'anitomyscript'
|
||||
import type { ResultOf } from 'gql.tada'
|
||||
import type { TorrentFile } from 'native'
|
||||
|
||||
import { client, episodes, type Media } from '$lib/modules/anilist'
|
||||
import { videoRx } from '$lib/utils'
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { writable } from 'simple-store-svelte'
|
|||
import { get } from 'svelte/store'
|
||||
|
||||
import type { ResolvedFile } from './resolver'
|
||||
import type { TorrentFile } from '../../../../app'
|
||||
import type { TorrentFile } from 'native'
|
||||
|
||||
import native from '$lib/modules/native'
|
||||
import { type defaults, settings, SUPPORTS } from '$lib/modules/settings'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { Media } from '$lib/modules/anilist'
|
||||
import type { ResolvedFile } from './resolver'
|
||||
import type { Track } from '../../../../app'
|
||||
import type { SessionMetadata } from 'native'
|
||||
|
||||
export interface Chapter {
|
||||
start: number
|
||||
|
|
@ -8,12 +9,6 @@ export interface Chapter {
|
|||
text: string
|
||||
}
|
||||
|
||||
export interface SessionMetadata {
|
||||
title: string
|
||||
description: string
|
||||
image: string
|
||||
}
|
||||
|
||||
export interface MediaInfo {
|
||||
file: ResolvedFile
|
||||
media: Media
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class={cn('w-full h-full', isMiniplayer && 'z-[49] absolute top-0 left-0 pointer-events-none cursor-grabbing')}
|
||||
<div class={cn('w-full h-full', isMiniplayer && 'z-[49] absolute top-0 left-0 pointer-events-none cursor-grabbing touch-none')}
|
||||
bind:this={wrapper}
|
||||
on:pointerdown={startDragging}
|
||||
on:pointerup|self={endDragging}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { MediaCell, NameCell, StatusCell } from './cells'
|
||||
|
||||
import type { LibraryEntry } from '$lib/../app'
|
||||
import type { LibraryEntry } from 'native'
|
||||
|
||||
import { goto } from '$app/navigation'
|
||||
import * as Table from '$lib/components/ui/table'
|
||||
|
|
|
|||
|
|
@ -11,21 +11,23 @@ import { storage } from './storage'
|
|||
import type { EpisodesResponse } from '../anizip/types'
|
||||
import type { TorrentResult } from 'hayase-extensions'
|
||||
|
||||
import { dev } from '$app/environment'
|
||||
import { options as extensionOptions, saved } from '$lib/modules/extensions'
|
||||
|
||||
// TODO: ember exclusions might not be needed anymore as parser was improved
|
||||
const exclusions = ['DTS', 'TrueHD', '[EMBER]']
|
||||
const isDev = location.hostname === 'localhost'
|
||||
|
||||
const video = document.createElement('video')
|
||||
|
||||
if (!isDev && !video.canPlayType('video/mp4; codecs="hev1.1.6.L93.B0"')) {
|
||||
if (!dev && !video.canPlayType('video/mp4; codecs="hev1.1.6.L93.B0"')) {
|
||||
exclusions.push('HEVC', 'x265', 'H.265')
|
||||
}
|
||||
if (!isDev && !video.canPlayType('audio/mp4; codecs="ac-3"')) {
|
||||
if (!dev && !video.canPlayType('audio/mp4; codecs="ac-3"')) {
|
||||
exclusions.push('AC3', 'AC-3')
|
||||
}
|
||||
if (!('audioTracks' in HTMLVideoElement.prototype)) {
|
||||
exclusions.push('DUAL')
|
||||
exclusions.push('MULTI')
|
||||
}
|
||||
video.remove()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { AuthResponse, Native, TorrentInfo } from '../../app'
|
||||
import type { AuthResponse, Native, TorrentInfo } from 'native'
|
||||
|
||||
import { sleep } from '$lib/utils'
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import { persisted } from 'svelte-persisted-store'
|
|||
import native from '../native'
|
||||
import { w2globby } from '../w2g/lobby'
|
||||
|
||||
import type { TorrentFile, TorrentInfo } from '$lib/../app'
|
||||
import type { Media } from '../anilist'
|
||||
import type { TorrentFile, TorrentInfo } from 'native'
|
||||
|
||||
const defaultTorrentInfo: TorrentInfo = {
|
||||
name: '',
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class='space-y-6 p-10 pb-0 w-full h-full flex flex-col min-w-0'>
|
||||
<div class='space-y-6 p-3 md:p-10 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'>
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
const _list = list
|
||||
</script>
|
||||
|
||||
<div class='flex flex-col items-center w-full h-full overflow-y-auto p-10 min-w-0' use:dragScroll>
|
||||
<div class='flex flex-col items-center w-full h-full overflow-y-auto p-3 md:p-10 min-w-0' use:dragScroll>
|
||||
<div class='space-y-0.5 self-start mb-6'>
|
||||
<h2 class='text-2xl font-bold'>Airing Calendar</h2>
|
||||
<p class='text-muted-foreground'>
|
||||
|
|
@ -138,8 +138,8 @@
|
|||
{#each aggregate($query.data, dayList) as { day, episodes } (day.date)}
|
||||
{@const sameMonth = isSameMonth(now, day.date)}
|
||||
<div>
|
||||
<div class='flex flex-col text-xs py-3 h-48' class:opacity-30={!sameMonth}>
|
||||
{#if !$breakpoints.md}
|
||||
<div class='flex flex-col text-xs py-3 h-24 lg:h-48' class:opacity-30={!sameMonth}>
|
||||
{#if !$breakpoints.lg}
|
||||
<Drawer.Root shouldScaleBackground portal='html'>
|
||||
<Drawer.Trigger class='h-full flex flex-col'>
|
||||
<div class={cn('w-6 h-6 flex items-center justify-center font-bold mx-3', isToday(day.date) && 'bg-[rgb(61,180,242)] rounded-full')}>
|
||||
|
|
@ -185,12 +185,12 @@
|
|||
<ButtonPrimitive.Root class={cn('flex items-center h-4 w-full group mt-1.5 px-3', +episode.airTime < Date.now() && 'opacity-30')} href='/app/anime/{episode.id}'>
|
||||
<div class='font-medium text-nowrap text-ellipsis overflow-hidden pr-2' title={episode.title?.userPreferred}>
|
||||
{#if status}
|
||||
<StatusDot variant={status} class='hidden lg:inline-flex' />
|
||||
<StatusDot variant={status} class='hidden xl:inline-flex' />
|
||||
{/if}
|
||||
{episode.title?.userPreferred}
|
||||
</div>
|
||||
<div class='ml-auto mr-1 text-nowrap hidden lg:inline-flex'>#{episode.episode}</div>
|
||||
<div class='text-neutral-400 group-select:text-neutral-200 ml-auto lg:ml-0'>{format(episode.airTime, 'HH:mm')}</div>
|
||||
<div class='ml-auto mr-1 text-nowrap hidden xl:inline-flex'>#{episode.episode}</div>
|
||||
<div class='text-neutral-400 group-select:text-neutral-200 ml-auto xl:ml-0'>{format(episode.airTime, 'HH:mm')}</div>
|
||||
</ButtonPrimitive.Root>
|
||||
{/each}
|
||||
{#if episodes.length > 6}
|
||||
|
|
@ -204,12 +204,12 @@
|
|||
<ButtonPrimitive.Root class={cn('flex items-center h-4 w-full group', +episode.airTime < Date.now() && 'text-neutral-300')} href='/app/anime/{episode.id}'>
|
||||
<div class='font-medium text-nowrap text-ellipsis overflow-hidden pr-2' title={episode.title?.userPreferred}>
|
||||
{#if status}
|
||||
<StatusDot variant={status} class='hidden lg:inline-flex' />
|
||||
<StatusDot variant={status} class='hidden xl:inline-flex' />
|
||||
{/if}
|
||||
{episode.title?.userPreferred}
|
||||
</div>
|
||||
<div class='ml-auto mr-1 text-nowrap hidden lg:inline-flex'>#{episode.episode}</div>
|
||||
<div class='text-neutral-400 group-select:text-neutral-900 ml-auto lg:ml-0'>{format(episode.airTime, 'HH:mm')}</div>
|
||||
<div class='ml-auto mr-1 text-nowrap hidden xl:inline-flex'>#{episode.episode}</div>
|
||||
<div class='text-neutral-400 group-select:text-neutral-900 ml-auto xl:ml-0'>{format(episode.airTime, 'HH:mm')}</div>
|
||||
</ButtonPrimitive.Root>
|
||||
{/each}
|
||||
</Tooltip.Content>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
]
|
||||
</script>
|
||||
|
||||
<div class='space-y-6 p-10 pb-0 w-full h-full flex flex-col'>
|
||||
<div class='space-y-6 p-3 md:p-10 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'>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
</script>
|
||||
|
||||
<div class='flex flex-col w-full relative h-full overflow-clip'>
|
||||
<div class='space-y-0.5 px-10 pt-10'>
|
||||
<div class='space-y-0.5 p-3 md:p-10 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.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ const config: Config = {
|
|||
center: true,
|
||||
padding: '2rem',
|
||||
screens: {
|
||||
'2xl': '1400px'
|
||||
'2xl': '1400px',
|
||||
xs: '480px'
|
||||
}
|
||||
},
|
||||
extend: {
|
||||
|
|
@ -88,6 +89,10 @@ const config: Config = {
|
|||
},
|
||||
fontFamily: {
|
||||
sans: [...fontFamily.sans]
|
||||
},
|
||||
screens: {
|
||||
'2xl': '1400px',
|
||||
xs: '480px'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue