Top zaps loading skeleton

This commit is contained in:
Bojan Mojsilovic 2024-04-26 15:52:07 +02:00
parent dc78cdd6b8
commit c5092a0c3a
4 changed files with 153 additions and 41 deletions

View File

@ -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;
}
}
}
}

View File

@ -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}

View File

@ -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') {

View File

@ -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);