# Embed filters — handoff

## Summary

Embed filters let users and room admins suppress URL preview/embeds for matching links. **Personal** filters live in per-room account data; **room-wide** filters are a room state event admins control. Patterns are regex strings tested against URLs before rendering embeds in the timeline and threads.

## User-facing behavior

- Per-user: configure patterns for a room (settings or thread UI — see consumers)
- Room admins: room-wide disabled patterns via `im.paarrot.room.embed_filters`
- Matching URLs skip embed cards (Giphy, Open Graph, etc.)

## Architecture

```
useRoomEmbedFilters (personal, account data)
useRoomWideEmbedFilters (room state)
  → combineEmbedFilters()
    → ThreadView / RoomTimeline embed rendering
```

## Key files

| Path | Role |
|------|------|
| `cinny/src/app/hooks/useRoomEmbedFilters.ts` | Hooks, types, combine logic |
| `cinny/src/types/matrix/room.ts` | `StateEvent.RoomEmbedFilters` |
| `cinny/src/app/features/room/ThreadView.tsx` | Consumer |
| `cinny/src/app/features/room/RoomTimeline.tsx` | Consumer |
| `cinny/src/app/features/common-settings/general/EmbedFilters.tsx` | Room-wide settings UI |
| `cinny/src/app/components/RenderMessageContent.tsx` | Embed render gating |
| `cinny/src/app/features/forum/useForumMessageRenderOptions.ts` | Forum post embed options |

## Data model

| Key | Scope | Content |
|-----|-------|---------|
| `im.paarrot.embed_filters` | Room account data (per user) | `{ disabledPatterns: string[] }` |
| `im.paarrot.room.embed_filters` | Room state | `{ disabledPatterns: string[] }` |

Patterns are JavaScript `RegExp` strings — invalid regex can throw; handle at input time.

## Dependencies

- `matrix-js-sdk` account data + state events

## Integration points

- **URL preview components**: `url-preview/` — embed gating happens before render
- **Thread view**: combines personal + room-wide filters

## Testing

### Manual

1. Add personal pattern blocking `example.com` in a room.
2. Post link; verify no embed.
3. As admin set room-wide pattern; verify all members affected.
4. Test thread view uses combined filters.

### Automated

- None

## Known issues & gotchas

- Two storage locations — document clearly for users (personal vs room-wide)
- Regex validation on save recommended — bad patterns break matching try/catch sites
- Account data type constant: `EMBED_FILTERS_ACCOUNT_DATA_TYPE` in hook file

## Future work

- UI in room settings for room-wide filters (if not complete)
- Import/export pattern lists
- Non-regex simple domain blocklist mode

## Related docs

- None dedicated

## Add your extra things here

- `combineEmbedFilters` merges personal + room-wide with dedup logic — read implementation before changing precedence
- `EmbedFiltersContent` interface in `useRoomEmbedFilters.ts`
