mirror of
https://github.com/PrimalHQ/primal-web-app.git
synced 2024-09-30 00:41:09 +00:00
Top zaps loading skeleton
This commit is contained in:
parent
dc78cdd6b8
commit
c5092a0c3a
@ -616,3 +616,83 @@
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
to {
|
||||
background-position-x: 0%
|
||||
}
|
||||
}
|
||||
|
||||
.topZapsLoading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: flex-start;
|
||||
|
||||
&.onlyFew {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.firstZap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 120px;
|
||||
height: 26px;
|
||||
margin: 0;
|
||||
border-radius: 12px;
|
||||
// background: var(--devider);
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: linear-gradient(-45deg, var(--devider) 35%, #333333 50%, var(--devider) 65%);
|
||||
background-size: 300%;
|
||||
background-position-x: 100%;
|
||||
animation: shimmer 0.6s infinite linear;
|
||||
}
|
||||
|
||||
.topZaps {
|
||||
display: flex;
|
||||
align-self: center;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
|
||||
.zapList {
|
||||
display: flex;
|
||||
align-self: center;
|
||||
gap: 6px;
|
||||
max-width: calc(100% - 30px);
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
|
||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||
&::-webkit-scrollbar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide scrollbar for IE, Edge and Firefox */
|
||||
-ms-overflow-style: none !important; /* IE and Edge */
|
||||
scrollbar-width: none !important; /* Firefox */
|
||||
|
||||
.topZap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin: 0;
|
||||
border-radius: 12px;
|
||||
// background: var(--devider);
|
||||
width: 70px;
|
||||
height: 26px;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: linear-gradient(-45deg, var(--devider) 35%, #333333 50%, var(--devider) 65%);
|
||||
background-size: 300%;
|
||||
background-position-x: 100%;
|
||||
animation: shimmer 0.6s infinite linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -299,49 +299,66 @@ const Note: Component<{
|
||||
<ParsedNote note={props.note} width={Math.min(574, window.innerWidth)} />
|
||||
</div>
|
||||
|
||||
<div class={`${styles.zapHighlights} ${reactionsState.topZaps.length < 4 ? styles.onlyFew : ''}`}>
|
||||
<Show when={firstZap()}>
|
||||
<button
|
||||
class={styles.firstZap}
|
||||
onClick={() => openReactionModal('zaps')}
|
||||
>
|
||||
<Avatar user={zapSender(firstZap())} size="micro" />
|
||||
<div class={styles.amount}>
|
||||
{firstZap().amount.toLocaleString()}
|
||||
<Show
|
||||
when={!threadContext?.isFetchingTopZaps}
|
||||
fallback={
|
||||
<div class={styles.topZapsLoading}>
|
||||
<div class={styles.firstZap}></div>
|
||||
<div class={styles.topZaps}>
|
||||
<div class={styles.zapList}>
|
||||
<div class={styles.topZap}></div>
|
||||
<div class={styles.topZap}></div>
|
||||
<div class={styles.topZap}></div>
|
||||
<div class={styles.topZap}></div>
|
||||
<div class={styles.topZap}></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class={styles.description}>
|
||||
{firstZap().message}
|
||||
</div>
|
||||
</button>
|
||||
</Show>
|
||||
<div class={styles.topZaps}>
|
||||
<div class={styles.zapList}>
|
||||
<For each={restZaps()}>
|
||||
{zap => (
|
||||
<button
|
||||
class={styles.topZap}
|
||||
onClick={() => openReactionModal('zaps')}
|
||||
>
|
||||
<Avatar user={zapSender(zap)} size="micro" />
|
||||
<div class={styles.amount}>
|
||||
{zap.amount.toLocaleString()}
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
||||
<Show when={reactionsState.moreZapsAvailable}>
|
||||
}
|
||||
>
|
||||
<div class={`${styles.zapHighlights} ${reactionsState.topZaps.length < 4 ? styles.onlyFew : ''}`}>
|
||||
<Show when={firstZap()}>
|
||||
<button
|
||||
class={styles.moreZaps}
|
||||
class={styles.firstZap}
|
||||
onClick={() => openReactionModal('zaps')}
|
||||
>
|
||||
<div class={styles.contextIcon}></div>
|
||||
<Avatar user={zapSender(firstZap())} size="micro" />
|
||||
<div class={styles.amount}>
|
||||
{firstZap().amount.toLocaleString()}
|
||||
</div>
|
||||
<div class={styles.description}>
|
||||
{firstZap().message}
|
||||
</div>
|
||||
</button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
<div class={styles.topZaps}>
|
||||
<div class={styles.zapList}>
|
||||
<For each={restZaps()}>
|
||||
{zap => (
|
||||
<button
|
||||
class={styles.topZap}
|
||||
onClick={() => openReactionModal('zaps')}
|
||||
>
|
||||
<Avatar user={zapSender(zap)} size="micro" />
|
||||
<div class={styles.amount}>
|
||||
{zap.amount.toLocaleString()}
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
|
||||
<Show when={reactionsState.moreZapsAvailable}>
|
||||
<button
|
||||
class={styles.moreZaps}
|
||||
onClick={() => openReactionModal('zaps')}
|
||||
>
|
||||
<div class={styles.contextIcon}></div>
|
||||
</button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<div
|
||||
class={styles.time}
|
||||
|
@ -56,6 +56,7 @@ export type ThreadContextStore = {
|
||||
notes: PrimalNote[],
|
||||
users: PrimalUser[],
|
||||
isFetching: boolean,
|
||||
isFetchingTopZaps: boolean,
|
||||
page: FeedPage,
|
||||
reposts: Record<string, string> | undefined,
|
||||
lastNote: PrimalNote | undefined,
|
||||
@ -83,6 +84,7 @@ export const initialData = {
|
||||
users: [],
|
||||
replyNotes: [],
|
||||
isFetching: false,
|
||||
isFetchingTopZaps: false,
|
||||
page: {
|
||||
messages: [],
|
||||
users: {},
|
||||
@ -300,6 +302,7 @@ export const ThreadProvider = (props: { children: ContextChildren }) => {
|
||||
};
|
||||
|
||||
const fetchTopZaps = (noteId: string) => {
|
||||
updateStore('isFetchingTopZaps', () => true);
|
||||
getEventZaps(noteId, account?.publicKey, `thread_zapps_${APP_ID}`, 10, 0);
|
||||
};
|
||||
|
||||
@ -363,6 +366,7 @@ export const ThreadProvider = (props: { children: ContextChildren }) => {
|
||||
if (subId === `thread_zapps_${APP_ID}`) {
|
||||
if (type === 'EOSE') {
|
||||
savePage(store.page);
|
||||
updateStore('isFetchingTopZaps', () => false);
|
||||
}
|
||||
|
||||
if (type === 'EVENT') {
|
||||
|
@ -18,13 +18,19 @@ export const zapNote = async (note: PrimalNote, sender: string | undefined, amou
|
||||
|
||||
const sats = Math.round(amount * 1000);
|
||||
|
||||
const zapReq = nip57.makeZapRequest({
|
||||
let payload = {
|
||||
profile: note.post.pubkey,
|
||||
event: note.msg.id,
|
||||
amount: sats,
|
||||
comment,
|
||||
relays: relays.map(r => r.url)
|
||||
});
|
||||
};
|
||||
|
||||
if (comment.length > 0) {
|
||||
// @ts-ignore
|
||||
payload.comment = comment;
|
||||
}
|
||||
|
||||
const zapReq = nip57.makeZapRequest(payload);
|
||||
|
||||
try {
|
||||
const signedEvent = await signEvent(zapReq);
|
||||
@ -57,12 +63,17 @@ export const zapProfile = async (profile: PrimalUser, sender: string | undefined
|
||||
|
||||
const sats = Math.round(amount * 1000);
|
||||
|
||||
const zapReq = nip57.makeZapRequest({
|
||||
let payload = {
|
||||
profile: profile.pubkey,
|
||||
amount: sats,
|
||||
comment,
|
||||
relays: relays.map(r => r.url)
|
||||
});
|
||||
};
|
||||
|
||||
if (comment.length > 0) {
|
||||
// @ts-ignore
|
||||
payload.comment = comment;
|
||||
}
|
||||
const zapReq = nip57.makeZapRequest(payload);
|
||||
|
||||
try {
|
||||
const signedEvent = await signEvent(zapReq);
|
||||
|
Loading…
Reference in New Issue
Block a user