diff options
Diffstat (limited to 'ui/routes/(app)')
| -rw-r--r-- | ui/routes/(app)/+layout.js | 8 | ||||
| -rw-r--r-- | ui/routes/(app)/+layout.svelte | 125 | ||||
| -rw-r--r-- | ui/routes/(app)/ch/[channel]/+page.svelte | 25 | ||||
| -rw-r--r-- | ui/routes/(app)/me/+page.svelte | 2 |
4 files changed, 51 insertions, 109 deletions
diff --git a/ui/routes/(app)/+layout.js b/ui/routes/(app)/+layout.js new file mode 100644 index 0000000..651bc8c --- /dev/null +++ b/ui/routes/(app)/+layout.js @@ -0,0 +1,8 @@ +import * as session from '$lib/session.svelte.js'; + +export async function load() { + let s = await session.boot(); + return { + session: s + }; +} diff --git a/ui/routes/(app)/+layout.svelte b/ui/routes/(app)/+layout.svelte index 7818505..9ec5244 100644 --- a/ui/routes/(app)/+layout.svelte +++ b/ui/routes/(app)/+layout.svelte @@ -8,61 +8,42 @@ import TinyGesture from 'tinygesture'; import * as api from '$lib/apiServer.js'; - import { - channelsList, - channelsMetaList, - currentUser, - logins, - messages, - onEvent - } from '$lib/store'; import ChannelList from '$lib/components/ChannelList.svelte'; import CreateChannelForm from '$lib/components/CreateChannelForm.svelte'; - let events = null; let gesture = null; + const { data, children } = $props(); + const { session } = data; + + onMount(session.begin.bind(session)); + onDestroy(session.end.bind(session)); + let pageContext = getContext('page'); - let { children } = $props(); - let loading = $state(true); let channel = $derived(page.params.channel); - let rawChannels = $derived($channelsList.channels); - let rawChannelsMeta = $derived($channelsMetaList.channelsMeta); - let rawMessages = $derived($messages); - - let enrichedChannels = $derived.by(() => { - const channels = rawChannels; - const channelsMeta = rawChannelsMeta; - const messages = rawMessages; + let rawChannels = $derived(session.channels); + let rawChannelsMeta = $derived(session.local.all); + let rawMessages = $derived(session.messages); + function enrichChannels(channels, channelsMeta, messages) { const enrichedChannels = []; - if (channels && messages) { - for (let ch of channels) { - let runs = messages.inChannel(ch.id); - let lastRun = runs?.slice(-1)[0]; - let lastMessage = lastRun?.messages.slice(-1)[0]; - let lastMessageAt = lastMessage?.at; - let hasUnreads = lastMessageAt > channelsMeta[ch.id]?.lastReadAt; - enrichedChannels.push({ - ...ch, - hasUnreads - }); - } + for (const ch of channels.values()) { + const channelMessages = messages.filter((message) => message.channel === ch.id); + const lastMessage = channelMessages.slice(-1)[0]; + const lastMessageAt = lastMessage?.at; + const lastReadAt = channelsMeta.get(ch.id)?.lastReadAt; + const hasUnreads = lastReadAt === null || lastMessageAt > lastReadAt; + enrichedChannels.push({ + ...ch, + hasUnreads + }); } return enrichedChannels; - }); - - function onBooted(boot) { - currentUser.set({ - id: boot.login.id, - username: boot.login.name - }); - logins.update((value) => value.setLogins(boot.logins)); - channelsList.update((value) => value.setChannels(boot.channels)); - messages.update((value) => value.setMessages(boot.messages)); } + const enrichedChannels = $derived(enrichChannels(rawChannels, rawChannelsMeta, rawMessages)); + function setUpGestures() { if (!browser) { // Meaningless if we're not in a browser, so... @@ -77,46 +58,14 @@ }); } - onMount(async () => { - let response = await api.boot(); - switch (response.status) { - case 200: - onBooted(response.data); - events = api.subscribeToEvents(response.data.resume_point); - events.onmessage = onEvent.fromMessage; - break; - case 401: - currentUser.set(null); - await goto('/login'); - break; - case 503: - currentUser.set(null); - await goto('/setup'); - break; - default: - // TODO: display error. - break; - } - setUpGestures(); - - loading = false; - }); + onMount(setUpGestures); onDestroy(async () => { - if (events !== null) { - events.close(); - } if (gesture !== null) { gesture.destroy(); } }); - function onbeforeunload(event) { - if (events !== null) { - events.close(); - } - } - const STORE_KEY_LAST_ACTIVE = 'pilcrow:lastActiveChannel'; function getLastActiveChannel() { @@ -142,25 +91,19 @@ } </script> -<svelte:window {onbeforeunload} /> - <svelte:head> <!-- TODO: unread count? --> <title>pilcrow</title> </svelte:head> -{#if loading} - <h2>Loading…</h2> -{:else} - <div id="interface"> - <nav id="sidebar" data-expanded={pageContext.showMenu}> - <ChannelList active={channel} channels={enrichedChannels} /> - <div class="create-channel"> - <CreateChannelForm {createChannel} /> - </div> - </nav> - <main> - {@render children?.()} - </main> - </div> -{/if} +<div id="interface"> + <nav id="sidebar" data-expanded={pageContext.showMenu}> + <ChannelList active={channel} channels={enrichedChannels} /> + <div class="create-channel"> + <CreateChannelForm {createChannel} /> + </div> + </nav> + <main> + {@render children?.()} + </main> +</div> diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte index 095e66a..c8507cc 100644 --- a/ui/routes/(app)/ch/[channel]/+page.svelte +++ b/ui/routes/(app)/ch/[channel]/+page.svelte @@ -3,24 +3,17 @@ import { page } from '$app/state'; import ActiveChannel from '$lib/components/ActiveChannel.svelte'; import MessageInput from '$lib/components/MessageInput.svelte'; - import { channelsList, channelsMetaList, currentUser, logins, messages } from '$lib/store'; + import { runs } from '$lib/runs.js'; import * as api from '$lib/apiServer'; - let channel = $derived(page.params.channel); - let messageRuns = $derived( - $messages.inChannel(channel).map(({ sender, messages }) => { - let senderName = $derived($logins.get(sender)); - let ownMessage = $derived($currentUser !== null && $currentUser.id === sender); - - return { - sender: senderName, - ownMessage, - messages - }; - }) - ); + const { data } = $props(); + const { session } = data; let activeChannel; + const channel = $derived(page.params.channel); + const messages = $derived(session.messages.filter((message) => message.channel === channel)); + const messageRuns = $derived(runs(messages, session.currentUser)); + function inView(parentElement, element) { const parRect = parentElement.getBoundingClientRect(); const parentTop = parRect.top; @@ -49,12 +42,12 @@ const lastInView = getLastVisibleMessage(); if (lastInView) { const at = DateTime.fromISO(lastInView.dataset.at); - $channelsMetaList.updateLastReadAt(channel, at); + session.local.updateLastReadAt(channel, at); } } $effect(() => { - const _ = $messages.inChannel(channel); + const _ = session.messages; setLastRead(); }); diff --git a/ui/routes/(app)/me/+page.svelte b/ui/routes/(app)/me/+page.svelte index ab214e9..0c960c8 100644 --- a/ui/routes/(app)/me/+page.svelte +++ b/ui/routes/(app)/me/+page.svelte @@ -5,14 +5,12 @@ import { goto } from '$app/navigation'; import * as api from '$lib/apiServer.js'; - import { currentUser } from '$lib/store'; let invites = $state([]); async function logOut() { const response = await api.logOut(); if (200 <= response.status && response.status < 300) { - currentUser.set(null); await goto('/login'); } } |
