180 lines
4.6 KiB
Svelte
180 lines
4.6 KiB
Svelte
<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;
|
|
}}
|
|
/>
|