feat: optimistically render user reactions on timeline #31

Closed
verbiricha wants to merge 1 commits from timeline-reactions into main
4 changed files with 33 additions and 4 deletions

View File

@ -1,9 +1,10 @@
import { useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { useSelector, useDispatch } from "react-redux";
import { faHeart, faReply, faThumbsDown, faTrash, faBolt, faRepeat } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import useEventPublisher from "../feed/EventPublisher";
import { addReaction } from "../state/Reactions"
import { normalizeReaction, Reaction } from "../Util";
import { NoteCreator } from "./NoteCreator";
import LNURLTip from "./LNURLTip";
@ -12,6 +13,7 @@ export default function NoteFooter(props) {
const reactions = props.reactions;
const ev = props.ev;
const dispatch = useDispatch()
const login = useSelector(s => s.login.publicKey);
const author = useSelector(s => s.users.users[ev.RootPubKey]);
const publisher = useEventPublisher();
@ -37,6 +39,7 @@ export default function NoteFooter(props) {
async function react(content) {
let evLike = await publisher.react(ev, content);
publisher.broadcast(evLike);
dispatch(addReaction(evLike.ToObject()))
}
async function deleteEvent() {

View File

@ -1,6 +1,8 @@
import { useMemo } from "react";
import { useSelector } from "react-redux";
import useTimelineFeed from "../feed/TimelineFeed";
import EventKind from "../nostr/EventKind";
import Event from "../nostr/Event";
import Note from "./Note";
import NoteReaction from "./NoteReaction";
@ -9,9 +11,12 @@ import NoteReaction from "./NoteReaction";
*/
export default function Timeline({ global, pubkeys }) {
const feed = useTimelineFeed(pubkeys, global);
const reactions = useSelector(s => s.reactions)
const feedReactions = feed?.others || []
const allReactions = [...new Set([...reactions.user, ...feedReactions])]
function reaction(id, kind = EventKind.Reaction) {
return feed?.others?.filter(a => a.kind === kind && a.tags.some(b => b[0] === "e" && b[1] === id));
return allReactions.filter(a => a.kind === kind && a.tags.some(b => b[0] === "e" && b[1] === id)).map(Event.FromObject);
}
const mainFeed = useMemo(() => {

19
src/state/Reactions.js Normal file
View File

@ -0,0 +1,19 @@
import { createSlice } from '@reduxjs/toolkit'
const ReactionsSlice = createSlice({
name: "Reactions",
initialState: {
/**
* User reactions
*/
user: [],
},
reducers: {
addReaction: (state, action) => {
state.user.push(action.payload)
},
}
});
export const { addReaction } = ReactionsSlice.actions;
export const reducer = ReactionsSlice.reducer;

View File

@ -1,12 +1,14 @@
import { configureStore } from "@reduxjs/toolkit";
import { reducer as UsersReducer } from "./Users";
import { reducer as LoginReducer } from "./Login";
import { reducer as ReactionsReducer } from "./Reactions";
const Store = configureStore({
reducer: {
users: UsersReducer,
login: LoginReducer
login: LoginReducer,
reactions: ReactionsReducer,
}
});
export default Store;
export default Store;