feat: optimistically render user reactions on timeline #31
@ -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() {
|
||||
|
@ -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
19
src/state/Reactions.js
Normal 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;
|
@ -1,11 +1,13 @@
|
||||
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,
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user