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() {
{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