@@ -23,29 +23,28 @@
|
||||
* Automatically import/export Invidious/Materialious.
|
||||
- Invidious is optional.
|
||||
* Enjoy Materialious without a Invidious instance via our YouTube backend.
|
||||
* Local video fallback if Invidious fails loading videos.
|
||||
- Invidious companion support.
|
||||
- [Invidious API extended integration.](https://github.com/Materialious/api-extended)
|
||||
- Local video fallback if Invidious fails loading videos.
|
||||
- Android TV support.
|
||||
- Support for disabling certificate validation for homelab users.
|
||||
- Sync your watch progress between Invidious sessions.
|
||||
- Watch sync parties.
|
||||
- Sponsorblock built-in.
|
||||
- [Return YouTube Dislike](https://github.com/Anarios/return-youtube-dislike) (RYD) built-in.
|
||||
- [DeArrow](https://github.com/ajayyy/DeArrow) built-in (With local processing fallback).
|
||||
- [DeArrow](https://github.com/ajayyy/DeArrow) built-in.
|
||||
- No ads.
|
||||
- No tracking.
|
||||
- Light/Dark themes.
|
||||
- Custom colour themes.
|
||||
- Integrates with Invidious subscriptions, watch history & more.
|
||||
- Integrates with Invidious subscriptions.
|
||||
- Live stream support.
|
||||
- Dash support.
|
||||
- Chapters.
|
||||
- Audio only mode.
|
||||
- Mini player (PIP.)
|
||||
- Playlists.
|
||||
- PWA support.
|
||||
- YT path redirects (So your redirect plugins should still work!)
|
||||
- YT path redirects.
|
||||
|
||||
# Docker deployment
|
||||
This version of Materialious is feature rich, has its own account system (optional) & is easier to setup.
|
||||
|
||||
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "us.materialio.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 218
|
||||
versionName "1.16.0"
|
||||
versionCode 219
|
||||
versionName "1.16.1"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -83,7 +83,11 @@
|
||||
|
||||
|
||||
|
||||
<release version="1.16.0" date="2026-2-18">
|
||||
|
||||
<release version="1.16.1" date="2026-2-18">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.16.1</url>
|
||||
</release>
|
||||
<release version="1.16.0" date="2026-2-18">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.16.0</url>
|
||||
</release>
|
||||
<release version="1.15.9" date="2026-2-17">
|
||||
|
||||
Generated
+37
-24
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.16.0",
|
||||
"version": "1.16.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "Materialious",
|
||||
"version": "1.16.0",
|
||||
"version": "1.16.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.0",
|
||||
@@ -58,22 +58,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector": {
|
||||
"version": "6.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.6.tgz",
|
||||
"integrity": "sha512-hBaJER6A9MpdG3WgdlOolHmbOYvSk46y7IQN/1+iqiCuUu6iWdQrs9DGKF8ocqsEqWujWf/V7b7vaDgiUmIvUg==",
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz",
|
||||
"integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@asamuzakjp/nwsapi": "^2.3.9",
|
||||
"bidi-js": "^1.0.3",
|
||||
"css-tree": "^3.1.0",
|
||||
"is-potential-custom-element-name": "^1.0.1",
|
||||
"lru-cache": "^11.2.4"
|
||||
"lru-cache": "^11.2.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": {
|
||||
"version": "11.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz",
|
||||
"integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==",
|
||||
"version": "11.2.6",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
|
||||
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
@@ -85,6 +85,18 @@
|
||||
"integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@bramus/specificity": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz",
|
||||
"integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"css-tree": "^3.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"specificity": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@bufbuild/protobuf": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.11.0.tgz",
|
||||
@@ -2788,15 +2800,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cssstyle": {
|
||||
"version": "5.3.7",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz",
|
||||
"integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.0.1.tgz",
|
||||
"integrity": "sha512-IoJs7La+oFp/AB033wBStxNOJt4+9hHMxsXUPANcoXL2b3W4DZKghlJ2cI/eyeRZIQ9ysvYEorVhjrcYctWbog==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@asamuzakjp/css-color": "^4.1.1",
|
||||
"@csstools/css-syntax-patches-for-csstree": "^1.0.21",
|
||||
"@asamuzakjp/css-color": "^4.1.2",
|
||||
"@csstools/css-syntax-patches-for-csstree": "^1.0.26",
|
||||
"css-tree": "^3.1.0",
|
||||
"lru-cache": "^11.2.4"
|
||||
"lru-cache": "^11.2.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
@@ -3142,9 +3154,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "40.2.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-40.2.1.tgz",
|
||||
"integrity": "sha512-0zOeyN8LB1KHIjVV5jyMmQmkqx3J8OkkVlab3p7vOM28jI46blxW7M52Tcdi6X2m5o2jj8ejOlAh5+boL3w8aQ==",
|
||||
"version": "40.4.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-40.4.1.tgz",
|
||||
"integrity": "sha512-N1ZXybQZL8kYemO8vAeh9nrk4mSvqlAO8xs0QCHkXIvRnuB/7VGwEehjvQbsU5/f4bmTKpG+2GQERe/zmKpudQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
@@ -4491,15 +4503,16 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsdom": {
|
||||
"version": "28.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.0.0.tgz",
|
||||
"integrity": "sha512-KDYJgZ6T2TKdU8yBfYueq5EPG/EylMsBvCaenWMJb2OXmjgczzwveRCoJ+Hgj1lXPDyasvrgneSn4GBuR1hYyA==",
|
||||
"version": "28.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz",
|
||||
"integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@acemir/cssom": "^0.9.31",
|
||||
"@asamuzakjp/dom-selector": "^6.7.6",
|
||||
"@asamuzakjp/dom-selector": "^6.8.1",
|
||||
"@bramus/specificity": "^2.4.2",
|
||||
"@exodus/bytes": "^1.11.0",
|
||||
"cssstyle": "^5.3.7",
|
||||
"cssstyle": "^6.0.1",
|
||||
"data-urls": "^7.0.0",
|
||||
"decimal.js": "^10.6.0",
|
||||
"html-encoding-sniffer": "^6.0.0",
|
||||
@@ -4510,7 +4523,7 @@
|
||||
"saxes": "^6.0.0",
|
||||
"symbol-tree": "^3.2.4",
|
||||
"tough-cookie": "^6.0.0",
|
||||
"undici": "^7.20.0",
|
||||
"undici": "^7.21.0",
|
||||
"w3c-xmlserializer": "^5.0.0",
|
||||
"webidl-conversions": "^8.0.1",
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.16.0",
|
||||
"version": "1.16.1",
|
||||
"description": "Modern material design for YouTube and Invidious.",
|
||||
"author": {
|
||||
"name": "Ward Pearce",
|
||||
@@ -45,4 +45,4 @@
|
||||
"capacitor",
|
||||
"electron"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+11
-11
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.15.4",
|
||||
"version": "1.16.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "materialious",
|
||||
"version": "1.15.4",
|
||||
"version": "1.16.1",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.1",
|
||||
@@ -2249,9 +2249,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/core": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.0.0.tgz",
|
||||
"integrity": "sha512-250HTVd/W/KdMygoqaedisvNbHbpbQTN2Hy/8ZYGm1nAqE0Fx7sGss4l0nDg33STxEdDhtVRoL2fIaaiukKseA==",
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.1.0.tgz",
|
||||
"integrity": "sha512-UfMBMWc1v7J+14AhH03QmeNwV3HZx3qnOWhpwnHfzALEwAwlV/itQOQqcasMQYhOHWL0tiymc5ByaLTn7KKQxw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
@@ -2286,9 +2286,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/share": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/share/-/share-8.0.0.tgz",
|
||||
"integrity": "sha512-VU+xT4LFwr4keIC0UKDqGQVAiNlAHwoTMQg8wVVSxtn/k32VOvvtqFfu63qnXr40WKytZWrxJfVESvRjd761yg==",
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/share/-/share-8.0.1.tgz",
|
||||
"integrity": "sha512-3cSBKBCJVon54rKDROP2rqGyeGks4pBh9TbaEk9S375Kbek/ZHe72N50zIa0Vn9Eac/SuhwgehO/mmA4CsUOiw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@capacitor/core": ">=8.0.0"
|
||||
@@ -4299,9 +4299,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/kit": {
|
||||
"version": "2.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.51.0.tgz",
|
||||
"integrity": "sha512-BkcfxVVYmfxHGYLugemb7TWW+y/MNZbxXHXJ141lyyi2ozq0Q4kbqoV0cBGlh7F0vNtCMvfr7UPnxIaBjcP9gg==",
|
||||
"version": "2.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.52.0.tgz",
|
||||
"integrity": "sha512-zG+HmJuSF7eC0e7xt2htlOcEMAdEtlVdb7+gAr+ef08EhtwUsjLxcAwBgUCJY3/5p08OVOxVZti91WfXeuLvsg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.16.0",
|
||||
"version": "1.16.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "npm run patch:github && vite dev",
|
||||
|
||||
@@ -68,6 +68,20 @@ export function setRegion(url: URL): URL {
|
||||
return url;
|
||||
}
|
||||
|
||||
export class HTTPError {
|
||||
msg: string;
|
||||
response: Response;
|
||||
|
||||
constructor(msg: string, response: Response) {
|
||||
this.msg = msg;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.msg;
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchErrorHandle(response: Response): Promise<Response> {
|
||||
if (!response.ok) {
|
||||
let message = 'Internal error';
|
||||
@@ -80,8 +94,9 @@ export async function fetchErrorHandle(response: Response): Promise<Response> {
|
||||
// Continue regardless of error
|
||||
}
|
||||
|
||||
throw Error(
|
||||
`${response.status} - ${response.statusText}\n${decodeURIComponent(response.url)}\n${message}`
|
||||
throw new HTTPError(
|
||||
`${response.status} - ${response.statusText}\n${decodeURIComponent(response.url)}\n${message}`,
|
||||
response
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
|
||||
interface Props {
|
||||
classes?: string;
|
||||
size?: string;
|
||||
}
|
||||
|
||||
let { classes = '' }: Props = $props();
|
||||
let { classes = '', size = '70px' }: Props = $props();
|
||||
|
||||
let fillColor = $state('');
|
||||
|
||||
@@ -35,8 +36,8 @@
|
||||
<svg
|
||||
version="1.1"
|
||||
class={classes}
|
||||
height="100%"
|
||||
width="70px"
|
||||
height={size}
|
||||
width={size}
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="50.17 104.37 109.67 88.27"
|
||||
|
||||
@@ -975,9 +975,11 @@
|
||||
</p>
|
||||
{#if !$isAndroidTvStore}
|
||||
<CaptionSettings {player} video={data.video} />
|
||||
<Settings {player} {playerElement} />
|
||||
<Airplay {playerElement} />
|
||||
<Pip {playerElement} />
|
||||
{#if playerElement}
|
||||
<Settings {player} {playerElement} />
|
||||
<Airplay {playerElement} />
|
||||
<Pip {playerElement} />
|
||||
{/if}
|
||||
<FullscreenToggle {toggleFullscreen} {playerIsFullscreen} />
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script lang="ts">
|
||||
let { playerElement }: { playerElement: HTMLMediaElement | undefined } = $props();
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let { playerElement }: { playerElement: HTMLMediaElement } = $props();
|
||||
|
||||
function hasWebkitShowPlaybackTargetPicker(
|
||||
el: HTMLMediaElement
|
||||
@@ -13,8 +15,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (!playerElement || playerElement.hasAttribute('x-webkit-airplay')) return;
|
||||
onMount(() => {
|
||||
if (playerElement.hasAttribute('x-webkit-airplay')) return;
|
||||
|
||||
if (hasWebkitShowPlaybackTargetPicker(playerElement)) {
|
||||
playerElement.setAttribute('x-webkit-airplay', 'allow');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
let { playerElement }: { playerElement: HTMLMediaElement | undefined } = $props();
|
||||
let { playerElement }: { playerElement: HTMLMediaElement } = $props();
|
||||
</script>
|
||||
|
||||
{#if document.pictureInPictureEnabled}
|
||||
|
||||
@@ -7,10 +7,8 @@
|
||||
import { playbackRates } from '$lib/player/index';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let {
|
||||
player,
|
||||
playerElement
|
||||
}: { player: shaka.Player; playerElement: HTMLMediaElement | undefined } = $props();
|
||||
let { player, playerElement }: { player: shaka.Player; playerElement: HTMLMediaElement } =
|
||||
$props();
|
||||
|
||||
let playerSettings: 'quality' | 'speed' | 'language' | 'root' = $state('root');
|
||||
let playerCurrentVideoTrack: shaka.extern.VideoTrack | undefined = $state(undefined);
|
||||
@@ -22,6 +20,11 @@
|
||||
setActiveVideoTrack();
|
||||
setActiveAudioTrack();
|
||||
});
|
||||
|
||||
player.addEventListener('trackschanged', () => {
|
||||
setActiveVideoTrack();
|
||||
setActiveAudioTrack();
|
||||
});
|
||||
});
|
||||
|
||||
function setActiveVideoTrack() {
|
||||
|
||||
@@ -72,6 +72,7 @@ export async function initI18n(selectedLocale: string = getUserLocale()): Promis
|
||||
await i18next.init(options);
|
||||
|
||||
locale.set(langToLoad);
|
||||
|
||||
_.set(i18next.t.bind(i18next));
|
||||
|
||||
await loadDayjsLocale(selectedLocale);
|
||||
|
||||
@@ -35,10 +35,10 @@ export const playbackRates = [
|
||||
export const playerDoubleTapSeek = 10.0;
|
||||
|
||||
export function goToPreviousVideo(playlistId: string | null) {
|
||||
playerState.set(undefined);
|
||||
|
||||
const previousVideos = get(playerPlaylistHistory);
|
||||
if (previousVideos.length > 1) {
|
||||
playerState.set(undefined);
|
||||
|
||||
goto(
|
||||
resolve('/watch/[videoId]?playlist=[playlistId]', {
|
||||
videoId: previousVideos[1],
|
||||
@@ -50,8 +50,6 @@ export function goToPreviousVideo(playlistId: string | null) {
|
||||
}
|
||||
|
||||
export async function goToNextVideo(video: VideoPlay, playlistId: string | null) {
|
||||
playerState.set(undefined);
|
||||
|
||||
const isAndroidTv = get(isAndroidTvStore);
|
||||
|
||||
if (!playlistId) {
|
||||
@@ -68,6 +66,8 @@ export async function goToNextVideo(video: VideoPlay, playlistId: string | null)
|
||||
return;
|
||||
}
|
||||
|
||||
playerState.set(undefined);
|
||||
|
||||
const playlist = await loadEntirePlaylist(playlistId);
|
||||
const playlistVideoIds = playlist.videos.map((value) => {
|
||||
return value.videoId;
|
||||
|
||||
@@ -375,3 +375,5 @@ export const channelCacheStore: Writable<{
|
||||
displayContent: { [key: string]: ChannelContent };
|
||||
};
|
||||
}> = writable({});
|
||||
|
||||
export const hideSearchStore: Writable<boolean> = writable(false);
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
rawMasterKeyStore,
|
||||
syncPartyPeerStore,
|
||||
themeColorStore,
|
||||
backendInUseStore
|
||||
backendInUseStore,
|
||||
hideSearchStore
|
||||
} from '$lib/store';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import 'beercss';
|
||||
@@ -67,10 +68,6 @@
|
||||
requestAnimationFrame(() => resetScroll());
|
||||
});
|
||||
|
||||
playerState.subscribe(() => {
|
||||
requestAnimationFrame(() => resetScroll());
|
||||
});
|
||||
|
||||
async function login() {
|
||||
if (isOwnBackend()?.internalAuth) {
|
||||
goto(resolve('/internal/login', {}));
|
||||
@@ -241,10 +238,11 @@
|
||||
|
||||
<div class="max m l"></div>
|
||||
|
||||
<div class="m l">
|
||||
<Search />
|
||||
</div>
|
||||
|
||||
{#if !$hideSearchStore}
|
||||
<div class="m l">
|
||||
<Search />
|
||||
</div>
|
||||
{/if}
|
||||
{#if !mobileSearchShow}
|
||||
<div class="max"></div>
|
||||
{/if}
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
<script lang="ts">
|
||||
import ItemsList from '$lib/components/layout/ItemsList.svelte';
|
||||
import { _ } from '$lib/i18n/index';
|
||||
import { feedCacheStore } from '$lib/store';
|
||||
import Logo from '$lib/components/Logo.svelte';
|
||||
import Search from '$lib/components/Search.svelte';
|
||||
import { feedCacheStore, hideSearchStore } from '$lib/store';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
onMount(() => {
|
||||
if (data.popularDisabled) {
|
||||
hideSearchStore.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
hideSearchStore.set(false);
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if data.popularDisabled}
|
||||
<div class="center-align">
|
||||
<div class="center">
|
||||
<div class="space"></div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 24 24"
|
||||
><path
|
||||
style="fill: var(--secondary);"
|
||||
d="M11.25 21.975Q9.3 21.825 7.612 21t-2.937-2.162q-1.25-1.338-1.963-3.1T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12v.475q-.425-.275-.988-.537t-1.037-.438q-.2-3.15-2.488-5.325T12 4q-1.4 0-2.638.45T7.1 5.7l6.125 6.125q-.475.2-.912.463t-.863.562L5.7 7.1q-.8 1.025-1.25 2.263T4 12q0 2.475 1.338 4.438T8.8 19.325q.45.7 1.125 1.425t1.325 1.225ZM17 20q1.475 0 2.738-.675T21.75 17.5q-.75-1.15-2.013-1.825T17 15q-1.475 0-2.738.675T12.25 17.5q.75 1.15 2.013 1.825T17 20Zm0 2q-2.4 0-4.288-1.263T10 17.5q.825-1.975 2.713-3.238T17 13q2.4 0 4.288 1.263T24 17.5q-.825 1.975-2.713 3.238T17 22Zm0-3q-.625 0-1.063-.438T15.5 17.5q0-.625.438-1.063T17 16q.625 0 1.063.438T18.5 17.5q0 .625-.438 1.063T17 19Z"
|
||||
/></svg
|
||||
>
|
||||
<h1>{$_('disabled')}</h1>
|
||||
<p>{$_('popularPageDisabled')}</p>
|
||||
<Logo size="200px" />
|
||||
<h1>Materialious</h1>
|
||||
<Search />
|
||||
</div>
|
||||
{:else}
|
||||
<ItemsList items={$feedCacheStore.popular ?? []} />
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.center {
|
||||
height: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { getPopular } from '$lib/api/index';
|
||||
import { getPopular, HTTPError } from '$lib/api/index';
|
||||
import { isYTBackend } from '$lib/misc';
|
||||
import { feedCacheStore, invidiousInstanceStore } from '$lib/store';
|
||||
import { error } from '@sveltejs/kit';
|
||||
@@ -22,18 +22,18 @@ export async function load() {
|
||||
let popularDisabled: boolean = false;
|
||||
|
||||
if (!popular) {
|
||||
let errorMsg: Error | undefined;
|
||||
let errorObj: HTTPError | undefined;
|
||||
try {
|
||||
popular = await getPopular();
|
||||
} catch (popularError) {
|
||||
errorMsg = popularError as Error;
|
||||
if (popularError instanceof HTTPError) errorObj = popularError;
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
if (errorMsg.toString() === 'Error: Administrator has disabled this endpoint.') {
|
||||
if (errorObj) {
|
||||
if (errorObj.response.status === 403) {
|
||||
popularDisabled = true;
|
||||
} else {
|
||||
throw error(500, errorMsg);
|
||||
throw error(500, errorObj.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -3,7 +3,7 @@ import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
LATEST_VERSION = "1.16.0"
|
||||
LATEST_VERSION = "1.16.1"
|
||||
RELEASE_DATE = datetime.now().strftime("%Y-%-m-%d") # Format: YYYY-M-D
|
||||
|
||||
WORKING_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "materialious")
|
||||
|
||||
Reference in New Issue
Block a user