diff --git a/VoidCat/spa/src/FilePaywall.js b/VoidCat/spa/src/FilePaywall.js index 90b26b1..0ce827a 100644 --- a/VoidCat/spa/src/FilePaywall.js +++ b/VoidCat/spa/src/FilePaywall.js @@ -4,6 +4,7 @@ import {PaywallServices} from "./Const"; import {useState} from "react"; import {LightningPaywall} from "./LightningPaywall"; import {useApi} from "./Api"; +import {VoidButton} from "./VoidButton"; export function FilePaywall(props) { const {Api} = useApi(); @@ -14,15 +15,11 @@ export function FilePaywall(props) { const [order, setOrder] = useState(); - async function fetchOrder(e) { - if(e.target.classList.contains("disabled")) return; - e.target.classList.add("disabled"); - + async function fetchOrder() { let req = await Api.createOrder(file.id); if (req.ok && req.status === 200) { setOrder(await req.json()); } - e.target.classList.remove("disabled"); } function reset() { @@ -42,7 +39,7 @@ export function FilePaywall(props) {

You must pay {FormatCurrency(pw.cost.amount, pw.cost.currency)} to view this file.

-
Pay
+ Pay ); } else { diff --git a/VoidCat/spa/src/GlobalStats.js b/VoidCat/spa/src/GlobalStats.js index 813299e..4f0aa8e 100644 --- a/VoidCat/spa/src/GlobalStats.js +++ b/VoidCat/spa/src/GlobalStats.js @@ -1,16 +1,14 @@ -import {Fragment, useEffect, useState} from "react"; +import {Fragment} from "react"; import FeatherIcon from "feather-icons-react"; import {FormatBytes} from "./Util"; import "./GlobalStats.css"; -import {useApi} from "./Api"; import moment from "moment"; import {useSelector} from "react-redux"; -export function GlobalStats(props) { - const {Api} = useApi(); +export function GlobalStats() { let stats = useSelector(state => state.info.stats); - + return (
diff --git a/VoidCat/spa/src/Login.js b/VoidCat/spa/src/Login.js index 37e4142..6238f29 100644 --- a/VoidCat/spa/src/Login.js +++ b/VoidCat/spa/src/Login.js @@ -3,8 +3,8 @@ import {useDispatch, useSelector} from "react-redux"; import {setAuth} from "./LoginState"; import {useApi} from "./Api"; import "./Login.css"; -import {btnDisable, btnEnable} from "./Util"; import HCaptcha from "@hcaptcha/react-hcaptcha"; +import {VoidButton} from "./VoidButton"; export function Login() { const {Api} = useApi(); @@ -15,8 +15,7 @@ export function Login() { const captchaKey = useSelector(state => state.info.stats.captchaSiteKey); const dispatch = useDispatch(); - async function login(e, fnLogin) { - if(!btnDisable(e.target)) return; + async function login(fnLogin) { setError(null); let req = await fnLogin(username, password, captchaResponse); @@ -28,8 +27,6 @@ export function Login() { setError(rsp.error); } } - - btnEnable(e.target); } return ( @@ -42,8 +39,8 @@ export function Login() {
setPassword(e.target.value)}/>
{captchaKey ? : null} -
login(e, Api.login)}>Login
-
login(e, Api.register)}>Register
+ login(Api.login)}>Login + login(Api.register)}>Register {error ?
{error}
: null} ); diff --git a/VoidCat/spa/src/NoPaywallConfig.js b/VoidCat/spa/src/NoPaywallConfig.js index 5ea9d6a..6a5c152 100644 --- a/VoidCat/spa/src/NoPaywallConfig.js +++ b/VoidCat/spa/src/NoPaywallConfig.js @@ -1,15 +1,13 @@ import FeatherIcon from "feather-icons-react"; import {useState} from "react"; -import {btnDisable, btnEnable} from "./Util"; +import {VoidButton} from "./VoidButton"; export function NoPaywallConfig(props) { const [saveStatus, setSaveStatus] = useState(); const privateFile = props.privateFile; const onSaveConfig = props.onSaveConfig; - async function saveConfig(e) { - if(!btnDisable(e.target)) return; - + async function saveConfig() { let cfg = { editSecret: privateFile.metadata.editSecret }; @@ -17,12 +15,11 @@ export function NoPaywallConfig(props) { if (typeof onSaveConfig === "function") { setSaveStatus(await onSaveConfig(cfg)); } - btnEnable(e.target); } return (
-
Save
+ Save {saveStatus ? : null}
) diff --git a/VoidCat/spa/src/Profile.js b/VoidCat/spa/src/Profile.js index 3be47a3..9d4da94 100644 --- a/VoidCat/spa/src/Profile.js +++ b/VoidCat/spa/src/Profile.js @@ -6,10 +6,11 @@ import "./Profile.css"; import {useDispatch, useSelector} from "react-redux"; import {logout, setProfile as setGlobalProfile} from "./LoginState"; import {DigestAlgo} from "./FileUpload"; -import {btnDisable, btnEnable, buf2hex, hasFlag} from "./Util"; +import {buf2hex, hasFlag} from "./Util"; import moment from "moment"; import FeatherIcon from "feather-icons-react"; import {FileList} from "./FileList"; +import {VoidButton} from "./VoidButton"; export function Profile() { const [profile, setProfile] = useState(); @@ -93,8 +94,6 @@ export function Profile() { } async function saveUser(e) { - if (!btnDisable(e.target)) return; - let r = await Api.updateUser({ id: profile.id, avatar: profile.avatar, @@ -106,19 +105,15 @@ export function Profile() { dispatch(setGlobalProfile(profile)); setSaved(true); } - btnEnable(e.target); } async function submitCode(e) { - if (!btnDisable(e.target)) return; - let r = await Api.submitVerifyCode(profile.id, emailCode); if (r.ok) { await loadProfile(); } else { setEmailCodeError("Invalid or expired code."); } - btnEnable(e.target); } async function sendNewCode() { @@ -138,8 +133,8 @@ export function Profile() {
setEmailCode(e.target.value)}/> -
Submit
-
dispatch(logout())}>Logout
+ Submit + dispatch(logout())}>Logout
{emailCodeError ? {emailCodeError} : null} {emailCodeError && !newCodeSent ? Send verfication email : null} @@ -165,13 +160,13 @@ export function Profile() {
-
Save
+ Save
{saved ? : null}
-
dispatch(logout())}>Logout
+ dispatch(logout())}>Logout
diff --git a/VoidCat/spa/src/StrikePaywallConfig.js b/VoidCat/spa/src/StrikePaywallConfig.js index 9c165b4..d61b4bb 100644 --- a/VoidCat/spa/src/StrikePaywallConfig.js +++ b/VoidCat/spa/src/StrikePaywallConfig.js @@ -1,7 +1,7 @@ import {useState} from "react"; import FeatherIcon from "feather-icons-react"; import {PaywallCurrencies} from "./Const"; -import {btnDisable, btnEnable} from "./Util"; +import {VoidButton} from "./VoidButton"; export function StrikePaywallConfig(props) { const file = props.file; @@ -16,8 +16,6 @@ export function StrikePaywallConfig(props) { const [saveStatus, setSaveStatus] = useState(); async function saveStrikeConfig(e) { - if(!btnDisable(e.target)) return; - let cfg = { editSecret, strike: { @@ -37,7 +35,6 @@ export function StrikePaywallConfig(props) { setSaveStatus(false); } } - btnEnable(e.target); } return ( @@ -57,7 +54,7 @@ export function StrikePaywallConfig(props) {
Price:
setPrice(parseFloat(e.target.value))}/>
-
Save
+ Save {saveStatus ? : null} ); diff --git a/VoidCat/spa/src/Util.js b/VoidCat/spa/src/Util.js index 7ae8f50..74b45d0 100644 --- a/VoidCat/spa/src/Util.js +++ b/VoidCat/spa/src/Util.js @@ -79,14 +79,4 @@ export function FormatCurrency(value, currency) { export function hasFlag(value, flag) { return (value & flag) === flag; -} - -export function btnDisable(btn){ - if(btn.classList.contains("disabled")) return false; - btn.classList.add("disabled"); - return true; -} - -export function btnEnable(btn){ - btn.classList.remove("disabled"); } \ No newline at end of file diff --git a/VoidCat/spa/src/VoidButton.js b/VoidCat/spa/src/VoidButton.js new file mode 100644 index 0000000..3aa3777 --- /dev/null +++ b/VoidCat/spa/src/VoidButton.js @@ -0,0 +1,18 @@ +export function VoidButton(props) { + async function handleClick(e) { + if (e.target.classList.contains("disabled")) return; + e.target.classList.add("disabled"); + + let fn = props.onClick; + if (typeof fn === "function") { + let ret = fn(e); + if (typeof ret === "object" && typeof ret.then === "function") { + await ret; + } + } + + e.target.classList.remove("disabled"); + } + + return
{props.children}
; +} \ No newline at end of file