main f6d8405

schema.ts RawHistoryFolder

1import { defineSchema, defineTable } from 'convex/server';
2import { v } from 'convex/values';
3
4export default defineSchema({
5	users: defineTable({
6		password: v.string(),
7		nickname: v.string(),
8		status: v.string(), // 'offline' | 'online' | 'away' | 'busy' | 'idle'
9		avatarUrl: v.optional(v.string()),
10		createdAt: v.number(),
11		lastSeen: v.optional(v.number()),
12		lastReadMentionTimestamp: v.optional(v.number()), // Timestamp of last read mention
13		// AIM profile
14		awayMessage: v.optional(v.string()), // Shown while status === 'away'
15		profile: v.optional(v.string()) // Free text "Get Info" profile
16	})
17		.index('by_nickname', ['nickname'])
18		.index('by_status', ['status']),
19
20	sessions: defineTable({
21		tokenHash: v.string(), // SHA-256 hash of the session token
22		userId: v.id('users'),
23		expiresAt: v.number(),
24		createdAt: v.number()
25	})
26		.index('by_tokenHash', ['tokenHash'])
27		.index('by_userId', ['userId']),
28
29	chatRooms: defineTable({
30		name: v.optional(v.string()),
31		type: v.string(), // 'direct' | 'group'
32		createdAt: v.number(),
33		createdBy: v.optional(v.id('users')),
34		topic: v.optional(v.string()),
35		// Direct rooms: exactly two members. Group rooms: undefined (open to all).
36		memberIds: v.optional(v.array(v.id('users'))),
37		// Stable key for direct rooms: sorted user ids joined by ':'
38		directKey: v.optional(v.string())
39	}).index('by_directKey', ['directKey']),
40
41	messages: defineTable({
42		chatRoomId: v.id('chatRooms'),
43		senderId: v.id('users'),
44		content: v.string(),
45		type: v.string(), // 'chat' | 'emote' | 'system' | 'auto-response'
46		timestamp: v.number(),
47		styleData: v.optional(v.string()),
48		hasFormatting: v.optional(v.boolean())
49	})
50		.index('by_chatRoom', ['chatRoomId'])
51		.index('by_timestamp', ['timestamp']),
52
53	// AIM buddy list: one row per (owner, buddy)
54	buddies: defineTable({
55		userId: v.id('users'),
56		buddyId: v.id('users'),
57		group: v.string(), // 'Buddies' | 'Family' | 'Co-Workers' | custom
58		createdAt: v.number()
59	})
60		.index('by_user', ['userId'])
61		.index('by_user_buddy', ['userId', 'buddyId']),
62
63	// Per-user read cursor per room (unread badges)
64	roomReads: defineTable({
65		userId: v.id('users'),
66		roomId: v.id('chatRooms'),
67		lastReadTimestamp: v.number()
68	})
69		.index('by_user', ['userId'])
70		.index('by_user_room', ['userId', 'roomId']),
71
72	// Typing indicators (short-lived, filtered by timestamp at read time)
73	typing: defineTable({
74		userId: v.id('users'),
75		roomId: v.id('chatRooms'),
76		updatedAt: v.number()
77	})
78		.index('by_room', ['roomId'])
79		.index('by_user_room', ['userId', 'roomId']),
80
81	userTextPreferences: defineTable({
82		userId: v.id('users'),
83		defaultStyle: v.object({
84			fontFamily: v.string(),
85			fontSize: v.number(),
86			color: v.optional(v.string()),
87			gradient: v.optional(v.array(v.string())),
88			bold: v.boolean(),
89			italic: v.boolean(),
90			underline: v.boolean(),
91			strikethrough: v.boolean()
92		}),
93		allowFormatting: v.boolean(),
94		maxMessageLength: v.number(),
95		createdAt: v.number(),
96		updatedAt: v.number()
97	}).index('by_userId', ['userId'])
98});

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