diff --git a/src/lib/components/ChatInput.svelte b/src/lib/components/ChatInput.svelte index 87bcfed..58326d9 100644 --- a/src/lib/components/ChatInput.svelte +++ b/src/lib/components/ChatInput.svelte @@ -40,7 +40,7 @@ viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" - class="size-3 mr-1" + class="mr-1 size-3" > {/if} - + {#if showThread && message.thread} - + {/if} diff --git a/src/lib/components/ChatMessageThread.svelte b/src/lib/components/ChatMessageThread.svelte index 386da5e..21f2bb9 100644 --- a/src/lib/components/ChatMessageThread.svelte +++ b/src/lib/components/ChatMessageThread.svelte @@ -3,16 +3,42 @@ import { Thread } from '$lib/schema'; import { CoState } from 'jazz-svelte'; import { useCurrentRoute } from '$lib/context'; - let { threadId }: { threadId: string } = $props(); + import { cn } from '@fuxui/base'; + import RelativeTime from 'svelte-relative-time'; + let { + threadId, + indented = true, + lastReadDate + }: { threadId: string; indented?: boolean; lastReadDate?: Date } = $props(); let thread = $derived(new CoState(Thread, threadId)); const route = useCurrentRoute(); + + // get the last message in the thread + let lastMessage = $derived(thread.current?.timeline?.at(-1)); + + let isNew = $derived.by(() => { + if (!lastReadDate) return thread.current?.timeline?.length !== 0; + if (!lastMessage) return false; + let date = lastMessage.createdAt; + if (!date) return false; + + return new Date(lastReadDate) < date; + });
+ {#if isNew} +
+
+
+ {/if}
({thread.current?.timeline?.length} messages) + + {#if lastMessage} + + updated + + {/if}
{ + if (route.threadId) { + view.active = 'threads'; + } else if(!goToThreads) { + view.active = 'channel'; + } + goToThreads = false; + }); + let { children } = $props(); function hideSidebar() { @@ -61,6 +74,8 @@ let newChannelName = $state(''); let showSpaceSelection = $state(false); + + let goToThreads = $state(false); @@ -83,6 +98,32 @@ > + + {#if route.channelId} + { + view.active = 'channel'; + if (route.threadId) { + // go to channel + goto(`${base}/${route.spaceId}/channel/${route.channelId}`); + } + } + }, + { + name: 'threads', + onclick: () => { + view.active = 'threads'; + goToThreads = true; + goto(`${base}/${route.spaceId}/channel/${route.channelId}`); + } + } + ]} + active={view.active} + /> + {/if}
@@ -140,7 +181,6 @@ onclick={hideSidebar} /> - {#each channel.subThreads ?? [] as thread} {#if thread} -
- {#each channel.current?.mainThread?.timeline ?? [] as message, index} - {#if message} - { - threadMessage = message; - createThreadModalOpen = true; - }} - /> +{#if view.active === 'channel'} +
+ {#each channel.current?.mainThread?.timeline ?? [] as message, index} + {#if message} + { + threadMessage = message; + createThreadModalOpen = true; + }} + /> + {/if} + {/each} + {#if channel.current?.mainThread?.timeline?.length === 0} +
+ No messages yet. Be the first to send a message! +
{/if} - {/each} - {#if channel.current?.mainThread?.timeline?.length === 0} -
- No messages yet. Be the first to send a message! -
- {/if} -
- - +
+ + +{:else} +
+ {#each channel.current?.subThreads ?? [] as thread} + {#if thread} + + {/if} + {/each} + {#if channel.current?.subThreads?.length === 0} +
+ No threads yet. Be the first to create a thread! +
+ {/if} +
+{/if}
diff --git a/src/routes/[spaceId]/view.svelte.ts b/src/routes/[spaceId]/view.svelte.ts new file mode 100644 index 0000000..e59458c --- /dev/null +++ b/src/routes/[spaceId]/view.svelte.ts @@ -0,0 +1,3 @@ +export const view = $state({ + active: 'channel' +});