Fix footer and context menu in article preview

This commit is contained in:
Bojan Mojsilovic 2024-05-30 14:34:03 +02:00
parent e28299e9f0
commit b606e90532
12 changed files with 90 additions and 29 deletions

View File

@ -1,4 +1,5 @@
.article {
position: relative;
display: flex;
flex-direction: column;
text-decoration: none;
@ -115,3 +116,9 @@
}
}
.upRightFloater {
position: absolute;
top: -6px;
right: 8px;
}

View File

@ -12,6 +12,7 @@ import { PrimalArticle, ZapOption } from '../../types/primal';
import { uuidv4 } from '../../utils';
import Avatar from '../Avatar/Avatar';
import { NoteReactionsState } from '../Note/Note';
import NoteContextTrigger from '../Note/NoteContextTrigger';
import ArticleFooter from '../Note/NoteFooter/ArticleFooter';
import NoteFooter from '../Note/NoteFooter/NoteFooter';
import NoteTopZaps from '../Note/NoteTopZaps';
@ -53,6 +54,7 @@ const ArticlePreview: Component<{
let latestTopZap: string = '';
let latestTopZapFeed: string = '';
let articleContextMenu: HTMLDivElement | undefined;
const onConfirmZap = (zapOption: ZapOption) => {
app?.actions.closeCustomZapModal();
@ -181,19 +183,48 @@ const ArticlePreview: Component<{
onCancel: onCancelZap,
});
const openReactionModal = (openOn = 'likes') => {
app?.actions.openReactionModal(props.article.id, {
likes: reactionsState.likes,
zaps: reactionsState.zapCount,
reposts: reactionsState.reposts,
quotes: reactionsState.quoteCount,
openOn,
});
};
const onContextMenuTrigger = () => {
app?.actions.openContextMenu(
props.article,
articleContextMenu?.getBoundingClientRect(),
() => {
app?.actions.openCustomZapModal(customZapInfo());
},
openReactionModal,
);
}
return (
<A class={styles.article} href={`/e/${props.article.naddr}`}>
<div class={styles.upRightFloater}>
<NoteContextTrigger
ref={articleContextMenu}
onClick={onContextMenuTrigger}
/>
</div>
<div class={styles.header}>
<div class={styles.userInfo}>
<Avatar user={props.article.author} size="micro"/>
<div class={styles.userName}>{userName(props.article.author)}</div>
<VerificationCheck user={props.article.author} />
<div class={styles.nip05}>{props.article.author.nip05 || ''}</div>
<Avatar user={props.article.user} size="micro"/>
<div class={styles.userName}>{userName(props.article.user)}</div>
<VerificationCheck user={props.article.user} />
<div class={styles.nip05}>{props.article.user.nip05 || ''}</div>
</div>
<div class={styles.time}>
{shortDate(props.article.published)}
</div>
</div>
<div class={styles.body}>
<div class={styles.text}>
<div class={styles.content}>

View File

@ -60,12 +60,12 @@ const NoteContextMenu: Component<{
const doMuteUser = () => {
account?.actions.addToMuteList(note()?.post.pubkey);
account?.actions.addToMuteList(note()?.pubkey);
props.onClose();
};
const doUnmuteUser = () => {
account?.actions.removeFromMuteList(note()?.post.pubkey);
account?.actions.removeFromMuteList(note()?.pubkey);
props.onClose();
};
@ -77,21 +77,21 @@ const NoteContextMenu: Component<{
const copyNoteLink = () => {
if (!props.data) return;
navigator.clipboard.writeText(`${window.location.origin}/e/${note().post.noteId}`);
navigator.clipboard.writeText(`${window.location.origin}/e/${note().noteId}`);
props.onClose()
toaster?.sendSuccess(intl.formatMessage(tToast.notePrimalLinkCoppied));
};
const copyNoteText = () => {
if (!props.data) return;
navigator.clipboard.writeText(`${note().post.content}`);
navigator.clipboard.writeText(`${note().content}`);
props.onClose()
toaster?.sendSuccess(intl.formatMessage(tToast.notePrimalTextCoppied));
};
const copyNoteId = () => {
if (!props.data) return;
navigator.clipboard.writeText(`${note().post.noteId}`);
navigator.clipboard.writeText(`${note().noteId}`);
props.onClose()
toaster?.sendSuccess(intl.formatMessage(tToast.noteIdCoppied));
};
@ -128,7 +128,7 @@ const NoteContextMenu: Component<{
const onClickOutside = (e: MouseEvent) => {
if (
!props.data ||
!document?.getElementById(`note_context_${note().post.id}`)?.contains(e.target as Node)
!document?.getElementById(`note_context_${note().id}`)?.contains(e.target as Node)
) {
props.onClose()
}
@ -222,7 +222,7 @@ const NoteContextMenu: Component<{
];
};
const noteContext = () => account?.publicKey !== note()?.post.pubkey ?
const noteContext = () => account?.publicKey !== note()?.pubkey ?
[ ...noteContextForEveryone, ...noteContextForOtherPeople()] :
noteContextForEveryone;
@ -251,7 +251,7 @@ const NoteContextMenu: Component<{
/>
<PrimalMenu
id={`note_context_${note()?.post.id}`}
id={`note_context_${note()?.id}`}
items={noteContext()}
hidden={!props.open}
position="note_footer"

View File

@ -181,7 +181,7 @@ const ArticleFooter: Component<{
return;
}
if (!canUserReceiveZaps(props.note.author)) {
if (!canUserReceiveZaps(props.note.user)) {
toast?.sendWarning(
intl.formatMessage(t.zapUnavailable),
);
@ -206,7 +206,7 @@ const ArticleFooter: Component<{
return;
}
if (account.relays.length === 0 || !canUserReceiveZaps(props.note.author)) {
if (account.relays.length === 0 || !canUserReceiveZaps(props.note.user)) {
return;
}

View File

@ -29,7 +29,7 @@ export type CustomZapInfo = {
};
export type NoteContextMenuInfo = {
note: PrimalNote,
note: PrimalNote | PrimalArticle,
position: DOMRect | undefined,
openCustomZap?: () => void,
openReactions?: () => void,
@ -72,7 +72,7 @@ export type AppContextStore = {
openCustomZapModal: (custonZapInfo: CustomZapInfo) => void,
closeCustomZapModal: () => void,
resetCustomZap: () => void,
openContextMenu: (note: PrimalNote, position: DOMRect | undefined, openCustomZapModal: () => void, openReactionModal: () => void) => void,
openContextMenu: (note: PrimalNote | PrimalArticle, position: DOMRect | undefined, openCustomZapModal: () => void, openReactionModal: () => void) => void,
closeContextMenu: () => void,
openLnbcModal: (lnbc: string, onPay: () => void) => void,
closeLnbcModal: () => void,
@ -155,7 +155,7 @@ export const AppProvider = (props: { children: JSXElement }) => {
};
const openContextMenu = (
note: PrimalNote,
note: PrimalNote | PrimalArticle,
position: DOMRect | undefined,
openCustomZap: () => void,
openReactions: () => void,

View File

@ -2,7 +2,7 @@ import { nip19 } from "nostr-tools";
import { createContext, createEffect, onCleanup, useContext } from "solid-js";
import { createStore, reconcile, unwrap } from "solid-js/store";
import { APP_ID } from "../App";
import { Kind } from "../constants";
import { Kind, minKnownProfiles } from "../constants";
import { getArticlesFeed, getEvents, getExploreFeed, getFeed, getFutureArticlesFeed, getFutureExploreFeed, getFutureFeed } from "../lib/feed";
import { fetchStoredFeed, saveStoredFeed } from "../lib/localStore";
import { setLinkPreviews } from "../lib/notes";
@ -307,7 +307,8 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
};
const fetchNotes = (topic: string, subId: string, until = 0, includeReplies?: boolean) => {
const [scope, timeframe] = topic.split(';');
const t = account?.publicKey || '532d830dffe09c13e75e8b145c825718fc12b0003f61d61e9077721c7fff93cb';
const [scope, timeframe] = t.split(';');
updateStore('isFetching', true);
updateStore('page', () => ({ messages: [], users: {}, postStats: {} }));
@ -329,7 +330,7 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
return;
}
getArticlesFeed(account?.publicKey, topic, `reads_feed_${subId}`, until, 20);
getArticlesFeed(account?.publicKey, t, `reads_feed_${subId}`, until, 20);
};
const clearNotes = () => {

View File

@ -32,6 +32,7 @@ export const getFeed = (user_pubkey: string | undefined, pubkey: string | undef
let payload = { limit, until: time, pubkey };
if (user_pubkey) {
// @ts-ignore dynamic property
payload.user_pubkey = user_pubkey;
}
if (include_replies) {

View File

@ -19,8 +19,8 @@ export const zapNote = async (note: PrimalNote, sender: string | undefined, amou
const sats = Math.round(amount * 1000);
let payload = {
profile: note.post.pubkey,
event: note.msg.id,
profile: note.pubkey,
event: note.id,
amount: sats,
relays: relays.map(r => r.url)
};
@ -55,7 +55,7 @@ export const zapArticle = async (note: PrimalArticle, sender: string | undefined
return false;
}
const callback = await getZapEndpoint(note.author);
const callback = await getZapEndpoint(note.user);
if (!callback) {
return false;

View File

@ -83,7 +83,14 @@ const Notifications: Component = () => {
const [relatedNotes, setRelatedNotes] = createStore<NotificationStore>({
notes: [],
users: [],
page: { messages: [], users: {}, postStats: {}, mentions: {}, noteActions: {} },
page: {
messages: [],
users: {},
postStats: {},
mentions: {},
noteActions: {},
topZaps: {},
},
reposts: {},
})
@ -91,7 +98,15 @@ const Notifications: Component = () => {
notes: [],
users: {},
userStats: {},
page: { messages: [], users: {}, postStats: {}, notifications: [], mentions: {}, noteActions: {} },
page: {
messages: [],
users: {},
postStats: {},
notifications: [],
mentions: {},
noteActions: {},
topZaps: {},
},
reposts: {},
notifications: [],
})

View File

@ -94,7 +94,7 @@ const Home: Component = () => {
}
if (newPostAuthors.length < 3) {
const users = context?.future.notes.map(note => note.author) || [];
const users = context?.future.notes.map(note => note.user) || [];
const uniqueUsers = users.reduce<PrimalUser[]>((acc, user) => {
const isDuplicate = acc.find(u => u && u.pubkey === user.pubkey);

View File

@ -366,8 +366,10 @@ export const convertToNotes: ConvertToNotes = (page, topZaps) => {
replyTo: replyTo && replyTo[1],
tags: msg.tags,
id: msg.id,
noteId: nip19.noteEncode(msg.id),
pubkey: msg.pubkey,
topZaps: [ ...tz ],
content: sanitize(msg.content),
};
});
}
@ -466,10 +468,11 @@ export const convertToArticles: ConvertToArticles = (page, topZaps) => {
image: '',
tags: [],
published: msg.created_at || 0,
content: msg.content,
author: convertToUser(user),
content: sanitize(msg.content),
user: convertToUser(user),
topZaps: [...tz],
naddr: nip19.naddrEncode({ identifier, pubkey, kind }),
noteId: nip19.naddrEncode({ identifier, pubkey, kind }),
msg,
mentionedNotes,
mentionedUsers,

View File

@ -498,8 +498,10 @@ export type PrimalNote = {
replyTo?: string,
id: string,
pubkey: string,
noteId: string,
tags: string[][],
topZaps: TopZap[],
content: string,
};
@ -510,7 +512,7 @@ export type PrimalArticle = {
tags: string[],
published: number,
content: string,
author: PrimalUser,
user: PrimalUser,
topZaps: TopZap[],
repost?: PrimalRepost,
mentionedNotes?: Record<string, PrimalNote>,
@ -519,6 +521,7 @@ export type PrimalArticle = {
id: string,
pubkey: string,
naddr: string,
noteId: string,
msg: NostrNoteContent,
wordCount: number,
noteActions: NoteActions,