Consolodate custom zap modal

This commit is contained in:
Bojan Mojsilovic 2024-03-15 16:21:02 +01:00
parent cd0a7e1b75
commit 1fe6b2851b
4 changed files with 103 additions and 67 deletions

View File

@ -18,6 +18,7 @@ import ZapAnimation from '../ZapAnimation/ZapAnimation';
import Landing from '../../pages/Landing'; import Landing from '../../pages/Landing';
import ReactionsModal from '../ReactionsModal/ReactionsModal'; import ReactionsModal from '../ReactionsModal/ReactionsModal';
import { useAppContext } from '../../contexts/AppContext'; import { useAppContext } from '../../contexts/AppContext';
import CustomZap from '../CustomZap/CustomZap';
export const [isHome, setIsHome] = createSignal(false); export const [isHome, setIsHome] = createSignal(false);
@ -154,6 +155,16 @@ const Layout: Component = () => {
stats={app?.reactionStats} stats={app?.reactionStats}
onClose={() => app?.actions.closeReactionModal()} onClose={() => app?.actions.closeReactionModal()}
/> />
<CustomZap
open={app?.showCustomZapModal}
note={app?.customZap?.note}
profile={app?.customZap?.profile}
onConfirm={app?.customZap?.onConfirm}
onSuccess={app?.customZap?.onSuccess}
onFail={app?.customZap?.onFail}
onCancel={app?.customZap?.onCancel}
/>
</div> </div>
</Show> </Show>
</div> </div>

View File

@ -20,7 +20,7 @@ import NoteContextMenu from '../NoteContextMenu';
import { getScreenCordinates } from '../../../utils'; import { getScreenCordinates } from '../../../utils';
import ZapAnimation from '../../ZapAnimation/ZapAnimation'; import ZapAnimation from '../../ZapAnimation/ZapAnimation';
import ReactionsModal from '../../ReactionsModal/ReactionsModal'; import ReactionsModal from '../../ReactionsModal/ReactionsModal';
import { useAppContext } from '../../../contexts/AppContext'; import { CustomZapInfo, useAppContext } from '../../../contexts/AppContext';
const NoteFooter: Component<{ note: PrimalNote, wide?: boolean, id?: string }> = (props) => { const NoteFooter: Component<{ note: PrimalNote, wide?: boolean, id?: string }> = (props) => {
@ -158,9 +158,45 @@ const NoteFooter: Component<{ note: PrimalNote, wide?: boolean, id?: string }> =
}; };
let quickZapDelay = 0; let quickZapDelay = 0;
const [isCustomZap, setIsCustomZap] = createSignal(false);
const [isZapping, setIsZapping] = createSignal(false); const [isZapping, setIsZapping] = createSignal(false);
const customZapInfo: CustomZapInfo = {
note: props.note,
onConfirm: (zapOption: ZapOption) => {
app?.actions.closeCustomZapModal();
setZappedAmount(() => zapOption.amount || 0);
setZappedNow(true);
setZapped(true);
animateZap();
},
onSuccess: (zapOption: ZapOption) => {
app?.actions.closeCustomZapModal();
setIsZapping(false);
setZappedNow(false);
setShowZapAnim(false);
setHideZapIcon(false);
setZapped(true);
},
onFail: (zapOption: ZapOption) => {
setZappedAmount(() => -(zapOption.amount || 0));
setZappedNow(true);
app?.actions.closeCustomZapModal();
setIsZapping(false);
setShowZapAnim(false);
setHideZapIcon(false);
setZapped(props.note.post.noteActions.zapped);
},
onCancel: (zapOption: ZapOption) => {
setZappedAmount(() => -(zapOption.amount || 0));
setZappedNow(true);
app?.actions.closeCustomZapModal();
setIsZapping(false);
setShowZapAnim(false);
setHideZapIcon(false);
setZapped(props.note.post.noteActions.zapped);
},
};
const startZap = (e: MouseEvent | TouchEvent) => { const startZap = (e: MouseEvent | TouchEvent) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -187,7 +223,7 @@ const NoteFooter: Component<{ note: PrimalNote, wide?: boolean, id?: string }> =
} }
quickZapDelay = setTimeout(() => { quickZapDelay = setTimeout(() => {
setIsCustomZap(true); app?.actions.openCustomZapModal(customZapInfo);
setIsZapping(true); setIsZapping(true);
}, 500); }, 500);
}; };
@ -207,7 +243,7 @@ const NoteFooter: Component<{ note: PrimalNote, wide?: boolean, id?: string }> =
return; return;
} }
if (!isCustomZap()) { if (app?.customZap === undefined) {
doQuickZap(); doQuickZap();
} }
}; };
@ -410,7 +446,7 @@ const NoteFooter: Component<{ note: PrimalNote, wide?: boolean, id?: string }> =
<NoteContextMenu <NoteContextMenu
note={props.note} note={props.note}
openCustomZap={() => { openCustomZap={() => {
setIsCustomZap(true); app?.actions.openCustomZapModal(customZapInfo);
}} }}
openReactions={() => { openReactions={() => {
app?.actions.openReactionModal(props.note.post.id, { app?.actions.openReactionModal(props.note.post.id, {
@ -422,44 +458,6 @@ const NoteFooter: Component<{ note: PrimalNote, wide?: boolean, id?: string }> =
}} }}
/> />
</div> </div>
<CustomZap
open={isCustomZap()}
note={props.note}
onConfirm={(zapOption: ZapOption) => {
setIsCustomZap(false);
setZappedAmount(() => zapOption.amount || 0);
setZappedNow(true);
setZapped(true);
animateZap();
}}
onSuccess={(zapOption: ZapOption) => {
setIsCustomZap(false);
setIsZapping(false);
setZappedNow(false);
setShowZapAnim(false);
setHideZapIcon(false);
setZapped(true);
}}
onFail={(zapOption: ZapOption) => {
setZappedAmount(() => -(zapOption.amount || 0));
setZappedNow(true);
setIsCustomZap(false);
setIsZapping(false);
setShowZapAnim(false);
setHideZapIcon(false);
setZapped(props.note.post.noteActions.zapped);
}}
onCancel={(zapOption: ZapOption) => {
setZappedAmount(() => -(zapOption.amount || 0));
setZappedNow(true);
setIsCustomZap(false);
setIsZapping(false);
setShowZapAnim(false);
setHideZapIcon(false);
setZapped(props.note.post.noteActions.zapped);
}}
/>
</div> </div>
) )
} }

View File

@ -1,4 +1,4 @@
import { createStore } from "solid-js/store"; import { createStore, reconcile } from "solid-js/store";
import { import {
createContext, createContext,
createEffect, createEffect,
@ -7,6 +7,7 @@ import {
onMount, onMount,
useContext useContext
} from "solid-js"; } from "solid-js";
import { PrimalNote, PrimalUser, ZapOption } from "../types/primal";
export type ReactionStats = { export type ReactionStats = {
likes: number, likes: number,
@ -15,14 +16,27 @@ export type ReactionStats = {
quotes: number, quotes: number,
}; };
export type CustomZapInfo = {
profile?: PrimalUser,
note?: PrimalNote,
onConfirm: (zapOption: ZapOption) => void,
onSuccess: (zapOption: ZapOption) => void,
onFail: (zapOption: ZapOption) => void,
onCancel: (zapOption: ZapOption) => void,
};
export type AppContextStore = { export type AppContextStore = {
isInactive: boolean, isInactive: boolean,
appState: 'sleep' | 'waking' | 'woke', appState: 'sleep' | 'waking' | 'woke',
showReactionsModal: string | undefined, showReactionsModal: string | undefined,
reactionStats: ReactionStats, reactionStats: ReactionStats,
showCustomZapModal: boolean,
customZap: CustomZapInfo | undefined,
actions: { actions: {
openReactionModal: (noteId: string, stats: ReactionStats) => void, openReactionModal: (noteId: string, stats: ReactionStats) => void,
closeReactionModal: () => void, closeReactionModal: () => void,
openCustomZapModal: (custonZapInfo: CustomZapInfo) => void,
closeCustomZapModal: () => void,
}, },
} }
@ -36,6 +50,8 @@ const initialData: Omit<AppContextStore, 'actions'> = {
reposts: 0, reposts: 0,
quotes: 0, quotes: 0,
}, },
showCustomZapModal: false,
customZap: undefined,
}; };
export const AppContext = createContext<AppContextStore>(); export const AppContext = createContext<AppContextStore>();
@ -71,6 +87,15 @@ export const AppProvider = (props: { children: JSXElement }) => {
updateStore('showReactionsModal', () => undefined); updateStore('showReactionsModal', () => undefined);
}; };
const openCustomZapModal = (customZapInfo: CustomZapInfo) => {
updateStore('customZap', reconcile({ ...customZapInfo }));
updateStore('showCustomZapModal', () => true);
};
const closeCustomZapModal = () => {
updateStore('showCustomZapModal', () => false);
};
// EFFECTS -------------------------------------- // EFFECTS --------------------------------------
onMount(() => { onMount(() => {
@ -111,6 +136,8 @@ export const AppProvider = (props: { children: JSXElement }) => {
actions: { actions: {
openReactionModal, openReactionModal,
closeReactionModal, closeReactionModal,
openCustomZapModal,
closeCustomZapModal,
} }
}); });

View File

@ -41,8 +41,8 @@ import VerificationCheck from '../components/VerificationCheck/VerificationCheck
import PhotoSwipeLightbox from 'photoswipe/lightbox'; import PhotoSwipeLightbox from 'photoswipe/lightbox';
import NoteImage from '../components/NoteImage/NoteImage'; import NoteImage from '../components/NoteImage/NoteImage';
import CustomZap from '../components/CustomZap/CustomZap';
import ProfileQrCodeModal from '../components/ProfileQrCodeModal/ProfileQrCodeModal'; import ProfileQrCodeModal from '../components/ProfileQrCodeModal/ProfileQrCodeModal';
import { CustomZapInfo, useAppContext } from '../contexts/AppContext';
const Profile: Component = () => { const Profile: Component = () => {
@ -51,6 +51,8 @@ const Profile: Component = () => {
const profile = useProfileContext(); const profile = useProfileContext();
const account = useAccountContext(); const account = useAccountContext();
const media = useMediaContext(); const media = useMediaContext();
const app = useAppContext();
const intl = useIntl(); const intl = useIntl();
const navigate = useNavigate(); const navigate = useNavigate();
@ -61,7 +63,6 @@ const Profile: Component = () => {
const [showContext, setContext] = createSignal(false); const [showContext, setContext] = createSignal(false);
const [confirmReportUser, setConfirmReportUser] = createSignal(false); const [confirmReportUser, setConfirmReportUser] = createSignal(false);
const [confirmMuteUser, setConfirmMuteUser] = createSignal(false); const [confirmMuteUser, setConfirmMuteUser] = createSignal(false);
const [isCustomZap, setIsCustomZap] = createSignal(false);
const [openQr, setOpenQr] = createSignal(false); const [openQr, setOpenQr] = createSignal(false);
const lightbox = new PhotoSwipeLightbox({ const lightbox = new PhotoSwipeLightbox({
@ -491,6 +492,25 @@ const Profile: Component = () => {
return !profile?.isFetching && profile?.isProfileFetched && profile?.profileKey === getHex(); return !profile?.isFetching && profile?.isProfileFetched && profile?.profileKey === getHex();
}; };
const customZapInfo: () => CustomZapInfo = () => ({
profile: profile?.userProfile,
onConfirm: (zapOption: ZapOption) => {
app?.actions.closeCustomZapModal();
},
onSuccess: (zapOption: ZapOption) => {
app?.actions.closeCustomZapModal();
toaster?.sendSuccess(intl.formatMessage(toastZapProfile, {
name: authorName(profile?.userProfile)
}))
},
onFail: (zapOption: ZapOption) => {
app?.actions.closeCustomZapModal();
},
onCancel: (zapOption: ZapOption) => {
app?.actions.closeCustomZapModal();
},
});
return ( return (
<> <>
<PageTitle title={ <PageTitle title={
@ -567,31 +587,11 @@ const Profile: Component = () => {
<Show when={!isCurrentUser()}> <Show when={!isCurrentUser()}>
<ButtonSecondary <ButtonSecondary
onClick={() => setIsCustomZap(true)} onClick={() => app?.actions.openCustomZapModal(customZapInfo())}
shrink={true} shrink={true}
> >
<div class={styles.zapIcon}></div> <div class={styles.zapIcon}></div>
</ButtonSecondary> </ButtonSecondary>
<CustomZap
open={isCustomZap()}
profile={profile?.userProfile}
onConfirm={(zapOption: ZapOption) => {
setIsCustomZap(false);
}}
onSuccess={(zapOption: ZapOption) => {
setIsCustomZap(false);
toaster?.sendSuccess(intl.formatMessage(toastZapProfile, {
name: authorName(profile?.userProfile)
}))
}}
onFail={(zapOption: ZapOption) => {
setIsCustomZap(false);
}}
onCancel={(zapOption: ZapOption) => {
setIsCustomZap(false);
}}
/>
</Show> </Show>
<Show when={account?.publicKey}> <Show when={account?.publicKey}>