+server.ts RawHistoryFolder

1import type { RequestHandler } from '@sveltejs/kit';
2import { users } from '$lib/db/convex.server';
3import { validateSessionToken } from '$lib/api/session.server';
4
5export const POST: RequestHandler = async ({ request, cookies }) => {
6	const token = cookies.get('session');
7
8	if (!token) {
9		return new Response(JSON.stringify({ error: 'Unauthorized' }), {
10			status: 401,
11			headers: { 'Content-Type': 'application/json' }
12		});
13	}
14
15	try {
16		const { user } = await validateSessionToken(token);
17
18		if (!user) {
19			return new Response(JSON.stringify({ error: 'Unauthorized' }), {
20				status: 401,
21				headers: { 'Content-Type': 'application/json' }
22			});
23		}
24
25		const body = await request.json();
26		const { timestamp } = body as { timestamp: number };
27
28		if (typeof timestamp !== 'number' || timestamp <= 0) {
29			return new Response(JSON.stringify({ error: 'Invalid timestamp' }), {
30				status: 400,
31				headers: { 'Content-Type': 'application/json' }
32			});
33		}
34
35		// Prevent far-future timestamps that could suppress notifications permanently
36		const now = Date.now();
37		const maxSkewMs = 5 * 60 * 1000; // 5 minutes clock skew tolerance
38		if (timestamp > now + maxSkewMs) {
39			return new Response(JSON.stringify({ error: 'Timestamp too far in the future' }), {
40				status: 400,
41				headers: { 'Content-Type': 'application/json' }
42			});
43		}
44
45		await users.updateLastReadMentionTimestamp(user.id, timestamp);
46
47		return new Response(JSON.stringify({ success: true }), {
48			status: 200,
49			headers: { 'Content-Type': 'application/json' }
50		});
51	} catch (error) {
52		console.error('Error updating mention read timestamp:', error);
53		return new Response(JSON.stringify({ error: 'Internal server error' }), {
54			status: 500,
55			headers: { 'Content-Type': 'application/json' }
56		});
57	}
58};

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 9

↑↓ moveenter openesc close