feat: Message timestamps
This commit is contained in:
parent
08493a24b7
commit
e3c8f7fa3a
2
TODO.md
2
TODO.md
@ -14,7 +14,7 @@ A more complex version of this list is available [here](https://trello.com/b/kJw
|
|||||||
- [x] Notifications
|
- [x] Notifications
|
||||||
- [x] Make the damn textbox stop unfocusing on every message submit
|
- [x] Make the damn textbox stop unfocusing on every message submit
|
||||||
- [ ] Message context menus
|
- [ ] Message context menus
|
||||||
- [ ] Message Timestamps
|
- [x] Message Timestamps
|
||||||
- [x] Markdown Support
|
- [x] Markdown Support
|
||||||
- [x] More Secure database passwords
|
- [x] More Secure database passwords
|
||||||
- [x] Minio
|
- [x] Minio
|
||||||
|
@ -20,13 +20,15 @@ io.on('connection', async (socket) => {
|
|||||||
if (msg.content !== '') {
|
if (msg.content !== '') {
|
||||||
console.log(`\x1b[35m[ws:kit]\x1b[0m message from ${socket.id}: ${msg.content}`);
|
console.log(`\x1b[35m[ws:kit]\x1b[0m message from ${socket.id}: ${msg.content}`);
|
||||||
// Store the message in the database
|
// Store the message in the database
|
||||||
await db.sendMessage(msg.channel, msg.content, msg.id, uuidv4());
|
const timestamp = new Date();
|
||||||
|
await db.sendMessage(msg.channel, msg.content, msg.id, uuidv4(), timestamp);
|
||||||
const sender = authdb.getUser(msg.id);
|
const sender = authdb.getUser(msg.id);
|
||||||
io!.emit('message', {
|
io!.emit('message', {
|
||||||
user: sender.username,
|
user: sender.username,
|
||||||
message: msg.content,
|
message: msg.content,
|
||||||
imageSrc: sender.image,
|
imageSrc: sender.image,
|
||||||
channel: msg.channel,
|
channel: msg.channel,
|
||||||
|
timestamp: timestamp.getTime(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { type TypeMessage } from '$lib/types';
|
import { type TypeMessage } from '$lib/types';
|
||||||
import Prose from '$lib/components/prose.svelte';
|
import Prose from '$lib/components/prose.svelte';
|
||||||
import renderMarkdown from '$lib/functions/renderMarkdown';
|
import renderMarkdown from '$lib/functions/renderMarkdown';
|
||||||
const { message, imageSrc, user }: TypeMessage = $props();
|
const { message, imageSrc, user, timestamp }: TypeMessage = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex w-full p-2 hover:bg-zinc-200 dark:hover:bg-stone-900">
|
<div class="flex w-full p-2 hover:bg-zinc-200 dark:hover:bg-stone-900">
|
||||||
@ -12,7 +12,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<p class="inline-size-full break-words font-bold">{user}</p>
|
<p class="inline-size-full flex items-center gap-1 break-words">
|
||||||
|
<span class="font-bold">{user}</span>
|
||||||
|
<span>·</span>
|
||||||
|
<span class="text-muted-foreground"
|
||||||
|
>{new Date(timestamp).toLocaleDateString('en-US', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
hour12: true,
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: 'numeric',
|
||||||
|
})}</span
|
||||||
|
>
|
||||||
|
</p>
|
||||||
<Prose class="inline-size-full text-wrap break-words font-sans">{@html renderMarkdown(message)}</Prose>
|
<Prose class="inline-size-full text-wrap break-words font-sans">{@html renderMarkdown(message)}</Prose>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,6 +34,7 @@ class Websocket {
|
|||||||
message: newMsg.message,
|
message: newMsg.message,
|
||||||
imageSrc: newMsg.imageSrc,
|
imageSrc: newMsg.imageSrc,
|
||||||
user: newMsg.user,
|
user: newMsg.user,
|
||||||
|
timestamp: newMsg.timestamp,
|
||||||
},
|
},
|
||||||
...this.messages,
|
...this.messages,
|
||||||
];
|
];
|
||||||
|
@ -28,13 +28,15 @@ export function startupSocketIOServer(httpServer: HttpServer | null) {
|
|||||||
if (msg.content !== '') {
|
if (msg.content !== '') {
|
||||||
console.log(`\x1b[35m[ws:kit]\x1b[0m message from ${socket.id}: ${msg.content}`);
|
console.log(`\x1b[35m[ws:kit]\x1b[0m message from ${socket.id}: ${msg.content}`);
|
||||||
// Store the message in the database
|
// Store the message in the database
|
||||||
await db.sendMessage(msg.channel, msg.content, msg.id, uuidv4());
|
const timestamp = new Date();
|
||||||
|
await db.sendMessage(msg.channel, msg.content, msg.id, uuidv4(), timestamp);
|
||||||
const sender = authdb.getUser(msg.id);
|
const sender = authdb.getUser(msg.id);
|
||||||
io!.emit('message', {
|
io!.emit('message', {
|
||||||
user: sender.username,
|
user: sender.username,
|
||||||
message: msg.content,
|
message: msg.content,
|
||||||
imageSrc: sender.image,
|
imageSrc: sender.image,
|
||||||
channel: msg.channel,
|
channel: msg.channel,
|
||||||
|
timestamp: timestamp.getTime(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6,6 +6,12 @@ interface Messages {
|
|||||||
error: Error | null;
|
error: Error | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CassandraTimestamp {
|
||||||
|
low: number;
|
||||||
|
high: number;
|
||||||
|
unsigned: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
function createDelay(ms: number) {
|
function createDelay(ms: number) {
|
||||||
return new Promise((res) => setTimeout(res, ms));
|
return new Promise((res) => setTimeout(res, ms));
|
||||||
}
|
}
|
||||||
@ -69,16 +75,15 @@ class Db {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send message method
|
// Send message method
|
||||||
async sendMessage(channelName: string, content: string, sender: string, id: string) {
|
async sendMessage(channelName: string, content: string, sender: string, id: string, timestamp: Date) {
|
||||||
try {
|
try {
|
||||||
const now = new Date();
|
|
||||||
channelName = sanitizeChannelName(channelName);
|
channelName = sanitizeChannelName(channelName);
|
||||||
await this.client.execute(`INSERT INTO channels.${channelName} (id, message_content, channel_name, timestamp, sender) VALUES (?, ?, ?, ?, ?)`, {
|
await this.client.execute(`INSERT INTO channels.${channelName} (id, message_content, channel_name, sender, timestamp) VALUES (?, ?, ?, ?, ?)`, {
|
||||||
id,
|
id,
|
||||||
message_content: content,
|
message_content: content,
|
||||||
channel_name: channelName,
|
channel_name: channelName,
|
||||||
timestamp: now.getTime(),
|
|
||||||
sender,
|
sender,
|
||||||
|
timestamp,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Error storing message: ${e as Error}`);
|
console.error(`Error storing message: ${e as Error}`);
|
||||||
@ -130,6 +135,13 @@ class Db {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Timestamp to Epoch method
|
||||||
|
tsEpoch(ts: CassandraTimestamp) {
|
||||||
|
const low = ts.low >>> 0;
|
||||||
|
const high = ts.high >>> 0;
|
||||||
|
return high * 2 ** 32 + low;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = new Db();
|
const db = new Db();
|
||||||
|
@ -2,6 +2,7 @@ export interface TypeMessage {
|
|||||||
message: string;
|
message: string;
|
||||||
imageSrc: string;
|
imageSrc: string;
|
||||||
user: string;
|
user: string;
|
||||||
|
timestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TypeFullMessage {
|
export interface TypeFullMessage {
|
||||||
@ -9,4 +10,5 @@ export interface TypeFullMessage {
|
|||||||
message: string;
|
message: string;
|
||||||
imageSrc: string;
|
imageSrc: string;
|
||||||
user: string;
|
user: string;
|
||||||
|
timestamp: number;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ export async function load({ params, request }): Promise<ChannelLoad> {
|
|||||||
user: sender.username,
|
user: sender.username,
|
||||||
imageSrc: sender.image,
|
imageSrc: sender.image,
|
||||||
channel: value.channel,
|
channel: value.channel,
|
||||||
|
timestamp: db.tsEpoch(value.timestamp),
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
|
|
||||||
{#snippet message(messages: TypeMessage[])}
|
{#snippet message(messages: TypeMessage[])}
|
||||||
{#each messages as message}
|
{#each messages as message}
|
||||||
<Message imageSrc={message.imageSrc} user={message.user} message={message.message} />
|
<Message imageSrc={message.imageSrc} user={message.user} message={message.message} timestamp={message.timestamp} />
|
||||||
{/each}
|
{/each}
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user