feat: calendar connections
This commit is contained in:
132
src/lib/components/lnv/sidebar/settings/CalendarSidebar.svelte
Normal file
132
src/lib/components/lnv/sidebar/settings/CalendarSidebar.svelte
Normal file
@ -0,0 +1,132 @@
|
||||
<script lang="ts">
|
||||
import { m } from "$lang/messages";
|
||||
import { CalendarPlusIcon } from "@lucide/svelte";
|
||||
import SidebarHeader from "../SidebarHeader.svelte";
|
||||
import SettingsButton from "./SettingsButton.svelte";
|
||||
import * as Drawer from "$lib/components/ui/drawer";
|
||||
import { Button } from "$lib/components/ui/button";
|
||||
import Input from "$lib/components/ui/input/input.svelte";
|
||||
import { fetchCalendars, findScheme, type AuthScheme, type DAVCalendar, type DAVCredentials } from "$lib/services/CalDAV";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
let calendars: (DAVCalendar & {credentials: DAVCredentials})[] = $state([]);
|
||||
|
||||
let calDavDrawerOpen = $state(false);
|
||||
let calDavLoading = $state(false);
|
||||
let calDavUrl = $state("");
|
||||
let calDavUsername = $state("");
|
||||
let calDavPassword = $state("");
|
||||
let calDavCalendars: DAVCalendar[] = $state([]);
|
||||
let calDavScheme: AuthScheme;
|
||||
|
||||
let calDavState = $state("");
|
||||
|
||||
async function fetchCalDav() {
|
||||
calDavState = m["sidebar.calendar.probing-server"]();
|
||||
calDavScheme = await findScheme(calDavUrl);
|
||||
calDavState = m["sidebar.calendar.discovering-calendars"]();
|
||||
calDavCalendars = await fetchCalendars(calDavUrl, { scheme: calDavScheme, username: calDavUsername, password: calDavPassword });
|
||||
calDavState = "";
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if(localStorage.getItem("calendars")) {
|
||||
calendars = JSON.parse(localStorage.getItem("calendars")!);
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<SidebarHeader>
|
||||
{m["sidebar.calendar.header"]()}
|
||||
</SidebarHeader>
|
||||
|
||||
<Drawer.Root bind:open={calDavDrawerOpen}>
|
||||
<Drawer.Content>
|
||||
<Drawer.Header>
|
||||
<Drawer.Title>{m["sidebar.calendar.connect"]()}</Drawer.Title>
|
||||
</Drawer.Header>
|
||||
<div class="p-4 pt-0 flex flex-col gap-2">
|
||||
{#if calDavCalendars}
|
||||
<Input type="url" placeholder="https://my-caldav-server.com/..." disabled={calDavLoading} bind:value={calDavUrl} />
|
||||
<Input type="text" placeholder="Username" disabled={calDavLoading} bind:value={calDavUsername} />
|
||||
<Input type="password" placeholder="Password" disabled={calDavLoading} bind:value={calDavPassword} />
|
||||
{#if calDavState}
|
||||
<span>{calDavState}</span>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if calDavCalendars.length > 0}
|
||||
<h3 class="font-medium pt-4">{m["sidebar.calendar.choose"]()}</h3>
|
||||
<ul class="max-h-48 overflow-y-auto">
|
||||
{#each calDavCalendars as calendar (calendar.url)}
|
||||
<li>
|
||||
<Button class="w-full" variant="secondary" onclick={() => {
|
||||
if(localStorage.getItem("calendars")) {
|
||||
const existing = JSON.parse(localStorage.getItem("calendars")!);
|
||||
existing.push({
|
||||
name: calendar.name,
|
||||
url: calendar.url,
|
||||
credentials: {
|
||||
username: calDavUsername,
|
||||
password: calDavPassword,
|
||||
scheme: calDavScheme
|
||||
}
|
||||
});
|
||||
localStorage.setItem("calendars", JSON.stringify(existing));
|
||||
} else {
|
||||
localStorage.setItem("calendars", JSON.stringify([{
|
||||
name: calendar.name,
|
||||
url: calendar.url,
|
||||
credentials: {
|
||||
username: calDavUsername,
|
||||
password: calDavPassword,
|
||||
scheme: calDavScheme
|
||||
}
|
||||
}]));
|
||||
}
|
||||
calendars.push({
|
||||
name: calendar.name,
|
||||
url: calendar.url,
|
||||
credentials: {
|
||||
username: calDavUsername,
|
||||
password: calDavPassword,
|
||||
scheme: calDavScheme
|
||||
}
|
||||
});
|
||||
}}>
|
||||
{calendar.name}
|
||||
</Button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
<Drawer.Footer>
|
||||
{#if calDavCalendars.length === 0}
|
||||
<Button onclick={async () => {
|
||||
calDavLoading = true;
|
||||
await fetchCalDav().catch((e) => {
|
||||
calDavState = e;
|
||||
calDavLoading = false;
|
||||
})
|
||||
}}>{m.submit()}</Button>
|
||||
{/if}
|
||||
<Drawer.Close>
|
||||
{calDavCalendars.length === 0 ? m.done() : m.cancel()}
|
||||
</Drawer.Close>
|
||||
</Drawer.Footer>
|
||||
</Drawer.Content>
|
||||
</Drawer.Root>
|
||||
|
||||
{#each calendars as calendar (calendar.url)}
|
||||
<div class="p-2 border rounded mb-2">
|
||||
<h3 class="font-medium">{calendar.name}</h3>
|
||||
<Button variant="destructive" size="sm" class="mt-2" onclick={() => {
|
||||
calendars = calendars.filter(c => c.url !== calendar.url);
|
||||
localStorage.setItem("calendars", JSON.stringify(calendars));
|
||||
}}>{m.delete()}</Button>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
<SettingsButton text={m["sidebar.calendar.connect"]()} icon={CalendarPlusIcon} onclick={() => {
|
||||
calDavDrawerOpen = true;
|
||||
}} />
|
||||
Reference in New Issue
Block a user