diff --git a/materialious/package-lock.json b/materialious/package-lock.json
index 39050f8a..8e58d9f7 100644
--- a/materialious/package-lock.json
+++ b/materialious/package-lock.json
@@ -12,6 +12,7 @@
"human-number": "^2.0.4",
"media-icons": "^0.10.0",
"sponsorblock-api": "^0.2.4",
+ "svelte-infinite-loading": "^1.3.8",
"svelte-persisted-store": "^0.9.1",
"vidstack": "^1.11.4"
},
@@ -7142,6 +7143,11 @@
"svelte": "^3.19.0 || ^4.0.0"
}
},
+ "node_modules/svelte-infinite-loading": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/svelte-infinite-loading/-/svelte-infinite-loading-1.3.8.tgz",
+ "integrity": "sha512-hn4o848LKd2Q+M11hiMWnfFxM1GHKVDi92HPZ1FYvfed4bEeRZL+QvFAQzhy1SACq6Si0CAJcQFUZpIYmAEnpQ=="
+ },
"node_modules/svelte-persisted-store": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/svelte-persisted-store/-/svelte-persisted-store-0.9.1.tgz",
diff --git a/materialious/package.json b/materialious/package.json
index 2b2894c5..bc11d80b 100644
--- a/materialious/package.json
+++ b/materialious/package.json
@@ -39,6 +39,7 @@
"human-number": "^2.0.4",
"media-icons": "^0.10.0",
"sponsorblock-api": "^0.2.4",
+ "svelte-infinite-loading": "^1.3.8",
"svelte-persisted-store": "^0.9.1",
"vidstack": "^1.11.4"
}
diff --git a/materialious/src/lib/Comment.svelte b/materialious/src/lib/Comment.svelte
index 72cd0f06..2ebab1d3 100644
--- a/materialious/src/lib/Comment.svelte
+++ b/materialious/src/lib/Comment.svelte
@@ -37,7 +37,7 @@
{/if}
- {comment.content}
+ {@html comment.contentHtml}
thumb_up {numberWithCommas(comment.likeCount)}
diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte
index 53c1faaa..1a77ab34 100644
--- a/materialious/src/lib/Player.svelte
+++ b/materialious/src/lib/Player.svelte
@@ -169,21 +169,9 @@
const currentTheme = await getDynamicTheme();
- document.documentElement.style.setProperty(
- '--video-controls-color',
- currentTheme['--secondary']
- );
- document.documentElement.style.setProperty(
- '--audio-controls-color',
- currentTheme['--secondary']
- );
- document.documentElement.style.setProperty(
- '--audio-play-button-bg',
- currentTheme['--secondary']
- );
document.documentElement.style.setProperty(
'--media-slider-track-fill-bg',
- currentTheme['--secondary']
+ currentTheme['--primary']
);
document.documentElement.style.setProperty('--media-menu-bg', currentTheme['--background']);
document.documentElement.style.setProperty(
@@ -191,12 +179,12 @@
currentTheme['--surface']
);
document.documentElement.style.setProperty(
- '--media-menu-item-color',
- currentTheme['--primary-text']
+ '--media-menu-text-color',
+ currentTheme['--on-background']
);
document.documentElement.style.setProperty(
'--media-menu-item-info-color',
- currentTheme['--primary-text']
+ currentTheme['--on-background']
);
document.documentElement.style.setProperty(
'--media-menu-section-bg',
diff --git a/materialious/src/lib/Thumbnail.svelte b/materialious/src/lib/Thumbnail.svelte
index 951ab8bb..6fb8e6ae 100644
--- a/materialious/src/lib/Thumbnail.svelte
+++ b/materialious/src/lib/Thumbnail.svelte
@@ -38,7 +38,12 @@
});
-
+
{#if loading}
{:else if loaded}
diff --git a/materialious/src/lib/misc.ts b/materialious/src/lib/misc.ts
index aad36367..a8099c05 100644
--- a/materialious/src/lib/misc.ts
+++ b/materialious/src/lib/misc.ts
@@ -40,31 +40,46 @@ export interface PhasedDescription {
export function phaseDescription(content: string): PhasedDescription {
const timestamps: { title: string; time: number; timePretty: string; }[] = [];
+ console.log(content);
const lines = content.split('\n');
- const regex = /(\d+:\d+(?::\d+)?)(?:\s(.+))?/;
- const filteredLines = lines.filter(line => {
- const match = regex.exec(line);
+ const urlRegex = /(\d+:\d+(?::\d+)?)<\/a>\s*(.+)/;
- if (match !== null) {
- const timestamp = match[1];
- const title = match[2] || '';
- timestamps.push({
- time: convertToSeconds(timestamp),
- title: title,
- timePretty: timestamp
- });
- return false;
+ let filteredLines: string[] = [];
+ lines.forEach(
+ (line) => {
+ const urlMatch = urlRegex.exec(line);
+ const timestampMatch = timestampRegex.exec(line);
+
+ if (urlMatch !== null && timestampMatch === null) {
+ // If line contains a URL but not a timestamp, modify the URL
+ const modifiedLine = line.replace(/ parseInt(part));
let seconds = 0;
diff --git a/materialious/src/routes/+layout.svelte b/materialious/src/routes/+layout.svelte
index a066b9f7..6c17fe38 100644
--- a/materialious/src/routes/+layout.svelte
+++ b/materialious/src/routes/+layout.svelte
@@ -535,7 +535,7 @@
{/each}
-
+
diff --git a/materialious/src/routes/+page.svelte b/materialious/src/routes/+page.svelte
index 999922cf..3946b935 100644
--- a/materialious/src/routes/+page.svelte
+++ b/materialious/src/routes/+page.svelte
@@ -1,10 +1,18 @@
-
+{#if data.popularDisabled}
+
+
+
+{:else}
+
+{/if}
diff --git a/materialious/src/routes/+page.ts b/materialious/src/routes/+page.ts
index b3b31184..faea9e87 100644
--- a/materialious/src/routes/+page.ts
+++ b/materialious/src/routes/+page.ts
@@ -1,7 +1,21 @@
import { getPopular } from '$lib/Api/index.js';
+import { error } from '@sveltejs/kit';
-export async function load({ params }) {
+export async function load() {
+ let popular = undefined;
+ let popularDisabled: boolean = false;
+
+ try {
+ popular = await getPopular();
+ } catch (errorMessage: any) {
+ if (errorMessage.toString() === 'Error: Administrator has disabled this endpoint.') {
+ popularDisabled = true;
+ } else {
+ error(500, errorMessage);
+ }
+ }
return {
- popular: await getPopular()
+ popular: popular,
+ popularDisabled: popularDisabled
};
}
\ No newline at end of file
diff --git a/materialious/src/routes/channel/[slug]/+page.svelte b/materialious/src/routes/channel/[slug]/+page.svelte
index 3096b2f3..82a482f0 100644
--- a/materialious/src/routes/channel/[slug]/+page.svelte
+++ b/materialious/src/routes/channel/[slug]/+page.svelte
@@ -5,7 +5,8 @@
import PlaylistThumbnail from '$lib/PlaylistThumbnail.svelte';
import Thumbnail from '$lib/Thumbnail.svelte';
import { cleanNumber } from '$lib/misc';
- import { onDestroy, onMount } from 'svelte';
+ import { onMount } from 'svelte';
+ import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
import { get } from 'svelte/store';
import { activePage, auth } from '../../../store';
@@ -19,22 +20,29 @@
let displayContent: ChannelContentPlaylists | ChannelContentVideos | undefined = undefined;
- async function handleScroll() {
+ async function loadMore(event: InfiniteEvent) {
if (typeof displayContent === 'undefined') return;
- const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
- if (scrollTop + clientHeight >= scrollHeight - 5) {
- const newContent = await getChannelContent(data.channel.authorId, {
- type: tab,
- continuation: displayContent.continuation
- });
- if ('videos' in newContent && 'videos' in displayContent) {
- displayContent.videos = [...displayContent.videos, ...newContent.videos];
- } else if ('playlists' in displayContent && 'playlists' in newContent) {
- displayContent.playlists = [...displayContent.playlists, ...newContent.playlists];
+ const newContent = await getChannelContent(data.channel.authorId, {
+ type: tab,
+ continuation: displayContent.continuation
+ });
+ if ('videos' in newContent && 'videos' in displayContent) {
+ if (displayContent.continuation === newContent.continuation) {
+ event.detail.complete();
+ } else {
+ event.detail.loaded();
}
- displayContent.continuation = newContent.continuation;
+ displayContent.videos = [...displayContent.videos, ...newContent.videos];
+ } else if ('playlists' in displayContent && 'playlists' in newContent) {
+ if (displayContent.continuation === newContent.continuation) {
+ event.detail.complete();
+ } else {
+ event.detail.loaded();
+ }
+ displayContent.playlists = [...displayContent.playlists, ...newContent.playlists];
}
+ displayContent.continuation = newContent.continuation;
}
async function changeTab(newTab: 'videos' | 'playlists' | 'streams' | 'shorts') {
@@ -49,12 +57,6 @@
if (get(auth)) {
isSubscribed = await amSubscribed(data.channel.authorId);
}
-
- window.addEventListener('scroll', handleScroll);
- });
-
- onDestroy(() => {
- window.removeEventListener('scroll', handleScroll);
});
async function toggleSubscribed() {
@@ -144,6 +146,8 @@
{/if}
+
+
{:else}
{/if}
diff --git a/materialious/src/routes/history/+page.svelte b/materialious/src/routes/history/+page.svelte
index ba4328cf..03fba9d4 100644
--- a/materialious/src/routes/history/+page.svelte
+++ b/materialious/src/routes/history/+page.svelte
@@ -3,7 +3,8 @@
import type { VideoPlay } from '$lib/Api/model';
import VideoList from '$lib/VideoList.svelte';
import { error } from '@sveltejs/kit';
- import { onDestroy, onMount } from 'svelte';
+ import { onMount } from 'svelte';
+ import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
import { activePage } from '../../store';
activePage.set('history');
@@ -28,23 +29,21 @@
}
}
- async function handleScroll() {
- const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
- if (scrollTop + clientHeight >= scrollHeight - 5) {
- currentPage += 1;
- await loadPageHistory();
+ async function loadMore(event: InfiniteEvent) {
+ const pastHistoryLen = Number(history.length);
+
+ await loadPageHistory();
+
+ if (pastHistoryLen === history.length) {
+ event.detail.complete();
+ } else {
+ event.detail.loaded();
}
}
onMount(async () => {
await loadPageHistory();
loaded = true;
-
- window.addEventListener('scroll', handleScroll);
- });
-
- onDestroy(() => {
- window.removeEventListener('scroll', handleScroll);
});
@@ -66,3 +65,5 @@
+
+
diff --git a/materialious/src/routes/playlist/[slug]/+page.svelte b/materialious/src/routes/playlist/[slug]/+page.svelte
index caec99a7..3c76517f 100644
--- a/materialious/src/routes/playlist/[slug]/+page.svelte
+++ b/materialious/src/routes/playlist/[slug]/+page.svelte
@@ -4,7 +4,7 @@
import VideoList from '$lib/VideoList.svelte';
import { cleanNumber } from '$lib/misc.js';
import { onMount } from 'svelte';
- import { activePage } from '../../../store.js';
+ import { activePage } from '../../../store';
export let data;
diff --git a/materialious/src/routes/search/[slug]/+page.svelte b/materialious/src/routes/search/[slug]/+page.svelte
index 425a7d7d..ed4ed92f 100644
--- a/materialious/src/routes/search/[slug]/+page.svelte
+++ b/materialious/src/routes/search/[slug]/+page.svelte
@@ -4,7 +4,7 @@
import ChannelThumbnail from '$lib/ChannelThumbnail.svelte';
import PlaylistThumbnail from '$lib/PlaylistThumbnail.svelte';
import Thumbnail from '$lib/Thumbnail.svelte';
- import { onDestroy, onMount } from 'svelte';
+ import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
import { activePage } from '../../../store';
export let data;
@@ -20,24 +20,20 @@
document.location.href = $page.url.href;
}
- async function handleScroll() {
- const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
- if (scrollTop + clientHeight >= scrollHeight - 5) {
- currentPage += 1;
- search = [
- ...search,
- ...(await getSearch(data.slug, { page: currentPage.toString(), type: data.searchType }))
- ];
+ async function loadMore(event: InfiniteEvent) {
+ currentPage++;
+ const newSearch = await getSearch(data.slug, {
+ page: currentPage.toString(),
+ type: data.searchType
+ });
+
+ if (newSearch.length === 0) {
+ event.detail.complete();
+ } else {
+ search = [...search, ...newSearch];
+ event.detail.loaded();
}
}
-
- onMount(() => {
- window.addEventListener('scroll', handleScroll);
- });
-
- onDestroy(() => {
- window.removeEventListener('scroll', handleScroll);
- });
@@ -91,3 +87,5 @@
{/each}
+
+
diff --git a/materialious/src/routes/subscriptions/+page.svelte b/materialious/src/routes/subscriptions/+page.svelte
index d93855a2..81020910 100644
--- a/materialious/src/routes/subscriptions/+page.svelte
+++ b/materialious/src/routes/subscriptions/+page.svelte
@@ -1,32 +1,28 @@
+
+
diff --git a/materialious/src/routes/trending/+page.svelte b/materialious/src/routes/trending/+page.svelte
index 6bc28178..ca6f269b 100644
--- a/materialious/src/routes/trending/+page.svelte
+++ b/materialious/src/routes/trending/+page.svelte
@@ -1,6 +1,6 @@