Added account deletion
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<script lang="ts">
|
||||
import { _ } from '$lib/i18n';
|
||||
import { logout } from '$lib/misc';
|
||||
|
||||
let clickCount = $state(0);
|
||||
const clicksToDelte = 3;
|
||||
let deleteDebounce: ReturnType<typeof setTimeout> | undefined;
|
||||
async function deleteAccount() {
|
||||
clickCount++;
|
||||
|
||||
if (deleteDebounce) clearTimeout(deleteDebounce);
|
||||
|
||||
deleteDebounce = setTimeout(() => {
|
||||
clickCount = 0;
|
||||
}, 10000);
|
||||
|
||||
if (clicksToDelte - clickCount === 0) {
|
||||
await fetch('/api/user/delete', { method: 'DELETE' });
|
||||
logout();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<h6>Passsword reset</h6>
|
||||
|
||||
<h6>Delete account</h6>
|
||||
<div class="space"></div>
|
||||
<button class="tertiary" onclick={deleteAccount}>
|
||||
<i>warning</i>
|
||||
<span>{$_('layout.deleteAccount')}</span>
|
||||
{#if clicksToDelte - clickCount > 0}
|
||||
<div class="tooltip">
|
||||
{$_('layout.clickXmoreTimesToDelete', {
|
||||
clicksTillDelete: clicksToDelte - clickCount
|
||||
})}
|
||||
</div>
|
||||
{/if}
|
||||
</button>
|
||||
@@ -7,15 +7,17 @@
|
||||
import Player from './Player.svelte';
|
||||
import Ryd from './RYD.svelte';
|
||||
import SponsorBlock from './SponsorBlock.svelte';
|
||||
import { isAndroidTvStore } from '$lib/store';
|
||||
import { isAndroidTvStore, rawMasterKeyStore } from '$lib/store';
|
||||
import About from './About.svelte';
|
||||
import Engine from './Engine.svelte';
|
||||
import { isUnrestrictedPlatform } from '$lib/misc';
|
||||
import { isOwnBackend } from '$lib/shared';
|
||||
import InternalAccount from './InternalAccount.svelte';
|
||||
|
||||
let activeTab = $state('interface');
|
||||
const isActive = (id: string) => activeTab === id;
|
||||
|
||||
const tabs: { id: string; label: string; icon: string; component: Component }[] = [
|
||||
let tabs: { id: string; label: string; icon: string; component: Component }[] = $state([
|
||||
{ id: 'interface', label: $_('layout.interface'), icon: 'grid_view', component: Interface },
|
||||
{ id: 'player', label: $_('layout.player.title'), icon: 'smart_display', component: Player },
|
||||
{ id: 'ryd', label: 'Return YT Dislike', icon: 'thumb_down', component: Ryd },
|
||||
@@ -33,7 +35,11 @@
|
||||
icon: 'info',
|
||||
component: About
|
||||
}
|
||||
];
|
||||
]);
|
||||
|
||||
let tabIds: string[] = $state([]);
|
||||
|
||||
setTabIds();
|
||||
|
||||
if (isUnrestrictedPlatform()) {
|
||||
tabs.splice(1, 0, {
|
||||
@@ -44,7 +50,28 @@
|
||||
});
|
||||
}
|
||||
|
||||
const tabIds = tabs.map((tab) => tab.id);
|
||||
function setTabIds() {
|
||||
tabs.forEach((tab) => {
|
||||
tabIds.push(tab.id);
|
||||
});
|
||||
}
|
||||
|
||||
rawMasterKeyStore.subscribe((value) => {
|
||||
if (isOwnBackend()?.internalAuth && value) {
|
||||
tabs.splice(1, 0, {
|
||||
id: 'account',
|
||||
label: $_('layout.materialiousAccount'),
|
||||
icon: 'person',
|
||||
component: InternalAccount
|
||||
});
|
||||
} else {
|
||||
tabs = tabs.filter((tab) => {
|
||||
return tab.id !== 'account';
|
||||
});
|
||||
}
|
||||
|
||||
setTabIds();
|
||||
});
|
||||
|
||||
let dialogType = $state('');
|
||||
|
||||
@@ -102,24 +129,26 @@
|
||||
|
||||
<div style="height: 100%;">
|
||||
<nav class="wrap s">
|
||||
<button class="large small-round surface-container-highest max" data-ui="#tab-menu">
|
||||
<i>{tabs[tabIds.indexOf(activeTab)].icon}</i>
|
||||
<span>{tabs[tabIds.indexOf(activeTab)].label}</span>
|
||||
<menu style="width: 100%;" data-ui="#tab-menu" id="tab-menu">
|
||||
{#each tabs as tab (tab)}
|
||||
<li
|
||||
onclick={() => {
|
||||
activeTab = tab.id;
|
||||
}}
|
||||
role="presentation"
|
||||
data-ui="#tab-menu"
|
||||
>
|
||||
<i>{tab.icon}</i>
|
||||
<span>{tab.label}</span>
|
||||
</li>
|
||||
{/each}
|
||||
</menu>
|
||||
</button>
|
||||
{#if tabIds}
|
||||
<button class="large small-round surface-container-highest max" data-ui="#tab-menu">
|
||||
<i>{tabs[tabIds.indexOf(activeTab)]?.icon}</i>
|
||||
<span>{tabs[tabIds.indexOf(activeTab)]?.label}</span>
|
||||
<menu style="width: 100%;" data-ui="#tab-menu" id="tab-menu">
|
||||
{#each tabs as tab (tab)}
|
||||
<li
|
||||
onclick={() => {
|
||||
activeTab = tab.id;
|
||||
}}
|
||||
role="presentation"
|
||||
data-ui="#tab-menu"
|
||||
>
|
||||
<i>{tab.icon}</i>
|
||||
<span>{tab.label}</span>
|
||||
</li>
|
||||
{/each}
|
||||
</menu>
|
||||
</button>
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
<div class="s">
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
"engine": "Backend engine",
|
||||
"syncParty": "Sync party",
|
||||
"about": "About",
|
||||
"materialiousAccount": "Account",
|
||||
"syncPartyWarning": "Please note your IP will be visible to users you invite.",
|
||||
"startSyncParty": "Start sync party",
|
||||
"endSyncParty": "End sync party",
|
||||
@@ -185,6 +186,8 @@
|
||||
"displayThumbnailAvatars": "Thumbnail avatars (Slow)",
|
||||
"searchHistory": "Search history",
|
||||
"companionUrl": "Companion URL",
|
||||
"deleteAccount": "Delete account",
|
||||
"clickXmoreTimesToDelete": "Click {{clicksTillDelete}} more time(s) to delete",
|
||||
"theme": {
|
||||
"theme": "Theme",
|
||||
"darkMode": "Dark mode",
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { getUser } from '$lib/server/user';
|
||||
|
||||
export async function DELETE({ locals }) {
|
||||
const user = await getUser(locals.userId);
|
||||
await user.delete();
|
||||
|
||||
return new Response();
|
||||
}
|
||||
Reference in New Issue
Block a user