517 lines
13 KiB
Svelte
517 lines
13 KiB
Svelte
<script lang="ts">
|
|
import { bookmarkletSaveToUrl } from '$lib/bookmarklet';
|
|
import { Capacitor } from '@capacitor/core';
|
|
import { _ } from 'svelte-i18n';
|
|
import { get } from 'svelte/store';
|
|
import {
|
|
authStore,
|
|
darkModeStore,
|
|
deArrowEnabledStore,
|
|
deArrowInstanceStore,
|
|
deArrowThumbnailInstanceStore,
|
|
instanceStore,
|
|
interfacePreviewVideoOnHoverStore,
|
|
interfaceSearchSuggestionsStore,
|
|
playerAlwaysLoopStore,
|
|
playerAutoPlayStore,
|
|
playerAutoplayNextByDefaultStore,
|
|
playerDashStore,
|
|
playerListenByDefaultStore,
|
|
playerMiniPlayerStore,
|
|
playerProxyVideosStore,
|
|
playerSavePlaybackPositionStore,
|
|
playerTheatreModeByDefaultStore,
|
|
returnYTDislikesInstanceStore,
|
|
returnYtDislikesStore,
|
|
sponsorBlockCategoriesStore,
|
|
sponsorBlockStore,
|
|
sponsorBlockUrlStore,
|
|
synciousInstanceStore,
|
|
synciousStore,
|
|
themeColorStore
|
|
} from '../store';
|
|
import { ensureNoTrailingSlash } from './misc';
|
|
|
|
let sponsorCategoriesList: string[] = [];
|
|
sponsorBlockCategoriesStore.subscribe((value) => (sponsorCategoriesList = value));
|
|
|
|
let sponsorBlockInstance = get(sponsorBlockUrlStore);
|
|
let synciousInstance = get(synciousInstanceStore);
|
|
let returnYTInstance = get(returnYTDislikesInstanceStore);
|
|
let invidiousInstance = get(instanceStore);
|
|
let deArrowUrl = get(deArrowInstanceStore);
|
|
let deArrowThumbnailUrl = get(deArrowThumbnailInstanceStore);
|
|
|
|
const sponsorCategories = [
|
|
{ name: $_('layout.sponsors.sponsor'), category: 'sponsor' },
|
|
{ name: $_('layout.sponsors.unpaidSelfPromotion'), category: 'selfpromo' },
|
|
{ name: $_('layout.sponsors.interactionReminder'), category: 'interaction' },
|
|
{ name: $_('layout.sponsors.intermissionIntroAnimation'), category: 'intro' },
|
|
{ name: $_('layout.sponsors.credits'), category: 'outro' },
|
|
{ name: $_('layout.sponsors.preViewRecapHook'), category: 'preview' },
|
|
{ name: $_('layout.sponsors.tangentJokes'), category: 'filler' }
|
|
];
|
|
|
|
function toggleSponsor(category: string) {
|
|
if (sponsorCategoriesList.includes(category)) {
|
|
sponsorBlockCategoriesStore.set(sponsorCategoriesList.filter((value) => value !== category));
|
|
} else {
|
|
sponsorCategoriesList.push(category);
|
|
sponsorBlockCategoriesStore.set(sponsorCategoriesList);
|
|
}
|
|
}
|
|
|
|
async function setColor(color: any) {
|
|
const target = color.target;
|
|
const hex = (target as { value: string }).value;
|
|
await ui('theme', hex);
|
|
themeColorStore.set(hex);
|
|
}
|
|
|
|
function toggleDarkMode() {
|
|
const isDark = get(darkModeStore);
|
|
|
|
if (isDark) {
|
|
ui('mode', 'light');
|
|
darkModeStore.set(false);
|
|
} else {
|
|
ui('mode', 'dark');
|
|
darkModeStore.set(true);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<dialog class="right" id="dialog-settings">
|
|
<nav>
|
|
<h4 class="max">{$_('layout.settings')}</h4>
|
|
<button class="circle transparent" data-ui="#dialog-settings"><i>close</i></button>
|
|
</nav>
|
|
<p>{$_('layout.customize')} Materialious</p>
|
|
|
|
<div class="settings">
|
|
<h6>{$_('layout.theme.theme')}</h6>
|
|
<button on:click={toggleDarkMode} class="no-margin">
|
|
{#if !$darkModeStore}
|
|
<i>dark_mode</i>
|
|
<span>{$_('layout.theme.darkMode')}</span>
|
|
{:else}
|
|
<i>light_mode</i>
|
|
<span>{$_('layout.theme.lightMode')}</span>
|
|
{/if}
|
|
</button>
|
|
<button>
|
|
<i>palette</i>
|
|
<span>{$_('layout.theme.color')}</span>
|
|
<input on:change={setColor} type="color" />
|
|
</button>
|
|
</div>
|
|
|
|
{#if Capacitor.isNativePlatform()}
|
|
<div class="settings">
|
|
<h6>Invidious</h6>
|
|
<form
|
|
on:submit|preventDefault={() => {
|
|
authStore.set(null);
|
|
instanceStore.set(ensureNoTrailingSlash(invidiousInstance));
|
|
}}
|
|
>
|
|
<nav>
|
|
<div class="field label border max">
|
|
<input bind:value={invidiousInstance} name="returnyt-instance" type="text" />
|
|
<label for="returnyt-instance">{$_('layout.instanceUrl')}</label>
|
|
</div>
|
|
<button class="square round">
|
|
<i>done</i>
|
|
</button>
|
|
</nav>
|
|
</form>
|
|
</div>
|
|
{/if}
|
|
|
|
<div class="settings">
|
|
<h6>Interface</h6>
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.searchSuggestions')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$interfaceSearchSuggestionsStore}
|
|
on:click={() => interfaceSearchSuggestionsStore.set(!$interfaceSearchSuggestionsStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.previewVideoOnHover')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$interfacePreviewVideoOnHoverStore}
|
|
on:click={() =>
|
|
interfacePreviewVideoOnHoverStore.set(!$interfacePreviewVideoOnHoverStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings">
|
|
<h6>{$_('layout.dataPreferences.dataPreferences')}</h6>
|
|
<p style="width: 240px;">
|
|
<a
|
|
href={`${get(instanceStore)}/preferences`}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
class="link"
|
|
>
|
|
{$_('layout.dataPreferences.content')}
|
|
</a>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="settings">
|
|
<h6>{$_('layout.player.title')}</h6>
|
|
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.miniPlayer')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerMiniPlayerStore}
|
|
on:click={() => playerMiniPlayerStore.set(!$playerMiniPlayerStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.autoPlay')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerAutoPlayStore}
|
|
on:click={() => playerAutoPlayStore.set(!$playerAutoPlayStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.alwaysLoopVideo')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerAlwaysLoopStore}
|
|
on:click={() => playerAlwaysLoopStore.set(!$playerAlwaysLoopStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
{#if !Capacitor.isNativePlatform()}
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.proxyVideos')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerProxyVideosStore}
|
|
on:click={() => playerProxyVideosStore.set(!$playerProxyVideosStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
{/if}
|
|
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.savePlaybackPosition')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerSavePlaybackPositionStore}
|
|
on:click={() => playerSavePlaybackPositionStore.set(!$playerSavePlaybackPositionStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.listenByDefault')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerListenByDefaultStore}
|
|
on:click={() => playerListenByDefaultStore.set(!$playerListenByDefaultStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="field no-margin m l">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.theatreModeByDefault')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerTheatreModeByDefaultStore}
|
|
on:click={() => playerTheatreModeByDefaultStore.set(!$playerTheatreModeByDefaultStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.autoPlayNextByDefault')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerAutoplayNextByDefaultStore}
|
|
on:click={() =>
|
|
playerAutoplayNextByDefaultStore.set(!$playerAutoplayNextByDefaultStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
{#if !Capacitor.isNativePlatform()}
|
|
<div class="field no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<div>{$_('layout.player.dash')}</div>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
bind:checked={$playerDashStore}
|
|
on:click={() => playerDashStore.set(!$playerDashStore)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
|
|
<div class="settings">
|
|
<h6>Return YT Dislikes</h6>
|
|
|
|
<form
|
|
on:submit|preventDefault={() =>
|
|
returnYTDislikesInstanceStore.set(ensureNoTrailingSlash(returnYTInstance))}
|
|
>
|
|
<nav>
|
|
<div class="field label border max">
|
|
<input bind:value={returnYTInstance} name="returnyt-instance" type="text" />
|
|
<label for="returnyt-instance">{$_('layout.instanceUrl')}</label>
|
|
</div>
|
|
<button class="square round">
|
|
<i>done</i>
|
|
</button>
|
|
</nav>
|
|
</form>
|
|
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<p>{$_('enabled')}</p>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
bind:checked={$returnYtDislikesStore}
|
|
on:click={() => returnYtDislikesStore.set(!$returnYtDislikesStore)}
|
|
type="checkbox"
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="settings">
|
|
<h6>Syncious</h6>
|
|
|
|
<form
|
|
on:submit|preventDefault={() =>
|
|
synciousInstanceStore.set(ensureNoTrailingSlash(synciousInstance))}
|
|
>
|
|
<nav>
|
|
<div class="field label border max">
|
|
<input bind:value={synciousInstance} name="syncious-instance" type="text" />
|
|
<label for="syncious-instance">{$_('layout.instanceUrl')}</label>
|
|
</div>
|
|
<button class="square round">
|
|
<i>done</i>
|
|
</button>
|
|
</nav>
|
|
</form>
|
|
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<p>{$_('enabled')}</p>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
bind:checked={$synciousStore}
|
|
on:click={() => synciousStore.set(!$synciousStore)}
|
|
type="checkbox"
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="settings">
|
|
<h6>Sponsorblock</h6>
|
|
|
|
<form
|
|
on:submit|preventDefault={() =>
|
|
sponsorBlockUrlStore.set(ensureNoTrailingSlash(sponsorBlockInstance))}
|
|
>
|
|
<nav>
|
|
<div class="field label border max">
|
|
<input bind:value={sponsorBlockInstance} name="sponsorblock-instance" type="text" />
|
|
<label for="sponsorblock-instance">{$_('layout.instanceUrl')}</label>
|
|
</div>
|
|
<button class="square round">
|
|
<i>done</i>
|
|
</button>
|
|
</nav>
|
|
</form>
|
|
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<p>{$_('enabled')}</p>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
bind:checked={$sponsorBlockStore}
|
|
on:click={() => sponsorBlockStore.set(!$sponsorBlockStore)}
|
|
type="checkbox"
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
|
|
{#each sponsorCategories as sponsor}
|
|
<div class="field middle-align no-margin">
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<p>{sponsor.name}</p>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
type="checkbox"
|
|
checked={sponsorCategoriesList.includes(sponsor.category)}
|
|
on:click={() => toggleSponsor(sponsor.category)}
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
|
|
<div class="settings">
|
|
<h6>{$_('layout.deArrow.title')}</h6>
|
|
|
|
<form
|
|
on:submit|preventDefault={() => deArrowInstanceStore.set(ensureNoTrailingSlash(deArrowUrl))}
|
|
>
|
|
<nav>
|
|
<div class="field label border max">
|
|
<input bind:value={deArrowUrl} name="dearrow-instance" type="text" />
|
|
<label for="dearrow-instance">{$_('layout.instanceUrl')}</label>
|
|
</div>
|
|
<button class="square round">
|
|
<i>done</i>
|
|
</button>
|
|
</nav>
|
|
</form>
|
|
|
|
<form on:submit|preventDefault={() => deArrowThumbnailInstanceStore.set(deArrowThumbnailUrl)}>
|
|
<nav>
|
|
<div class="field label border max">
|
|
<input bind:value={deArrowThumbnailUrl} name="dearrow-thumbnail-instance" type="text" />
|
|
<label for="dearrow-thumbnail-instance">{$_('layout.deArrow.thumbnailInstanceUrl')}</label
|
|
>
|
|
</div>
|
|
<button class="square round">
|
|
<i>done</i>
|
|
</button>
|
|
</nav>
|
|
</form>
|
|
|
|
<nav class="no-padding">
|
|
<div class="max">
|
|
<p>{$_('enabled')}</p>
|
|
</div>
|
|
<label class="switch">
|
|
<input
|
|
bind:checked={$deArrowEnabledStore}
|
|
on:click={() => deArrowEnabledStore.set(!$deArrowEnabledStore)}
|
|
type="checkbox"
|
|
/>
|
|
<span></span>
|
|
</label>
|
|
</nav>
|
|
</div>
|
|
|
|
{#if !Capacitor.isNativePlatform()}
|
|
<div class="settings">
|
|
<h6>{$_('layout.bookmarklet')}</h6>
|
|
<button
|
|
class="no-margin"
|
|
on:click={async () => await navigator.clipboard.writeText(bookmarkletSaveToUrl())}
|
|
>{$_('copyUrl')}</button
|
|
>
|
|
</div>
|
|
{/if}
|
|
</dialog>
|
|
|
|
<style>
|
|
.settings h6 {
|
|
margin: 1em 0 0.3em 0;
|
|
}
|
|
|
|
form {
|
|
margin: 1em 0;
|
|
}
|
|
</style>
|