mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-25 18:24:24 +01:00
feat: implement custom modals for no-webln error on mobile and web
Fixes #91
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import React, { Component, ErrorInfo, ReactNode } from "react";
|
||||
import ErrorMessage from "../ErrorMessage/ErrorMessage";
|
||||
|
||||
interface Props {
|
||||
place?: string
|
||||
@@ -25,7 +26,14 @@ class ErrorBoundary extends Component<Props, State> {
|
||||
|
||||
public render() {
|
||||
if (this.state.hasError) {
|
||||
return <h1>Sorry.. there was an error</h1>;
|
||||
return <ErrorMessage message={
|
||||
<p className="text-body3">
|
||||
Sorry, something went wrong...😵
|
||||
<br />
|
||||
Try refreshing the page.
|
||||
</p>
|
||||
|
||||
} type="unknown"></ErrorMessage>;
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
interface Props {
|
||||
message?: string,
|
||||
message?: string | JSX.Element,
|
||||
type?: 'unknown' | 'fetching'
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ export default function ErrorMessage({
|
||||
|
||||
return (
|
||||
<div className="bg-red-50 border border-red-500 rounded-12 text-gray-900 px-20 py-36 flex flex-col items-center ">
|
||||
<p >
|
||||
<div >
|
||||
{messageToShow}
|
||||
</p>
|
||||
</div>
|
||||
<a href='/' className='text-primary-500 mt-36 underline' >Back to home page</a>
|
||||
</div>
|
||||
)
|
||||
|
||||
69
src/Components/Modals/NoWeblnModal/NoWeblnModal.tsx
Normal file
69
src/Components/Modals/NoWeblnModal/NoWeblnModal.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { motion } from 'framer-motion'
|
||||
import { useAppSelector } from 'src/utils/hooks';
|
||||
import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer'
|
||||
import Button from 'src/Components/Button/Button'
|
||||
import { IoClose } from 'react-icons/io5';
|
||||
import NutImg from './nut.png'
|
||||
import AlbyImg from './alby.png'
|
||||
|
||||
export default function NoWeblnModal({ onClose, direction, ...props }: ModalCard) {
|
||||
|
||||
const isMobile = useAppSelector(s => s.ui.isMobileScreen);
|
||||
|
||||
|
||||
let content: JSX.Element;
|
||||
|
||||
if (isMobile)
|
||||
content = <>
|
||||
<div className="flex justify-center my-24">
|
||||
<img
|
||||
src={NutImg}
|
||||
className='w-full max-w-[164px] aspect-square object-cover'
|
||||
alt="Nut images" />
|
||||
</div>
|
||||
<h3 className="text-h4 font-bolder">
|
||||
Oops! Looks like you’re browsing on mobile.
|
||||
</h3>
|
||||
<p className="text-body4 text-gray-600 mt-8">
|
||||
In order to use BOLT🔩FUN’s voting button, you need to use a lightning browser wallet like Alby. You can download the extension on your desktop and try again.
|
||||
</p>
|
||||
</>
|
||||
else
|
||||
content = <>
|
||||
<div className="flex justify-center my-24">
|
||||
<img
|
||||
src={AlbyImg}
|
||||
className='w-full max-w-[164px] aspect-square object-cover'
|
||||
alt="Nut images" />
|
||||
</div>
|
||||
<h3 className="text-h4 font-bolder">
|
||||
Oops! Looks like you don’t have Alby installed
|
||||
</h3>
|
||||
<p className="text-body4 text-gray-600 mt-8">
|
||||
In order to use BOLT🔩FUN’s voting button, you’ll need to use a lightning browser wallet like Alby. Download it to continue.
|
||||
</p>
|
||||
<Button
|
||||
color='black'
|
||||
fullWidth
|
||||
newTab
|
||||
className='mt-32'
|
||||
href='https://getalby.com'
|
||||
>Download Alby</Button>
|
||||
</>
|
||||
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
custom={direction}
|
||||
variants={modalCardVariants}
|
||||
initial='initial'
|
||||
animate="animate"
|
||||
exit='exit'
|
||||
className="modal-card max-w-[343px] p-24 rounded-xl relative"
|
||||
>
|
||||
<IoClose className='absolute text-body2 top-24 right-24 hover:cursor-pointer' onClick={onClose} />
|
||||
<h2 className='text-h5 font-bold'>No WebLB Detected</h2>
|
||||
{content}
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
BIN
src/Components/Modals/NoWeblnModal/alby.png
Normal file
BIN
src/Components/Modals/NoWeblnModal/alby.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
4
src/Components/Modals/NoWeblnModal/index.ts
Normal file
4
src/Components/Modals/NoWeblnModal/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
import { lazyModal } from 'src/utils/helperFunctions';
|
||||
|
||||
export const { LazyComponent: NoWeblnModal } = lazyModal(() => import('./NoWeblnModal'))
|
||||
BIN
src/Components/Modals/NoWeblnModal/nut.png
Normal file
BIN
src/Components/Modals/NoWeblnModal/nut.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
@@ -17,56 +17,65 @@ export const useDonate = () => {
|
||||
onError: (error: any) => void,
|
||||
onSetteled: () => void
|
||||
}>) => {
|
||||
setPaymentStatus(PaymentStatus.FETCHING_PAYMENT_DETAILS)
|
||||
donateMutation({
|
||||
variables: {
|
||||
amountInSat: amount
|
||||
},
|
||||
onCompleted: async (donationData) => {
|
||||
try {
|
||||
setPaymentStatus(PaymentStatus.AWAITING_PAYMENT);
|
||||
const webln = await Wallet_Service.getWebln()
|
||||
const paymentResponse = await webln.sendPayment(donationData.donate.payment_request);
|
||||
setPaymentStatus(PaymentStatus.PAID);
|
||||
|
||||
//Confirm Voting payment
|
||||
confirmDonation({
|
||||
variables: {
|
||||
paymentRequest: donationData.donate.payment_request,
|
||||
preimage: paymentResponse.preimage
|
||||
},
|
||||
onCompleted: () => {
|
||||
setPaymentStatus(PaymentStatus.PAYMENT_CONFIRMED);
|
||||
config?.onSuccess?.();
|
||||
config?.onSetteled?.()
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error)
|
||||
setPaymentStatus(PaymentStatus.NETWORK_ERROR);
|
||||
config?.onError?.(error);
|
||||
config?.onSetteled?.();
|
||||
alert("A network error happened while confirming the payment...")
|
||||
},
|
||||
refetchQueries: [
|
||||
'DonationsStats'
|
||||
]
|
||||
})
|
||||
} catch (error) {
|
||||
setPaymentStatus(PaymentStatus.CANCELED);
|
||||
config?.onError?.(error);
|
||||
config?.onSetteled?.();
|
||||
alert("Payment rejected by user")
|
||||
Wallet_Service.getWebln()
|
||||
.then(webln => {
|
||||
if (!webln) {
|
||||
config?.onError?.(new Error('No WebLN Detetcted'))
|
||||
config?.onSetteled?.()
|
||||
return
|
||||
}
|
||||
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error);
|
||||
setPaymentStatus(PaymentStatus.NETWORK_ERROR);
|
||||
config?.onError?.(error);
|
||||
config?.onSetteled?.();
|
||||
alert("A network error happened...")
|
||||
}
|
||||
})
|
||||
setPaymentStatus(PaymentStatus.FETCHING_PAYMENT_DETAILS)
|
||||
donateMutation({
|
||||
variables: {
|
||||
amountInSat: amount
|
||||
},
|
||||
onCompleted: async (donationData) => {
|
||||
try {
|
||||
setPaymentStatus(PaymentStatus.AWAITING_PAYMENT);
|
||||
const paymentResponse = await webln.sendPayment(donationData.donate.payment_request);
|
||||
setPaymentStatus(PaymentStatus.PAID);
|
||||
|
||||
//Confirm Voting payment
|
||||
confirmDonation({
|
||||
variables: {
|
||||
paymentRequest: donationData.donate.payment_request,
|
||||
preimage: paymentResponse.preimage
|
||||
},
|
||||
onCompleted: () => {
|
||||
setPaymentStatus(PaymentStatus.PAYMENT_CONFIRMED);
|
||||
config?.onSuccess?.();
|
||||
config?.onSetteled?.()
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error)
|
||||
setPaymentStatus(PaymentStatus.NETWORK_ERROR);
|
||||
config?.onError?.(error);
|
||||
config?.onSetteled?.();
|
||||
alert("A network error happened while confirming the payment...")
|
||||
},
|
||||
refetchQueries: [
|
||||
'DonationsStats'
|
||||
]
|
||||
})
|
||||
} catch (error) {
|
||||
setPaymentStatus(PaymentStatus.CANCELED);
|
||||
config?.onError?.(error);
|
||||
config?.onSetteled?.();
|
||||
alert("Payment rejected by user")
|
||||
}
|
||||
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error);
|
||||
setPaymentStatus(PaymentStatus.NETWORK_ERROR);
|
||||
config?.onError?.(error);
|
||||
config?.onSetteled?.();
|
||||
alert("A network error happened...")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
}, [confirmDonation, donateMutation]);
|
||||
|
||||
const isLoading = paymentStatus !== PaymentStatus.DEFAULT && paymentStatus !== PaymentStatus.PAYMENT_CONFIRMED && paymentStatus !== PaymentStatus.NOT_PAID && paymentStatus !== PaymentStatus.NETWORK_ERROR && paymentStatus !== PaymentStatus.CANCELED
|
||||
|
||||
@@ -12,6 +12,7 @@ import { LinkingAccountModal } from "src/features/Profiles/pages/EditProfilePage
|
||||
|
||||
import { ComponentProps } from "react";
|
||||
import { generateId } from "src/utils/helperFunctions";
|
||||
import { NoWeblnModal } from "src/Components/Modals/NoWeblnModal";
|
||||
|
||||
export enum Direction {
|
||||
START,
|
||||
@@ -34,6 +35,7 @@ export const ALL_MODALS = {
|
||||
Claim_SubmittedCard,
|
||||
Claim_FundWithdrawCard,
|
||||
ConfirmModal,
|
||||
NoWeblnModal,
|
||||
LinkingAccountModal,
|
||||
|
||||
// Text Editor Modals
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { requestProvider, MissingProviderError, WebLNProvider } from 'webln';
|
||||
import { store } from '../redux/store'
|
||||
import { connectWallet as connectWalletStore } from '../redux/features/wallet.slice'
|
||||
import { openModal } from 'src/redux/features/modals.slice';
|
||||
|
||||
|
||||
class _Wallet_Service {
|
||||
@@ -10,20 +11,19 @@ class _Wallet_Service {
|
||||
|
||||
async getWebln() {
|
||||
if (!this.isConnected) await this.connectWallet();
|
||||
return this.webln as WebLNProvider;
|
||||
return this.webln;
|
||||
}
|
||||
|
||||
init() {
|
||||
const connectedPreviously = localStorage.getItem('wallet-connected')
|
||||
if (connectedPreviously)
|
||||
this.connectWallet();
|
||||
// const connectedPreviously = localStorage.getItem('wallet-connected')
|
||||
// if (connectedPreviously)
|
||||
// this.connectWallet();
|
||||
}
|
||||
|
||||
async connectWallet() {
|
||||
try {
|
||||
const webln = await requestProvider();
|
||||
store.dispatch(connectWalletStore())
|
||||
localStorage.setItem('wallet-connected', 'yes')
|
||||
this.webln = webln;
|
||||
this.isConnected = false;
|
||||
}
|
||||
@@ -35,11 +35,13 @@ class _Wallet_Service {
|
||||
message = "Check out https://getalby.com to get a web enabled lightning wallet";
|
||||
}
|
||||
|
||||
console.log(message);
|
||||
|
||||
|
||||
localStorage.removeItem('wallet-connected')
|
||||
// Show the error (though you should probably use something better than alert!)
|
||||
alert(message);
|
||||
store.dispatch(openModal({
|
||||
Modal: "NoWeblnModal"
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,81 +41,93 @@ export const useVote = (params: Params) => {
|
||||
|
||||
if (!itemId || !itemType) return;
|
||||
|
||||
setPaymentStatus(PaymentStatus.FETCHING_PAYMENT_DETAILS)
|
||||
voteMutaion({
|
||||
variables: {
|
||||
itemId,
|
||||
itemType,
|
||||
amountInSat: amount
|
||||
},
|
||||
onCompleted: async (votingData) => {
|
||||
try {
|
||||
setPaymentStatus(PaymentStatus.AWAITING_PAYMENT);
|
||||
const webln = await Wallet_Service.getWebln()
|
||||
const paymentResponse = await webln.sendPayment(votingData.vote.payment_request);
|
||||
setPaymentStatus(PaymentStatus.PAID);
|
||||
|
||||
//Confirm Voting payment
|
||||
confirmVote({
|
||||
variables: {
|
||||
paymentRequest: votingData.vote.payment_request,
|
||||
preimage: paymentResponse.preimage
|
||||
},
|
||||
onCompleted: () => {
|
||||
setPaymentStatus(PaymentStatus.PAYMENT_CONFIRMED);
|
||||
onSuccess?.(votingData.vote.amount_in_sat);
|
||||
onSetteled?.()
|
||||
},
|
||||
update(cache, { data }) {
|
||||
try {
|
||||
const { item_id, item_type, amount_in_sat } = data!.confirmVote;
|
||||
const { votes_count } = cache.readFragment({
|
||||
id: `${item_type}:${item_id}`,
|
||||
fragment: gql`
|
||||
fragment My${item_type} on ${item_type} {
|
||||
votes_count
|
||||
}`
|
||||
}) ?? {};
|
||||
cache.writeFragment({
|
||||
id: `${item_type}:${item_id}`,
|
||||
fragment: gql`
|
||||
fragment My${item_type} on ${item_type} {
|
||||
votes_count
|
||||
}
|
||||
`,
|
||||
data: {
|
||||
votes_count: votes_count + amount_in_sat
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
onError?.(error)
|
||||
}
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
setPaymentStatus(PaymentStatus.NETWORK_ERROR);
|
||||
onError?.(error);
|
||||
onSetteled?.();
|
||||
alert("A network error happened while confirming the payment...")
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
setPaymentStatus(PaymentStatus.CANCELED);
|
||||
onError?.(error);
|
||||
onSetteled?.();
|
||||
alert("Payment rejected by user")
|
||||
Wallet_Service.getWebln()
|
||||
.then(webln => {
|
||||
|
||||
if (!webln) {
|
||||
onError?.(new Error('No WebLN Detetcted'))
|
||||
onSetteled?.()
|
||||
return
|
||||
}
|
||||
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error);
|
||||
setPaymentStatus(PaymentStatus.NETWORK_ERROR);
|
||||
onError?.(error);
|
||||
onSetteled?.();
|
||||
alert("A network error happened...")
|
||||
}
|
||||
})
|
||||
setPaymentStatus(PaymentStatus.FETCHING_PAYMENT_DETAILS)
|
||||
voteMutaion({
|
||||
variables: {
|
||||
itemId,
|
||||
itemType,
|
||||
amountInSat: amount
|
||||
},
|
||||
onCompleted: async (votingData) => {
|
||||
try {
|
||||
setPaymentStatus(PaymentStatus.AWAITING_PAYMENT);
|
||||
const paymentResponse = await webln.sendPayment(votingData.vote.payment_request);
|
||||
setPaymentStatus(PaymentStatus.PAID);
|
||||
|
||||
//Confirm Voting payment
|
||||
confirmVote({
|
||||
variables: {
|
||||
paymentRequest: votingData.vote.payment_request,
|
||||
preimage: paymentResponse.preimage
|
||||
},
|
||||
onCompleted: () => {
|
||||
setPaymentStatus(PaymentStatus.PAYMENT_CONFIRMED);
|
||||
onSuccess?.(votingData.vote.amount_in_sat);
|
||||
onSetteled?.()
|
||||
},
|
||||
update(cache, { data }) {
|
||||
try {
|
||||
const { item_id, item_type, amount_in_sat } = data!.confirmVote;
|
||||
const { votes_count } = cache.readFragment({
|
||||
id: `${item_type}:${item_id}`,
|
||||
fragment: gql`
|
||||
fragment My${item_type} on ${item_type} {
|
||||
votes_count
|
||||
}`
|
||||
}) ?? {};
|
||||
cache.writeFragment({
|
||||
id: `${item_type}:${item_id}`,
|
||||
fragment: gql`
|
||||
fragment My${item_type} on ${item_type} {
|
||||
votes_count
|
||||
}
|
||||
`,
|
||||
data: {
|
||||
votes_count: votes_count + amount_in_sat
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
onError?.(error)
|
||||
}
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
setPaymentStatus(PaymentStatus.NETWORK_ERROR);
|
||||
onError?.(error);
|
||||
onSetteled?.();
|
||||
alert("A network error happened while confirming the payment...")
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
setPaymentStatus(PaymentStatus.CANCELED);
|
||||
onError?.(error);
|
||||
onSetteled?.();
|
||||
alert("Payment rejected by user")
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error);
|
||||
setPaymentStatus(PaymentStatus.NETWORK_ERROR);
|
||||
onError?.(error);
|
||||
onSetteled?.();
|
||||
alert("A network error happened...")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
}, [confirmVote, voteMutaion, params.itemId, params.itemType, params.onError, params.onSetteled, params.onSuccess]);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user