mirror of
https://github.com/PrimalHQ/primal-web-app.git
synced 2024-09-30 00:41:09 +00:00
Fix footer and context menu in article preview
This commit is contained in:
parent
e28299e9f0
commit
b606e90532
@ -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;
|
||||
}
|
||||
|
@ -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}>
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 = () => {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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: [],
|
||||
})
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
5
src/types/primal.d.ts
vendored
5
src/types/primal.d.ts
vendored
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user