Files
logseq/docs/agent-guide/002-reactions.md
2026-02-01 21:45:31 +08:00

77 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR: Reactions via Properties
## Status
- Proposed
## Context
- Users want lightweight reactions (e.g., 👍 ❤️) on blocks and pages.
- Reactions must be stored in the graph so they sync, can be queried, and work across devices.
- The system already uses properties to attach structured metadata to blocks/pages.
- We need to show who reacted and which emoji they used.
## Decision
- Store reactions as separate entities linked to the reacted block/page.
- Each reaction entity records:
- Emoji id (from Logseqs supported `emojis-data` set).
- Optional `:logseq.property/created-by-ref` pointing to the reacting user (absent for anonymous graphs).
- Reacted block/page reference.
- `:block/created-at` timestamp for the reaction entity.
- No `:logseq.property/reactions` collection property is required; use the reverse ref
`(:logseq.property.reaction/_target node-entity)` to fetch reactions for a node.
- Keep the property name namespaced in logseq.db.frontend.property/built-in-properties.
### Proposed entity shape
```
{:db/id ...
:logseq.property.reaction/emoji-id "smile"
:logseq.property/created-by-ref <user-db-id> ;; omitted for anonymous graphs
:logseq.property.reaction/target <target-db-id> ;; block/page db id
:block/created-at 1710000000000}
```
### Read/write rules
- Toggling a reaction adds/removes a reaction entity for the current emoji/user.
- If anonymous, only one reaction per emoji per block/page (no user id).
- Reactions are derived via reverse reference lookup; no dedicated collection
property is stored on the node.
### Example queries
```clj
;; Given a block/page entity `node-entity`, fetch all reactions.
(:logseq.property.reaction/_target node-entity)
;; Filter reactions by emoji id.
(filter #(= "smile" (:logseq.property.reaction/emoji-id %))
(:logseq.property.reaction/_target node-entity))
;; Count reactions per emoji id.
(->> (:logseq.property.reaction/_target node-entity)
(map :logseq.property.reaction/emoji-id)
(frequencies))
;; Filter reactions by user id (when present).
(filter #(= user-db-id (:logseq.property/created-by-ref %))
(:logseq.property.reaction/_target node-entity))
```
## Consequences
- Reactions sync naturally as part of DB transactions and are queryable.
- Data model supports “who reacted” and multiple users per emoji without map merging.
- Adds more entities; need efficient queries and indexes.
## Alternatives Considered
- **Dedicated table/attribute per emoji**: complicates schema, increases complexity.
- **Property map (emoji -> users)**: smaller but harder to resolve conflicts and query per user.
- **Inline text markers**: not structured, hard to query and sync.
## Open Questions
- Which user identifier should be stored as `:logseq.property/created-by-ref`?
Each user has a page in the graph
- How to handle anonymous/local graphs (no user identity)?
Record reactions, for anonymous graphs, don't store :logseq.property/created-by-ref
## Notes for Implementation
- Add emoji entity schema to DB validation.
- UI should show a summary (emoji + count) and a hover/popover with user list.
- User can toggle reaction.