detached e7b86a4

fix(convex): preserve original timestamps in message migration

commit
e7b86a4aac545e5902ad82c0e750021e15b76fc3
author
bnema · · 2026-01-18 20:36 UTC
parent
f8c7979
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +7 -4
M src/convex/http.ts +4 -2
@@ -256,7 +256,8 @@ http.route({
256256 handler: httpAction(async (ctx, request) => {
257257 if (!validateSecret(request)) return unauthorizedResponse();
258258
259- const { chatRoomId, senderId, content, type, styleData, hasFormatting } = await request.json();
259+ const { chatRoomId, senderId, content, type, styleData, hasFormatting, timestamp } =
260+ await request.json();
260261 try {
261262 const message = await ctx.runMutation(internal.messagesInternal.send, {
262263 chatRoomId,
@@ -264,7 +265,8 @@ http.route({
264265 content,
265266 type,
266267 styleData,
267- hasFormatting
268+ hasFormatting,
269+ timestamp
268270 });
269271 return new Response(JSON.stringify(message), {
270272 headers: { 'Content-Type': 'application/json' }
@@ -256,7 +256,8 @@ http.route({
256 handler: httpAction(async (ctx, request) => {256 handler: httpAction(async (ctx, request) => {
257 if (!validateSecret(request)) return unauthorizedResponse();257 if (!validateSecret(request)) return unauthorizedResponse();
258 258
259- const { chatRoomId, senderId, content, type, styleData, hasFormatting } = await request.json();259+ const { chatRoomId, senderId, content, type, styleData, hasFormatting, timestamp } =
260+ await request.json();
260 try {261 try {
261 const message = await ctx.runMutation(internal.messagesInternal.send, {262 const message = await ctx.runMutation(internal.messagesInternal.send, {
262 chatRoomId,263 chatRoomId,
@@ -264,7 +265,8 @@ http.route({
264 content,265 content,
265 type,266 type,
266 styleData,267 styleData,
267- hasFormatting268+ hasFormatting,
269+ timestamp
268 });270 });
269 return new Response(JSON.stringify(message), {271 return new Response(JSON.stringify(message), {
270 headers: { 'Content-Type': 'application/json' }272 headers: { 'Content-Type': 'application/json' }
M src/convex/messagesInternal.ts +3 -2
@@ -41,7 +41,8 @@ export const send = internalMutation({
4141 content: v.string(),
4242 type: v.optional(v.string()),
4343 styleData: v.optional(v.string()),
44- hasFormatting: v.optional(v.boolean())
44+ hasFormatting: v.optional(v.boolean()),
45+ timestamp: v.optional(v.number())
4546 },
4647 handler: async (ctx, args) => {
4748 // Verify room exists
@@ -61,7 +62,7 @@ export const send = internalMutation({
6162 senderId: args.senderId,
6263 content: args.content,
6364 type: args.type ?? 'chat',
64- timestamp: Date.now(),
65+ timestamp: args.timestamp ?? Date.now(),
6566 styleData: args.styleData,
6667 hasFormatting: args.hasFormatting ?? false
6768 });
@@ -41,7 +41,8 @@ export const send = internalMutation({
41 content: v.string(),41 content: v.string(),
42 type: v.optional(v.string()),42 type: v.optional(v.string()),
43 styleData: v.optional(v.string()),43 styleData: v.optional(v.string()),
44- hasFormatting: v.optional(v.boolean())44+ hasFormatting: v.optional(v.boolean()),
45+ timestamp: v.optional(v.number())
45 },46 },
46 handler: async (ctx, args) => {47 handler: async (ctx, args) => {
47 // Verify room exists48 // Verify room exists
@@ -61,7 +62,7 @@ export const send = internalMutation({
61 senderId: args.senderId,62 senderId: args.senderId,
62 content: args.content,63 content: args.content,
63 type: args.type ?? 'chat',64 type: args.type ?? 'chat',
64- timestamp: Date.now(),65+ timestamp: args.timestamp ?? Date.now(),
65 styleData: args.styleData,66 styleData: args.styleData,
66 hasFormatting: args.hasFormatting ?? false67 hasFormatting: args.hasFormatting ?? false
67 });68 });

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 8

↑↓ moveenter openesc close