From ef9c73501c5e872aee1f7630462ec02dddcac13e Mon Sep 17 00:00:00 2001 From: devsyncwrld Date: Wed, 2 Sep 2026 23:36:23 -0300 Subject: [PATCH] =?UTF-8?q?feat(profile):=20a=20full=20identity=20system?= =?UTF-8?q?=20=E2=80=94=20name=20styles,=20decorations,=20effects,=20namep?= =?UTF-8?q?lates,=20tag,=20links,=20board?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The owner asked for profile customisation that is "completo e FODA", pointing at Discord's profile editor. This is the whole thing, end to end, with a live preview. What a user can now set, and where it shows: - Display name style: 10 fonts × 9 effects (solid, gradient, neon, toon, pop, gummy, prism, glitch, fire) × two colours. Popout and full profile. - Avatar decoration: 10 (ring, neon, flames, stars, halo, vines, pixel, hearts, frost, crown). Inline SVG — no image assets, scales to any size. - Profile effect over the banner: 9 (sparkles, rain, snow, matrix, confetti, aurora, embers, bubbles, hearts). CSS particles with seeded positions so re-renders do not change the weather. - Nameplate behind the member-list row: 10 presets + custom two-colour. - Theme: two colours washed behind the card, and the banner fallback. - Pronouns, and a clan-style tag (emoji + 2–4 letters) beside the name, also on the member row. - Links, up to 5, with the brand icon picked from the host. - Board: favourite game, up to 5 in rotation, up to 10 wanted, a quote. Games come from Steam search through a small server proxy (cached, 10 min) or are typed by hand; covers only load from Steam's CDN. - Badges, derived rather than stored: instance admin, server owner, founder (joined in the space's first month), veteran (a year), OG (six months), stylist. Nothing to grant, revoke or migrate. Storage is one JSON column, users.profile_style (migration 0019), and one normaliser in shared/profile.ts that both the server (on write and on read) and the client (on render) run. It never throws: unknown ids fall back, strings are cut to their limits, colours must be #rrggbb, link URLs must be https, cover URLs must be a Steam CDN host. Kept out of the federation durable-field set on purpose — peers on older builds do not know the field, and it is cosmetic. The editor is a new Settings > Profile tab. Its preview is the same ProfileCard component the popout renders, with the draft style swapped in — what you see while editing is, by construction, what others see. Fonts are OFL builds self-hosted from public/fonts alongside DM Sans, latin subsets only, ~120 KB in total. Verified: web build, 517 web tests (11 new: normaliser bounds and fallbacks, link icon detection, badge derivation), server typecheck, 804 server tests. Co-Authored-By: Claude Fable 5.1 --- docs/roadmap-resenha.md | 23 +- .../drizzle/0019_glamorous_crusher_hogan.sql | 1 + .../server/drizzle/meta/0019_snapshot.json | 4535 +++++++++++++++++ packages/server/drizzle/meta/_journal.json | 7 + packages/server/src/db/schema.ts | 4 + packages/server/src/index.ts | 2 + packages/server/src/routes/games.ts | 48 + packages/server/src/routes/users.ts | 15 +- packages/server/src/utils/sanitize.ts | 8 + packages/shared/package.json | 4 +- packages/shared/src/profile.ts | 250 + packages/shared/src/types.ts | 4 + packages/web/public/fonts/Bangers-400.woff2 | Bin 0 -> 8104 bytes packages/web/public/fonts/Cinzel-700.woff2 | Bin 0 -> 8256 bytes packages/web/public/fonts/Fredoka-600.woff2 | Bin 0 -> 5188 bytes packages/web/public/fonts/OFL.txt | 6 + packages/web/public/fonts/Orbitron-700.woff2 | Bin 0 -> 6528 bytes packages/web/public/fonts/Pacifico-400.woff2 | Bin 0 -> 28828 bytes .../public/fonts/PermanentMarker-400.woff2 | Bin 0 -> 29564 bytes .../public/fonts/PlayfairDisplay-700.woff2 | Bin 0 -> 12360 bytes .../web/public/fonts/PressStart2P-400.woff2 | Bin 0 -> 6704 bytes .../web/public/fonts/RubikMonoOne-400.woff2 | Bin 0 -> 6156 bytes packages/web/public/fonts/SpaceMono-700.woff2 | Bin 0 -> 7332 bytes packages/web/src/api/client.ts | 8 + .../src/components/layout/MemberSidebar.tsx | 21 +- .../components/modals/UserProfileModal.tsx | 63 +- .../src/components/modals/UserSettings.tsx | 6 +- .../modals/settingsPanels/ProfilePanel.tsx | 336 ++ .../components/profile/DecoratedAvatar.tsx | 132 + .../src/components/profile/ProfileBadges.tsx | 33 + .../src/components/profile/ProfileCard.tsx | 114 + .../components/profile/ProfileEffectLayer.tsx | 59 + .../src/components/profile/ProfileLinks.tsx | 49 + .../src/components/profile/ProfileTagChip.tsx | 15 + .../src/components/profile/ProfileWidgets.tsx | 93 + .../web/src/components/profile/StyledName.tsx | 19 + .../components/ui/UserProfilePopout.test.tsx | 7 +- .../src/components/ui/UserProfilePopout.tsx | 105 +- packages/web/src/i18n/locales/en.ts | 109 + packages/web/src/i18n/locales/pt-BR.ts | 109 + packages/web/src/stores/authStore.ts | 4 +- packages/web/src/styles/globals.css | 171 + packages/web/src/utils/profileStyle.test.ts | 103 + packages/web/src/utils/profileStyle.ts | 94 + 44 files changed, 6441 insertions(+), 116 deletions(-) create mode 100644 packages/server/drizzle/0019_glamorous_crusher_hogan.sql create mode 100644 packages/server/drizzle/meta/0019_snapshot.json create mode 100644 packages/server/src/routes/games.ts create mode 100644 packages/shared/src/profile.ts create mode 100644 packages/web/public/fonts/Bangers-400.woff2 create mode 100644 packages/web/public/fonts/Cinzel-700.woff2 create mode 100644 packages/web/public/fonts/Fredoka-600.woff2 create mode 100644 packages/web/public/fonts/Orbitron-700.woff2 create mode 100644 packages/web/public/fonts/Pacifico-400.woff2 create mode 100644 packages/web/public/fonts/PermanentMarker-400.woff2 create mode 100644 packages/web/public/fonts/PlayfairDisplay-700.woff2 create mode 100644 packages/web/public/fonts/PressStart2P-400.woff2 create mode 100644 packages/web/public/fonts/RubikMonoOne-400.woff2 create mode 100644 packages/web/public/fonts/SpaceMono-700.woff2 create mode 100644 packages/web/src/components/modals/settingsPanels/ProfilePanel.tsx create mode 100644 packages/web/src/components/profile/DecoratedAvatar.tsx create mode 100644 packages/web/src/components/profile/ProfileBadges.tsx create mode 100644 packages/web/src/components/profile/ProfileCard.tsx create mode 100644 packages/web/src/components/profile/ProfileEffectLayer.tsx create mode 100644 packages/web/src/components/profile/ProfileLinks.tsx create mode 100644 packages/web/src/components/profile/ProfileTagChip.tsx create mode 100644 packages/web/src/components/profile/ProfileWidgets.tsx create mode 100644 packages/web/src/components/profile/StyledName.tsx create mode 100644 packages/web/src/utils/profileStyle.test.ts create mode 100644 packages/web/src/utils/profileStyle.ts diff --git a/docs/roadmap-resenha.md b/docs/roadmap-resenha.md index df6b9ff9..cd4dad08 100644 --- a/docs/roadmap-resenha.md +++ b/docs/roadmap-resenha.md @@ -65,10 +65,27 @@ Ordem sugerida: as pequenas primeiro, as grandes uma de cada vez. | # | Feature | Tamanho | Observação técnica | |---|---|---|---| -## Próximo foco (pedido em 2026-09-02): personalização do usuário e do perfil +## Identidade do perfil (entregue 2026-09-02, pedido: "completo e FODA") -A definir com o dono. Já existe: avatar, banner (imagem ou GIF), cor do avatar -e do banner, sobre mim, status personalizado, atividade (Spotify/jogos). +Uma coluna JSON (`users.profile_style`, migração 0019) normalizada no servidor +por `shared/profile.ts`. Aba **Perfil** nas configurações com prévia ao vivo +(`ProfilePanel` renderiza o mesmo `ProfileCard` que o popout). + +| Peça | Onde aparece | Detalhe | +|---|---|---| +| Estilo do nome — 10 fontes × 9 efeitos × 2 cores | popout, perfil completo | Fontes OFL em `public/fonts`; efeitos são CSS (`.name-fx-*`) | +| Decoração do avatar — 10 | popout, perfil, editor | SVG inline em `DecoratedAvatar`, sem imagens | +| Efeito do perfil — 9 | banner do popout e do perfil | Partículas CSS com posições semeadas (`ProfileEffectLayer`) | +| Nameplate — 10 + personalizado | lista de membros | `.nameplate-*` | +| Tema (2 cores) | fundo do cartão e banner sem imagem | | +| Pronomes, tag (emoji + 2–4 letras) | ao lado do nome; tag também na lista de membros | | +| Links (até 5) | popout e aba Sobre | Ícone detectado pelo host; só https | +| Quadro: jogo favorito, rotação (5), quero jogar (10), citação | aba Quadro do perfil; tira "Coleção" no popout | Busca na Steam via `/api/games/search` (proxy, cache 10 min); capas só de CDN da Steam | +| Emblemas derivados | popout e perfil | admin, dono, fundador (1º mês), veterano (1 ano), OG (6 meses), estiloso — nada é armazenado | + +Fora do escopo desta entrega, candidatos a seguir: perfil por servidor +(apelido/avatar por servidor), emblemas concedidos pelo admin, molduras +animadas por upload, status com expiração. ## Pendente — ideias aprovadas diff --git a/packages/server/drizzle/0019_glamorous_crusher_hogan.sql b/packages/server/drizzle/0019_glamorous_crusher_hogan.sql new file mode 100644 index 00000000..05c22433 --- /dev/null +++ b/packages/server/drizzle/0019_glamorous_crusher_hogan.sql @@ -0,0 +1 @@ +ALTER TABLE `users` ADD `profile_style` text; \ No newline at end of file diff --git a/packages/server/drizzle/meta/0019_snapshot.json b/packages/server/drizzle/meta/0019_snapshot.json new file mode 100644 index 00000000..734009f1 --- /dev/null +++ b/packages/server/drizzle/meta/0019_snapshot.json @@ -0,0 +1,4535 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "29446faf-d621-49d7-a6ff-813332f27afb", + "prevId": "b48dfc32-e13a-47c2-8c0f-21baa5ea7573", + "tables": { + "attachments": { + "name": "attachments", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dm_message_id": { + "name": "dm_message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "uploader_id": { + "name": "uploader_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "original_name": { + "name": "original_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "mimetype": { + "name": "mimetype", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "thumbnail_filename": { + "name": "thumbnail_filename", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "width": { + "name": "width", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "height": { + "name": "height", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "duration": { + "name": "duration", + "type": "real", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "playable": { + "name": "playable", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_url": { + "name": "source_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "federation_status": { + "name": "federation_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "federation_meta": { + "name": "federation_meta", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_attachments_message_id": { + "name": "idx_attachments_message_id", + "columns": [ + "message_id" + ], + "isUnique": false + }, + "idx_attachments_dm_message_id": { + "name": "idx_attachments_dm_message_id", + "columns": [ + "dm_message_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "attachments_message_id_messages_id_fk": { + "name": "attachments_message_id_messages_id_fk", + "tableFrom": "attachments", + "tableTo": "messages", + "columnsFrom": [ + "message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "attachments_dm_message_id_dm_messages_id_fk": { + "name": "attachments_dm_message_id_dm_messages_id_fk", + "tableFrom": "attachments", + "tableTo": "dm_messages", + "columnsFrom": [ + "dm_message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "audit_events": { + "name": "audit_events", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "actor_id": { + "name": "actor_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_type": { + "name": "target_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "target_id": { + "name": "target_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_audit_events_space_created": { + "name": "idx_audit_events_space_created", + "columns": [ + "space_id", + "created_at" + ], + "isUnique": false + }, + "idx_audit_events_actor": { + "name": "idx_audit_events_actor", + "columns": [ + "actor_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "audit_events_space_id_spaces_id_fk": { + "name": "audit_events_space_id_spaces_id_fk", + "tableFrom": "audit_events", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "audit_events_actor_id_users_id_fk": { + "name": "audit_events_actor_id_users_id_fk", + "tableFrom": "audit_events", + "tableTo": "users", + "columnsFrom": [ + "actor_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "bans": { + "name": "bans", + "columns": { + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "banned_by": { + "name": "banned_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_bans_space_id": { + "name": "idx_bans_space_id", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "bans_space_id_spaces_id_fk": { + "name": "bans_space_id_spaces_id_fk", + "tableFrom": "bans", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "bans_user_id_users_id_fk": { + "name": "bans_user_id_users_id_fk", + "tableFrom": "bans", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "bans_banned_by_users_id_fk": { + "name": "bans_banned_by_users_id_fk", + "tableFrom": "bans", + "tableTo": "users", + "columnsFrom": [ + "banned_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "bans_space_id_user_id_pk": { + "columns": [ + "space_id", + "user_id" + ], + "name": "bans_space_id_user_id_pk" + } + }, + "uniqueConstraints": {} + }, + "category_overrides": { + "name": "category_overrides", + "columns": { + "category_id": { + "name": "category_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_type": { + "name": "target_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_id": { + "name": "target_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "allow": { + "name": "allow", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'0'" + }, + "deny": { + "name": "deny", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'0'" + } + }, + "indexes": { + "idx_category_overrides_category_id": { + "name": "idx_category_overrides_category_id", + "columns": [ + "category_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "category_overrides_category_id_channel_categories_id_fk": { + "name": "category_overrides_category_id_channel_categories_id_fk", + "tableFrom": "category_overrides", + "tableTo": "channel_categories", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "category_overrides_category_id_target_type_target_id_pk": { + "columns": [ + "category_id", + "target_type", + "target_id" + ], + "name": "category_overrides_category_id_target_type_target_id_pk" + } + }, + "uniqueConstraints": {} + }, + "channel_categories": { + "name": "channel_categories", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_channel_categories_space_id": { + "name": "idx_channel_categories_space_id", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "channel_categories_space_id_spaces_id_fk": { + "name": "channel_categories_space_id_spaces_id_fk", + "tableFrom": "channel_categories", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "channel_overrides": { + "name": "channel_overrides", + "columns": { + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_type": { + "name": "target_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_id": { + "name": "target_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "allow": { + "name": "allow", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'0'" + }, + "deny": { + "name": "deny", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'0'" + } + }, + "indexes": { + "idx_channel_overrides_channel_id": { + "name": "idx_channel_overrides_channel_id", + "columns": [ + "channel_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "channel_overrides_channel_id_channels_id_fk": { + "name": "channel_overrides_channel_id_channels_id_fk", + "tableFrom": "channel_overrides", + "tableTo": "channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "channel_overrides_channel_id_target_type_target_id_pk": { + "columns": [ + "channel_id", + "target_type", + "target_id" + ], + "name": "channel_overrides_channel_id_target_type_target_id_pk" + } + }, + "uniqueConstraints": {} + }, + "channels": { + "name": "channels", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "topic": { + "name": "topic", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "category_id": { + "name": "category_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_channels_space_id": { + "name": "idx_channels_space_id", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "channels_space_id_spaces_id_fk": { + "name": "channels_space_id_spaces_id_fk", + "tableFrom": "channels", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "dm_channels": { + "name": "dm_channels", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "federated_id": { + "name": "federated_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "owner_home_user_id": { + "name": "owner_home_user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "owner_home_instance": { + "name": "owner_home_instance", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "metadata_updated_at": { + "name": "metadata_updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + } + }, + "indexes": { + "idx_dm_federated": { + "name": "idx_dm_federated", + "columns": [ + "federated_id" + ], + "isUnique": true, + "where": "federated_id IS NOT NULL" + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "dm_members": { + "name": "dm_members", + "columns": { + "dm_channel_id": { + "name": "dm_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "closed": { + "name": "closed", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + } + }, + "indexes": { + "idx_dm_members_user_id": { + "name": "idx_dm_members_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "dm_members_dm_channel_id_dm_channels_id_fk": { + "name": "dm_members_dm_channel_id_dm_channels_id_fk", + "tableFrom": "dm_members", + "tableTo": "dm_channels", + "columnsFrom": [ + "dm_channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "dm_members_user_id_users_id_fk": { + "name": "dm_members_user_id_users_id_fk", + "tableFrom": "dm_members", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "dm_members_dm_channel_id_user_id_pk": { + "columns": [ + "dm_channel_id", + "user_id" + ], + "name": "dm_members_dm_channel_id_user_id_pk" + } + }, + "uniqueConstraints": {} + }, + "dm_messages": { + "name": "dm_messages", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "dm_channel_id": { + "name": "dm_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reply_to_id": { + "name": "reply_to_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'user'" + }, + "edited_at": { + "name": "edited_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_instance": { + "name": "source_instance", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source_message_id": { + "name": "source_message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encryption_version": { + "name": "encryption_version", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_dm_messages_dm_channel_id": { + "name": "idx_dm_messages_dm_channel_id", + "columns": [ + "dm_channel_id" + ], + "isUnique": false + }, + "idx_dm_messages_user_id": { + "name": "idx_dm_messages_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_dm_messages_source_unique": { + "name": "idx_dm_messages_source_unique", + "columns": [ + "source_instance", + "source_message_id" + ], + "isUnique": true, + "where": "source_instance IS NOT NULL" + } + }, + "foreignKeys": { + "dm_messages_dm_channel_id_dm_channels_id_fk": { + "name": "dm_messages_dm_channel_id_dm_channels_id_fk", + "tableFrom": "dm_messages", + "tableTo": "dm_channels", + "columnsFrom": [ + "dm_channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "dm_messages_user_id_users_id_fk": { + "name": "dm_messages_user_id_users_id_fk", + "tableFrom": "dm_messages", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "dm_messages_reply_to_id_dm_messages_id_fk": { + "name": "dm_messages_reply_to_id_dm_messages_id_fk", + "tableFrom": "dm_messages", + "tableTo": "dm_messages", + "columnsFrom": [ + "reply_to_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "dm_reactions": { + "name": "dm_reactions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "dm_message_id": { + "name": "dm_message_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "emoji": { + "name": "emoji", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_dm_reactions_dm_message_id": { + "name": "idx_dm_reactions_dm_message_id", + "columns": [ + "dm_message_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "dm_reactions_dm_message_id_dm_messages_id_fk": { + "name": "dm_reactions_dm_message_id_dm_messages_id_fk", + "tableFrom": "dm_reactions", + "tableTo": "dm_messages", + "columnsFrom": [ + "dm_message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "dm_reactions_user_id_users_id_fk": { + "name": "dm_reactions_user_id_users_id_fk", + "tableFrom": "dm_reactions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "embeds": { + "name": "embeds", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dm_message_id": { + "name": "dm_message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "embed_type": { + "name": "embed_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "embed_url": { + "name": "embed_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "width": { + "name": "width", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "height": { + "name": "height", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_embeds_message_id": { + "name": "idx_embeds_message_id", + "columns": [ + "message_id" + ], + "isUnique": false + }, + "idx_embeds_dm_message_id": { + "name": "idx_embeds_dm_message_id", + "columns": [ + "dm_message_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "embeds_message_id_messages_id_fk": { + "name": "embeds_message_id_messages_id_fk", + "tableFrom": "embeds", + "tableTo": "messages", + "columnsFrom": [ + "message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "embeds_dm_message_id_dm_messages_id_fk": { + "name": "embeds_dm_message_id_dm_messages_id_fk", + "tableFrom": "embeds", + "tableTo": "dm_messages", + "columnsFrom": [ + "dm_message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "federation_attach_proofs": { + "name": "federation_attach_proofs", + "columns": { + "token": { + "name": "token", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "home_user_id": { + "name": "home_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_domain": { + "name": "target_domain", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "used_at": { + "name": "used_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "federation_file_queue": { + "name": "federation_file_queue", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "peer_origin": { + "name": "peer_origin", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "dm_message_id": { + "name": "dm_message_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_url": { + "name": "source_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_filename": { + "name": "target_filename", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "original_name": { + "name": "original_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "mimetype": { + "name": "mimetype", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'pending'" + }, + "rejection_reason": { + "name": "rejection_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "next_retry_at": { + "name": "next_retry_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "federation_mutation_log": { + "name": "federation_mutation_log", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "context_id": { + "name": "context_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "context_type": { + "name": "context_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'dm'" + }, + "mutation_type": { + "name": "mutation_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "mutated_at": { + "name": "mutated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_mutation_log_time": { + "name": "idx_mutation_log_time", + "columns": [ + "mutated_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "federation_outbox": { + "name": "federation_outbox", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "peer_id": { + "name": "peer_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "context_id": { + "name": "context_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_id": { + "name": "entity_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "context_type": { + "name": "context_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'dm'" + }, + "event_type": { + "name": "event_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "encryption_version": { + "name": "encryption_version", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "next_retry_at": { + "name": "next_retry_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_outbox_retry": { + "name": "idx_outbox_retry", + "columns": [ + "next_retry_at" + ], + "isUnique": false + }, + "federation_outbox_peer_id_entity_id_unique": { + "name": "federation_outbox_peer_id_entity_id_unique", + "columns": [ + "peer_id", + "entity_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "federation_outbox_peer_id_federation_peers_id_fk": { + "name": "federation_outbox_peer_id_federation_peers_id_fk", + "tableFrom": "federation_outbox", + "tableTo": "federation_peers", + "columnsFrom": [ + "peer_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "federation_peers": { + "name": "federation_peers", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "origin": { + "name": "origin", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "instance_name": { + "name": "instance_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "hmac_secret": { + "name": "hmac_secret", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'active'" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_failure_at": { + "name": "last_failure_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "consecutive_failures": { + "name": "consecutive_failures", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "consecutive_auth_failures": { + "name": "consecutive_auth_failures", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "last_probe_at": { + "name": "last_probe_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "probe_attempts": { + "name": "probe_attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "last_synced_at": { + "name": "last_synced_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "remote_max_upload_size": { + "name": "remote_max_upload_size", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "nonce_supported": { + "name": "nonce_supported", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "pending_hmac_secret": { + "name": "pending_hmac_secret", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "secret_rotation_at": { + "name": "secret_rotation_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "secret_rotated_at": { + "name": "secret_rotated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auto_rotate_interval_days": { + "name": "auto_rotate_interval_days", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 90 + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "approval_token": { + "name": "approval_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "peer_instance_id": { + "name": "peer_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "observed_peer_instance_id": { + "name": "observed_peer_instance_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "needs_attention_reason": { + "name": "needs_attention_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "federation_peers_origin_unique": { + "name": "federation_peers_origin_unique", + "columns": [ + "origin" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "federation_reset_events": { + "name": "federation_reset_events", + "columns": { + "origin": { + "name": "origin", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "dead_epoch": { + "name": "dead_epoch", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "new_epoch": { + "name": "new_epoch", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "detected_at": { + "name": "detected_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "resolved_at": { + "name": "resolved_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "stub_count": { + "name": "stub_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "orphaned_account_count": { + "name": "orphaned_account_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "acknowledged_at": { + "name": "acknowledged_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "friend_requests": { + "name": "friend_requests", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "from_id": { + "name": "from_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "to_id": { + "name": "to_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'pending'" + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "relay_message_id": { + "name": "relay_message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_friend_requests_to_id": { + "name": "idx_friend_requests_to_id", + "columns": [ + "to_id" + ], + "isUnique": false + }, + "idx_friend_requests_from_id": { + "name": "idx_friend_requests_from_id", + "columns": [ + "from_id" + ], + "isUnique": false + }, + "idx_friend_requests_relay_message_id": { + "name": "idx_friend_requests_relay_message_id", + "columns": [ + "relay_message_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "friend_requests_from_id_users_id_fk": { + "name": "friend_requests_from_id_users_id_fk", + "tableFrom": "friend_requests", + "tableTo": "users", + "columnsFrom": [ + "from_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "friend_requests_to_id_users_id_fk": { + "name": "friend_requests_to_id_users_id_fk", + "tableFrom": "friend_requests", + "tableTo": "users", + "columnsFrom": [ + "to_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "friends": { + "name": "friends", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "friend_id": { + "name": "friend_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_friends_user_id": { + "name": "idx_friends_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_friends_friend_id": { + "name": "idx_friends_friend_id", + "columns": [ + "friend_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "friends_user_id_users_id_fk": { + "name": "friends_user_id_users_id_fk", + "tableFrom": "friends", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "friends_friend_id_users_id_fk": { + "name": "friends_friend_id_users_id_fk", + "tableFrom": "friends", + "tableTo": "users", + "columnsFrom": [ + "friend_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "friends_user_id_friend_id_pk": { + "columns": [ + "user_id", + "friend_id" + ], + "name": "friends_user_id_friend_id_pk" + } + }, + "uniqueConstraints": {} + }, + "gif_favorites": { + "name": "gif_favorites", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "gif_id": { + "name": "gif_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "preview_url": { + "name": "preview_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "width": { + "name": "width", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "height": { + "name": "height", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_gif_favorites_user_id": { + "name": "idx_gif_favorites_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "gif_favorites_user_id_users_id_fk": { + "name": "gif_favorites_user_id_users_id_fk", + "tableFrom": "gif_favorites", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "gif_favorites_user_id_gif_id_pk": { + "columns": [ + "user_id", + "gif_id" + ], + "name": "gif_favorites_user_id_gif_id_pk" + } + }, + "uniqueConstraints": {} + }, + "instance_settings": { + "name": "instance_settings", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "instance_name": { + "name": "instance_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'Backspace'" + }, + "worker_id": { + "name": "worker_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "instance_id": { + "name": "instance_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "discovery_enabled": { + "name": "discovery_enabled", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "max_bitrate_kbps": { + "name": "max_bitrate_kbps", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 20000 + }, + "min_bitrate_kbps": { + "name": "min_bitrate_kbps", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 500 + }, + "bitrate_step_kbps": { + "name": "bitrate_step_kbps", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 500 + }, + "allowed_resolutions": { + "name": "allowed_resolutions", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'540,720,1080'" + }, + "allowed_framerates": { + "name": "allowed_framerates", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'30,45,60'" + }, + "max_resolution": { + "name": "max_resolution", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1080 + }, + "max_framerate": { + "name": "max_framerate", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 60 + }, + "registration_open": { + "name": "registration_open", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "federated_registration_open": { + "name": "federated_registration_open", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "gif_api_key": { + "name": "gif_api_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "bitrate_matrix_overrides": { + "name": "bitrate_matrix_overrides", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "allow_custom_bitrate": { + "name": "allow_custom_bitrate", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "max_upload_size_bytes": { + "name": "max_upload_size_bytes", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "federation_relay_enabled": { + "name": "federation_relay_enabled", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "federation_relay_ttl_days": { + "name": "federation_relay_ttl_days", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 30 + }, + "default_auto_rotate_interval_days": { + "name": "default_auto_rotate_interval_days", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 90 + }, + "auto_accept_peering": { + "name": "auto_accept_peering", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "invite_links": { + "name": "invite_links", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "max_uses": { + "name": "max_uses", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "used_count": { + "name": "used_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "invite_links_token_unique": { + "name": "invite_links_token_unique", + "columns": [ + "token" + ], + "isUnique": true + }, + "idx_invite_links_created_at": { + "name": "idx_invite_links_created_at", + "columns": [ + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "invite_links_created_by_users_id_fk": { + "name": "invite_links_created_by_users_id_fk", + "tableFrom": "invite_links", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "invite_redemptions": { + "name": "invite_redemptions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "invite_id": { + "name": "invite_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "registrant_username": { + "name": "registrant_username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "redeemed_at": { + "name": "redeemed_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_invite_redemptions_invite_id": { + "name": "idx_invite_redemptions_invite_id", + "columns": [ + "invite_id" + ], + "isUnique": false + }, + "idx_invite_redemptions_user_id": { + "name": "idx_invite_redemptions_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "invite_redemptions_invite_id_invite_links_id_fk": { + "name": "invite_redemptions_invite_id_invite_links_id_fk", + "tableFrom": "invite_redemptions", + "tableTo": "invite_links", + "columnsFrom": [ + "invite_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invite_redemptions_user_id_users_id_fk": { + "name": "invite_redemptions_user_id_users_id_fk", + "tableFrom": "invite_redemptions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "join_requests": { + "name": "join_requests", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'pending'" + }, + "decided_by": { + "name": "decided_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "decided_at": { + "name": "decided_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_join_requests_space_id_status": { + "name": "idx_join_requests_space_id_status", + "columns": [ + "space_id", + "status" + ], + "isUnique": false + } + }, + "foreignKeys": { + "join_requests_space_id_spaces_id_fk": { + "name": "join_requests_space_id_spaces_id_fk", + "tableFrom": "join_requests", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "join_requests_user_id_users_id_fk": { + "name": "join_requests_user_id_users_id_fk", + "tableFrom": "join_requests", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "join_requests_decided_by_users_id_fk": { + "name": "join_requests_decided_by_users_id_fk", + "tableFrom": "join_requests", + "tableTo": "users", + "columnsFrom": [ + "decided_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "member_roles": { + "name": "member_roles", + "columns": { + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_member_roles_user_id_space_id": { + "name": "idx_member_roles_user_id_space_id", + "columns": [ + "user_id", + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "member_roles_space_id_spaces_id_fk": { + "name": "member_roles_space_id_spaces_id_fk", + "tableFrom": "member_roles", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_roles_user_id_users_id_fk": { + "name": "member_roles_user_id_users_id_fk", + "tableFrom": "member_roles", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_roles_role_id_roles_id_fk": { + "name": "member_roles_role_id_roles_id_fk", + "tableFrom": "member_roles", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "member_roles_space_id_user_id_role_id_pk": { + "columns": [ + "space_id", + "user_id", + "role_id" + ], + "name": "member_roles_space_id_user_id_role_id_pk" + } + }, + "uniqueConstraints": {} + }, + "messages": { + "name": "messages", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reply_to_id": { + "name": "reply_to_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "edited_at": { + "name": "edited_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pinned_at": { + "name": "pinned_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pinned_by": { + "name": "pinned_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sticker_id": { + "name": "sticker_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'user'" + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_messages_channel_id": { + "name": "idx_messages_channel_id", + "columns": [ + "channel_id" + ], + "isUnique": false + }, + "idx_messages_user_id": { + "name": "idx_messages_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_messages_channel_pinned": { + "name": "idx_messages_channel_pinned", + "columns": [ + "channel_id", + "pinned_at" + ], + "isUnique": false + }, + "idx_messages_channel_user_created": { + "name": "idx_messages_channel_user_created", + "columns": [ + "channel_id", + "user_id", + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "messages_channel_id_channels_id_fk": { + "name": "messages_channel_id_channels_id_fk", + "tableFrom": "messages", + "tableTo": "channels", + "columnsFrom": [ + "channel_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "messages_user_id_users_id_fk": { + "name": "messages_user_id_users_id_fk", + "tableFrom": "messages", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "messages_reply_to_id_messages_id_fk": { + "name": "messages_reply_to_id_messages_id_fk", + "tableFrom": "messages", + "tableTo": "messages", + "columnsFrom": [ + "reply_to_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "peer_approval_notifications": { + "name": "peer_approval_notifications", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "peer_origin": { + "name": "peer_origin", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "trigger_reason": { + "name": "trigger_reason", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "trigger_target": { + "name": "trigger_target", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "read_at": { + "name": "read_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_peer_approval_notifications_user_id": { + "name": "idx_peer_approval_notifications_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "peer_approval_notifications_user_id_users_id_fk": { + "name": "peer_approval_notifications_user_id_users_id_fk", + "tableFrom": "peer_approval_notifications", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "peer_approval_requests": { + "name": "peer_approval_requests", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "origin": { + "name": "origin", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "direction": { + "name": "direction", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'inbound'" + }, + "instance_name": { + "name": "instance_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "hmac_secret": { + "name": "hmac_secret", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "requested_at": { + "name": "requested_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "approval_token": { + "name": "approval_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "peer_approval_requests_origin_direction_unique": { + "name": "peer_approval_requests_origin_direction_unique", + "columns": [ + "origin", + "direction" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "peer_approval_subscribers": { + "name": "peer_approval_subscribers", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "request_id": { + "name": "request_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "trigger_reason": { + "name": "trigger_reason", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "trigger_target": { + "name": "trigger_target", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_peer_approval_subscribers_user_id": { + "name": "idx_peer_approval_subscribers_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "peer_approval_subscribers_request_id_user_id_trigger_reason_trigger_target_unique": { + "name": "peer_approval_subscribers_request_id_user_id_trigger_reason_trigger_target_unique", + "columns": [ + "request_id", + "user_id", + "trigger_reason", + "trigger_target" + ], + "isUnique": true + } + }, + "foreignKeys": { + "peer_approval_subscribers_request_id_peer_approval_requests_id_fk": { + "name": "peer_approval_subscribers_request_id_peer_approval_requests_id_fk", + "tableFrom": "peer_approval_subscribers", + "tableTo": "peer_approval_requests", + "columnsFrom": [ + "request_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "peer_approval_subscribers_user_id_users_id_fk": { + "name": "peer_approval_subscribers_user_id_users_id_fk", + "tableFrom": "peer_approval_subscribers", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "reactions": { + "name": "reactions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "emoji": { + "name": "emoji", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_reactions_message_id": { + "name": "idx_reactions_message_id", + "columns": [ + "message_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "reactions_message_id_messages_id_fk": { + "name": "reactions_message_id_messages_id_fk", + "tableFrom": "reactions", + "tableTo": "messages", + "columnsFrom": [ + "message_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "reactions_user_id_users_id_fk": { + "name": "reactions_user_id_users_id_fk", + "tableFrom": "reactions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "read_states": { + "name": "read_states", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_read_message_id": { + "name": "last_read_message_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_read_states_user_id": { + "name": "idx_read_states_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "read_states_user_id_users_id_fk": { + "name": "read_states_user_id_users_id_fk", + "tableFrom": "read_states", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "read_states_user_id_channel_id_pk": { + "columns": [ + "user_id", + "channel_id" + ], + "name": "read_states_user_id_channel_id_pk" + } + }, + "uniqueConstraints": {} + }, + "roles": { + "name": "roles", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'#b9bbbe'" + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_roles_space_id": { + "name": "idx_roles_space_id", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "roles_space_id_spaces_id_fk": { + "name": "roles_space_id_spaces_id_fk", + "tableFrom": "roles", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "soundboard_sounds": { + "name": "soundboard_sounds", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "uploader_id": { + "name": "uploader_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_soundboard_space": { + "name": "idx_soundboard_space", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "soundboard_sounds_space_id_spaces_id_fk": { + "name": "soundboard_sounds_space_id_spaces_id_fk", + "tableFrom": "soundboard_sounds", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "soundboard_sounds_uploader_id_users_id_fk": { + "name": "soundboard_sounds_uploader_id_users_id_fk", + "tableFrom": "soundboard_sounds", + "tableTo": "users", + "columnsFrom": [ + "uploader_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "space_emojis": { + "name": "space_emojis", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "uploader_id": { + "name": "uploader_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_space_emojis_space": { + "name": "idx_space_emojis_space", + "columns": [ + "space_id" + ], + "isUnique": false + }, + "idx_space_emojis_space_name": { + "name": "idx_space_emojis_space_name", + "columns": [ + "space_id", + "name" + ], + "isUnique": true + } + }, + "foreignKeys": { + "space_emojis_space_id_spaces_id_fk": { + "name": "space_emojis_space_id_spaces_id_fk", + "tableFrom": "space_emojis", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "space_emojis_uploader_id_users_id_fk": { + "name": "space_emojis_uploader_id_users_id_fk", + "tableFrom": "space_emojis", + "tableTo": "users", + "columnsFrom": [ + "uploader_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "space_folder_members": { + "name": "space_folder_members", + "columns": { + "folder_id": { + "name": "folder_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "space_folder_members_folder_id_space_folders_id_fk": { + "name": "space_folder_members_folder_id_space_folders_id_fk", + "tableFrom": "space_folder_members", + "tableTo": "space_folders", + "columnsFrom": [ + "folder_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "space_folder_members_folder_id_space_id_pk": { + "columns": [ + "folder_id", + "space_id" + ], + "name": "space_folder_members_folder_id_space_id_pk" + } + }, + "uniqueConstraints": {} + }, + "space_folders": { + "name": "space_folders", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "space_folders_user_id_users_id_fk": { + "name": "space_folders_user_id_users_id_fk", + "tableFrom": "space_folders", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "space_members": { + "name": "space_members", + "columns": { + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "nickname": { + "name": "nickname", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "joined_at": { + "name": "joined_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_space_members_user_id": { + "name": "idx_space_members_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "space_members_space_id_spaces_id_fk": { + "name": "space_members_space_id_spaces_id_fk", + "tableFrom": "space_members", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "space_members_user_id_users_id_fk": { + "name": "space_members_user_id_users_id_fk", + "tableFrom": "space_members", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "space_members_space_id_user_id_pk": { + "columns": [ + "space_id", + "user_id" + ], + "name": "space_members_space_id_user_id_pk" + } + }, + "uniqueConstraints": {} + }, + "space_stickers": { + "name": "space_stickers", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "filename": { + "name": "filename", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "uploader_id": { + "name": "uploader_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_space_stickers_space": { + "name": "idx_space_stickers_space", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "space_stickers_space_id_spaces_id_fk": { + "name": "space_stickers_space_id_spaces_id_fk", + "tableFrom": "space_stickers", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "space_stickers_uploader_id_users_id_fk": { + "name": "space_stickers_uploader_id_users_id_fk", + "tableFrom": "space_stickers", + "tableTo": "users", + "columnsFrom": [ + "uploader_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "spaces": { + "name": "spaces", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "banner": { + "name": "banner", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "avatar_color": { + "name": "avatar_color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "owner_id": { + "name": "owner_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "invite_code": { + "name": "invite_code", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "visibility": { + "name": "visibility", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'private'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "spaces_invite_code_unique": { + "name": "spaces_invite_code_unique", + "columns": [ + "invite_code" + ], + "isUnique": true + } + }, + "foreignKeys": { + "spaces_owner_id_users_id_fk": { + "name": "spaces_owner_id_users_id_fk", + "tableFrom": "spaces", + "tableTo": "users", + "columnsFrom": [ + "owner_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "spotify_connections": { + "name": "spotify_connections", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "spotify_user_id": { + "name": "spotify_user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "spotify_connections_user_id_users_id_fk": { + "name": "spotify_connections_user_id_users_id_fk", + "tableFrom": "spotify_connections", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "user_federation_registry": { + "name": "user_federation_registry", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "origin": { + "name": "origin", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "remote_user_id": { + "name": "remote_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "''" + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'connected'" + }, + "added_at": { + "name": "added_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_connected_at": { + "name": "last_connected_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "disconnected_at": { + "name": "disconnected_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "user_federation_registry_user_id_users_id_fk": { + "name": "user_federation_registry_user_id_users_id_fk", + "tableFrom": "user_federation_registry", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_federation_registry_user_id_origin_pk": { + "columns": [ + "user_id", + "origin" + ], + "name": "user_federation_registry_user_id_origin_pk" + } + }, + "uniqueConstraints": {} + }, + "user_space_layout": { + "name": "user_space_layout", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "layout": { + "name": "layout", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'[]'" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "user_space_layout_user_id_users_id_fk": { + "name": "user_space_layout_user_id_users_id_fk", + "tableFrom": "user_space_layout", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'offline'" + }, + "custom_status": { + "name": "custom_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_admin": { + "name": "is_admin", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "home_instance": { + "name": "home_instance", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "home_user_id": { + "name": "home_user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "replicated_instances": { + "name": "replicated_instances", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'[]'" + }, + "banner": { + "name": "banner", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "accent_color": { + "name": "accent_color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "avatar_color": { + "name": "avatar_color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "bio": { + "name": "bio", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_deleted": { + "name": "is_deleted", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "discoverable": { + "name": "discoverable", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 1 + }, + "profile_updated_at": { + "name": "profile_updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password_changed_at": { + "name": "password_changed_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "show_activity": { + "name": "show_activity", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "profile_style": { + "name": "profile_style", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "federation_registry_updated_at": { + "name": "federation_registry_updated_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "federation_heal_pending": { + "name": "federation_heal_pending", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "federation_home_orphaned": { + "name": "federation_home_orphaned", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "users_username_unique": { + "name": "users_username_unique", + "columns": [ + "username" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "voice_restrictions": { + "name": "voice_restrictions", + "columns": { + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "restriction_type": { + "name": "restriction_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "moderator_id": { + "name": "moderator_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_voice_restrictions_space_id": { + "name": "idx_voice_restrictions_space_id", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "voice_restrictions_space_id_spaces_id_fk": { + "name": "voice_restrictions_space_id_spaces_id_fk", + "tableFrom": "voice_restrictions", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "voice_restrictions_user_id_users_id_fk": { + "name": "voice_restrictions_user_id_users_id_fk", + "tableFrom": "voice_restrictions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "voice_restrictions_moderator_id_users_id_fk": { + "name": "voice_restrictions_moderator_id_users_id_fk", + "tableFrom": "voice_restrictions", + "tableTo": "users", + "columnsFrom": [ + "moderator_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "voice_restrictions_space_id_user_id_restriction_type_pk": { + "columns": [ + "space_id", + "user_id", + "restriction_type" + ], + "name": "voice_restrictions_space_id_user_id_restriction_type_pk" + } + }, + "uniqueConstraints": {} + }, + "voice_sessions": { + "name": "voice_sessions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "started_at": { + "name": "started_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ended_at": { + "name": "ended_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_voice_sessions_space_started": { + "name": "idx_voice_sessions_space_started", + "columns": [ + "space_id", + "started_at" + ], + "isUnique": false + }, + "idx_voice_sessions_user": { + "name": "idx_voice_sessions_user", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_voice_sessions_ended": { + "name": "idx_voice_sessions_ended", + "columns": [ + "ended_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "voice_sessions_space_id_spaces_id_fk": { + "name": "voice_sessions_space_id_spaces_id_fk", + "tableFrom": "voice_sessions", + "tableTo": "spaces", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "voice_sessions_user_id_users_id_fk": { + "name": "voice_sessions_user_id_users_id_fk", + "tableFrom": "voice_sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/packages/server/drizzle/meta/_journal.json b/packages/server/drizzle/meta/_journal.json index 21f2e144..5c637488 100644 --- a/packages/server/drizzle/meta/_journal.json +++ b/packages/server/drizzle/meta/_journal.json @@ -134,6 +134,13 @@ "when": 1788401450986, "tag": "0018_eminent_kid_colt", "breakpoints": true + }, + { + "idx": 19, + "version": "6", + "when": 1788402724322, + "tag": "0019_glamorous_crusher_hogan", + "breakpoints": true } ] } \ No newline at end of file diff --git a/packages/server/src/db/schema.ts b/packages/server/src/db/schema.ts index 40697c6a..6d55b7cf 100644 --- a/packages/server/src/db/schema.ts +++ b/packages/server/src/db/schema.ts @@ -22,6 +22,10 @@ export const users = sqliteTable('users', { profileUpdatedAt: integer('profile_updated_at'), passwordChangedAt: integer('password_changed_at'), showActivity: integer('show_activity').notNull().default(1), + // JSON ProfileStyle (shared/profile.ts), normalised on write. One column, + // not twelve: every field is optional, nothing is queried by value, and the + // shape keeps growing. Null means defaults. + profileStyle: text('profile_style'), federationRegistryUpdatedAt: integer('federation_registry_updated_at').default(0), federationHealPending: integer('federation_heal_pending').default(0), federationHomeOrphaned: integer('federation_home_orphaned').default(0), diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index b5bcb96e..835352f8 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -31,6 +31,7 @@ import { searchRoutes } from './routes/search.js'; import { adminRoutes } from './routes/admin.js'; import { gifRoutes } from './routes/gif.js'; import { federationRoutes } from './routes/federation.js'; +import { gameRoutes } from './routes/games.js'; import { startFederationWorkers, stopFederationWorkers } from './utils/federationWorker.js'; import { startBackupWorker, stopBackupWorker } from './utils/backupWorker.js'; import './utils/federationRollback.js'; // Side-effect: registers rollback callbacks for outbox terminal failures. @@ -150,6 +151,7 @@ async function main(): Promise { await app.register(searchRoutes); await app.register(adminRoutes); await app.register(gifRoutes); + await app.register(gameRoutes); await app.register(federationRoutes); await app.register(registerWebSocket); diff --git a/packages/server/src/routes/games.ts b/packages/server/src/routes/games.ts new file mode 100644 index 00000000..3eac4e79 --- /dev/null +++ b/packages/server/src/routes/games.ts @@ -0,0 +1,48 @@ +import type { FastifyInstance } from 'fastify'; +import { authenticate } from '../utils/auth.js'; +import { steamCoverUrl } from '@backspace/shared/src/profile.js'; + +/** + * Game lookup for profile widgets, backed by Steam's public store search. + * + * Proxied rather than called from the browser: the store endpoint has no CORS + * headers, and going through here means one place to cache, to bound the + * query, and to swap the source later without touching clients. No key is + * involved — it is the same unauthenticated endpoint the store website uses. + */ +interface SteamSearchItem { id: number; name: string; tiny_image?: string } +interface GameHit { appId: number; name: string; cover: string; header: string } + +const CACHE_TTL_MS = 10 * 60 * 1000; +const cache = new Map(); + +export async function gameRoutes(app: FastifyInstance): Promise { + app.get<{ Querystring: { q?: string } }>('/api/games/search', { preHandler: authenticate }, async (request, reply) => { + const q = (request.query.q ?? '').trim().slice(0, 60); + if (q.length < 2) return reply.send({ hits: [] }); + + const key = q.toLowerCase(); + const cached = cache.get(key); + if (cached && Date.now() - cached.at < CACHE_TTL_MS) return reply.send({ hits: cached.hits }); + + try { + const url = `https://store.steampowered.com/api/storesearch/?term=${encodeURIComponent(q)}&l=brazilian&cc=BR`; + const res = await fetch(url, { signal: AbortSignal.timeout(6000), headers: { 'User-Agent': 'Resenhacord/1.0' } }); + if (!res.ok) return reply.send({ hits: [] }); + const data = (await res.json()) as { items?: SteamSearchItem[] }; + const hits: GameHit[] = (data.items ?? []).slice(0, 8).map((it) => ({ + appId: it.id, + name: it.name, + cover: steamCoverUrl(it.id), + header: `https://cdn.cloudflare.steamstatic.com/steam/apps/${it.id}/header.jpg`, + })); + cache.set(key, { at: Date.now(), hits }); + if (cache.size > 500) cache.delete(cache.keys().next().value!); + return reply.send({ hits }); + } catch { + // Upstream hiccup is not the user's problem: an empty list lets them + // type the title by hand instead. + return reply.send({ hits: [] }); + } + }); +} diff --git a/packages/server/src/routes/users.ts b/packages/server/src/routes/users.ts index c4bcd76d..db591f0b 100644 --- a/packages/server/src/routes/users.ts +++ b/packages/server/src/routes/users.ts @@ -15,6 +15,7 @@ import { config } from '../config.js'; import { buildFederationHeaders, getOurOrigin } from '../utils/federationAuth.js'; import { extractDomain } from './federation.js'; import path from 'path'; +import { normalizeProfileStyle } from '@backspace/shared/src/profile.js'; /** Validates that a URL is a safe asset URL (relative upload path, bare filename, or http/https) */ export function isValidAssetUrl(url: string | null | undefined): boolean { @@ -187,7 +188,7 @@ export async function userRoutes(app: FastifyInstance): Promise { }); app.patch<{ Body: UpdateUserRequest }>('/api/users/@me', { preHandler: authenticate }, async (request, reply) => { - const { displayName, avatar, banner, accentColor, avatarColor, bio, customStatus, status, replicatedInstances, homeUserId, profileUpdatedAt, discoverable, showActivity } = request.body; + const { displayName, avatar, banner, accentColor, avatarColor, bio, customStatus, status, replicatedInstances, homeUserId, profileUpdatedAt, discoverable, showActivity, profileStyle } = request.body; const db = getDb(); const updateData: Record = {}; @@ -426,12 +427,22 @@ export async function userRoutes(app: FastifyInstance): Promise { (updateData as Record).showActivity = showActivity ? 1 : 0; } + // Profile style is normalised, never rejected: the shared normaliser + // clamps lengths, drops bad URLs and falls back on unknown ids, so the + // stored value is always well-formed. Null resets to defaults. Kept out of + // DURABLE_PROFILE_FIELDS on purpose — peers on older builds do not know + // the field, and it is cosmetic, so it stays local to this instance. + if (profileStyle !== undefined) { + (updateData as Record).profileStyle = + profileStyle === null ? null : JSON.stringify(normalizeProfileStyle(profileStyle)); + } + if (Object.keys(updateData).length === 0) { return reply.code(400).send({ error: 'No fields to update', statusCode: 400 }); } // Detect profile changes and stamp timestamp - const hasProfileChange = ['displayName', 'avatar', 'banner', 'accentColor', 'avatarColor', 'bio', 'customStatus'].some(f => f in updateData); + const hasProfileChange = ['displayName', 'avatar', 'banner', 'accentColor', 'avatarColor', 'bio', 'customStatus', 'profileStyle'].some(f => f in updateData); const hasDurableChange = DURABLE_PROFILE_FIELDS.some(f => f in updateData); if (hasDurableChange) { (updateData as Record).profileUpdatedAt = Date.now(); diff --git a/packages/server/src/utils/sanitize.ts b/packages/server/src/utils/sanitize.ts index d4f65faa..bbe64ec8 100644 --- a/packages/server/src/utils/sanitize.ts +++ b/packages/server/src/utils/sanitize.ts @@ -1,6 +1,11 @@ import type { User, ReplicatedInstance } from '@backspace/shared'; +import { normalizeProfileStyle } from '@backspace/shared/src/profile.js'; import { schema } from '../db/index.js'; +function safeParse(json: string): unknown { + try { return JSON.parse(json); } catch { return null; } +} + export function sanitizeUser(row: typeof schema.users.$inferSelect, isSelf = false): User { // Tombstoned (deleted) users — return anonymized profile if (row.isDeleted === 1) { @@ -54,6 +59,9 @@ export function sanitizeUser(row: typeof schema.users.$inferSelect, isSelf = fal homeInstance: row.homeInstance ?? null, homeUserId: row.homeUserId ?? null, replicatedInstances, + // Re-normalised on read as well: a row written by an older build (or a + // stricter future one) still comes out complete and bounded. + profileStyle: row.profileStyle ? normalizeProfileStyle(safeParse(row.profileStyle)) : null, ...(isSelf ? { showActivity: row.showActivity !== 0, diff --git a/packages/shared/package.json b/packages/shared/package.json index 7256b63b..1800ac91 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -18,7 +18,9 @@ "./src/audit": "./src/audit.ts", "./src/audit.js": "./src/audit.ts", "./src/mentions": "./src/mentions.ts", - "./src/mentions.js": "./src/mentions.ts" + "./src/mentions.js": "./src/mentions.ts", + "./src/profile": "./src/profile.ts", + "./src/profile.js": "./src/profile.ts" }, "scripts": { "build": "tsc", diff --git a/packages/shared/src/profile.ts b/packages/shared/src/profile.ts new file mode 100644 index 00000000..e4c6d94d --- /dev/null +++ b/packages/shared/src/profile.ts @@ -0,0 +1,250 @@ +/** + * Profile identity: everything a user can style about how they appear, beyond + * the avatar/banner/bio fields that predate it. + * + * Stored as one JSON column (`users.profile_style`) rather than a dozen + * columns: the shape will keep growing (new effects, new widgets), every field + * is optional, and nothing here is ever queried by value. The server + * normalises on write with `normalizeProfileStyle`, so what reaches clients is + * always a complete, bounded, well-formed object. + * + * Catalog ids are strings on purpose — a client that does not know an id + * (older build, other instance) falls back to `none`/`default` instead of + * crashing on an enum it has never seen. + */ + +export const NAME_FONTS = [ + 'default', 'display', 'comic', 'script', 'pixel', 'future', 'serif', 'mono', 'round', 'marker', +] as const; +export type NameFont = (typeof NAME_FONTS)[number]; + +export const NAME_EFFECTS = [ + 'solid', 'gradient', 'neon', 'toon', 'pop', 'gummy', 'prism', 'glitch', 'fire', +] as const; +export type NameEffect = (typeof NAME_EFFECTS)[number]; + +export const AVATAR_DECORATIONS = [ + 'none', 'ring', 'neon', 'flames', 'stars', 'halo', 'vines', 'pixel', 'hearts', 'frost', 'crown', +] as const; +export type AvatarDecoration = (typeof AVATAR_DECORATIONS)[number]; + +export const PROFILE_EFFECTS = [ + 'none', 'sparkles', 'rain', 'snow', 'matrix', 'confetti', 'aurora', 'embers', 'bubbles', 'hearts', +] as const; +export type ProfileEffect = (typeof PROFILE_EFFECTS)[number]; + +export const NAMEPLATES = [ + 'none', 'sunset', 'ocean', 'neon', 'forest', 'royal', 'brasil', 'cyber', 'blossom', 'midnight', 'custom', +] as const; +export type Nameplate = (typeof NAMEPLATES)[number]; + +export interface NameStyle { + font: NameFont; + effect: NameEffect; + /** Two hex colours. Solid uses the first; every other effect uses both. */ + colors: [string, string]; +} + +export interface ProfileTheme { + /** Two hex colours behind the card and the banner fallback. */ + colors: [string, string]; +} + +export interface ProfileTag { + /** 2–4 characters, shown uppercase in a chip next to the name. */ + text: string; + /** Single emoji (grapheme) in front of the text; empty for none. */ + emoji: string; + color: string; +} + +export interface ProfileLink { + label: string; + url: string; +} + +export interface GameEntry { + /** Steam app id when picked from search; null for a free-typed title. */ + appId: number | null; + name: string; + /** https URL of a cover image (Steam CDN when picked from search). */ + cover: string | null; + note: string; + tags: string[]; +} + +export interface ProfileQuote { + text: string; + author: string; +} + +export interface ProfileWidgets { + favoriteGame: GameEntry | null; + rotation: GameEntry[]; + wishlist: GameEntry[]; + quote: ProfileQuote | null; +} + +export interface ProfileStyle { + name: NameStyle; + theme: ProfileTheme | null; + decoration: AvatarDecoration; + effect: ProfileEffect; + nameplate: Nameplate; + /** Only read when nameplate === 'custom'. */ + nameplateColors: [string, string]; + pronouns: string; + tag: ProfileTag | null; + links: ProfileLink[]; + widgets: ProfileWidgets; +} + +export const PROFILE_LIMITS = { + pronouns: 40, + tagMin: 2, + tagMax: 4, + links: 5, + linkLabel: 24, + linkUrl: 200, + gameName: 80, + gameNote: 80, + gameTags: 3, + gameTag: 16, + rotation: 5, + wishlist: 10, + quoteText: 140, + quoteAuthor: 40, +} as const; + +export const DEFAULT_PROFILE_STYLE: ProfileStyle = { + name: { font: 'default', effect: 'solid', colors: ['#efefef', '#7c6cf6'] }, + theme: null, + decoration: 'none', + effect: 'none', + nameplate: 'none', + nameplateColors: ['#7c6cf6', '#f472b6'], + pronouns: '', + tag: null, + links: [], + widgets: { favoriteGame: null, rotation: [], wishlist: [], quote: null }, +}; + +// ─── Normalisation ──────────────────────────────────────────────────────────── + +const HEX = /^#[0-9a-fA-F]{6}$/; +/** Domains whose images a profile may embed. Anything else is dropped, not + * proxied — a profile is not a place to load arbitrary third-party pixels. */ +const COVER_HOSTS = ['cdn.cloudflare.steamstatic.com', 'cdn.akamai.steamstatic.com', 'shared.cloudflare.steamstatic.com', 'shared.akamai.steamstatic.com', 'steamcdn-a.akamaihd.net']; + +function pick(value: unknown, allowed: readonly T[], fallback: T): T { + return typeof value === 'string' && (allowed as readonly string[]).includes(value) ? (value as T) : fallback; +} +function hex(value: unknown, fallback: string): string { + return typeof value === 'string' && HEX.test(value) ? value.toLowerCase() : fallback; +} +function str(value: unknown, max: number): string { + return typeof value === 'string' ? value.trim().slice(0, max) : ''; +} +function httpsUrl(value: unknown, max: number): string | null { + if (typeof value !== 'string') return null; + const v = value.trim(); + if (v.length === 0 || v.length > max) return null; + try { + const u = new URL(v); + return u.protocol === 'https:' ? u.toString() : null; + } catch { return null; } +} +function coverUrl(value: unknown): string | null { + const u = httpsUrl(value, 300); + if (!u) return null; + try { return COVER_HOSTS.includes(new URL(u).hostname) ? u : null; } catch { return null; } +} +/** First grapheme only — one emoji, not a sentence hidden in the tag. */ +function oneGrapheme(value: unknown): string { + if (typeof value !== 'string') return ''; + const s = value.trim(); + if (!s) return ''; + const seg = (Intl as unknown as { Segmenter?: new (l: string, o: { granularity: string }) => { segment: (s: string) => Iterable<{ segment: string }> } }).Segmenter; + if (seg) { + for (const g of new seg('und', { granularity: 'grapheme' }).segment(s)) return g.segment; + } + return Array.from(s)[0] ?? ''; +} +function game(value: unknown): GameEntry | null { + if (!value || typeof value !== 'object') return null; + const v = value as Record; + const name = str(v.name, PROFILE_LIMITS.gameName); + if (!name) return null; + const appId = typeof v.appId === 'number' && Number.isInteger(v.appId) && v.appId > 0 ? v.appId : null; + const tags = Array.isArray(v.tags) + ? v.tags.map((t) => str(t, PROFILE_LIMITS.gameTag)).filter(Boolean).slice(0, PROFILE_LIMITS.gameTags) + : []; + return { appId, name, cover: coverUrl(v.cover), note: str(v.note, PROFILE_LIMITS.gameNote), tags }; +} +function games(value: unknown, max: number): GameEntry[] { + return Array.isArray(value) ? value.map(game).filter((g): g is GameEntry => g !== null).slice(0, max) : []; +} + +/** + * Coerces any input into a valid ProfileStyle. Never throws: unknown ids fall + * back to defaults, over-long strings are cut, bad colours are replaced, bad + * URLs are dropped. The server stores exactly this output. + */ +export function normalizeProfileStyle(input: unknown): ProfileStyle { + const d = DEFAULT_PROFILE_STYLE; + const v = (input && typeof input === 'object' ? input : {}) as Record; + const name = (v.name && typeof v.name === 'object' ? v.name : {}) as Record; + const nameColors = Array.isArray(name.colors) ? name.colors : []; + const theme = (v.theme && typeof v.theme === 'object' ? v.theme : null) as Record | null; + const themeColors = theme && Array.isArray(theme.colors) ? theme.colors : null; + const npColors = Array.isArray(v.nameplateColors) ? v.nameplateColors : []; + const tag = (v.tag && typeof v.tag === 'object' ? v.tag : null) as Record | null; + const tagText = tag ? str(tag.text, PROFILE_LIMITS.tagMax).toUpperCase().replace(/[^A-Z0-9]/g, '') : ''; + const widgets = (v.widgets && typeof v.widgets === 'object' ? v.widgets : {}) as Record; + const quote = (widgets.quote && typeof widgets.quote === 'object' ? widgets.quote : null) as Record | null; + const quoteText = quote ? str(quote.text, PROFILE_LIMITS.quoteText) : ''; + + const links: ProfileLink[] = Array.isArray(v.links) + ? v.links.map((l) => { + const o = (l && typeof l === 'object' ? l : {}) as Record; + const url = httpsUrl(o.url, PROFILE_LIMITS.linkUrl); + if (!url) return null; + const label = str(o.label, PROFILE_LIMITS.linkLabel) || new URL(url).hostname.replace(/^www\./, ''); + return { label, url }; + }).filter((l): l is ProfileLink => l !== null).slice(0, PROFILE_LIMITS.links) + : []; + + return { + name: { + font: pick(name.font, NAME_FONTS, d.name.font), + effect: pick(name.effect, NAME_EFFECTS, d.name.effect), + colors: [hex(nameColors[0], d.name.colors[0]), hex(nameColors[1], d.name.colors[1])], + }, + theme: themeColors ? { colors: [hex(themeColors[0], '#7c6cf6'), hex(themeColors[1], '#0b0b10')] } : null, + decoration: pick(v.decoration, AVATAR_DECORATIONS, d.decoration), + effect: pick(v.effect, PROFILE_EFFECTS, d.effect), + nameplate: pick(v.nameplate, NAMEPLATES, d.nameplate), + nameplateColors: [hex(npColors[0], d.nameplateColors[0]), hex(npColors[1], d.nameplateColors[1])], + pronouns: str(v.pronouns, PROFILE_LIMITS.pronouns), + tag: tagText.length >= PROFILE_LIMITS.tagMin + ? { text: tagText, emoji: oneGrapheme(tag?.emoji), color: hex(tag?.color, '#7c6cf6') } + : null, + links, + widgets: { + favoriteGame: game(widgets.favoriteGame), + rotation: games(widgets.rotation, PROFILE_LIMITS.rotation), + wishlist: games(widgets.wishlist, PROFILE_LIMITS.wishlist), + quote: quoteText ? { text: quoteText, author: str(quote?.author, PROFILE_LIMITS.quoteAuthor) } : null, + }, + }; +} + +/** Whether a style differs from the defaults — used to skip rendering work. */ +export function isDefaultProfileStyle(s: ProfileStyle | null | undefined): boolean { + return !s || JSON.stringify(s) === JSON.stringify(DEFAULT_PROFILE_STYLE); +} + +/** Steam's poster-format cover for an app id. */ +export function steamCoverUrl(appId: number): string { + return `https://cdn.cloudflare.steamstatic.com/steam/apps/${appId}/library_600x900.jpg`; +} diff --git a/packages/shared/src/types.ts b/packages/shared/src/types.ts index ed03d43e..cad82020 100644 --- a/packages/shared/src/types.ts +++ b/packages/shared/src/types.ts @@ -29,6 +29,8 @@ export interface User { showActivity?: boolean; /** Self-view only: this federated account's home instance was reset/lost — it now operates as a sovereign local account (detach spec). */ federationHomeOrphaned?: boolean; + /** Name style, decorations, effects, tag, links, widgets. See shared/profile.ts. Null = defaults. */ + profileStyle?: import('./profile').ProfileStyle | null; } export interface ReplicatedInstance { @@ -591,6 +593,8 @@ export interface UpdateUserRequest { profileUpdatedAt?: number; discoverable?: boolean; showActivity?: boolean; + /** Normalised server-side; pass null to reset to defaults. */ + profileStyle?: import('./profile').ProfileStyle | null; } export interface UpdateMemberRequest { diff --git a/packages/web/public/fonts/Bangers-400.woff2 b/packages/web/public/fonts/Bangers-400.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..b3ae675008cfb4a9a4f1de4f8f2d567949fad27b GIT binary patch literal 8104 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 literal 0 HcmV?d00001 diff --git a/packages/web/public/fonts/Fredoka-600.woff2 b/packages/web/public/fonts/Fredoka-600.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2795c694fcd35786f311a5c12f922c655f5e3246 GIT binary patch literal 5188 zcmV-K6uawpPew8T0RR9102D+35C8xG04%Hk02AW?0RR9100000000000000000000 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 literal 0 HcmV?d00001 diff --git a/packages/web/public/fonts/OFL.txt b/packages/web/public/fonts/OFL.txt index 19a32766..a599d62b 100644 --- a/packages/web/public/fonts/OFL.txt +++ b/packages/web/public/fonts/OFL.txt @@ -91,3 +91,9 @@ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +--- +Display fonts for profile name styles (latin subsets, Google Fonts builds), all +licensed under the SIL Open Font License 1.1 above: +Bangers, Cinzel, Fredoka, Orbitron, Pacifico, Permanent Marker, Playfair Display, +Press Start 2P, Rubik Mono One, Space Mono. diff --git a/packages/web/public/fonts/Orbitron-700.woff2 b/packages/web/public/fonts/Orbitron-700.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..46db8ddaa0f1fecad9cb02268f0b637f38b4011a GIT binary patch literal 6528 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 literal 0 HcmV?d00001 diff --git a/packages/web/public/fonts/Pacifico-400.woff2 b/packages/web/public/fonts/Pacifico-400.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..daa0db973b55d54ff4719becf309293b596ef290 GIT binary patch literal 28828 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 literal 0 HcmV?d00001 diff --git a/packages/web/public/fonts/PermanentMarker-400.woff2 b/packages/web/public/fonts/PermanentMarker-400.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..203ccaeb9c2bab914dbb05e4501915a16315200b GIT binary patch literal 29564 zcmV)FK)=6tPew8T0RR910CRi*4gdfE0ThG)0COP#0RR9100000000000000000000 z00006U;u)62m%R$VG4t`7=pMb3xhBK0X7081BP4^*D3@c1%w(0gJ%o}8|l(H$h?*d z-0c8Wv-f2YRQcs>lVQs9xxWjwFFK-|+hfwJX{;X#@G;|DhKF z?(`5TGM)!$Zr!$9B#T=xY8xAo3!+^Vy}@Xa5hVtrZKBMlL@_A=n>6adN)U{EP_*B- z-Zx*SgMFBCkf7L){ocKYO30pFyH!H8R*7WDHl0MIk>yMBc05rBzjwRmY1n*EHOwMU z(%gfv*7sf0r~xPMEb8gDLu!U3{Dg^9|J->qP}qq{9NBr={Co|ncH^<-eds9%xOZCs z|MR-#&%cay;7BDwF4*rOsfeF^mr;kk%VckN`A|Kv06#g`|F5mK2)>xx_kN5;7u(ph zOAGCs34r2WVMr>jUi^9Q!c}fexBnS z7zE2!K2JJ|Eo1@nX#Ya7)Z5uu>*$D$QbA=?Xq9$@^Z1c2`_}0y)r<`Pj%^z+r-IN2<93%}g~rm_;+kDvUkMf_R%2v! zhE{26;M55zW(t1;+<=XHQE&q`{zXAEPJr6Zv$VclUvGcGHrUx0vy{T#Y zKR!S#jzrPL(S+ZEBrMm##{eZtW_k%3bHqRq4{LYd4K^*_(gz@9|%IvVbNR zs33MSmDg;*0{wjT`|ZDzq0LY<;8(D>_Pxv4w2((6VGm)m&4yY-j`&Ke|LI^;q?Lr7 zW$5a9t{ZE8hoi5ckVOI&qV27ItKIXG&`2YV1Q7`#gdlm>@IH4907N2T4Uho%bJhTW zbyp|D-brx5*jeSE_6>6W^pr;tQGgWZL4_}xvcQ{vRPJ&!^)g=w#}q;lHna#BSHZ}z zc^7Pu&-zNgEzyb2`P|RL7l^~=SaWzBJB}YmN&6nu->WRU{Zc4ua~g-mu`KgV?`Pe! z)_M5Tri&i&(cc9u>a{zbn{NBQb&p*dHMwO6l4e_M)~;8N zDVt1aupJRWo1Hc~VG>SQp*j+CKu)WiUFzZt74w z8A{kk5`Gip7K0jaFtAGE6d_>TfxVM}81Dq~+}FPEr*()wAU5tC1n>WUGaTT4xk-?< z{ylu{@cCeULpGiTA_gDxRQoP|&*0$K0e>TpU)=>nt*IZ3cGe0oIp4)>zg`Jd<-7nc4;n~{@g>K{1 zArOkZ76ga7ySWL)KFJPqpkRT?R^ht1e~Q!7x-Uy{x9bTZ@2Zdk<2)w;v8@0u3xxaN z>0{GTmM1pH$A{zKLRk)4ftK^?e4;o`QDVNPl%~YW>^<_!3<*psu=Lw^MNLjN1WbmQ zFJ6T}(29d?G@9lm={8?zTg@f;ho|FnMyZuafdF;=X{u`v;MqX16m`qb7!$VPI^CWU zP0oZ8ct6GEv$=NYeIncEGjQS~vu_3xig5rG@+1)flY0@iqtZ5=W@$1refBA;S1|kx zeX*eUI%2F7*syVVwR)RB2)k=>;SeA(U#D*9^tR&W{;pgIqE(=xfRHba{k7&6M;jQ< z`Y~n5(T4PqnD)%6g{rv$Wa$g%}{T z%Odx~0cvcoKTlTP;t$TPX8_5=1TzEV?2b!^IZ8f*{$n}L)Nm4Pa}F|+KO`5v3^&XGYE^2%V}3B zVK$x1a;#PZXXRWy#g<=@Sg>o08&Uo0ZlYU?=*l+ptPDClvAdQwzEYEGq$}4&{7CTFmZ$S6`RKi(6oT+MwDQApzFoQo$s;-;3i=g|DOC& zCNWyF8lTKOj@e4MM`)I;bzuO9{}9*H=JgHecuT zX47Zfk>r;KBbXF|uuK;UKxyvgLXu2r!~gWS{%+f{JrN-7P#dOH%z-g!odm}*3n5P$ zi|lD60SmU$l)#z47a4yjg&ZdG$@!e~v*dfzG-R7e0J&Bx21&)wE2&)h<4rWTcWvNMY48}y_iSEl&`=VcC zx=Uu>JPTd#QRe*u()4U>KOK|lr zV1Q8+))zrBwqxurQ=z`o4YB}7?mrrsz3|C@YhlYKfz?4VNzqPl=o>5D!XuV?~u5DY#QRKNw6IRTM8@tlhx zCa1SrEJ?zxNKXq&I++I&lm?AZqxtaRMx~TN&Mtf5At$suX#$5>R!l)5HDVkrff8~h zT1H6)^bVj6oTd%|YoC{AV;-~FCma!z7$AnSISS>l>I1u2p+%oDiHUzV+#hlt>x*a4 z4gmYoRfE4Pwq)vlxw5PZ|An{8Gl+!olYc8GN`TGC@$tL9Ay-iCE?~}oRBAwa&pK_I zGlDlH%#V+0d3a&^2W@F5^LeD2nu0y*LbMP;?^-@pk__fioQ$$32x*N14CFvjSbCAK z;u#U>(i8{)G#&cPn}w|`W_2!&Q~AEFcwZ}{n*4qo%zpLCofHF>-W~HWJ$YG7xx7#? zOis^{WMk(~Ceg4?-}Wd=Y{<4j8>0;DARr__A6CCcK<#$hjsEr^Ab%?kc6Z%&Pr5Fb zcU-no05Jla(m40GC!Xt&t3ZJuiHz@t_x6->r;|t#Ygr@8C9;FIdI~xDS}i6aaV($~ zjX{uYCU{(tr!oZTcrv-ZDrWrz*eg-|zCX*_2Kixa%<^V>KI7w)fVz=%Z z+)W{m;2wlD;7CB1~7$VMEn zuc`0^YEeV9r;(U3ayOl*DVJ*G?8XnC3G<2nF$HLE*Z#(} zZ9l1hvG9A1NcxZOE8iF-UQ%q*w*LIH-7rXA2AVV@oZzh)n+Je(DA%W9|A#}u8Zp^_f{*j4-K?MJA4q% z&!?9*BMH4*r8W6(qH3r-e&RUk^hlV)KS0N}TnPvmBlj|G+EUpjS1U)r^t5fZY0 z(DQm&zZ|(5%u_}Nm~fNb3CalC}VHApx5i4<5^7x^I(VcC(s%Sc0u2MHxXsws(~ym(wzUDqk*`TEPS($b>^!6uuB3`Y1V7p3&Pwigr@8$F(bgV6N{2By|U{qKNCvv-87nYZ%Scb#a zV}s5MTC((JF*3cWPn-|`Ld!3Bm)YJNn)R>VYhkFG@NjuF4#ry1pS$tL5vS5mRE-mx zed0yrZ#v=NQUUvGIe}(LaYrFWcN|yIC7F;{{79m%7FG5$Fuc42H*>&VrYXEp=J0RF zxmsmJ-I_KL2#^VD^j~&C({>vXio05a&tEHsYP}ZAc6dP8O+#(dQ{b>gpU6TcKAs=i zRV@U%enAkq=DOecYz>kVCgu~;nKW)eRw*CB^ zqyR}wLiTWS7*dYYW?o^XkDLn4N0a^C-5sME8`+Jp>I~G3>AWa-jU@*xuxFx5;MHqe zKAT=fvU=qX5pnKB>C1rfmj$IGw!3pwNx9FMBp&C?HEOutes>L2YaqZHVbA6V<)@Hl z$V8wzTkP;Ofm0mxcoLw6s^N%Ww0JyeiEReX|4HF(5$c^ki+SXWYXTLi?kCYLboK$Nl z#iVgZEP6aU_qQl9Mx!nR*S6(?^PY+rUf(o)C`@cc_&BzbQBfDZ$}M|-sV5OUTvyHl ziCc^lIGEgXl3S~EH-9Fa1s`)EspJViDUl`3gq<#o>bAHQa^E=e#sSU*cBZP-sFsv1 z-kfy4?CR4(s%M$h>b@5Kw;DcE6={aFA@rcnsX(^!TG7S>$>}SF8mrzd%5F|Z37E)` z0&>%X{F7+@oV~2pKM&-0a--|N=#e4X?8-^99E!X%)qw;!IOXU>;-q=FK2~$+u|8e8Oso?k?5_Pom|OQizDJE@h(<6#r1hmf#E4E01B+1eYU`Zwihm| zl1MQ10*jvvH*`I=BW0VEcdrC$~U z#u*kXZ>LKAGm`WRK4tf{8+-0;wk%ewWH&dpS{gr}Bp*#&+>3gUWAPm4=hJGEaP`7H z+_jLq`GoCg;gv-z=FHt^vU7Wq;RZGh|IHJ84-UMaIk#Da8DDe%5$9)28m)wvCiv=C zn+F(jKMm>TGtC0dz14izNITytHo{r=;#CL_t}}C9kg{};pp`h21g1no_>7qD@u{j| z^0Jt?F83yw|plT7WS)rjsRrI+7SK&JOd6EdPUNySf{b;R&_DZdi z;NQQEzZj);9|8><$YLVTvSdoX!pu|20zcSVz~zB)Vfq#uC?9XMVI5J=I(2~Hk>BCP@r8edDKno$o3lxGYB3D7HPrQfK}S z3e`%nncK%0F$)H}FK9E31Tr);HULY}Kwpj-wN#QX~Z9@6tN_q!O6tZv!OI2zA1zLX10HDAvNMLH{eKOc5{9XVxtWAd&j;J zP5HT7gFBe|ck6H*4&w(Ob90Fs3P8Jh%gIm^6LHo~FNI8JA?Zy=vMlBsaM)|Y%Hy(p zPl-0Kgvlx1gVk-^lJLTKDsBjnjn>*vfz0q`v)h-(p0@`gvew%g(UF|!losUUu84V(gU{_o zHWIi{yX>x-+nYqxJ{H<5m#ozd_kh{6tz>;U!_PR)|TOE03B&6@(i9@)CCI?fhQ=+Lrt3}|7BS@*yT}*BggIb8XnG0 zXf%dEXf}cXg7V~5CSsv5D6(NBtNv1#j@<&Nup#I$5dbk|&E-^VUv6xItlhi>fEw>} z(C$A@lEP@#;%=E|YEqP0r2$-qZbDYl{{M91#VR90i@nfkAiWbnv-2%NTYt_?r?hfs z!FLzR8+Q>y#f34{HQ0lq`4VIOhB4GTAI}E(_43qErk)Y1fpIBq%L;g$AfUr$k=8+X zpcbcVJ8c}dvqrhWMl;J1I0pQdjkYzsSp5=V>ywkF7>+Pbzic=-%lnJx*|VAsQkb}~ zqf8~}Q^GC?FDb+-%nnr?*hn1hUgR4KCLFe9oV;@AY>q!yrDCslKjas1w%LKyIn1*1 z#l`J)Loo&3Ms{n$I9WtPWIium&IRV>%f37aAq#ec=aG$)>h4jfHT$fTTY zjmcMq-f^i3wCjl~JQ~}+w3=fxZfA|j zt3X7OMzhY4a5sDF72WvQOsvtMP}-AiAr_;u++Cjr%?jfh!l77GTnBqu@MtI3jY66+ zxq=zH@tF`f$)k@M(WOW07TK)E%(Opc6Rr2{ptg8|xtjI~^tBSH6%%zy=+U2%wM_lw z5o^@MbXEfI#ygzrbyU#Z$K%wOW-RnIq#s)7cK8BPYfl%D*!abM(XJ3NVXqJ z3XOVltDg3z8`3uJDz(5Q-yEc~PrxS<$HigCrQl1j4)>pDEpuL|*Ja@gG9|r42D89z zukCR~J(OcXLnwEM`KW~Cb_C(eAZCb}dvocH^LHSkV839{s+1p36{I$=HV{&(!`(jM zEOF@5D5x}j7zj~kf3CtQy z(Anq(K0`k0yHEf--_RKw!H)=nJ3i845vEJ~)2^%eRs^`nsFv*$k}3+a=9u3rIHy z;wC_}7SdAv2Kzl)-$c+$jP)P*)P#>+{gsm&0yWG~`RqY0}g`Z)r3Az3D{m9p!Pr+A_xZa46{zy3etZcGtTu~ zNW=xGzbNLA!iR_|M^ICeG5rf6Djl5Z-;E8<+lQ+Oo?^Kj#yNzX6w_Cr*M^(*ef5Ft zmP=4ehjAKwYrfBoO9+v7@G3;nu0X(lp#Z{uL@>g+p5v+Fs_*0L7VarKpdBr;43pcN z9v7u2k>hppJ;Ng0o9%ny_y0_cRd`S{jFZ4i5FWk?;dF?Khoe{=5Xc}yb5=6grMs_( z`Qk+ph@R8%a@YU+zvG>iM!^PcWF{L83c@v+ZJ)Xqeo*YSI}=T$wtM*}%(BIgwXphT z#4K?zgVQp}TV8TW+>_Gjc@%$QpY#As4pb__E?T#4Uv2gFKGqv72c4P6;U}I?UQz;# zBaVlde7kdaRX=r=wY-X4Oz?ENSwB_}Ve3Zv-5=Ai$4Ia~$v2qLuZcyrR_;d5L^0s1 zvm5aHnW&WeES}HU zn(Rt2D4jf3S5xZW5rQJ>0djqs2hfVm=u{|t zY-#R7Ex0qreN-c;G9XdlJY1P2m-%0Nm%+D?8>czdm-aRqrwt4*jmj0xsMI06Cni2F z8mGr zBS~w@6()?rM`^)Xm=#(xxhp^HL5_X`6CbwRFm0X(#ra!dyjKn23WpQ1J>3ndpg}Nr z2=VjMy*P-tIP%Zg%H0Dw?lL8Cvme%FKhr^oJeyc@uocm+ZqmxjE*g!kQlq zhi$hhv?s2mde%gz_%=z@*?Z@-(y~w&>E|EES(&*svY!@1i8;i#{tEd~ytC;^Z^m(v z+Bkx81gxm;?W*ffA&uOdw#i8dZ=)j+VVVB%8p`IU2@}^(R*y97mf^>r@T=`pwE8!U zbuT3%sNr{f z5}R14h2m>scIuv8{ke&AnSUNR9! zi@y@T|Jt5cwc^7G#=yU?U$=~h7gAkY0I!P!BU^COl1=o2^}+7^oY~0T^Rxv*n*5TJ z05Ii(MH9R8V-$NN2-)jAqz3#E|M(52SH_Jm9n<>#<*D=fM)R(n7DEo92$3N*meu_; z4U0cuIEKMUB6|vGeYa|2yU{&e-@9z;u3&OA@iHu*-tW=o`D+MKHaHjlt$Vn-e>JKb zr`vBG$=W+P0l3YUxVzp`0aRKd4{CCk&DEwIcd|zmB91@4(wlj7!*UUcv-VP$jsSTj z$~X_*uCUqsG6ZN(kRfbNJWqO0QDTm~yx9(LL*&1D9ZJjX#$gF^PgMQ`E?5vNDfSk4 zbgJ}!FJ6T`{*`{wD4T%g2%SP#E=a(|7^-~YJRCHPJ)mq%9x**5C2ZAhX{5h9<#YXt zcmHbf81*Yqru4Y3hH{0!82&bM3D0D4z8qNHH= z0WyZbv1H4&v~90->q=mj$b)Z1Ux0asZAkpI9@~o$FCTXar0XfRgxB99aEkbuw3?b7 zPHn9`SsJG(fkJY)&%fx4F23i?viThOBA25?*txL9U=EC{?Jom-rT)a48xuR=1z1lb zqNCBli+;38oAmZMeqx{mZv!;r6d(Yto8v~?9wx!f-|q3)(aO{W>@lI>^0eE_tsKbS z5(LI`2sz9tq`)ku2VYh-#=v17U<=)F#{Uth^x6;2+0SO#EO?O7=`4+jWKIqY`x9K& zuj`?E5~HM*bsqyP!1;ev1$p=Wb}C7;z^lY{N%7XRflQ|Z#I#|_ZMLERL4J%s(<)A? zgqqXR_$BSScE)-o#(~Ntq0RQo7X{??dI~-k`-Y1Db_y4;wJ&Tn72YSSlf**t+%aEg z?Rb*ICcUIp-jHhd!M%K`8wLCLU6bwFb`;uf)UF3u`S{866&%)ytWT-Ef>67gOr^yj zjyNPTpc`y&w(8Ibl=RV-*|TeoR4zqeJS}aHWVPcU)qOr`Y+~l7*+8R=9YJ^S5A^Y* zNfKG(KjzI*IG&IeGPH?o^^Q4MmlSS!j{w879l zSkQMH4a4QbOfyyFWxaoxHe*&R&G*Hk=BHkR5?!=1hCar9vKv5v`o+Z8tpTv*Pt6k% ze=j`?>OC*Kcy5sY{QHNzIIct!qvV;?R?I-e?+$hUx9fX_VQv7-I>92W%zQBe(FFPj zBzpY=)cj)=Y_=p`(=uX1*}fN5>cL#A+?W7N^iaa={wuIacmkYUuqle^)?;>FoaxbB zHi!n`+)}IS?h$@xVg(clr9)XEH3=KY`9f*G-ZBi2gJ~0$HLad3?YiY)TvOe!2D@81 zr?**L#D&>$m4*1p+mwqCn$uZE{oy1Dr;E2-DbDZE!O86AOL<>0|-%qmAz|Dsr}M%tC^Xg_o~>$K%!yoyR?B4s$g{L^Owh zw_&&{b8o_|Sdb-v$oAN_TEDNWL_ZgmtWEF5j?6R-T9wPvYKNLlU2&HFNRS%G z(8@dK{;SE^At(+C?h1h$bC~V{y84X;)A=Y9jCFGzlI;&E3w7@?oLYV3?au zz3chVxs{K=hI$)FIy}k=3P*_fVN9vdCR@Tvb}bh)A_AOabL;fyqgKx+)jixwh2p?t zCK%vY^5>twc8OZykAm0X@()$cD?qOyRqG#@OE!H73S{{>ru{|@04--(i4X;%w(W|2 zv0ZKEj1#tZQ4Vjhg;Vh;l=Zy5&C|skJzUl(YlU_b@C1}FA6~S^n44^u#eqFCO{B(Y zaZWg>z2*M8F+ZY{9c8e`Ei)Cniw7K->WyN#jZkijThq_(zFAJD&Q7^J<^+X2tu@4O z2cjEg<#4vt&HzP5mp?1sXD(Y_!ZS$FBu3%hE| zYWeL0SP%Bqc+!2Ut~~hG;WZCE;B-{A-m7BycHpJs%)KBOwmgnt1QVN7$GSO5;~Vq5 z1MBiL_@CsW&m-hK!~{4#ECNmtZhdO0DP8!<1+^jU*T~)>jgNQcjz3OTY3;$N>~PbR za^{k2XrB4?N?yqQ;WgVp`|jV5>>vF2rHy7x!7C~3%XQ58k?7D6C#V5@b|#Hkjy&^Y zVsX6xQ^XvAb`Trv3l%^F4Ms}T&<=j(NB`idmz7YrtZ-*~vW-ky6&Mf{qIp8C{Xhyf zTUwa$e|VcSzpd_<6Pt z`1Ryy3Z<4@ru$VwihvAOA;wC{e;bGk&a!ein;G-g*6&%hVTCeZknnSq{_NLZ#fu6o zWIKOFQVXEiFNEr!*zPSxOGIPxoW;#V9erNex{a%9)c~@O|u>LycIP0h9g!29u zcS7(aKj-f8kEt*ujQF+-X?44Xthb2+hiXn_XlnB%LXG@NSFa$-;c0vF2CE zgN)0+RT(XMKUMY^Pq{?Qw?7_1IDPOV!3FalbUU0O(vRA}_E>xB4ou^L?IMVq|8yjp z5eVf;)7t5~N%cIr`X$mgwNU$bX}8u{CHE~5`;*&jHy0bSSbR%6j(uSAU1 z8Ea}gYP+XF8KmOdzHlIhj;5pR(v(iIz99 zqee5pvH1F_x81@L_(S{En3b)1=IS@5h(~{jsvfu2Lr(G#*pTCp#R%J~qbJ+9Gk4{GVk+V6>CjxOX847omXsn)Ql1tV^AWB`KlI27|b)-GbUQu ztBPBV&5&SBBc@D?Znjm^uAJb~s6o>%=h4|AiSqeg|5I^ef5{T1_P4!FTTH80$4RA9 zO^hLWT7~<}%9Jo5KUpGW$SK901**b5l}L)ASE+5oW=b%oU4Srf`f>yr`|4_3r&Z`* zKOXzo7g+cjVv~G~5)tPQ!^J#Jc&#a&|H-X+{M@K*_lO?R1qK8qYB1DRz->NdO`++= zc}#*2RM{ql_ZP!z}7(FHYPg}Jk3Ysr6 zN3foYU7q)@Ke;!!OE|LJ2||QfFyUB`jLvHQb&(yKSoPH5Z(q z&T)|yhGhBsCuY^gGu_f&N7C8r0ApFzG`i!0bI zpO!UrSf~m-PNYPHTzEC`z=nH*34d8==J9U|@XK-LQV
    S}D~Xz1ggD{L7{ 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 Jo`3ha{{z9RE`|UA literal 0 HcmV?d00001 diff --git a/packages/web/public/fonts/PlayfairDisplay-700.woff2 b/packages/web/public/fonts/PlayfairDisplay-700.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..46f4a832b76fa760987a2f47600223ff8e11c8dd GIT binary patch literal 12360 zcmV-OFt^WlPew8T0RR9105C`Z5C8xG0B%SC059eM0RR9100000000000000000000 z0000QfiN4Z5FCOA24Fu^R6$fk0D@2v2nvCa1oLAHf*=3^HUcCAgggWw1%+S-iZKia z8}eNh~tBR|%bx(>`~B?F>M32-TVt)TSHSgM@1Ei0afl|;-ZCb~3NFEtevE}S7>F2)z!0>vX zcf~wt>$Z2MoewJD6Ox~Dvwv^bXLdb;)v?+t?RUQgt5NZM@f9xQnz>dL3N?`p4U~G# zQu;gq%<#CvkHeBK0uW$_4SENFqbOCU(%4WDb1R^lUZ+2OQz{^pl2gzr$S?|u0{=YsE1tMxk;jL0NJpgK z&o@yU#YN@WyyR=PCJU?!-}Z?1oofP+!iIAqe}}tKXrrZW{}l;GkW7LE7bJ+-@Af?! zx^;?sS{Px2aWeMYi@yW48s6M%~% zMFcvtK;VP39sKp}?rRI+S<taPLiT0QmwJ{@RL}g5l{K$-8cq1XKVF*=7ruq573|f%ydjbgp z;BW8({O(8JdgL=BZX5Q2%le&h%mKUf+hUV7mRaNt2xJ1tzi=3UbSs9v5%!f*esToN z0EZDW(GV`AFkI$@U7mcd2LZu`ml5c)+DoYJHT-;rpBX@m&a@mh3?TP~$V}7T2P0IG zOsL8MT6j=&(5`8Yu!i`bBw~5-;|gWdo?M@(YMKN6(bJSfSMp z0RXJq;+#5PFD4k2p*$jNMs>))8i>qh(vJZst>rxTxC@NA8A9%V&KG zsc5~~x9gG*e+w2UW&D6A@mBE zY*ZZBR2ju-ti^$95eObR$U zK;4_bNDxa)0mvwm$WbSXVhaz0O!A#NBTQg2MK{yJ5S}XA0Z8S@89LQi5eSIyG1qJq zOef_)n6P95*cghKRmU2_w61ceq61lHyh?rutP%v&piU7`S$b3qM2JYDWPpZt0=Pz6 zRdpbD&xEU|AR0J{n(xhT#Pdqnq z+Qcu!xcWqPh-m7Bu?hRwyrzzkG4-Sr$1`-6qGI76^V|MRuFB?nQc{@g;>y+Qkw|enMI<^~V_b zURc1vKp+tWT;!I?ucfDLlRe|9YYF)S3dMu&EBGVd9pZlBL-NQI-x6X{R8^!Jr$rs; zF<``u1snFEQ=5y+{i)ZA&w&4A0D^=FXGBI6;-tw8vxJB#Kqy(v-;Gh zD8i6DXBLxlEQavf(k$ZH3{b{kLtKPVMh4{-`eR6vtNE#`0qocGTsKdTSnMI0FjvXT zvPdPVQXAHdAUw@F!Pyq-h%P<)4wOT_m+C8`z9Z#W0PEsh`%7wC(wK{!cutcUa~86` zT6SV(ECXp!4n9~;&srmnOplag zwPYt^t|`zQi(z^fH%7<}m^n3u%)1=pbm^Y(ARc+*TSER(NEM%|nKU$QR|k3w7}I3M z3>Ix**EQ>A>6JA~zYK^VA;LtBdB#PW4EZP+%K#nLa+I%!t{cxmYSbi6>M@@tV5!RK z9PE*j^R(`&rpW(DY5Q-i4VOpjVsx+yL{G_bK1Ou-uJeWg(qQsOEG-;YFtAllbeI+8 z&=+VG14@3XyF-bP1!J)!_eZ>qlzY-c^2ih467rcMP*p#qhM)zV`oMrOP2Mqs1)Fwy z7sb8wn)(>O0SFQzOw`z(IB7CwWxl>!Ai$9S=@Uk{%x#}@=rME>ODK7I5hYb0x~zY9 z?9K`#PtE5w;e%yy1@ZP-*LBxpb@B*_Ty9sy=wYs&OC|n}!e#!{w$GyyL1buw2*a9l z#iz>E@wJn9)c8@JY)5PBh%x#*hKPhK^|4U>S7xuoew?7`btMZZKseO;Qz1ehg< zP6n45_vM7g^T$;tJd%-GLPIFWP-MWrZ-+z#nprrHJW`^r$7PSL*dt`VhvHfY1~OG@ z+A@s4kFU4}Q9%(WZGtl4ZHD*tViI4Expd=7wtnJdm(MACWrEH;^%(+D>78T&aZQV% znD(yg;N8l-f?mDbZ|*fgooA%~bN^S$>)@`)@4I0f%_ zT<#*`9nL&K&B@O3@qZow-UQYxBszOD0OL`wgun}Ip4?%;YCU2%CNLkN^@R@KKuaJ1 ze#KKEFa|&nM0RU9Vgb-2=ZXQpN8-c<^SKneh>?)HmJpGl&iK5yJ$^D6FaaX6hj=)L zZ&Zx#(YJ>2HUW6a0dd)o4A=0FuF-q*8MH~0mwxrAxAgj(hk$=6z`r;EKi&dB2eTO; zyYTIPa|}?mv{;%a-YeFsV%&0!6yleZfpb-hh0-n__%zT%n)@clvlS53$#pA!)+JV=cN~i+ zI9AMa#C_G`(x3$Qx9GEskzz>1nS_KPk>`XvkunWTA|;FhMN&b=I{e-P%gLfZEO=n9 zfe13++GYg;hM7hQ7_tY(vJrs(`Z{lO9Ge)zK z#h{Q`tCIK(RLTwN^*L-N&SdA{;rLoMmg&=SC=^_Rho;X{`>tbLxFl18<3!713sYjE z5GiXdT&;{KnQx@{HL6UDm7mV%6Rj&llYU=?uH9^&fG_e*8HJ)vN16ELWcfxo7epVjno?*5BxN+xZ$(?I=<-+!oheQySS#g)Y$jkJN zvEgYOjJ8A_aEN9v1NE{WY!38u%78KsFinEb6aP=~(@z?qPQ0o(Gxobu0Vibl`&FSL z2vPnaWw)~;>tsIY&y%RdKpkQtBX-MwI{_{%W@j#fmv$xL?9Z%o((_%S0{W}S#^%Yu z!@qlrnxI2^KNT)-(;LdpX;-SGX)YB(9P&7`ruvk>7~S0~>Fx3XKZQ8G6M~G6cAD=B zu)uO15DnUFciZr&SaGY}&BwbSe-YCvI^dX&Qn>DCH~M!Y{W z)d&u;myDY6Kc1T#0w(gs2%Bj3%+ZjPzIqH_bi6CF`qX9tFW{#GHqlT_5S2-MopwAx z=G?%QP)dF5B*&{ti?BFZ*Dic=1RPiXvN7iXBbT0tnYF`#YoSt}?iCa~|Ck}_CE?17 zC%-2r_94Iy{QNhnm7sEx6|I5Ear*pYT-yR8dqW~LP%D_$?MFg1h|2TR*mDDwRdQS~ zn6GF~ZP3`><_VRtOrR;n=lFbxrme&u37%F#YNw<$8pJgkj;I?`UmX;+_@um%ir{ov z@FB^XjDF5LDOPe(p^`^tHx*pnK(#Fe&w#QLD6I7|WwRu2T_7i{h%%Ta`+}%aBw*xA zfJi(=h$qYvHuXi$3wsfNu+Cx~JR=sqeS5m6IXENj6)Z!nmr`wV0R$57%3Y}qQ`;j#5~KByuF}PInCDXng%)f zhv6wIH_9eJ?NUzZ=q0xj)y%HL+J zHoa<05Em|EO^(lp<8IQCz-QG29Kgy%T9~ZFo?|d9cR_1tDf%(aSK)d{V%b9>?&+&j zcmm)DcHA_6!f35>eESAMG*lIE2u24E8k&rVcXP=5yG-EFWdD z!(R_zlQh{|9Zrq*$0a9AIRm3rlM9lYASZJ9aiyfFG~$Cc0UF}l?3c7;VkU0$lQ20D z-ycQIg(LrwQ*664BQ_GYtqV>f>W5>B$oZLElF|MVU82Dc0hwGr%e2m$$3kyplAo0w z5BO;kZ>Lhpeh_tR5Mai*(1&4cA?{djq(`sWDK(JTIZ$+2$Ul)t?bMO#K8gLCu?6mj zFdda(ffzVVuF!l$72?_(m<+~x#ZbHF17Q_QRjjnqmyT=I)|$=GRQi8F&9GCEUA;cT zXP(`#r+CAocV`RQHMw!F!|2Z+d680hD1Z#+LP+5sF#c1|9V8D(l8uM=W<%@B@>cWp z^?|qN4BbJ#i#Z4OuDZ2ri>+yrTharO;bW(KT4mAhKS?4EpT9lElPO_=G+F?Ai+ z$n1;<+>=ClF?^;9kg(-`uHC@aRGr_u{CpEmBdC~;KHOz#o4Z89_tT?1dpfH{qvRz|Z4nuuY=*95r|M7ensG6z9FJl17mM=xgY*MVYcnJ}RQK(t2z0%$IE*IaRazK~K| zp<;rhS=p>fJej@NM`dZQvu3H@A?$f14xV0Vi@&tR?zwF~yNt{1F-uc1=L$6P5uF;L zhAdO;cpSf^+QuzHc@5Dl8k3spxgRZy&q!HcI!YQ0r=NjWFd4j@LKX2A`bgfoI5iyn z?*BZW&DS}AXiI@nMchPKtRmL6i8a;HiIOSJ{Y8<@Q2EAMt`5cPTK(yw61!w`Mpdzt zWt~MuUaO1ixyu%MXh>F!>9@e7yI#b)fk1g$iLR#-5h6*u7GeQne@a<60JG--k3(NH z{VFXu0~$s<(-$@^Lo-`yJ;kXhyL?***ZH*;`(!RR-+kroI>qc-j|>%cq9Btdc4mLX zIt|g43M;dYC%P4+ZTK!j@8IZz*jD_Hye@;vXv)T=Ds|q{ylA(U8w2Yj^_`Y`{+6(D zL)vlNPbzVqhq9fnm4uk}9gls-Sb#U1sZd3v@YfKQjq-Sz zRfJM-88xhQStk!SBh+XTO&lphdm2N^i)iZ(;rnV)fDM}%6AiKEF>*)`wU}R&AcH_^v>2)Ea z#SQk`hNkh+$3h<_Gh25-B`4EAIsb$^iXD5{F}IS-1kIMUZ>@bVtiAw~Z@Nzz4U;$_ zXOic|OId;&c18gG$Wg3S3xSzYiW@8w3HGUo7~8XUX?5BZjoHM~*mZpVe^gT0wQCDs z>fJDS^KQ-q4cDH{{a7`EjAjF+E(gp-MCVK=M_Aj}7e*vY&y65ZuYgfGj`-eBc^sUO z792rTn}KMkD-Ti`N+9~81x3kXWuVBGOoq!ybryZPa+0TDp{9^o0=qSNpc{Gm>ab)& zdWbxxkXOY|h!5Z41-+B=GeUVK1%L_)^;~+II!&7fHjH}nWsylKPK*K7mtq-l?!L`y zJeb6qZr4?z3%owY0z*ZH%_8zL+v+&Qq*SZ|YQ`|9v@A7O=9#mvpy=Sd#>vO`l>z&Z z3(jF6^k^(HsLc1`S|#txy@CkA-YM61`8|c)9;40K~oL#w)QI!K7cs>s10F^NpY$`(5BcO2T+qLLcaUBE3yGTBxq(+I*-N86zK()+;MWB|UWiiZWpPb{Ls>eMn|!efdCR$h%}z^?3;|{Lj^t znC1Voy|d;5A{yaf6Hk#Be;zYj)x~d|9Za1IO^p7t>SioeLeu0!V8bZNhkBr?vE=xH zvYCjVOf}V>TcX)JYmRA8VZP;kt9>(TOuO@dXs9DUQa(BB*VYwDIGJ8=ld^aQQtGr%KY-G_@Cu39}Y0asvxU62Lk@y9Dp<8`m65J_u)}1r5G#$1u2+WUKLET7(O*9 z+C!G<|E4EuGpt^JL4(Sdl!|RABe(vG6^jEivM_>2GB1?u7SEzeRdrs=yT9io8nSGY zlCo#Wz|tWTT*hKxF<4xlp~|PwVJ=1Zqh4fe24uHYK_ke(qdyfchR&zZS5osaUO0mV zmzhRtp?ZzBt_}jKVN~1k$$GD=$%q=#VWqYdu0(ZbKG~3>X>z0PY*?wyg+&!0Apumc zX^Bj`*^i7I7*ob@C!QkeKtlE_3liaWTs-(Wm|?q?q2zkjsGB&goM0nT_0vrb-GmAni(-(GlkVdj*Q&a<(Z00FNm2f zK2-$*e|K-wpY|A+K#l?qP41?I_TLwX-xG_sx zV``Sp>6v9uYAv7aUeJ&TShV8mnXRd`dmtuvlqEJ45vNO|BV&_g1(yWq-H#@r7tMhz zt=&J<;cS^wmb9=w0sIhmUUg55Qqp0$JPS6U;(IEW_LLNT##aSNfblL3IMPC=wC_mJ zXMANU>HB_LOy1k3gM~c6qNUbZ65Fb)6I<&nseyV+QfqZ}Qd_+xg|4u)u3BYjQ7GeE zR;`L}1&`yV>i<=tU6Wz6GzF%hqSJ~Oa(@c0M4Gd#`ue<7VO>I6zSJWBCt^>xkEu;y z)Mpf;RV5tBakH0M=mcNWR8PKSG@~3S+lTr&feaO|QNT}F^L<42-wLhSn=g*%{}OR+ z&gP!SMpOVz384jo+R5{rD&eR#Vi_e z#LC^V2<`<~PJ`I%Zmogir12%8V@p90(8t})A@}`RRe&iX=*e=r^0SSS2Zx;s($H2$FtQ~3`@o7 z1eQKUtWVwyrVk+$jmW>*Bd>*gD;%IBlxQr{qYn86`e%B-Kpl$oU>tzZ;eb_)Yc5D8 zq(i^5V$eOq;$Xz`m{rUL%1V#jK-VSur7etY(T9myw8M!8#NExr4l!gOsaXfypkaP? z3nSHenY*$*3F&38d${)(jWt3M!Xe{UMJ!@c74b&XiKJySkFz zH~@J3@f5(gXsN@Xw0QMn+LZ?>4f)VAK(DMOyGxxZ=e~H}OU)bnVM$O)qEp8C{IQX5 zgH*Y`sJo55;{(6Os(rZk;W~CNJ+qy=@@Bx<%E$($QU7$Y!>3oN-N}Y*LD577nyJC%Xr!+XjdVQv5n2Em1~TH;s~2=>+nomts`OXq ztM|X&0hJ*S8sk=O$OlUscjQBcBD7$3DW344J5dC%&)r4uNlGlC1x~L*B~Z92Dm@_)J`L9=QUp zCRi+<3p)`(hwk4+7l*&RIE_6a{CgZ388aZ*Ko>xS_j13!=vBJcG9&>)&S(ch>EmNn z@<_R^{8r+rw`a`!p;+RS$|eNd>6b-a;k*+FxVNAGj;(#qo5 zOK$jA$4;GZvo)7aPh7CXUS8eqw6#}EO>A9cN!mrnAXW^p;?o7JLrCx4Ui<_3M?2KY zH1bY5qc=5Lp-ZQBNttfTA-wn35u~vIQfsoHvw3g|AQw_ws-Q7O?=LUqKg$)E?Ik2_ zGx|sn1^is`T-cR#`T=3MfVY03ffQq=@7eG?NGRV^(c{S6Y@jzxg;mUP58&yh!Aey% zY|v+exw89_r$b#x@0p%dvvb*dy_JO^nKlz@L=N0tmTlh0nu!KW81f%f@Grw*Qe)j!b)^)@Mauy@Xd#o{IiKS_DLXJa*9kvfCq!AKrehEJpc z}Ar9mdePL3sqrqJ_J*@!DP z)icBr_*tb+UaCSR2>Dz!q6`igm3d6^cZmSq|*H{9?$#4Y?ZB zrrQ0l|M3cTcjq+lz45#hxmu9sbJPejVklle90r>xRD%l1vRRpVUpr#u(inIo$zo)q zv+;XFP6Nkl;JGC-f!`lr!wWgnih#mK;agb+5-^&WX>Mggj9VOo@RNuQ>lGF@-P@o8 zo%`k1Y)5|zRGx{ofTPtXSG$JAzOZlwMqj(^MRb-gQ^`G2vxS8{{J>AnN(q7F(b?OI zvkuRjTX1Cmm^Zz-#qwt0OK4$f=L zKfbkW?{wr1@@JkYSR&gyYmR15C|^fU0rGt_YqY!5^S2V#h8u4C&^+Xx7GEXz+X^!D zXy}ov5Fntkq)FhluzgZTLiPe>8NC=Xs`8=JRg_wRBxyFa`fRe+qW)^%!(CAW^hs^V zj0aO}1yOk36R>nB2`<85c(J4yO1(NgcKP$vFeP_v6o9+601wR7dn!^>lgk>lK4k_A zQA#-y@pdu3Te&idZgo$ow6Y33h6LjjVG+uymjeZce2O4vkm64+zSpAvsh4^!8a=cW z*Gz}IQC8cFOMCS{%(yQJ5Oc1MlZyx#RoBa3!G!Xg>hr+dpSOF3i9ocR`t26npKa*M z8N+>24|^rEEFzdrEmVYM`YUSG?$jAJTYbUgNv(~Jkgr5($zrx;atNtWIcSb3dHeLw zryU8x9isHFV%YDprxzBo>-t$NDdLZsY*}QU2^@q_5iehCYspv)`mX|^1DEj!LK0q$ zCQY+Ypc*0aCmnV*13Fj@6;|`Es1-{}@hm|R!602TX=#h7Pm?eNi?z7~aE0K2Lns}I z#>hTAcbG?v3}d8jcSl8b(KNyiili_wT~kK<4D1C0{@A=WQ`RQV?r* zlG~74b(jXP5Is7hMrxv)oyv_$v{A@JMn&=_0Um(C1kL=uNW4=-&+1^sy;1g@dvWoO zWH&J{K>R5^4NZ$YIeQt3o2UuDJ}F{^YHW#9Y2QX3zI<%)U_jNk@z}A=(a&h~jrP&p z`MRLMLWf!_kWK?MQ2rMs*OC9 zk_wB(0hogF7pu}#XGN$X6PCz=FnD|RGK)PV*K9B5eeVU;taiO2G0-3jseN(#8@4j} zt0nlbh$~*zx)8H_y@`5F=&vn-Xa;q{e8qC!ml><&^0k5>53_<~E+3Pwj3PxIYwQNC z1c(tOPbv$-Li4Q_^HEB2F?lBJ2Pki&jjI1z38V|mYqDdm$lrP*!4sPC9)9T+jpu+h z?+o$(7KSoO*7V4!ydDRdeu`*`oIcI4_P%$7n6um)u{R&T1lw?6e($R=1D47{)O!ut zn*~x~;3J^Iz3nuCeMJQ07b$_zLgW#2s@nEk;6 z$_KY>@=q34Ax1YJ9T-Ojzu7Jim-ajwK*k2qjAa|A*^cj|_0lC?7)%3m2u-_r?{|ca zs2hney#gL3CzwVs7`+6gJQD_*Oe_!`Q09nuqP3ZIGjvef>BPu_qKeZ|H6+AJH$O5E~FKQ;Nqn{r^ zjfU1mMcB+oLae(!^D7TWnNaSqw3U@v=2tlXTU5QMBfzh9q~=P^c#rKry*j$`71Eeh zgjSyvU@xcFUi$hRNC-A30Bg17&IN$cjhsU&BdqgOD*n%(IJWjnG`#@P%jdp*IUvu& z$RU%;cey;h33hYBU4S4I zr4aOd>Npqk42&r3T$Ta@lv7uCuRw2H1*SDowB(jip3k zyM@WW*{FSdeSjbmB@^^QXw=|}vXN&hF|u}Ec{0I(&M8y=|6r_bKRaa?wvLms-wLE^ zuapXYK40^gElP1GX3@JTbX5w(pFbxjQK}2h(NE!f2nunCX!$aA2+-s;K)-|qKskRJ zPkZY0Bxbs(banOinmRT5$!FJC1b3k7AN57z2v#)r6FfKChj9t?xIF<*qFC4`qKbpC zJGEXg$3Zd1(B*E3vxS@?$%&5&7)Yu&KAHG{m|T%iX09{{gV1qV{4M%eq0WE}s3?Y+ zsuuF?Y2;S4mis~6PR_1(=^e3PrG!_qGYO{Ny^`s{&XS6D$AM!kI+L|rCQ0uvW=;er zkux)z-y4Z4(gD}gvbX$mg_LR7r?&e>S3XCi|Iv6fg*&b+qlGEDEWx+%nZxh3t)t49 z398czq-CE-k%x~BVHb_TEL~#aO#7tP($Yx_8WSgd%@`d;$hCbpzONUdqkt91BcYS4 z!An}o9H*d+(70%XO^RNl@+6}ocS)jqH-(3{>lSj}f9KCi=Xt2D`dS9BK`dU%p{*;9@#j$svqO_em>r9d_r5?{5HKj4U5v;z zuO#PRjU(OpK&{IIOA+YRX34!K&;8+T+%wU=XF@d5cjb?+hrBiBu>bdj}Acv2oM;+_= zsdh?fI=#8(kJMto{an5SNy})s{3oYug#8R zU%9msY`=Rj_|u8ygWdOr72tWN?YIgUzjC29Le`J9n=WN%@_)m`FIADF=hY#~^2xmVmL7dJKLL#KB)s_-`cvszhS0|gX(Qbip(f<~* z$(l%#0VN_)B%DMOG6{oN2{4QMHl9mDTnSwk3phcFHhvUt-O%UlFX_6{I z`GkHN^!9|{FoVDybZ~Ko0iC0tY#H2K;cqA5za;!T|(`eSiK;@&_v75`K#y z5Pk&sVnrnc0DOPsp}$Rf`zWko5E2+b06*BPTx~f14^Yy2tohkANyyzD<-`ZzIY^xg zC`cuteY#|d%<#8B z9US;puY;V-=T2-f^`EjI|I}63kak4&tX>RwpKKGpeezmOo(RVmEeCOf92UPR)Qjpm|zl&|0V#(0Vmy z?M6pf&Dqi8=6l#R3AakERlOU_3&l&4i~#sJOjl1v60CAqiM!KFZjkv7<8@O%0lBwP zKnj?MC*w(IzN5u>NvF3&OOD6VxC4o|Ylz1}JZr5mb5(-BAgR-uZW{tdYcS|OYSPYvubiyZ8%6d(=1uA>N6erL>iHTG{$aRAuYVv zp12mmK&<_1)&j&x$Hc%a@*I>3(B-)VU7?VJ4TShj*?wBF& zsCz4$a7U9xg30W7$R;PO5eE>3;TF@*OblyFHdazSupOIf(L}5l8cb33f>}INy;$#`l8H8=DocQPmwYfu%lyNgZRy70qflg7)Z$|sA*^!n3!4F zxcFt|{TGB^5Ad(+8yw;hL`hauO*c%-cBnKuf-*2Bi_PKk_yVB_7fYlvxk9N@YqUDO z!DuqaTdX#_!|6&$Oq%4Dkd%^^k(HBIQ1lE|QdUt_Q-^41YH91}>ggL8dhrT1GKRqs zNK~kYF)=kWx4`1?1R{y-&3j5*fp{af<GYRRsL$Eaa25Z0woRl`TVACTQgDdT_K&^ZtPLPZ=`oTW0=6?_#N#%r{64)oK z1Q>$zf{lxVVtEt{cL3>%95==GfI#32`L|MF2$p8wU=0|7lhURZYsH81dc5h)0l3 z92hR?@fqqKkH@z-fe zED1glPrv(KcbL6=Lg*73hI51_r)c$`e>cBhJ2^q^Iui)VrI3n)r#Yn}O0S5I>$e-D z`Ze>!bo}p$mcVvDuu(jtB+H^M01qwTl5f;rW3~4a1}e$0^qub&^)EogX5<8xWq}PL z&%L=%xO28t={j9qVXM`300Br<|I?Nd6pfRpd7AI)PTCM{NJmD{4@x$7DP5GA?W(5@ z@WZ+IRuPRh(mQq*Hosq~e)+nm-57x2xA&L8@tl>Eq!KClf7vjb4YyeN7SdE8qD(DQ zut>w}Nd&-uxtE`$G>MS4x0viNS+j>CtE-N|A{3JGIE<+;=EdZ;&BW~Z0s#7ZRm=80 zfE@C)7jP*%ZK@on-_?fNc2U}$i%NL^e}MRa$R)5~fRxEilr~UwBrlKxPD2GJUP@Wg zX&s~F+{VzwSYKB;#LlJN7B1@6JpcR2>e%jyFD|9^sD2Q9@fS-HLr5YRYz7~PxF{I= z_0=nWj=ld+O>KXzEYczDgw*Z6&wm+CYnkd_aVU5o>z5D&z(J!Cy8F-+0*B72Bk%wK z7yzuV0|1!#DcuDL5N;9X0E71>X+=wX1OO74mls5=kgth~4*>a!p8|mRDV-^J004xq z`&^kK3Mh_+AcD#x5gAp#&?&><0JzB>WIH?9>F(>XUg+&UV&7svXTN2iv42V1Bo(jN zZK|wnM+Z95J?ugDG<%JGz`n`8%YMcFz`m9?ONlR!Ij#R~{g3N!fLZg~$C3@g{}B+E zpwXFz%&6LBj|;BC9e5N^0{|Fw66#sdz=}pTG_h;u(87sUF0^rL=RpTAI!&48M^*qi zLF9!{5Jpi1B{pCq44crUY%@$-z|EMo72UR>B8ncDp_i;rOux7Ria`lORKqkQwi}f+ zrjBtb6VfL6kik4V{*8YN$K8v|xqLZmIev=E!`HYRh@bxd7H(+SA%0p5{vZGC`*f$e z1|7t794N5%3!d>cS|;B{wwYQ|(>a>yNI}iNZLneIi5#1lCFTh({T2kCf+y*e)48Xh z;}ra0j7)pmCdVCoa5A8!5-mklci%-T*4#1&j%|Mnh8ji5jAv9)lt%I?lSy!UVoH;2 zQh*N*z&V;*)+BIP$&j*)ba0do==cVxs;a3`T2+X#c&6$p>KK4b&8MKmw<9Gb(4qtr zvr4LZGF_}#oEB+Ez?Cd_j3v}6kX8E##gugwI2yL>8l_9qv`VJ!#I$YJb~TDx1&zH( zN*fos9Xg&-(rM-076M{mS(a4^0zwIy!j5y&PEwUp%G0W2%GFMO@{3`ISAPN{De+Rj zJeW;ytxoVk=-3c|y)`6`1MIz1S_n?2CJY)S;}ka+Td>_v+0+cQ3KZ3#)7Lc@=Qvp= zjuD{;aFJtQpw{USE72OoYR7uI^&$ur?#g{nk4~xrbn(?v7b;3ny16)k?pjZ;4*K5B z8{rqj&PK`S&*2G8HRW-FJe5yh+mD6q>g&?3wp*@Kextk-*Y-|X6YFYl-GE-;9aks=Bxs#BJ?SWBjc<`!9hF=b`n;5kMP1f8?%fl3!2(G9ve z$(%)*$#+|TpwcICqSO-6vVaIsR0!$Z5R*7&(lMcV)=J&BP1QAAz=Q`h}co|KmHu#@*mn?sG! z#0vzkJ?(L7chzgbvt!6MQb6B(<4#uuL{wBIAe7~?d!@OhS6C$@9-9sJgHS@-F;3x7 z$}{7LNX>U;nL3#GQ`647XHA0ub(8USll4&56_6=GAponZ#~T|v@v9(D%H~zkCO6NA z6?M$U(I`syP=<+&=cP=m8s9&jM&RjGDDr%I7X+SbAo6sdRQ1En0+4Ak%ukF$8y`|o zY2(JuHQ^wISQ3zFHf~u`GbQkVO!LfECzDhYUo)Fb?o`hl9u`br(nvw-@FemcZE~q0 zkah}Ux*)@x5=b8mQ?WuV*3^WT7XhWY$XZl&+R84^XE8LsMZlz_c)IwYAQ)GfJ_}6h zx-rj%l9M>0`GE}S<8j+eXhf}5X&4WsLmQW0ao3E^Za_ppc7hC|>UA}JczC_W2YQD^z%7I*+|hc%i#3ayk{XlWm>N>D%4!3P{Y>+HqvSvGW%OmqMf> zs4#4ljF>y*VmZq}scP7@KzG3rg@k}f)&k}yebK(x?;{+Gt1Q+ut-0@PZfS1P#ctxy$R|*1G#R;yC6I_!=k>Itl zB3>6O;`Om2-XI9v7$>+XPOo>f{?*QePpwOYE^WIhCbqBl<9WP^$nx{Ufa&^;_SZ%J zL;eHy7xFR=AK!x7fD&1#mFkg!IP*eYJg^WE0!F&EOHCkltTO_;Im?D29$&eT>`LSnMQdg~CmkrfRhkyAPm%F?T879pMeu&81q3aOKQFpL{ZkEgIsz^6^ zcHIOIlrfI4uZvKF;m^>4S*6J?va{)aDVd4fA{m&ciiwSJ$@OZvTG?A4Yq#AJ9V(_K z!qP<3F!Z`87&R`ic2cF&NTn);!ex)#A6%{|iV7FQbQmgv0P7{V z*^tfoT89ZsGubk+}?f(hzWL5XTn63 zBZ%j;6&4&kF)&3~s2JGqJWhZ`x6Y6i;X7WmP;g+Ba9|Bt)y+Dx1i4IbvZUp?TBa#8 zK`A5b$h*LV^i#s?TyA%!7a>Vh2O%oA9anZuZXWdZb-OLp(dPP^buy6Nw9wKPaKH!5 zDoPM)%8HuslJd0M@cyJAuB395xO=u~jAy1jJmhwMipt1Lv!W3wKPV?vka53_G!pYS zi{`d{F2>MV6)=!aQw0-#y?5G;e(AGBri=V#g&T^;t6xEcgWi;r#kQLEMN6kWPT0_o ziuiUB`HXNdV2`2bh@%_IK6_i`b$^rz@%($s^vX2CNf+fYLu0)PB1OU_+D1CFybEqS zH=jeAZvP%+&ee2|dm|{`sM~Lr+q#hhp)!&3E;Rj!;9qk+%2X24FGzl;LoDV@qL$5Q zgdX$Ut)F;`y+ogW^c~2ZYahAE_Xhik-&PXUYeueDbzM>jQ=uUVN2s#eI+W}7P5m*p z9HCUMJ3yi%Nms06QcYuVZ#Z&bHcem#pvF87lJ@DhKs_ir&~D(;e9{6x zKJxx;B1yV&Sp+gsTZ=B4@hf2rg8&hMOfz@3n+A>H?7^QLB@|=iH#s(1MA`KBv$W@8 zqha}=QXJ*o=Ikya%XJJm`lQ>Q$h&zstip{^4JI>fg<+Q`1I%*t-CEG>iMo z37AZ2a${RL6lhNS?v-qevjjX?*^#25QNg+UkJHGsS(O@@^I(qK%hgD( z{C*r^m_#p=psmc;tJT65!xqUsp>)JFEVayy;5p5kj5b}GPjhnI{Skw`y&w6YqF5n2 zuFXKoTmzayZ>!PzfQ)xu04EBBeMd z!J-m1Hqu=Nr%9O5^lO)l73gX^Z`>e!3E57%vtuO(Y#Tlg)S8RSH+ak9j}|{P)>*gp zb@F!;?1AEAF}Pla9vUF>!?}*OW1(RSg+=pDK8FunF3L9sD%g{DY8VIw>9rq)L(E|x z{lJ3w%Kv}cObF>OX~U36M(l|P1vxyAMgS!+a5-J*g>HaWx+2d{j}JKF$b6eMUw<9^ z*Z=jaApjD>eWT@hZg*;>+#(O4)DKcRUCzR)(iM^IGMMLb3mv9Z%37}XGRN{{r#EPB z^G-k3x#{DpHQ>u{qyO=keBRd6hqo{OTJ@?1+gL+I#pBrOZy$bJAyKBgB85-|gBq!4AM|W?y_?Y5 zom$s=y;uA28%#)d+Av21c!i(l>>NA!wk-}su2)zo2`4<)@ouDki4(o;#j^GGWk>spJ99^sX3jI1fghJKOnmi4#n6 zoh>-;M{tJT*4V(~7s*&aO^tQOL`AEEWU@aBK@;gmdWqgQ9C5lJ*e(=b1LNE@rLM(4 zJ!v`o@gct)Lh^aZQym`IF^Q*kSCEJrXmm=^UQoSHRQ3*Aax?i(B63;*hYn*{U932Wqn&O7K? z!`AZ?@bvb?#8#Qc!$L+1i3Cd{k5)?gB`*l51D)wQsmAd2S0e#SIuc%jHk$bdxhPd5 zOlYt~#U$A~NQ~-7ZJpV+i!7DA7Z&~TbBRukbL3}8F#zq#9VU(*WH$Go`HI-cgiD#T zV@|jy?Q(^Uq!)^f`So70zh0LF-yz&2<%|X4#71Q=sWz6eTNA9f zTAyb&k^o_nfxto+G?+TBY4UxBCXPl@G%>C7swJLwF{3jz);302KvLiptLP?sycem= zweLIT0`7@8AZM{M%{#CMazZ*j_%oCEqRE^o{DV|Z_m#@6exf71#OOVhm_^A2b+6yN zjhE9d)KYG#?r=fzX9#9(oW}GnRUT!J3m>p7GVv)U(fh_E^91uvl-$bLZAn`%0NQr8 zWE%OIH_f-e;GEZ-+T~`-vrao)fbtp6HaA!mf!177yas0m#bv8J{(u~Zn&_~3(JXON zd4M#gyUw1?3TH&iL8mAB}NP5n9?(lo8pHNBMh*5>d+8K68rt4^%cnM%|$sBjG* z8@iB~N*@Mj*;M_kC+*lTj>q-b`X69~KqQTUBfI3$=HFB1{;n+f&D9ys!?UQCGQG$= z1x3C5fQg!|j&9QgY(uHFgyx%f3X9SI^ZXXQR+e94Dx*PCRK{wJE&ix-c-Qojd#43z z`ZC00?D6nNfp=YF(yCyzRaTk?2DW^SSL4dLx53gTib7+1q{a#=w1ke`&0Bwp=kuody%3Ej|VS>JcKD8+6!*D8HWgC^C0h zoP#z%NoK!Tvoa3SA;WSAIKLq4#4{;&KlcK=6Igj{nJ)O~$|G*OjO4c&m z>Y$xG^@f)1=BZQKZ|~cI)7XpiaXw#qOfl0R^&mYHs9>zgl88cRP#m!|HX^w9$zf6T z;}v*$d)XP>+ldKN1|Qbx5V*wraK@lz>dBa6+kNP2lnCfN7-l?6+RkzFTV#uEm!T&J z2D+1(yqFJB22!Uscg>#Bw>3qqalKc4x$|o~P}tgae!5IguTQvI)@yFj^S!tfi%-SI z+hw~~qo#*fq&PA8wthkj*z(Y;)&MS%j#MdnD0dEt>y~euyS*DDhd>EB3K4!% z^c9t%U_*J{4v`HkPjB=)MJahnqt{c(eI1PVM>gEA;3BY!-Gqw@Hyd|5zA-hTdqIX` zy$z`QEppSGjmzt#6f?im5|Hm$w)6+RX!pUk`4Jgrd}H)FxL3A;(c-ql4U#f;AaUw^ zeiG-zbl1&PM+s7Rb_!UW#~RkK93benauurgKUdKzel@i}ySz*i;{W^UAOt8AOURmx5>mI+36kZ_WbLh*VT9QVPn z-cs7xuJSTdqiQ%^|~1G4pWkC!ItP?a)D@~agoUzwC-il zyI*NWIA1CZSSoT(2Uv|m9I||9mkl$Y0FA@gCq2m=rAKAt|1$G0ip}2$r6yH=aoOQ0 zNy@;$IdSmY%!*oCj++bbWO)3`B1b{MFTRWB=GpciNmFZsfK(MEOb80%z17$*j9PA9 zN?FU5vdbRNk^ZVCXfV$9F_FMN1-}>i$l9BltS<*1a*2T}!36^^iGa^5KnDbwVEIcX zQj$GwVp)ie%B2nz4pzt-Auz6Lj%tGIv*B&+kuklYEyH2j5Ixz-S(uolO(WuMLET;- z#?-NS=j(T`YI$8=U;Y>=(VsTXI)BD6m1lW|aH&oK z(W-6E#P9p^>oX#HYKng;l@Hs0g=4bi+rQ?Pd{iwcNSOu!h+>dtoBYiBKGk429wqEf z+&MAz){06Q+js++qMH$)5gIDytQ0jW<1@{%*Tn!k(|r*z6;N)fnn=ir|Mxul4i}xB z{^uNZvBlfwZ;(AQRa6F2{bXUV&D z2)kDmFjmXoJx}DsJ^%>9Xkmb4L$1m+R(yqX@_L)--?|wh0s7vXx#hc43t6r=NxmF0kAOZi!-xFfI4g`ka;BqFjF*;sOak0y}yd9m)a5*r_6n!O1VqAq|c?VXsD`dJGwJ!fq#>H0hKz zC!Eq^OuY%a?RDCrUTa3RPe3hn)Df~)4VoHF*LJzE<+>ZWS@~y89yf17Mc$THZglgt z+)>Az$6;Wvef`BI&99Il43Dwr&hbmd4>z<;O-!! z;i~8QI&`wL_A3iS?2~9Vp0V35vYvuWjEz`x*tWUH>r$Km=GCshiWdI^EWq)os2GM5 zB!x=rgUM#gjy(sCoH%pg%8fe@p1gST;frr^^?wBY2xA6PV1y=L>q5XPk z3Mt;l*9#vO1`B>+(avly4p%edGufGV`sOtMZ@9{TmGdeKz+k7vJMlr|L|%*NE{XA* z#v_d{bLz5d)gJ!Xt^%=f-?<+}ue$vBdLhsC&o$3&u`*Zc7p-4kW4FI3M4rD&yJpbc G2LJ#r>&vhJ literal 0 HcmV?d00001 diff --git a/packages/web/public/fonts/RubikMonoOne-400.woff2 b/packages/web/public/fonts/RubikMonoOne-400.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..1a999c85c3e477358e34ca7337588917e4c72943 GIT binary patch literal 6156 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 literal 0 HcmV?d00001 diff --git a/packages/web/public/fonts/SpaceMono-700.woff2 b/packages/web/public/fonts/SpaceMono-700.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..7ddc67d691571057003061768abb138f876643ee GIT binary patch literal 7332 zcmV;V99!dePew8T0RR91034(M5dZ)H07VD@031L70RR9100000000000000000000 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 Promise; }; + readonly games: { + search: (q: string) => Promise<{ hits: { appId: number; name: string; cover: string; header: string }[] }>; + }; + readonly pins: { list: (channelId: string) => Promise<{ messages: MessageWithUser[] }>; pin: (messageId: string) => Promise<{ success: boolean }>; @@ -786,6 +790,10 @@ export class BackspaceApiClient { removeSticker: (id) => request('DELETE', `/stickers/${id}`), }; + this.games = { + search: (q: string) => request<{ hits: { appId: number; name: string; cover: string; header: string }[] }>('GET', `/games/search?q=${encodeURIComponent(q)}`), + }; + this.pins = { list: (channelId: string) => request<{ messages: MessageWithUser[] }>('GET', `/channels/${channelId}/pins`), pin: (messageId: string) => request<{ success: boolean }>('PUT', `/messages/${messageId}/pin`), diff --git a/packages/web/src/components/layout/MemberSidebar.tsx b/packages/web/src/components/layout/MemberSidebar.tsx index 026cd891..009d9ce6 100644 --- a/packages/web/src/components/layout/MemberSidebar.tsx +++ b/packages/web/src/components/layout/MemberSidebar.tsx @@ -11,6 +11,8 @@ import { getPrimaryActivity } from '@backspace/shared/src/activities.js'; import { parseFederatedUsername, isFederationGlobeApplicable } from '../../utils/identity'; import { useCanonicalUserView } from '../../utils/userViewLookup'; import { useDelayedLoading } from '../../hooks/useDelayedLoading'; +import { getProfileStyle, nameplateProps } from '../../utils/profileStyle'; +import { ProfileTagChip } from '../profile/ProfileTagChip'; /** * Derives the display group for a member based on their highest-positioned role @@ -71,15 +73,19 @@ function MemberSidebarRow({ const { baseName } = parseFederatedUsername(canonical.username); const displayName = canonical.displayName ?? baseName; + const style = getProfileStyle(canonical); + const plate = isOffline ? null : nameplateProps(style.nameplate, style.nameplateColors); + const rowClass = isRichActivity ? `flex items-center gap-2.5 px-2.5 py-2 rounded-[10px] mb-1 cursor-pointer transition-colors glass-pill border-l-2 ${accentClass}` - : 'flex items-center gap-2.5 px-2 py-1.5 rounded-[4px] hover:bg-interactive-hover cursor-pointer group transition-colors'; + : `flex items-center gap-2.5 px-2 py-1.5 rounded-[4px] cursor-pointer group transition-colors ${plate ? plate.className : 'hover:bg-interactive-hover'}`; return (
    onClickMember(e, canonical)} className={rowClass} + style={plate?.style} >
    - +
    + + {!isOffline && style.tag && } +
    {!isOffline && isFederationGlobeApplicable(canonical) && (
    @{parseFederatedUsername(canonical.username).domain}
    )} diff --git a/packages/web/src/components/modals/UserProfileModal.tsx b/packages/web/src/components/modals/UserProfileModal.tsx index bc0c03fb..3d566497 100644 --- a/packages/web/src/components/modals/UserProfileModal.tsx +++ b/packages/web/src/components/modals/UserProfileModal.tsx @@ -16,8 +16,16 @@ import { useAuthStore } from '../../stores/authStore'; import { getAvatarGradient, getSpaceGradient, adjustColor, mutedGradient } from '../../utils/gradients'; import { parseFederatedUsername, isSelf, canonicalUserMatch } from '../../utils/identity'; import { loadFederatedMutuals, type TaggedMutualFriend, type MutualSpace } from '../../utils/mutuals'; +import { StyledName } from '../profile/StyledName'; +import { DecoratedAvatar } from '../profile/DecoratedAvatar'; +import { ProfileEffectLayer } from '../profile/ProfileEffectLayer'; +import { ProfileTagChip } from '../profile/ProfileTagChip'; +import { ProfileBadges } from '../profile/ProfileBadges'; +import { ProfileLinks } from '../profile/ProfileLinks'; +import { ProfileBoard } from '../profile/ProfileWidgets'; +import { getProfileStyle, computeBadges, themeGradient } from '../../utils/profileStyle'; -type Tab = 'about' | 'friends' | 'spaces'; +type Tab = 'about' | 'board' | 'friends' | 'spaces'; type FriendshipStatus = | { state: 'self' } @@ -68,6 +76,9 @@ export function UserProfileModal() { const currentUser = useAuthStore((s) => s.user); const t = useT(); + const allSpaces = useSpaceStore((st) => st.spaces); + const currentSpaceIdForBadges = useSpaceStore((st) => st.currentSpaceId); + const spaceMembers = useSpaceStore((st) => st.members); const [user, setUser] = useState(null); const [userOrigin, setUserOrigin] = useState(''); const [activeTab, setActiveTab] = useState('about'); @@ -164,6 +175,9 @@ export function UserProfileModal() { const { baseName, domain } = parseFederatedUsername(user.username); const displayName = user.displayName ?? baseName; + const style = getProfileStyle(user); + const profileSpace = allSpaces.find((sp) => sp.id === currentSpaceIdForBadges) ?? null; + const profileMember = spaceMembers.find((m) => m.userId === user.id) ?? null; // Banner — use correct API client for remote users const profileApi = getApiForOrigin(userOrigin); @@ -265,6 +279,7 @@ export function UserProfileModal() { const tabs: { key: Tab; label: string; count?: number }[] = [ { key: 'about', label: 'About' }, + { key: 'board', label: t('profile.tab.board') }, { key: 'friends', label: 'Mutual Friends', count: mutualFriends.length }, { key: 'spaces', label: 'Mutual Spaces', count: mutualSpaces.length }, ]; @@ -278,9 +293,10 @@ export function UserProfileModal() { className="h-[100px] flex-shrink-0 relative" style={bannerSrc ? { backgroundImage: `url(${bannerSrc})`, backgroundSize: 'cover', backgroundPosition: 'center' } - : { background: bannerFallback } + : { background: themeGradient(style) ?? bannerFallback } } > + {/* Close button */} + @@ -197,6 +199,7 @@ export function UserSettingsModal() {
    User Settings
    + @@ -250,6 +253,7 @@ export function UserSettingsModal() { )} {tab === 'account' && } + {tab === 'profile' && } {tab === 'voice' && } {tab === 'privacy' && } {tab === 'connections' && } diff --git a/packages/web/src/components/modals/settingsPanels/ProfilePanel.tsx b/packages/web/src/components/modals/settingsPanels/ProfilePanel.tsx new file mode 100644 index 00000000..b2df2450 --- /dev/null +++ b/packages/web/src/components/modals/settingsPanels/ProfilePanel.tsx @@ -0,0 +1,336 @@ +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { useAuthStore } from '../../../stores/authStore'; +import { useUIStore } from '../../../stores/uiStore'; +import { api } from '../../../api/client'; +import { useT, type TranslationKey } from '../../../i18n'; +import { parseFederatedUsername } from '../../../utils/identity'; +import { getProfileStyle, nameStyleProps, nameplateProps } from '../../../utils/profileStyle'; +import { ProfileCard } from '../../profile/ProfileCard'; +import { DecoratedAvatar } from '../../profile/DecoratedAvatar'; +import { ProfileEffectLayer } from '../../profile/ProfileEffectLayer'; +import { Avatar } from '../../ui/Avatar'; +import { + NAME_FONTS, NAME_EFFECTS, AVATAR_DECORATIONS, PROFILE_EFFECTS, NAMEPLATES, PROFILE_LIMITS, + DEFAULT_PROFILE_STYLE, normalizeProfileStyle, steamCoverUrl, + type ProfileStyle, type GameEntry, +} from '@backspace/shared/src/profile'; + +/** Colour pairs offered as one-click presets for name and theme. */ +const PALETTES: [string, string][] = [ + ['#efefef', '#7c6cf6'], ['#f97316', '#fde047'], ['#22d3ee', '#a855f7'], ['#4ade80', '#22d3ee'], + ['#f472b6', '#fbbf24'], ['#fb7185', '#7c3aed'], ['#a3e635', '#16a34a'], ['#ffffff', '#94a3b8'], +]; + +function Section({ title, hint, children }: { title: string; hint?: string; children: React.ReactNode }) { + return ( +
    +
    {title}
    + {hint &&

    {hint}

    } +
    {children}
    +
    + ); +} + +function ColorPair({ value, onChange }: { value: [string, string]; onChange: (v: [string, string]) => void }) { + return ( +
    + {PALETTES.map((p) => ( +
    + ); +} + +function GameSearch({ onPick, placeholder }: { onPick: (g: GameEntry) => void; placeholder: string }) { + const t = useT(); + const [q, setQ] = useState(''); + const [hits, setHits] = useState<{ appId: number; name: string; cover: string }[]>([]); + const [busy, setBusy] = useState(false); + const timer = useRef | null>(null); + useEffect(() => { + if (timer.current) clearTimeout(timer.current); + if (q.trim().length < 2) { setHits([]); return; } + timer.current = setTimeout(async () => { + setBusy(true); + try { setHits((await api.games.search(q.trim())).hits); } catch { setHits([]); } finally { setBusy(false); } + }, 350); + return () => { if (timer.current) clearTimeout(timer.current); }; + }, [q]); + const pick = (g: GameEntry) => { onPick(g); setQ(''); setHits([]); }; + return ( +
    + setQ(e.target.value)} placeholder={placeholder} className="input-standard w-full text-sm" + onKeyDown={(e) => { if (e.key === 'Enter' && q.trim()) { e.preventDefault(); pick({ appId: null, name: q.trim(), cover: null, note: '', tags: [] }); } }} /> + {(hits.length > 0 || busy) && ( +
    + {busy && hits.length === 0 &&
    {t('profile.editor.searching')}
    } + {hits.map((h) => ( + + ))} + {q.trim() && !busy && ( + + )} +
    + )} +
    + ); +} + +function GameEditor({ game, onChange, onRemove, withNote }: { game: GameEntry; onChange: (g: GameEntry) => void; onRemove: () => void; withNote?: boolean }) { + const t = useT(); + return ( +
    + {game.cover ? :
    } +
    +
    {game.name}
    + {withNote && ( + onChange({ ...game, note: e.target.value })} + placeholder={t('profile.editor.gameNote')} className="input-standard w-full text-xs py-1" /> + )} + onChange({ ...game, tags: e.target.value.split(',').map((x) => x.trim()).filter(Boolean).slice(0, PROFILE_LIMITS.gameTags) })} + placeholder={t('profile.editor.gameTags')} className="input-standard w-full text-xs py-1" /> +
    + +
    + ); +} + +export function ProfilePanel() { + const t = useT(); + const user = useAuthStore((s) => s.user); + const updateProfile = useAuthStore((s) => s.updateProfile); + const addToast = useUIStore((s) => s.addToast); + + const saved = useMemo(() => getProfileStyle(user), [user]); + const [draft, setDraft] = useState(saved); + const [saving, setSaving] = useState(false); + const [error, setError] = useState(''); + useEffect(() => { setDraft(saved); }, [saved]); + + if (!user) return null; + const displayName = user.displayName ?? parseFederatedUsername(user.username).baseName; + const bannerSrc = user.banner ? (user.banner.startsWith('http') || user.banner.startsWith('/') ? user.banner : api.uploads.url(user.banner)) : null; + const preview: typeof user = { ...user, profileStyle: draft }; + const isDirty = JSON.stringify(normalizeProfileStyle(draft)) !== JSON.stringify(saved); + + const set = (k: K, v: ProfileStyle[K]) => setDraft((d) => ({ ...d, [k]: v })); + const setW = (k: K, v: ProfileStyle['widgets'][K]) => setDraft((d) => ({ ...d, widgets: { ...d.widgets, [k]: v } })); + + const handleSave = async () => { + setSaving(true); setError(''); + try { + await updateProfile({ profileStyle: normalizeProfileStyle(draft) }); + addToast(t('profile.editor.saved'), 'success', 2000); + } catch (e) { setError(e instanceof Error ? e.message : t('profile.editor.saveFailed')); } + finally { setSaving(false); } + }; + const handleReset = () => setDraft(DEFAULT_PROFILE_STYLE); + + const chip = (active: boolean) => `px-2.5 py-1.5 rounded-md text-sm border transition-colors ${active ? 'border-accent-primary bg-accent-primary/15 text-txt-primary' : 'border-white/[0.06] bg-white/[0.03] text-txt-secondary hover:bg-white/[0.06]'}`; + const tile = (active: boolean) => `relative rounded-lg border-2 p-2 flex flex-col items-center gap-1 transition-colors ${active ? 'border-accent-primary bg-accent-primary/10' : 'border-white/[0.06] bg-white/[0.03] hover:bg-white/[0.06]'}`; + + return ( +
    +

    {t('profile.editor.title')}

    +

    {t('profile.editor.subtitle')}

    + +
    +
    + {/* Name style */} +
    +
    {t('profile.editor.font')}
    +
    + {NAME_FONTS.map((f) => ( + + ))} +
    +
    {t('profile.editor.effect')}
    +
    + {NAME_EFFECTS.map((e) => { + const p = nameStyleProps({ font: 'default', effect: e, colors: draft.name.colors }); + return ( + + ); + })} +
    +
    {t('profile.editor.colors')}
    + set('name', { ...draft.name, colors: c })} /> +
    + + {/* Decoration */} +
    +
    + {AVATAR_DECORATIONS.map((d) => ( + + ))} +
    +
    + + {/* Profile effect */} +
    +
    + {PROFILE_EFFECTS.map((e) => ( + + ))} +
    +
    + + {/* Nameplate */} +
    +
    + {NAMEPLATES.map((n) => { + const p = nameplateProps(n, draft.nameplateColors); + return ( + + ); + })} +
    + {draft.nameplate === 'custom' && set('nameplateColors', c)} />} +
    + + {/* Theme */} +
    +
    + + set('theme', { colors: c })} /> +
    +
    + + {/* Identity: pronouns + tag */} +
    +
    + +
    + {t('profile.editor.tag')} +
    + set('tag', { text: draft.tag?.text ?? '', emoji: e.target.value, color: draft.tag?.color ?? '#7c6cf6' })} placeholder="🔥" className="input-standard w-12 text-center" /> + set('tag', { text: e.target.value.toUpperCase(), emoji: draft.tag?.emoji ?? '', color: draft.tag?.color ?? '#7c6cf6' })} placeholder="STRT" className="input-standard w-24 uppercase tracking-wider" /> + + {draft.tag && } +
    +

    {t('profile.editor.tag.hint')}

    +
    +
    +
    + + {/* Links */} +
    +
    + {draft.links.map((l, i) => ( +
    + set('links', draft.links.map((x, j) => j === i ? { ...x, label: e.target.value } : x))} placeholder={t('profile.editor.linkLabel')} className="input-standard w-36 text-sm" /> + set('links', draft.links.map((x, j) => j === i ? { ...x, url: e.target.value } : x))} placeholder="https://" className="input-standard flex-1 text-sm" /> + +
    + ))} + {draft.links.length < PROFILE_LIMITS.links && ( + + )} +
    +
    + + {/* Board */} +
    +
    +
    +
    {t('profile.widgets.favoriteGame')}
    + {draft.widgets.favoriteGame + ? setW('favoriteGame', g)} onRemove={() => setW('favoriteGame', null)} /> + : setW('favoriteGame', g)} />} +
    +
    +
    {t('profile.widgets.rotation')} · {draft.widgets.rotation.length}/{PROFILE_LIMITS.rotation}
    +
    + {draft.widgets.rotation.map((g, i) => setW('rotation', draft.widgets.rotation.map((x, j) => j === i ? n : x))} onRemove={() => setW('rotation', draft.widgets.rotation.filter((_, j) => j !== i))} />)} + {draft.widgets.rotation.length < PROFILE_LIMITS.rotation && setW('rotation', [...draft.widgets.rotation, g])} />} +
    +
    +
    +
    {t('profile.widgets.wishlist')} · {draft.widgets.wishlist.length}/{PROFILE_LIMITS.wishlist}
    +
    + {draft.widgets.wishlist.map((g, i) => ( +
    + {g.cover ? :
    {g.name}
    } + +
    + ))} +
    + {draft.widgets.wishlist.length < PROFILE_LIMITS.wishlist && setW('wishlist', [...draft.widgets.wishlist, g])} />} +
    +
    +
    {t('profile.editor.quote')}
    +