feat: space sidebar drag-and-drop reordering with folder system

Add user_space_layout table and PUT /api/users/@me/space-layout endpoint
for persisting per-user sidebar ordering. Spaces can be freely reordered
via drag-and-drop, folders created by dragging one space onto another,
and folders auto-dissolve when they have fewer than 2 members. Includes
folder context menu (rename, color, ungroup), collapsed folder mini-grid
icons, multi-tab sync via WebSocket, and localStorage collapse state.
Removes the rigid native/federated split — federated spaces now intermix
freely while keeping their globe badge.
This commit is contained in:
Jannis Braun
2026-03-12 03:38:22 +01:00
parent 39174e5454
commit dbd964d40c
12 changed files with 1006 additions and 93 deletions
+7
View File
@@ -192,10 +192,17 @@ export const spaceFolders = sqliteTable('space_folders', {
export const spaceFolderMembers = sqliteTable('space_folder_members', {
folderId: text('folder_id').notNull().references(() => spaceFolders.id, { onDelete: 'cascade' }),
spaceId: text('space_id').notNull().references(() => spaces.id, { onDelete: 'cascade' }),
position: integer('position').default(0),
}, (table) => ({
pk: primaryKey({ columns: [table.folderId, table.spaceId] }),
}));
export const userSpaceLayout = sqliteTable('user_space_layout', {
userId: text('user_id').primaryKey().references(() => users.id, { onDelete: 'cascade' }),
layout: text('layout').notNull().default('[]'),
updatedAt: integer('updated_at').notNull(),
});
export const instanceSettings = sqliteTable('instance_settings', {
id: integer('id').primaryKey().default(1),
instanceName: text('instance_name').default('Backspace'),