@@ -7,8 +7,8 @@ android {
|
||||
applicationId "us.materialio.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 8
|
||||
versionName "1.0.8"
|
||||
versionCode 9
|
||||
versionName "1.0.9"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.0.8",
|
||||
"version": "1.0.9",
|
||||
"description": "Modern material design for Invidious.",
|
||||
"author": {
|
||||
"name": "Ward Pearce",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.0.8",
|
||||
"version": "1.0.9",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
instanceStore,
|
||||
returnYTDislikesInstanceStore,
|
||||
synciousInstanceStore
|
||||
} from '../../store';
|
||||
} from '../store';
|
||||
import type {
|
||||
Channel,
|
||||
ChannelContentPlaylists,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
export let comment: Comment;
|
||||
export let videoId: string;
|
||||
|
||||
let replies: Comments;
|
||||
let replies: Comments | undefined = undefined;
|
||||
|
||||
async function loadReplies(continuation: string) {
|
||||
try {
|
||||
@@ -18,6 +18,16 @@
|
||||
});
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function commentTimestamps(html: string): string {
|
||||
const regex =
|
||||
/<a href="([^"]+)" data-onclick="jump_to_time" data-jump-time="(\d+)">(\d+:\d+(?::\d+)?)<\/a>\s*(.+)/;
|
||||
const replacement = `<a href="/watch/${videoId}?time=$2" data-sveltekit-preload-data="off" class="link">$3</a>`;
|
||||
|
||||
const processedHtml = html.replace(regex, replacement);
|
||||
|
||||
return processedHtml;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="comment">
|
||||
@@ -42,7 +52,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
<p style="margin-bottom: 0;">
|
||||
{@html comment.contentHtml}
|
||||
{@html commentTimestamps(comment.contentHtml)}
|
||||
</p>
|
||||
<div style="display: flex;">
|
||||
<p><i>thumb_up</i> {numberWithCommas(comment.likeCount)}</p>
|
||||
@@ -75,6 +85,11 @@
|
||||
<i class="primary-text">expand_more</i>
|
||||
<span class="primary-text">{comment.replies.replyCount} {$_('replies')}</span>
|
||||
</button>
|
||||
{:else if replies}
|
||||
<button on:click={() => (replies = undefined)} class="transparent replies">
|
||||
<i class="primary-text">expand_less</i>
|
||||
<span class="primary-text">{$_('hideReplies')}</span>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { get } from 'svelte/store';
|
||||
import { miniPlayerSrcStore, playerProxyVideosStore } from '../store';
|
||||
import { proxyVideoUrl } from './misc';
|
||||
import { miniPlayerSrcStore, playerProxyVideosStore } from './store';
|
||||
|
||||
let currentTime: number = 0;
|
||||
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
<script lang="ts">
|
||||
import 'vidstack/bundle';
|
||||
|
||||
import { App } from '@capacitor/app';
|
||||
import { page } from '$app/stores';
|
||||
import type { Page } from '@sveltejs/kit';
|
||||
import { SponsorBlock, type Category } from 'sponsorblock-api';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import type { MediaTimeUpdateEvent, PlayerSrc, VideoSrc } from 'vidstack';
|
||||
import type { MediaPlayerElement } from 'vidstack/elements';
|
||||
import { deleteVideoProgress, getVideoProgress, saveVideoProgress } from './Api';
|
||||
import type { VideoPlay } from './Api/model';
|
||||
import { getBestThumbnail, proxyVideoUrl, videoLength, type PhasedDescription } from './misc';
|
||||
import {
|
||||
authStore,
|
||||
instanceStore,
|
||||
miniPlayerSrcStore,
|
||||
playerAlwaysLoopStore,
|
||||
playerAndroidBackgroundPlayStore,
|
||||
playerAutoPlayStore,
|
||||
playerDashStore,
|
||||
playerProxyVideosStore,
|
||||
@@ -21,22 +24,34 @@
|
||||
sponsorBlockCategoriesStore,
|
||||
sponsorBlockUrlStore,
|
||||
synciousStore
|
||||
} from '../store';
|
||||
import { deleteVideoProgress, getVideoProgress, saveVideoProgress } from './Api';
|
||||
import type { VideoPlay } from './Api/model';
|
||||
import { getBestThumbnail, proxyVideoUrl, videoLength, type PhasedDescription } from './misc';
|
||||
} from './store';
|
||||
import { getDynamicTheme } from './theme';
|
||||
|
||||
export let data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null };
|
||||
export let audioMode = false;
|
||||
export let player: MediaPlayerElement;
|
||||
export let isSyncing: boolean = false;
|
||||
export let isEmbed: boolean = false;
|
||||
|
||||
let src: PlayerSrc = [];
|
||||
let categoryBeingSkipped = '';
|
||||
let playerIsLive = false;
|
||||
let playerPosSet = false;
|
||||
|
||||
function loadTimeFromUrl(page: Page): boolean {
|
||||
if (player) {
|
||||
const timeGivenUrl = page.url.searchParams.get('time');
|
||||
if (timeGivenUrl && !isNaN(parseFloat(timeGivenUrl))) {
|
||||
player.currentTime = Number(timeGivenUrl);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
page.subscribe((pageUpdate) => loadTimeFromUrl(pageUpdate));
|
||||
|
||||
export function seekTo(time: number) {
|
||||
if (typeof player !== 'undefined') {
|
||||
player.currentTime = time;
|
||||
@@ -123,11 +138,11 @@
|
||||
}
|
||||
|
||||
if (get(playerDashStore)) {
|
||||
src = [{ src: data.video.dashUrl + '?local=true', type: 'application/dash+xml' }];
|
||||
|
||||
player.addEventListener('dash-can-play', async () => {
|
||||
await loadPlayerPos();
|
||||
});
|
||||
|
||||
src = [{ src: data.video.dashUrl + '?local=true', type: 'application/dash+xml' }];
|
||||
} else {
|
||||
let formattedSrc;
|
||||
src = data.video.formatStreams.map((format) => {
|
||||
@@ -193,12 +208,7 @@
|
||||
if (playerPosSet) return;
|
||||
playerPosSet = true;
|
||||
|
||||
const paramTime = new URLSearchParams(window.location.search).get('time');
|
||||
|
||||
if (paramTime && !isNaN(parseFloat(paramTime))) {
|
||||
player.currentTime = Number(paramTime);
|
||||
return;
|
||||
}
|
||||
if (loadTimeFromUrl($page)) return;
|
||||
|
||||
let toSetTime = 0;
|
||||
|
||||
@@ -250,19 +260,6 @@
|
||||
player.destroy();
|
||||
playerPosSet = false;
|
||||
});
|
||||
|
||||
// Background play for Android.
|
||||
App.addListener('appStateChange', (state) => {
|
||||
// Very much backwards logic, but for whatever reason
|
||||
// Calling play() within a conditional breaks background play.
|
||||
// Maybe a race condition.
|
||||
|
||||
player.play();
|
||||
|
||||
if (!get(playerAndroidBackgroundPlayStore)) {
|
||||
player.pause();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if audioMode}
|
||||
@@ -294,9 +291,11 @@
|
||||
{/if}
|
||||
</media-player>
|
||||
|
||||
<div class="snackbar" id="sponsorblock-alert">
|
||||
<span
|
||||
>{$_('skipping')}
|
||||
<span class="bold" style="text-transform: capitalize;">{categoryBeingSkipped}</span></span
|
||||
>
|
||||
</div>
|
||||
{#if !isEmbed}
|
||||
<div class="snackbar" id="sponsorblock-alert">
|
||||
<span
|
||||
>{$_('skipping')}
|
||||
<span class="bold" style="text-transform: capitalize;">{categoryBeingSkipped}</span></span
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
import Mousetrap from 'mousetrap';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { interfaceSearchSuggestionsStore } from '../store';
|
||||
import { getSearchSuggestions } from './Api';
|
||||
import { interfaceSearchSuggestionsStore } from './store';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
if (search.trim() === '') return;
|
||||
|
||||
selectedSuggestionIndex = -1;
|
||||
goto(`/search/${encodeURIComponent(search)}`);
|
||||
dispatch('searchSubmitted');
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { ensureNoTrailingSlash } from './misc';
|
||||
import {
|
||||
authStore,
|
||||
darkModeStore,
|
||||
@@ -30,8 +31,7 @@
|
||||
synciousInstanceStore,
|
||||
synciousStore,
|
||||
themeColorStore
|
||||
} from '../store';
|
||||
import { ensureNoTrailingSlash } from './misc';
|
||||
} from './store';
|
||||
|
||||
let sponsorCategoriesList: string[] = [];
|
||||
sponsorBlockCategoriesStore.subscribe((value) => (sponsorCategoriesList = value));
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { syncPartyConnectionsStore, syncPartyPeerStore } from '../store';
|
||||
import { syncPartyConnectionsStore, syncPartyPeerStore } from './store';
|
||||
|
||||
function changeVideoEvent(conn: DataConnection) {
|
||||
conn.on('data', (data) => {
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { getDeArrow, getThumbnail, getVideo, getVideoProgress } from './Api';
|
||||
import type { Notification, PlaylistPageVideo, Video, VideoBase, VideoPlay } from './Api/model';
|
||||
import ShareVideo from './ShareVideo.svelte';
|
||||
import { cleanNumber, getBestThumbnail, proxyVideoUrl, videoLength } from './misc';
|
||||
import type { PlayerEvents } from './player';
|
||||
import {
|
||||
authStore,
|
||||
deArrowEnabledStore,
|
||||
@@ -11,12 +16,7 @@
|
||||
syncPartyConnectionsStore,
|
||||
syncPartyPeerStore,
|
||||
synciousStore
|
||||
} from '../store';
|
||||
import { getDeArrow, getThumbnail, getVideo, getVideoProgress } from './Api';
|
||||
import type { Notification, PlaylistPageVideo, Video, VideoBase, VideoPlay } from './Api/model';
|
||||
import ShareVideo from './ShareVideo.svelte';
|
||||
import { cleanNumber, getBestThumbnail, proxyVideoUrl, videoLength } from './misc';
|
||||
import type { PlayerEvents } from './player';
|
||||
} from './store';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -238,12 +238,7 @@
|
||||
</video>
|
||||
</div>
|
||||
{:else}
|
||||
<img
|
||||
class="responsive"
|
||||
style="max-width: 100%;min-height: 160px;"
|
||||
src={img.src}
|
||||
alt="Thumbnail for video"
|
||||
/>
|
||||
<img class="responsive" src={img.src} alt="Thumbnail for video" />
|
||||
{/if}
|
||||
{:else}
|
||||
<p>{$_('thumbnail.failedToLoadImage')}</p>
|
||||
@@ -339,6 +334,10 @@
|
||||
max-height: 160px;
|
||||
}
|
||||
|
||||
.thumbnail img {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 650px) {
|
||||
.thumbnail {
|
||||
max-height: 100%;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { authStore } from '../store';
|
||||
import { removePlaylistVideo } from './Api';
|
||||
import type { Notification, PlaylistPageVideo, Video, VideoBase } from './Api/model';
|
||||
import Thumbnail from './Thumbnail.svelte';
|
||||
import { authStore } from './store';
|
||||
|
||||
export let videos: VideoBase[] | Video[] | Notification[] | PlaylistPageVideo[] = [];
|
||||
export let oneItemPerRow: boolean = false;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { page } from '$app/stores';
|
||||
import { get } from 'svelte/store';
|
||||
import {
|
||||
darkModeStore,
|
||||
deArrowEnabledStore,
|
||||
@@ -24,7 +23,8 @@ import {
|
||||
synciousInstanceStore,
|
||||
synciousStore,
|
||||
themeColorStore
|
||||
} from '../store';
|
||||
} from '$lib/store';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
const persistedStores = [
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"deleteAllHistory": "Delete all history",
|
||||
"skipping": "Skipping",
|
||||
"replies": "replies",
|
||||
"hideReplies": "Hide replies",
|
||||
"hideVideo": "Hide video",
|
||||
"syncParty": {
|
||||
"userJoined": "User joined your watch party.",
|
||||
|
||||
@@ -3,8 +3,8 @@ import { page } from '$app/stores';
|
||||
import humanNumber from 'human-number';
|
||||
import type Peer from 'peerjs';
|
||||
import { get } from 'svelte/store';
|
||||
import { instanceStore } from '../store';
|
||||
import type { Image } from './Api/model';
|
||||
import { instanceStore } from './store';
|
||||
|
||||
export function truncate(value: string, maxLength: number = 50): string {
|
||||
return value.length > maxLength ? `${value.substring(0, maxLength)}...` : value;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script src="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { activePageStore } from '../store';
|
||||
import { activePageStore } from '$lib/store';
|
||||
|
||||
activePageStore.set(null);
|
||||
</script>
|
||||
+13
-11
@@ -11,6 +11,14 @@
|
||||
import SyncParty from '$lib/SyncParty.svelte';
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
import { bookmarkletLoadFromUrl, loadSettingsFromEnv } from '$lib/externalSettings';
|
||||
import {
|
||||
activePageStore,
|
||||
authStore,
|
||||
darkModeStore,
|
||||
instanceStore,
|
||||
syncPartyPeerStore,
|
||||
themeColorStore
|
||||
} from '$lib/store';
|
||||
import { App } from '@capacitor/app';
|
||||
import { Browser } from '@capacitor/browser';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
@@ -20,14 +28,6 @@
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { pwaInfo } from 'virtual:pwa-info';
|
||||
import {
|
||||
activePageStore,
|
||||
authStore,
|
||||
darkModeStore,
|
||||
instanceStore,
|
||||
syncPartyPeerStore,
|
||||
themeColorStore
|
||||
} from '../store';
|
||||
|
||||
let mobileSearchShow = false;
|
||||
|
||||
@@ -191,8 +191,10 @@
|
||||
><i>menu</i></button
|
||||
>
|
||||
|
||||
<Logo classes="m l" />
|
||||
<h6 class="l">Materialious</h6>
|
||||
<nav on:click={() => goto('/')} style="cursor: pointer;" class="m l">
|
||||
<Logo />
|
||||
<h6 class="l">Materialious</h6>
|
||||
</nav>
|
||||
|
||||
<div class="max m l"></div>
|
||||
|
||||
@@ -271,7 +273,7 @@
|
||||
|
||||
<dialog class="left small" id="menu-expanded">
|
||||
<header class="fixed">
|
||||
<nav>
|
||||
<nav on:click={() => goto('/')} style="cursor: pointer;">
|
||||
<button class="transparent circle large" data-ui="#menu-expanded"><i>menu</i></button>
|
||||
<div style="width: 20%;">
|
||||
<Logo />
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import VideoList from '$lib/VideoList.svelte';
|
||||
import { activePageStore } from '../store';
|
||||
import { activePageStore } from '$lib/store';
|
||||
|
||||
export let data;
|
||||
|
||||
+1
-1
@@ -2,8 +2,8 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import PageLoading from '$lib/PageLoading.svelte';
|
||||
import { authStore } from '$lib/store';
|
||||
import { onMount } from 'svelte';
|
||||
import { authStore } from '../../store';
|
||||
|
||||
// Auth response handling for Desktop
|
||||
onMount(() => {
|
||||
+1
-1
@@ -5,12 +5,12 @@
|
||||
import PlaylistThumbnail from '$lib/PlaylistThumbnail.svelte';
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
import { cleanNumber, getBestThumbnail } from '$lib/misc';
|
||||
import { activePageStore, authStore } from '$lib/store';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
import { get } from 'svelte/store';
|
||||
import { activePageStore, authStore } from '../../../store';
|
||||
|
||||
export let data;
|
||||
|
||||
+1
-1
@@ -3,12 +3,12 @@
|
||||
import type { VideoPlay } from '$lib/Api/model';
|
||||
import PageLoading from '$lib/PageLoading.svelte';
|
||||
import VideoList from '$lib/VideoList.svelte';
|
||||
import { activePageStore, synciousStore } from '$lib/store';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
import { get } from 'svelte/store';
|
||||
import { activePageStore, synciousStore } from '../../store';
|
||||
|
||||
activePageStore.set('history');
|
||||
|
||||
+1
-1
@@ -3,10 +3,10 @@
|
||||
import type { PlaylistPageVideo } from '$lib/Api/model.js';
|
||||
import VideoList from '$lib/VideoList.svelte';
|
||||
import { cleanNumber, unsafeRandomItem } from '$lib/misc.js';
|
||||
import { activePageStore, playlistSettingsStore } from '$lib/store';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { activePageStore, playlistSettingsStore } from '../../../store';
|
||||
|
||||
export let data;
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { deletePersonalPlaylist, getPersonalPlaylists, postPersonalPlaylist } from '$lib/Api';
|
||||
import PlaylistThumbnail from '$lib/PlaylistThumbnail.svelte';
|
||||
import { activePageStore } from '$lib/store';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { activePageStore } from '../../store';
|
||||
|
||||
export let data;
|
||||
|
||||
+1
-1
@@ -4,9 +4,9 @@
|
||||
import PageLoading from '$lib/PageLoading.svelte';
|
||||
import PlaylistThumbnail from '$lib/PlaylistThumbnail.svelte';
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
import { activePageStore } from '$lib/store';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
import { activePageStore } from '../../../store';
|
||||
|
||||
export let data;
|
||||
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { getFeed } from '$lib/Api/index.js';
|
||||
import VideoList from '$lib/VideoList.svelte';
|
||||
import { activePageStore } from '$lib/store';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
import { activePageStore } from '../../store';
|
||||
|
||||
export let data;
|
||||
|
||||
+3
-2
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { deleteUnsubscribe } from '$lib/Api';
|
||||
import { activePageStore } from '$lib/store';
|
||||
import Fuse from 'fuse.js';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { activePageStore } from '../../../store';
|
||||
|
||||
activePageStore.set(null);
|
||||
|
||||
@@ -48,11 +48,12 @@
|
||||
{#each subscriptions as sub}
|
||||
<article>
|
||||
<nav>
|
||||
<a href={`/channel/${sub.authorId}`} style="flex: 1;"
|
||||
<a href={`/channel/${sub.authorId}`}
|
||||
><h6>
|
||||
{sub.author}
|
||||
</h6></a
|
||||
>
|
||||
<div class="max"></div>
|
||||
<button on:click={async () => unsubscribe(sub.authorId)} class="border">Unsubscribe</button>
|
||||
</nav>
|
||||
</article>
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import VideoList from '$lib/VideoList.svelte';
|
||||
import { activePageStore } from '../../store';
|
||||
import { activePageStore } from '$lib/store';
|
||||
|
||||
export let data;
|
||||
|
||||
+9
-2
@@ -4,12 +4,19 @@ import { error } from '@sveltejs/kit';
|
||||
export async function load({ url }) {
|
||||
const videoId = url.searchParams.get('v');
|
||||
const playlistId = url.searchParams.get('list');
|
||||
const timestamp = url.searchParams.get('t');
|
||||
|
||||
if (videoId) {
|
||||
let goToUrl = `/watch/${videoId}`;
|
||||
let goToUrl = new URL(`${location.origin}/watch/${videoId}`);
|
||||
|
||||
if (playlistId) {
|
||||
goToUrl += `?playlist=${playlistId}`;
|
||||
goToUrl.searchParams.set('playlist', playlistId);
|
||||
}
|
||||
|
||||
if (timestamp) {
|
||||
goToUrl.searchParams.set('time', timestamp);
|
||||
}
|
||||
|
||||
goto(goToUrl);
|
||||
} else {
|
||||
error(404);
|
||||
+11
-6
@@ -16,11 +16,6 @@
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
import { cleanNumber, getBestThumbnail, numberWithCommas, unsafeRandomItem } from '$lib/misc';
|
||||
import type { PlayerEvents } from '$lib/player';
|
||||
import type { DataConnection } from 'peerjs';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import type { MediaPlayerElement } from 'vidstack/elements';
|
||||
import {
|
||||
activePageStore,
|
||||
authStore,
|
||||
@@ -32,7 +27,12 @@
|
||||
playlistSettingsStore,
|
||||
syncPartyConnectionsStore,
|
||||
syncPartyPeerStore
|
||||
} from '../../../store';
|
||||
} from '$lib/store';
|
||||
import type { DataConnection } from 'peerjs';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import type { MediaPlayerElement } from 'vidstack/elements';
|
||||
|
||||
export let data;
|
||||
|
||||
@@ -461,6 +461,11 @@
|
||||
<span>{cleanNumber(returnYTDislikes.dislikes)}</span>
|
||||
</button>
|
||||
</nav>
|
||||
{:else}
|
||||
<button style="cursor: default;" class="border">
|
||||
<i class="small">thumb_up</i>
|
||||
<span>{cleanNumber(data.video.likeCount)}</span>
|
||||
</button>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
+3
-3
@@ -7,14 +7,14 @@ import {
|
||||
postHistory
|
||||
} from '$lib/Api/index.js';
|
||||
import { phaseDescription } from '$lib/misc';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { get } from 'svelte/store';
|
||||
import {
|
||||
authStore,
|
||||
playerProxyVideosStore,
|
||||
returnYTDislikesInstanceStore,
|
||||
returnYtDislikesStore
|
||||
} from '../../../store';
|
||||
} from '$lib/store';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
export async function load({ params, url }) {
|
||||
let video;
|
||||
@@ -0,0 +1,23 @@
|
||||
import { getVideo } from '$lib/Api/index.js';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { get } from 'svelte/store';
|
||||
import type { PhasedDescription } from '../../../../lib/misc.js';
|
||||
import { playerProxyVideosStore } from '../../../../lib/store.js';
|
||||
|
||||
export async function load({ params }) {
|
||||
let video;
|
||||
try {
|
||||
video = await getVideo(params.slug, get(playerProxyVideosStore));
|
||||
} catch (errorMessage: any) {
|
||||
error(500, errorMessage);
|
||||
}
|
||||
|
||||
return {
|
||||
video: video,
|
||||
content: {
|
||||
description: '',
|
||||
timestamps: []
|
||||
} as PhasedDescription,
|
||||
playlistId: null
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import Player from '$lib/Player.svelte';
|
||||
import type { MediaPlayerElement } from 'vidstack/elements';
|
||||
|
||||
export let data;
|
||||
export let layout = false;
|
||||
|
||||
let player: MediaPlayerElement;
|
||||
</script>
|
||||
|
||||
<Player bind:player isEmbed={true} {data} />
|
||||
+1
-1
@@ -5,7 +5,7 @@ import json
|
||||
import os
|
||||
import re
|
||||
|
||||
LATEST_VERSION = "1.0.8"
|
||||
LATEST_VERSION = "1.0.9"
|
||||
WORKING_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "materialious")
|
||||
|
||||
ROOT_PACKAGE = os.path.join(WORKING_DIR, "package.json")
|
||||
|
||||
Reference in New Issue
Block a user