Implemented auto load option

This commit is contained in:
WardPearce
2026-03-05 13:10:29 +13:00
parent 0f872f2eaf
commit 2c84c03caf
6 changed files with 113 additions and 9 deletions
@@ -3,10 +3,16 @@
import { ChannelSchema, VideoSchema, type SchemaStructure } from '$lib/filtering/schemas';
import { _ } from '$lib/i18n';
import { titleCase, camelCaseToHuman } from '$lib/letterCasing';
import { filterContentListStore } from '$lib/store';
import {
filterContentListStore,
filterContentUrlAutoUpdateStore,
filterContentUrlStore
} from '$lib/store';
import type z from 'zod';
import { addToast } from '../Toast.svelte';
import { Clipboard } from '@capacitor/clipboard';
let remoteFilterListUrl: string = $state('');
let remoteFilterListUrl: string = $state($filterContentUrlStore ?? '');
let remoteError: string = $state('');
type FilterType = 'channel' | 'video';
@@ -33,11 +39,33 @@
try {
contentFilters = await loadContentFilterFromURL(remoteFilterListUrl);
filterContentListStore.set(contentFilters);
filterContentUrlStore.set(remoteFilterListUrl);
filterContentUrlAutoUpdateStore.set(false);
} catch (errorMsg) {
remoteError = (errorMsg as Error).message;
}
}
async function exportAsJSON() {
await Clipboard.write({
string: JSON.stringify(
{
version: 'v1',
createdFor: 'materialious',
filterBy: contentFilters
},
null,
2
)
});
addToast({
data: {
text: $_('player.share.copiedSuccess')
}
});
}
function addFilter(type: FilterType) {
if (!contentFilters) contentFilters = [];
@@ -58,6 +86,10 @@
}
</script>
<article class="error-container">
<p>{$_('layout.backendEngine.warning')}</p>
</article>
<form onsubmit={loadFilterList}>
<nav>
<div
@@ -77,7 +109,33 @@
</nav>
</form>
{#if $filterContentUrlStore}
<nav class="no-padding">
<div class="max">
<p>{$_('layout.filter.autoUpdate')}</p>
</div>
<label class="switch" tabindex="0">
<input
bind:checked={$filterContentUrlAutoUpdateStore}
onclick={() => filterContentUrlAutoUpdateStore.set(!$filterContentUrlAutoUpdateStore)}
type="checkbox"
role="switch"
/>
<span></span>
</label>
</nav>
<div class="space"></div>
{/if}
{#if contentFilters}
{#if contentFilters.length > 0}
<button class="surface-container-highest" onclick={exportAsJSON}>
<i>content_copy</i>
<span>{$_('copy')}</span>
</button>
<div class="space"></div>
{/if}
{#each contentFilters as filter (filter)}
<article class="no-margin surface-container-high">
<div class="grid">
@@ -195,7 +253,10 @@
<div class="field label border">
<input
oninput={(event: Event & { currentTarget: HTMLInputElement }) => {
condition.value = event.currentTarget.value;
condition.value =
schema[filter.type][condition.field] === 'number'
? Number(event.currentTarget.value)
: event.currentTarget.value;
filterContentListStore.set(contentFilters);
}}
name="value"
@@ -233,7 +294,7 @@
<i>add</i>
<span>Add filter</span>
</button>
<menu class="min">
<menu>
{#each filterTypes as filterType (filterType)}
<li role="presentation" onclick={() => addFilter(filterType)}>{titleCase(filterType)}</li>
{/each}
@@ -51,7 +51,9 @@ import {
playerYouTubeJsAlways,
interfaceSearchHistoryEnabled,
playerPreferredVolumeStore,
watchHistoryEnabledStore
watchHistoryEnabledStore,
filterContentUrlStore,
filterContentUrlAutoUpdateStore
} from '$lib/store';
import { isOwnBackend } from '$lib/shared';
@@ -258,6 +260,16 @@ export const persistedStores: PersistedStore<any>[] = [
name: 'watchHistoryEnabled',
store: watchHistoryEnabledStore,
schema: zBoolean
},
{
name: 'filterContentUrl',
store: filterContentUrlStore,
schema: zString
},
{
name: 'filterContentUrlAutoUpdate',
store: filterContentUrlAutoUpdateStore,
schema: zBoolean
}
];
+1 -1
View File
@@ -68,7 +68,7 @@ export function isItemFiltered(item: FeedItem): boolean {
switch (condition.operator) {
case 'equals':
return fieldValue === condition.value;
return fieldValue.toString() === condition.value.toString();
case 'in':
return Array.isArray(condition.value) && (condition.value as any[]).includes(fieldValue);
+2 -1
View File
@@ -261,7 +261,8 @@
},
"filter": {
"title": "Content Filters",
"url": "Import Filters from URL"
"url": "Import Filters from URL",
"autoUpdate": "Automatically update filter from URL"
},
"deArrow": {
"title": "DeArrow",
+12
View File
@@ -347,6 +347,18 @@ export const filterContentListStore: Writable<z.infer<typeof zFilterSchema> | un
'filterContentList'
);
export const filterContentUrlStore: Writable<string | undefined> = persist(
writable(),
createStorage(),
'filterContentUrl'
);
export const filterContentUrlAutoUpdateStore: Writable<boolean> = persist(
writable(false),
createStorage(),
'filterContentUrlAutoUpdate'
);
export const feedLoadingStore: Writable<boolean> = writable(false);
export const feedCacheStore: Writable<{
[key: string]: (VideoBase | Video | PlaylistPageVideo)[];
+20 -2
View File
@@ -12,7 +12,10 @@ import {
invidiousInstanceStore,
interfaceDefaultPage,
isAndroidTvStore,
rawMasterKeyStore
rawMasterKeyStore,
filterContentListStore,
filterContentUrlStore,
filterContentUrlAutoUpdateStore
} from '$lib/store';
import { get, type Writable } from 'svelte/store';
import { Capacitor } from '@capacitor/core';
@@ -21,6 +24,7 @@ import { deserialize } from '@macfja/serializer';
import { isYTBackend } from '$lib/misc';
import { isOwnBackend } from '$lib/shared/index';
import '$lib/fetchProxy';
import { loadContentFilterFromURL } from '$lib/filtering/index.js';
export const ssr = false;
export const prerender = false;
@@ -37,7 +41,10 @@ export async function load({ url }) {
invidiousInstance: invidiousInstanceStore,
authToken: invidiousAuthStore,
backendInUse: backendInUseStore,
rawMasterKey: rawMasterKeyStore
rawMasterKey: rawMasterKeyStore,
filterContentList: filterContentListStore,
filterContentUrl: filterContentUrlStore,
filterContentUrlAutoUpdate: filterContentUrlAutoUpdateStore
};
for (const [key, store] of Object.entries(preferenceKey)) {
@@ -48,6 +55,17 @@ export async function load({ url }) {
}
}
if (get(filterContentUrlAutoUpdateStore)) {
const filterUrl = get(filterContentUrlStore);
if (filterUrl) {
try {
loadContentFilterFromURL(filterUrl);
} catch {
// Continue regardless of error
}
}
}
const resolvedRoot = resolve('/', {});
if (url.pathname.startsWith(resolvedRoot + '@')) {