feat: GIF search (Klipy), stickers, emoji picker, and bug fixes

- Add GIF search powered by Klipy API with correct response mapping
  (file.sm/hd tiers, not flat files structure)
- Add sticker system: packs, upload with auto-downscale, send in messages
- Add tabbed InputPopover with emoji, GIF, and sticker pickers
- Fix GIF API key migration race condition (column-add loop vs rename)
- Fix masked API key corruption on settings save (server + client guards)
- Fix sticker packs 403 (reversed isMember parameter order)
- Fix emoji picker not filling popover width (perLine 8→9, CSS 100%)
- Add error logging for Klipy API failures
This commit is contained in:
Jannis Braun
2026-03-15 02:04:37 +01:00
parent 7113f47b17
commit 3de6e4a668
26 changed files with 2160 additions and 50 deletions
+15
View File
@@ -96,6 +96,7 @@ function handleEvent(origin: string, event: ServerEvent): void {
setUser(event.user);
useSettingsStore.getState().setIsAdmin(event.user.isAdmin ?? false);
useSettingsStore.getState().fetchStreamingLimits();
useSettingsStore.getState().fetchGifEnabled();
}
// Normalize asset URLs for remote origins before dispatching to stores
@@ -754,6 +755,20 @@ function handleEvent(origin: string, event: ServerEvent): void {
break;
}
// ─── Sticker events (all origins) ────────────────────────────────────
case 'sticker_pack_created':
case 'sticker_pack_updated':
case 'sticker_pack_deleted':
case 'sticker_created':
case 'sticker_deleted': {
// Invalidate the sticker picker cache so next open fetches fresh data
import('../components/chat/StickerPicker').then(({ invalidateStickerCache }) => {
invalidateStickerCache();
});
break;
}
case 'pong':
break;