From d0c8c02a91b982c83a6986afa624174ba35a4346 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Sat, 6 Apr 2024 17:57:18 +1300 Subject: [PATCH 1/3] Improved watch sync --- materialious/src/lib/Thumbnail.svelte | 31 ++++-- materialious/src/routes/+layout.svelte | 73 ++++++++++++- .../src/routes/watch/[slug]/+page.svelte | 102 ++++-------------- materialious/src/store.ts | 7 +- 4 files changed, 121 insertions(+), 92 deletions(-) diff --git a/materialious/src/lib/Thumbnail.svelte b/materialious/src/lib/Thumbnail.svelte index 4a8f6fb1..370d3b62 100644 --- a/materialious/src/lib/Thumbnail.svelte +++ b/materialious/src/lib/Thumbnail.svelte @@ -1,22 +1,27 @@ onClick(video.videoId)} data-sveltekit-preload-data="off" + on:click={syncChangeVideo} > {#if loading} diff --git a/materialious/src/routes/+layout.svelte b/materialious/src/routes/+layout.svelte index aedf6ead..98c29d58 100644 --- a/materialious/src/routes/+layout.svelte +++ b/materialious/src/routes/+layout.svelte @@ -6,9 +6,12 @@ import PageLoading from '$lib/PageLoading.svelte'; import Search from '$lib/Search.svelte'; import Thumbnail from '$lib/Thumbnail.svelte'; + import type { PlayerEvents } from '$lib/player'; import 'beercss'; import 'material-dynamic-colors'; - import { onMount } from 'svelte'; + import type { DataConnection } from 'peerjs'; + import Peer from 'peerjs'; + import { onDestroy, onMount } from 'svelte'; import { get } from 'svelte/store'; import { pwaInfo } from 'virtual:pwa-info'; import { @@ -30,6 +33,8 @@ sponsorBlock, sponsorBlockCategories, sponsorBlockUrl, + syncPartyConnections, + syncPartyPeer, themeColor } from '../store'; @@ -97,6 +102,47 @@ { name: 'Filler Tangent/Jokes', category: 'filler' } ]; + function changeVideoEvent(conn: DataConnection) { + conn.on('data', (data) => { + const events = data as PlayerEvents; + const currentUrl = new URL(location.href); + + events.events.forEach((event) => { + if (event.type === 'change-video' && event.videoId) { + currentUrl.pathname = `/watch/${event.videoId}`; + goto(currentUrl); + } + }); + }); + } + + async function startWatchSync() { + const currentUrl = new URL(location.href); + + if ($syncPartyPeer) { + $syncPartyPeer.disconnect(); + syncPartyPeer.set(null); + currentUrl.searchParams.delete('sync'); + window.history.pushState({ path: currentUrl.toString() }, '', currentUrl.toString()); + return; + } + + const peerId = crypto.randomUUID(); + currentUrl.searchParams.set('sync', peerId); + window.history.pushState({ path: currentUrl.toString() }, '', currentUrl.toString()); + + $syncPartyPeer = new Peer(peerId); + + if ($syncPartyPeer) { + $syncPartyPeer.on('connection', (conn) => { + conn.on('open', () => { + changeVideoEvent(conn); + syncPartyConnections.set([...($syncPartyConnections || []), conn]); + }); + }); + } + } + function toggleSponsor(category: string) { if (sponsorCategoriesList.includes(category)) { sponsorBlockCategories.set(sponsorCategoriesList.filter((value) => value !== category)); @@ -182,6 +228,27 @@ if (isLoggedIn) { loadNotifications().catch(() => auth.set(null)); } + + const currentUrl = new URL(location.href); + const syncId = currentUrl.searchParams.get('sync'); + if (syncId) { + $syncPartyPeer = new Peer(crypto.randomUUID()); + $syncPartyPeer.on('open', () => { + if (!$syncPartyPeer) return; + + const conn = $syncPartyPeer.connect(syncId); + syncPartyConnections.set([...($syncPartyConnections || []), conn]); + + changeVideoEvent(conn); + }); + } + }); + + onDestroy(() => { + if ($syncPartyPeer) { + $syncPartyPeer.disconnect(); + $syncPartyPeer = null; + } }); $: webManifestLink = pwaInfo ? pwaInfo.webManifest.linkTag : ''; @@ -227,6 +294,10 @@ code
Star us on Github!
+ {#if isLoggedIn}