preserve chat replies and threads
This commit is contained in:
+29
-2
@@ -23,6 +23,7 @@
|
||||
let activityFilter: 'all' | 'moderation' = 'all';
|
||||
let chatMessages: Array<{ event_id: string; message_id: string; user_id: string; user_name: string; text: string; fragments: Array<{ type: string; text: string; emote_id?: string }>; sent_at: string; reply_parent_message_id?: string }> = [];
|
||||
let chatReplyParent: { message_id: string; user_name: string } | undefined;
|
||||
let chatThreadRoot: { message_id: string; user_name: string; text: string } | undefined;
|
||||
let pinnedMessageIds: string[] = [];
|
||||
let notifications: Array<{ id: string; severity: string; title: string; message: string; seen_at: string | null; created_at: string }> = [];
|
||||
let showNotifications = false;
|
||||
@@ -226,6 +227,7 @@
|
||||
collaborationInvites = [];
|
||||
showCollaboration = false;
|
||||
chatReplyParent = undefined;
|
||||
chatThreadRoot = undefined;
|
||||
pinnedMessageIds = [];
|
||||
}
|
||||
|
||||
@@ -243,12 +245,12 @@
|
||||
const event: { event_type?: string } = JSON.parse(message.data);
|
||||
if (event.event_type === 'connection.ready') realtimeState = 'CONNECTED';
|
||||
else if ('event_id' in event && event.event_type) {
|
||||
const activity = event as { event_id: string; event_type: string; occurred_at: string; payload?: { message_id?: string; chatter_user_id?: string; chatter_user_name?: string; message?: { text?: string; fragments?: Array<{ type: string; text: string; emote?: { id?: string } }> } } };
|
||||
const activity = event as { event_id: string; event_type: string; occurred_at: string; payload?: { message_id?: string; chatter_user_id?: string; chatter_user_name?: string; message?: { text?: string; fragments?: Array<{ type: string; text: string; emote?: { id?: string } }> }; reply?: { parent_message_id?: string } } };
|
||||
if (!activityEvents.some((item) => item.event_id === activity.event_id)) {
|
||||
activityEvents = [activity, ...activityEvents].slice(0, 100);
|
||||
}
|
||||
if (activity.event_type === 'twitch.channel.chat.message' && activity.payload?.message?.text) {
|
||||
chatMessages = [{ event_id: activity.event_id, message_id: activity.payload.message_id ?? activity.event_id, user_id: activity.payload.chatter_user_id ?? '', user_name: activity.payload.chatter_user_name ?? 'unknown', text: activity.payload.message.text, fragments: (activity.payload.message.fragments ?? []).map((fragment) => ({ type: fragment.type, text: fragment.text, emote_id: fragment.emote?.id })), sent_at: activity.occurred_at }, ...chatMessages].slice(0, 100);
|
||||
chatMessages = [{ event_id: activity.event_id, message_id: activity.payload.message_id ?? activity.event_id, user_id: activity.payload.chatter_user_id ?? '', user_name: activity.payload.chatter_user_name ?? 'unknown', text: activity.payload.message.text, fragments: (activity.payload.message.fragments ?? []).map((fragment) => ({ type: fragment.type, text: fragment.text, emote_id: fragment.emote?.id })), sent_at: activity.occurred_at, reply_parent_message_id: activity.payload.reply?.parent_message_id }, ...chatMessages].slice(0, 100);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
@@ -551,6 +553,10 @@
|
||||
chatReplyParent = { message_id: message.message_id, user_name: message.user_name };
|
||||
}
|
||||
|
||||
function openChatThread(message: { message_id: string; user_name: string; text: string }) {
|
||||
chatThreadRoot = { message_id: message.message_id, user_name: message.user_name, text: message.text };
|
||||
}
|
||||
|
||||
function moderateChatUser(userId: string) {
|
||||
if (!userId) return;
|
||||
moderationUserId = userId;
|
||||
@@ -911,5 +917,26 @@
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
{#if chatMessages.some((message) => message.reply_parent_message_id)}
|
||||
<section class="panel thread-index-panel">
|
||||
<div class="panel-header"><span>CHAT THREADS</span></div>
|
||||
{#each chatMessages.filter((message) => message.reply_parent_message_id) as reply}
|
||||
{@const root = chatMessages.find((message) => message.message_id === reply.reply_parent_message_id)}
|
||||
{#if root}<button class="thread-index-row" onclick={() => openChatThread(root)}><span>{root.user_name}: {root.text}</span><span class="micro">OPEN THREAD</span></button>{/if}
|
||||
{/each}
|
||||
</section>
|
||||
{/if}
|
||||
{#if chatThreadRoot}
|
||||
<section class="panel chat-thread-panel">
|
||||
<div class="panel-header"><span>THREAD · @{chatThreadRoot.user_name}</span><button class="secondary" onclick={() => (chatThreadRoot = undefined)}>CLOSE</button></div>
|
||||
<div class="thread-root"><strong>{chatThreadRoot.user_name}</strong><span>{chatThreadRoot.text}</span></div>
|
||||
<div class="thread-replies">
|
||||
{#each chatMessages.filter((message) => message.reply_parent_message_id === chatThreadRoot?.message_id) as reply}
|
||||
<div class="thread-reply"><strong>{reply.user_name}</strong><span>{reply.text}</span></div>
|
||||
{:else}<div class="empty-row">No replies received yet.</div>{/each}
|
||||
</div>
|
||||
<button class="primary" onclick={() => chatThreadRoot && replyToChatMessage(chatThreadRoot)}>REPLY IN THREAD</button>
|
||||
</section>
|
||||
{/if}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -901,3 +901,33 @@ label {
|
||||
min-width: 28px;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
.chat-thread-panel,
|
||||
.thread-index-panel {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.thread-index-row,
|
||||
.thread-reply {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--ui-divider);
|
||||
background: transparent;
|
||||
color: var(--ed-fg);
|
||||
text-align: left;
|
||||
}
|
||||
.thread-index-row:hover {
|
||||
background: var(--ui-surface-hi);
|
||||
}
|
||||
.thread-root {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid var(--ui-line-focus);
|
||||
}
|
||||
.thread-replies {
|
||||
margin: 6px 0 10px 18px;
|
||||
border-left: 2px solid var(--ui-line-focus);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user