feat: mark all dms read

This commit is contained in:
Kieran 2023-01-18 22:04:52 +00:00
parent 2f3c46629d
commit 621bb5f6ee
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
3 changed files with 60 additions and 33 deletions

View File

@ -1,33 +1,38 @@
import "./DM.css";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import { useInView } from 'react-intersection-observer';
import useEventPublisher from "../feed/EventPublisher";
import Event from "../nostr/Event";
import NoteTime from "./NoteTime";
import Text from "./Text";
import { lastReadDm, setLastReadDm } from "../pages/MessagesPage";
import { setLastReadDm } from "../pages/MessagesPage";
import { RootState } from "../state/Store";
import { HexKey, TaggedRawEvent } from "../nostr";
import { incDmInteraction } from "../state/Login";
export type DMProps = {
data: any
data: TaggedRawEvent
}
export default function DM(props: DMProps) {
const pubKey = useSelector<any>(s => s.login.publicKey);
const dispatch = useDispatch();
const pubKey = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
const publisher = useEventPublisher();
const [content, setContent] = useState("Loading...");
const [decrypted, setDecrypted] = useState(false);
const { ref, inView, entry } = useInView();
const { ref, inView } = useInView();
const isMe = props.data.pubkey === pubKey;
async function decrypt() {
let e = new Event(props.data);
if (!isMe) {
setLastReadDm(e.PubKey);
}
let decrypted = await publisher.decryptDm(e);
setContent(decrypted || "<ERROR>");
if (!isMe) {
setLastReadDm(e.PubKey);
dispatch(incDmInteraction());
}
}
useEffect(() => {

View File

@ -1,9 +1,11 @@
import { useMemo } from "react";
import { useSelector } from "react-redux"
import { useDispatch, useSelector } from "react-redux"
import { HexKey, RawEvent } from "../nostr";
import ProfileImage from "../element/ProfileImage";
import { hexToBech32 } from "../Util";
import { incDmInteraction } from "../state/Login";
import { RootState } from "../state/Store";
type DmChat = {
pubkey: HexKey,
@ -12,12 +14,14 @@ type DmChat = {
}
export default function MessagesPage() {
const myPubKey = useSelector<any, string>(s => s.login.publicKey);
const dms = useSelector<any, RawEvent[]>(s => s.login.dms);
const dispatch = useDispatch();
const myPubKey = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
const dms = useSelector<RootState, RawEvent[]>(s => s.login.dms);
const dmInteraction = useSelector<RootState, number>(s => s.login.dmInteraction);
const chats = useMemo(() => {
return extractChats(dms, myPubKey);
}, [dms]);
return extractChats(dms, myPubKey!);
}, [dms, myPubKey, dmInteraction]);
function person(chat: DmChat) {
return (
@ -30,9 +34,19 @@ export default function MessagesPage() {
)
}
function markAllRead() {
for (let c of chats) {
setLastReadDm(c.pubkey);
}
dispatch(incDmInteraction());
}
return (
<>
<h3>Messages</h3>
<div className="flex">
<h3 className="f-grow">Messages</h3>
<div className="btn" onClick={() => markAllRead()}>Mark All Read</div>
</div>
{chats.sort((a, b) => b.newestMessage - a.newestMessage).map(person)}
</>
)
@ -81,7 +95,6 @@ function newestMessage(dms: RawEvent[], myPubKey: HexKey, pk: HexKey) {
return dmsInChat(dms, pk).reduce((acc, v) => acc = v.created_at > acc ? v.created_at : acc, 0);
}
export function extractChats(dms: RawEvent[], myPubKey: HexKey) {
const keys = dms.map(a => [a.pubkey, dmTo(a)]).flat();
const filteredKeys = Array.from(new Set<string>(keys));

View File

@ -52,9 +52,27 @@ interface LoginStore {
/**
* Encrypted DM's
*/
dms: TaggedRawEvent[]
dms: TaggedRawEvent[],
/**
* Counter to trigger refresh of unread dms
*/
dmInteraction: 0
};
const InitState = {
loggedOut: undefined,
publicKey: undefined,
privateKey: undefined,
relays: {},
latestRelays: 0,
follows: [],
notifications: [],
readNotifications: 0,
dms: [],
dmInteraction: 0
} as LoginStore;
export interface SetRelaysPayload {
relays: Record<string, RelaySettings>,
createdAt: number
@ -62,14 +80,7 @@ export interface SetRelaysPayload {
const LoginSlice = createSlice({
name: "Login",
initialState: <LoginStore>{
relays: {},
latestRelays: 0,
follows: [],
notifications: [],
readNotifications: 0,
dms: []
},
initialState: InitState,
reducers: {
init: (state) => {
state.privateKey = window.localStorage.getItem(PrivateKeyItem) ?? undefined;
@ -182,17 +193,14 @@ const LoginSlice = createSlice({
];
}
},
incDmInteraction: (state) => {
state.dmInteraction += 1;
},
logout: (state) => {
window.localStorage.removeItem(PrivateKeyItem);
window.localStorage.removeItem(PublicKeyItem);
window.localStorage.removeItem(NotificationsReadItem);
state.privateKey = undefined;
state.publicKey = undefined;
state.follows = [];
state.notifications = [];
window.localStorage.clear();
Object.assign(state, InitState);
state.loggedOut = true;
state.readNotifications = 0;
state.dms = [];
state.relays = Object.fromEntries(DefaultRelays.entries());
},
markNotificationsRead: (state) => {
state.readNotifications = new Date().getTime();
@ -210,6 +218,7 @@ export const {
setFollows,
addNotifications,
addDirectMessage,
incDmInteraction,
logout,
markNotificationsRead
} = LoginSlice.actions;