dm homepage placeholder
This commit is contained in:
@@ -187,39 +187,50 @@
|
||||
bind:this={scrollContainer}
|
||||
onscroll={handleScroll}
|
||||
>
|
||||
{#if chat.activeChannelId && !chat.hasMoreMessages}
|
||||
{@const dm = chat.activeDms.find(d => d.channelId === chat.activeChannelId)}
|
||||
{#if chat.activeServer}
|
||||
<div class="history-start-marker-wrapper">
|
||||
<div class="history-start-marker">
|
||||
<div class="hash-icon">#</div>
|
||||
<div class="text-content">
|
||||
<h1>Welcome to #{chat.activeChannel?.name || 'this channel'}!</h1>
|
||||
<p>This is the start of the #{chat.activeChannel?.name || 'this channel'} channel.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
{:else if dm}
|
||||
{@const myIdHex = chat.identity?.toHexString()}
|
||||
{@const otherIdentity = dm.sender.toHexString() === myIdHex ? dm.recipient : dm.sender}
|
||||
{@const recipient = chat.users.find(u => u.identity.toHexString() === otherIdentity.toHexString())}
|
||||
{#if recipient}
|
||||
{#if chat.activeChannelId}
|
||||
{#if !chat.hasMoreMessages}
|
||||
{@const dm = chat.activeDms.find(d => d.channelId === chat.activeChannelId)}
|
||||
{#if chat.activeServer}
|
||||
<div class="history-start-marker-wrapper">
|
||||
<div class="history-start-marker">
|
||||
<Avatar user={recipient} size={64} />
|
||||
<div class="hash-icon">#</div>
|
||||
<div class="text-content">
|
||||
<h1>{recipient.name || 'Unknown User'}</h1>
|
||||
<p>This is the beginning of your direct message history with <strong>{recipient.name || 'this user'}</strong>.</p>
|
||||
<h1>Welcome to #{chat.activeChannel?.name || 'this channel'}!</h1>
|
||||
<p>This is the start of the #{chat.activeChannel?.name || 'this channel'} channel.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
{:else if dm}
|
||||
{@const myIdHex = chat.identity?.toHexString()}
|
||||
{@const otherIdentity = dm.sender.toHexString() === myIdHex ? dm.recipient : dm.sender}
|
||||
{@const recipient = chat.users.find(u => u.identity.toHexString() === otherIdentity.toHexString())}
|
||||
{#if recipient}
|
||||
<div class="history-start-marker-wrapper">
|
||||
<div class="history-start-marker">
|
||||
<Avatar user={recipient} size={64} />
|
||||
<div class="text-content">
|
||||
<h1>{recipient.name || 'Unknown User'}</h1>
|
||||
<p>This is the beginning of your direct message history with <strong>{recipient.name || 'this user'}</strong>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if !chat.activeChannelId}
|
||||
{#each visibleMessages as msg, i (msg.id.toString())}
|
||||
{@const isHighlighted = (chat.pendingThreadParentMessageId === msg.id) || (chat.activeThread?.parentMessageId === msg.id)}
|
||||
<MessageItem
|
||||
{msg}
|
||||
prevMsg={i > 0 ? visibleMessages[i-1] : null}
|
||||
{isHighlighted}
|
||||
onContentLoad={handleContentLoad}
|
||||
/>
|
||||
{/each}
|
||||
<div bind:this={messagesEndRef} style="height: 1px; flex-shrink: 0;"></div>
|
||||
{:else}
|
||||
<div class="empty-state">
|
||||
<div class="empty-state-icon">
|
||||
<i class="fas fa-comments"></i>
|
||||
@@ -228,17 +239,6 @@
|
||||
<p>Choose a channel from a server or a direct message to start chatting.</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#each visibleMessages as msg, i (msg.id.toString())}
|
||||
{@const isHighlighted = (chat.pendingThreadParentMessageId === msg.id) || (chat.activeThread?.parentMessageId === msg.id)}
|
||||
<MessageItem
|
||||
{msg}
|
||||
prevMsg={i > 0 ? visibleMessages[i-1] : null}
|
||||
{isHighlighted}
|
||||
onContentLoad={handleContentLoad}
|
||||
/>
|
||||
{/each}
|
||||
<div bind:this={messagesEndRef} style="height: 1px; flex-shrink: 0;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export class ChatService {
|
||||
this.#voice = new VoiceService(this.#db, this.#nav, () => this.identity);
|
||||
this.#account = new AccountService();
|
||||
this.#server = new ServerManagementService();
|
||||
this.#dm = new DirectMessagingService();
|
||||
this.#dm = new DirectMessagingService(this.#db, () => this.identity);
|
||||
|
||||
// Session-only image processing: creates Blob URLs directly from Database data.
|
||||
// This ditched the persistent IndexedDB cache to prevent stale data between reloads.
|
||||
|
||||
@@ -1,13 +1,40 @@
|
||||
import { useReducer } from "spacetimedb/svelte";
|
||||
import { reducers } from "../../module_bindings";
|
||||
import type { Identity } from "spacetimedb";
|
||||
import type { DatabaseService } from "./database.svelte";
|
||||
|
||||
export class DirectMessagingService {
|
||||
#openDirectMessageReducer = useReducer(reducers.openDirectMessage);
|
||||
#closeDirectMessageReducer = useReducer(reducers.closeDirectMessage);
|
||||
#db: DatabaseService;
|
||||
#identity: () => Identity | null;
|
||||
|
||||
constructor(db: DatabaseService, identity: () => Identity | null) {
|
||||
this.#db = db;
|
||||
this.#identity = identity;
|
||||
}
|
||||
|
||||
handleOpenDirectMessage = (recipient: Identity) => {
|
||||
this.#openDirectMessageReducer({ recipient });
|
||||
const identity = this.#identity();
|
||||
if (!identity) return;
|
||||
|
||||
// Check if DM session already exists
|
||||
const existing = this.#db.directMessages.find(dm =>
|
||||
(dm.sender.isEqual(identity) && dm.recipient.isEqual(recipient)) ||
|
||||
(dm.sender.isEqual(recipient) && dm.recipient.isEqual(identity))
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
// Session exists, open it if closed
|
||||
if (existing.sender.isEqual(identity) && !existing.isOpenSender) {
|
||||
this.#openDirectMessageReducer({ recipient });
|
||||
} else if (existing.recipient.isEqual(identity) && !existing.isOpenRecipient) {
|
||||
this.#openDirectMessageReducer({ recipient });
|
||||
}
|
||||
} else {
|
||||
// No session, create it
|
||||
this.#openDirectMessageReducer({ recipient });
|
||||
}
|
||||
};
|
||||
|
||||
handleCloseDirectMessage = (channelId: bigint) => {
|
||||
|
||||
@@ -118,9 +118,12 @@ export class MessagingService {
|
||||
}
|
||||
|
||||
#updateBuckets(newMessages: readonly Types.VisibleMessageRow[]) {
|
||||
const activeChannelId = this.#nav.activeChannelId;
|
||||
const tempBuckets = new Map<bigint, Map<bigint, Types.Message & { seqId?: bigint, reactions: Types.Reaction[], imageIds: bigint[] }>>();
|
||||
|
||||
for (const m of newMessages) {
|
||||
if (activeChannelId && m.channelId !== activeChannelId) continue;
|
||||
|
||||
let bucketMap = tempBuckets.get(m.channelId);
|
||||
if (!bucketMap) {
|
||||
bucketMap = new Map();
|
||||
|
||||
@@ -60,6 +60,17 @@ export class NavigationService {
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const activeDms = this.activeDms;
|
||||
const isCurrentChannelValid =
|
||||
this.activeChannelId &&
|
||||
activeDms.some((dm) => dm.channelId === this.activeChannelId);
|
||||
|
||||
if (!isCurrentChannelValid) {
|
||||
untrack(() => {
|
||||
this.activeChannelId = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user