diff --git a/package-lock.json b/package-lock.json index 766d83b..d7c502f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.105.5", "license": "MIT", "dependencies": { - "@cashu/cashu-ts": "^0.9.0", + "@cashu/cashu-ts": "0.9.0", "@cookbook/solid-intl": "0.1.2", "@jukben/emoji-search": "3.0.0", "@kobalte/core": "0.11.0", @@ -25,7 +25,8 @@ "photoswipe": "5.4.3", "qr-code-styling": "^1.6.0-rc.1", "sass": "1.67.0", - "solid-js": "1.7.11" + "solid-js": "1.7.11", + "solid-transition-group": "^0.2.3" }, "devDependencies": { "@formatjs/cli": "^6.0.4", @@ -961,6 +962,14 @@ "solid-js": "^1.6.12" } }, + "node_modules/@solid-primitives/transition-group": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@solid-primitives/transition-group/-/transition-group-1.0.5.tgz", + "integrity": "sha512-G3FuqvL13kQ55WzWPX2ewiXdZ/1iboiX53195sq7bbkDbXqP6TYKiadwEdsaDogW5rPnPYAym3+xnsNplQJRKQ==", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, "node_modules/@solid-primitives/trigger": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@solid-primitives/trigger/-/trigger-1.0.8.tgz", @@ -2150,6 +2159,22 @@ "solid-js": "^1.3" } }, + "node_modules/solid-transition-group": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/solid-transition-group/-/solid-transition-group-0.2.3.tgz", + "integrity": "sha512-iB72c9N5Kz9ykRqIXl0lQohOau4t0dhel9kjwFvx81UZJbVwaChMuBuyhiZmK24b8aKEK0w3uFM96ZxzcyZGdg==", + "dependencies": { + "@solid-primitives/refs": "^1.0.5", + "@solid-primitives/transition-group": "^1.0.2" + }, + "engines": { + "node": ">=18.0.0", + "pnpm": ">=8.6.0" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "license": "BSD-3-Clause", diff --git a/package.json b/package.json index 41399d6..adffb91 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "photoswipe": "5.4.3", "qr-code-styling": "^1.6.0-rc.1", "sass": "1.67.0", - "solid-js": "1.7.11" + "solid-js": "1.7.11", + "solid-transition-group": "0.2.3" } } diff --git a/src/components/Note/Note.module.scss b/src/components/Note/Note.module.scss index 8128388..8647e1f 100644 --- a/src/components/Note/Note.module.scss +++ b/src/components/Note/Note.module.scss @@ -351,7 +351,7 @@ height: 0; } - .firstZap { + .topZap { display: flex; align-items: center; gap: 8px; @@ -387,13 +387,52 @@ &:hover { background: var(--subtile-devider); } + + transition: all 0.6s; + } + + .moreZaps { + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background: var(--devider); + width: 26px; + height: 26px; + padding: 0; + margin: 0; + border: none; + outline: none; + + .contextIcon { + width: 16px; + height: 14px; + background-color: var(--text-secondary-2); + -webkit-mask: url(../../assets/icons/context.svg) no-repeat 0 / 100%; + mask: url(../../assets/icons/context.svg) no-repeat 0 / 100%; + } + + &:hover { + .contextIcon { + background-color: var(--text-primary); + } + } } } - } } +.topZapEnterTransition { + opacity: 0; + transform: translateX(300px); +} + +.topZapExitTransition { + opacity: 0; + transform: translate7(30px); +} + .noteNotificationLink { text-decoration: none; color: unset; diff --git a/src/components/Note/Note.tsx b/src/components/Note/Note.tsx index cd1c751..7d0a748 100644 --- a/src/components/Note/Note.tsx +++ b/src/components/Note/Note.tsx @@ -97,6 +97,8 @@ const Note: Component<{ let noteContextMenu: HTMLDivElement | undefined; + let latestTopZap: string = ''; + const onConfirmZap = (zapOption: ZapOption) => { app?.actions.closeCustomZapModal(); batch(() => { @@ -106,6 +108,40 @@ const Note: Component<{ updateReactionsState('zapped', () => true); updateReactionsState('showZapAnim', () => true) }); + + addTopZap(zapOption) + }; + + const addTopZap = (zapOption: ZapOption) => { + console.log('AADD') + + const pubkey = account?.publicKey; + + if (!pubkey) return; + + const oldZaps = [ ...reactionsState.topZaps ]; + + latestTopZap = uuidv4() as string; + + const newZap = { + amount: zapOption.amount || 0, + message: zapOption.message || '', + pubkey, + eventId: props.note.post.id, + id: latestTopZap, + }; + + if (!threadContext?.users.find((u) => u.pubkey === pubkey)) { + threadContext?.actions.fetchUsers([pubkey]) + } + + const zaps = [ ...oldZaps, { ...newZap }].sort((a, b) => b.amount - a.amount); + updateReactionsState('topZaps', () => [...zaps]); + }; + + const removeTopZap = (zapOption: ZapOption) => { + const zaps = reactionsState.topZaps.filter(z => z.id !== latestTopZap); + updateReactionsState('topZaps', () => [...zaps]); }; const onSuccessZap = (zapOption: ZapOption) => { @@ -116,21 +152,21 @@ const Note: Component<{ if (!pubkey) return; - const oldZaps = [ ...reactionsState.topZaps ]; + // const oldZaps = [ ...reactionsState.topZaps ]; - const newZap = { - amount: zapOption.amount || 0, - message: zapOption.message || '', - pubkey, - eventId: props.note.post.id, - id: uuidv4() as string, - }; + // const newZap = { + // amount: zapOption.amount || 0, + // message: zapOption.message || '', + // pubkey, + // eventId: props.note.post.id, + // id: uuidv4() as string, + // }; - if (!threadContext?.users.find((u) => u.pubkey === pubkey)) { - threadContext?.actions.fetchUsers([pubkey]) - } + // if (!threadContext?.users.find((u) => u.pubkey === pubkey)) { + // threadContext?.actions.fetchUsers([pubkey]) + // } - const zaps = [ ...oldZaps, { ...newZap }].sort((a, b) => b.amount - a.amount); + // const zaps = [ ...oldZaps, { ...newZap }].sort((a, b) => b.amount - a.amount); batch(() => { updateReactionsState('zapCount', (z) => z + 1); @@ -140,7 +176,7 @@ const Note: Component<{ updateReactionsState('showZapAnim', () => false); updateReactionsState('hideZapIcon', () => false); updateReactionsState('zapped', () => true); - updateReactionsState('topZaps', () => [...zaps]); + // updateReactionsState('topZaps', () => [...zaps]); }); }; @@ -156,6 +192,8 @@ const Note: Component<{ updateReactionsState('hideZapIcon', () => false); updateReactionsState('zapped', () => props.note.post.noteActions.zapped); }); + + removeTopZap(zapOption); }; const onCancelZap = (zapOption: ZapOption) => { @@ -170,6 +208,8 @@ const Note: Component<{ updateReactionsState('hideZapIcon', () => false); updateReactionsState('zapped', () => props.note.post.noteActions.zapped); }); + + removeTopZap(zapOption); }; const customZapInfo: () => CustomZapInfo = () => ({ @@ -293,6 +333,7 @@ const Note: Component<{ customZapInfo={customZapInfo()} wide={true} large={true} + onZapAnim={addTopZap} /> diff --git a/src/components/Note/NoteFooter/NoteFooter.tsx b/src/components/Note/NoteFooter/NoteFooter.tsx index 606b1df..4662457 100644 --- a/src/components/Note/NoteFooter/NoteFooter.tsx +++ b/src/components/Note/NoteFooter/NoteFooter.tsx @@ -1,5 +1,5 @@ import { batch, Component, createEffect, Show } from 'solid-js'; -import { MenuItem, PrimalNote } from '../../../types/primal'; +import { MenuItem, PrimalNote, ZapOption } from '../../../types/primal'; import { sendRepost, triggerImportEvents } from '../../../lib/notes'; import styles from './NoteFooter.module.scss'; @@ -22,7 +22,6 @@ import NoteFooterActionButton from './NoteFooterActionButton'; import { NoteReactionsState } from '../Note'; import { SetStoreFunction } from 'solid-js/store'; import BookmarkNote from '../../BookmarkNote/BookmarkNote'; -import { APP_ID } from '../../../App'; export const lottieDuration = () => zapMD.op * 1_000 / zapMD.fr; @@ -34,6 +33,7 @@ const NoteFooter: Component<{ updateState: SetStoreFunction, customZapInfo: CustomZapInfo, large?: boolean, + onZapAnim?: (zapOption: ZapOption) => void, }> = (props) => { const account = useAccountContext(); @@ -268,10 +268,12 @@ const NoteFooter: Component<{ batch(() => { props.updateState('isZapping', () => true); - props.updateState('showZapAnim', () => true); props.updateState('satsZapped', (z) => z + amount); + props.updateState('showZapAnim', () => true); }); + console.log('QUICK ZAP: ', props.onZapAnim) + props.onZapAnim && props.onZapAnim({ amount, message, emoji }) setTimeout(async () => { const success = await zapNote(props.note, account.publicKey, amount, message, account.relays); diff --git a/src/components/Note/NoteTopZaps.tsx b/src/components/Note/NoteTopZaps.tsx index 6dbf268..f28d464 100644 --- a/src/components/Note/NoteTopZaps.tsx +++ b/src/components/Note/NoteTopZaps.tsx @@ -2,6 +2,7 @@ import { Component, createMemo, createSignal, For, Show } from "solid-js"; import { hookForDev } from "../../lib/devTools"; import { TopZap, useThreadContext } from "../../contexts/ThreadContext"; import Avatar from "../Avatar/Avatar"; +import { TransitionGroup } from 'solid-transition-group'; import styles from "./Note.module.scss"; const NoteTopZaps: Component<{ @@ -62,39 +63,45 @@ const NoteTopZaps: Component<{ } >
- - {(zap, index) => ( - <> - + + 3}> +
- + + )} +
- 3}> -
-
- - )} - - - - - + + + +
);