feat: implement custom modals for no-webln error on mobile and web

Fixes #91
This commit is contained in:
MTG2000
2022-08-09 18:11:32 +03:00
parent 28eadcc1ff
commit f73e55377c
10 changed files with 236 additions and 130 deletions

View File

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

View File

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

View 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 youre browsing on mobile.
</h3>
<p className="text-body4 text-gray-600 mt-8">
In order to use BOLT🔩FUNs 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 dont have Alby installed
</h3>
<p className="text-body4 text-gray-600 mt-8">
In order to use BOLT🔩FUNs voting button, youll 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>
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -0,0 +1,4 @@
import { lazyModal } from 'src/utils/helperFunctions';
export const { LazyComponent: NoWeblnModal } = lazyModal(() => import('./NoWeblnModal'))

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

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

View File

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

View File

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

View File

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