2023-04-20 10:03:36 +02:00
import React , { useState , useEffect , useRef } from "react" ;
2023-03-15 15:25:09 +01:00
import { Link , useLocation , useNavigate } from "react-router-dom" ;
import Modal from "react-modal" ;
2023-04-20 10:03:36 +02:00
import { deleteCaches , setAccount , useAccount } from "@plebbit/plebbit-react-hooks" ;
2023-04-19 16:00:31 +02:00
import { StyledModal } from "./styled/SettingsModal.styled" ;
2023-04-08 13:27:17 +02:00
import useGeneralStore from "../hooks/stores/useGeneralStore" ;
2023-04-19 16:00:31 +02:00
import useError from "../hooks/useError" ;
import useSuccess from "../hooks/useSuccess" ;
2023-03-15 15:25:09 +01:00
const customOverlayStyles = {
overlay : {
backgroundColor : 'rgba(0,0,0,.25)'
}
};
const SettingsModal = ({ isOpen , closeModal }) => {
2023-04-08 13:27:17 +02:00
const selectedStyle = useGeneralStore ( state => state . selectedStyle );
2023-03-15 15:25:09 +01:00
const navigate = useNavigate ();
const location = useLocation ();
2023-04-18 22:21:28 +02:00
const [ expanded , setExpanded ] = useState ([]);
2023-04-19 16:00:31 +02:00
const [ errorMessage , setErrorMessage ] = useState ( null );
const [ successMessage , setSuccessMessage ] = useState ( null );
useError ( errorMessage , [ errorMessage ]);
useSuccess ( successMessage , [ successMessage ]);
2023-03-15 15:25:09 +01:00
2023-04-20 10:03:36 +02:00
const account = useAccount ();
const gatewayRef = useRef ();
const ipfsRef = useRef ();
const pubsubRef = useRef ();
const dataPathRef = useRef ();
2023-04-20 13:59:04 +02:00
const isValidURL = ( url ) => {
try {
new URL ( url );
return true ;
} catch {
return false ;
}
};
const handleSavePlebbitOptions = async () => {
const gatewayUrls = gatewayRef . current . value . split ( '\n' ). filter ( url => url . trim ());
const ipfsClientsOptions = ipfsRef . current . value . split ( '\n' ). filter ( url => url . trim ()) || undefined ;
const pubsubClientsOptions = pubsubRef . current . value . split ( '\n' ). filter ( url => url . trim ());
const invalidUrls = [
... gatewayUrls ,
...( ipfsClientsOptions || []),
... pubsubClientsOptions ,
]. filter (( url ) => ! isValidURL ( url ));
if ( invalidUrls . length > 0 ) {
setErrorMessage ( `Invalid URL(s): ${ invalidUrls . join ( ', ' ) } ` );
return ;
}
const plebbitOptions = {
ipfsGatewayUrls : gatewayUrls ,
ipfsHttpClientsOptions : ipfsClientsOptions ,
pubsubHttpClientsOptions : pubsubClientsOptions ,
};
try {
await setAccount ({ ... account , plebbitOptions });
localStorage . setItem ( "toastMessage" , "Settings Saved" );
window . location . reload ();
} catch ( error ) {
setErrorMessage ( error . message );
}
};
const handleResetPlebbitOptions = async () => {
setErrorMessage ( null );
setSuccessMessage ( null );
const defaultGatewayUrls = [
'https://ipfs.io' ,
'https://ipfsgateway.xyz' ,
'https://cloudflare-ipfs.com'
];
const defaultPubsubHttpClientsOptions = [ 'https://pubsubprovider.xyz/api/v0' ];
gatewayRef . current . value = defaultGatewayUrls . join ( '\n' );
ipfsRef . current . value = "" ;
pubsubRef . current . value = defaultPubsubHttpClientsOptions . join ( '\n' );
dataPathRef . current . value = "" ;
try {
await setAccount ({
... account ,
plebbitOptions : {
ipfsGatewayUrls : defaultGatewayUrls ,
ipfsHttpClientsOptions : undefined ,
pubsubHttpClientsOptions : defaultPubsubHttpClientsOptions ,
},
});
localStorage . setItem ( "toastMessage" , "Settings Reset" );
window . location . reload ();
} catch ( error ) {
setErrorMessage ( error . message );
}
};
2023-04-19 16:20:43 +02:00
2023-03-15 15:25:09 +01:00
const handleCloseModal = () => {
closeModal ();
if ( location . pathname === "/settings" ) {
navigate ( - 1 , { replace : true });
} else {
navigate ( "/settings" , { state : { from : location } });
}
};
2023-04-19 16:20:43 +02:00
2023-04-18 22:21:28 +02:00
const toggleExpanded = ( index ) => {
setExpanded (( prevExpanded ) => {
const newExpanded = [... prevExpanded ];
if ( newExpanded . includes ( index )) {
newExpanded . splice ( newExpanded . indexOf ( index ), 1 );
} else {
newExpanded . push ( index );
}
return newExpanded ;
});
};
2023-04-19 16:20:43 +02:00
2023-04-18 22:21:28 +02:00
const expandAll = () => {
if ( expanded . length === 3 ) {
setExpanded ([]);
} else {
setExpanded ([ 0 , 1 , 2 ]);
}
};
2023-04-19 16:20:43 +02:00
2023-04-19 16:00:31 +02:00
useEffect (() => {
if ( localStorage . getItem ( "cacheCleared" ) === "true" ) {
setSuccessMessage ( "Cache Cleared" );
localStorage . removeItem ( "cacheCleared" );
}
}, []);
2023-04-20 13:59:04 +02:00
useEffect (() => {
2023-04-20 16:50:15 +02:00
const toastFromStorage = localStorage . getItem ( "toastMessage" );
if ( toastFromStorage ) {
setSuccessMessage ( toastFromStorage );
2023-04-20 13:59:04 +02:00
localStorage . removeItem ( "toastMessage" );
}
}, []);
2023-04-18 22:21:28 +02:00
2023-03-15 15:25:09 +01:00
return (
< StyledModal
isOpen = { isOpen }
onRequestClose = { closeModal }
contentLabel = "Settings"
style = { customOverlayStyles }
selectedStyle = { selectedStyle }
2023-04-18 22:21:28 +02:00
expanded = { expanded }
2023-03-15 15:25:09 +01:00
>
< div className = "panel" >
< div className = "panel-header" >
Settings
< Link to = "" onClick = { handleCloseModal }>
< span className = "icon" title = "close" />
</ Link >
</ div >
2023-04-18 22:21:28 +02:00
< div className = "all-div" >
[
< button className = "all-button"
onClick = { expandAll } style = {{ all : "unset" , cursor : "pointer" }}>
{ expanded . length === 3 ? "Collapse All Settings" : "Expand All Settings" }
</ button >
]
</ div >
2023-04-20 10:03:36 +02:00
{ /* <ul>
2023-04-18 22:21:28 +02:00
<li className="settings-cat-lbl">
<span className={`${expanded.includes(0) ? 'minus' : 'plus'}`}
onClick={() => toggleExpanded(0)}
/>
<span className="settings-pointer" style={{cursor: "pointer"}}
onClick={() => toggleExpanded(0)}
>Account</span>
</li>
<ul className="settings-cat" style={{ display: expanded.includes(0) ? 'block' : 'none' }}>
<li>
</li>
</ul>
</ul>
<ul>
<li className="settings-cat-lbl">
<span className={`${expanded.includes(1) ? 'minus' : 'plus'}`}
onClick={() => toggleExpanded(1)}
/>
<span className="settings-pointer" style={{cursor: "pointer"}}
onClick={() => toggleExpanded(1)}
>Profile</span>
</li>
<ul className="settings-cat" style={{ display: expanded.includes(1) ? 'block' : 'none' }}>
<li>
</li>
</ul>
2023-04-20 10:03:36 +02:00
</ul> */ }
2023-04-18 22:21:28 +02:00
< ul >
< li className = "settings-cat-lbl" >
2023-04-19 16:33:49 +02:00
< span className = { ` ${ expanded . includes ( 2 ) ? 'minus' : 'plus' } ` }
onClick = {() => toggleExpanded ( 2 )}
/>
< span className = "settings-pointer" style = {{ cursor : "pointer" }}
onClick = {() => toggleExpanded ( 2 )}
> Plebbit Options </ span >
< div className = "plebbit-options-buttons"
style = {{ display : expanded . includes ( 2 ) ? 'block' : 'none' }}
>
2023-04-20 13:59:04 +02:00
< button className = "save-button" onClick = { handleSavePlebbitOptions }> Save </ button >
< button className = "reset-button" onClick = { handleResetPlebbitOptions }> Reset </ button >
2023-04-19 16:33:49 +02:00
</ div >
2023-04-18 22:21:28 +02:00
</ li >
< ul className = "settings-cat" style = {{ display : expanded . includes ( 2 ) ? 'block' : 'none' }}>
< li className = "settings-option disc" >
2023-04-19 14:00:45 +02:00
IPFS Gateway URLs </ li >
< li className = "settings-tip" > Optional URLs of IPFS gateways .</ li >
2023-04-18 22:21:28 +02:00
< div className = "settings-input" >
2023-04-19 14:00:45 +02:00
< textarea placeholder = "IPFS Gateway URLs"
2023-04-20 13:59:04 +02:00
defaultValue = { account ? . plebbitOptions ? . ipfsGatewayUrls . join ( "\n" )}
2023-04-20 10:03:36 +02:00
ref = { gatewayRef }
2023-04-19 13:56:38 +02:00
/>
2023-04-18 22:21:28 +02:00
</ div >
</ ul >
< ul className = "settings-cat" style = {{ display : expanded . includes ( 2 ) ? 'block' : 'none' }}>
< li className = "settings-option disc" >
2023-04-20 10:03:36 +02:00
IPFS HTTP Clients Options </ li >
< li className = "settings-tip" > Optional URLs of IPFS APIs or IpfsHttpClientOptions , 'http://localhost:5001/api/v0' to use a local IPFS node .</ li >
2023-04-18 22:21:28 +02:00
< div className = "settings-input" >
2023-04-21 10:00:01 +02:00
< textarea placeholder = "IPFS HTTP Clients Options"
2023-04-20 13:59:04 +02:00
defaultValue = { account ? . plebbitOptions ? . ipfsHttpClientsOptions ? account ? . plebbitOptions ? . ipfsHttpClientsOptions . join ( "\n" ) : '' }
2023-04-20 10:03:36 +02:00
ref = { ipfsRef }
/>
2023-04-18 22:21:28 +02:00
</ div >
</ ul >
< ul className = "settings-cat" style = {{ display : expanded . includes ( 2 ) ? 'block' : 'none' }}>
< li className = "settings-option disc" >
2023-04-20 10:03:36 +02:00
PubSub HTTP Clients Options </ li >
< li className = "settings-tip" > Optional URLs or IpfsHttpClientOptions used for pubsub publishing when ipfsHttpClientOptions isn 't available, like in the browser.</li>
2023-04-18 22:21:28 +02:00
<div className="settings-input">
2023-04-21 10:00:01 +02:00
<textarea placeholder="PubSub HTTP Clients Options"
2023-04-20 13:59:04 +02:00
defaultValue={account?.plebbitOptions?.pubsubHttpClientsOptions.join("\n")}
2023-04-20 10:03:36 +02:00
ref={pubsubRef}
/>
2023-04-19 13:56:38 +02:00
</div>
</ul>
<ul className="settings-cat" style={{ display: expanded.includes(2) ? ' block ' : ' none ' }}>
<li className="settings-option disc">
Data Path (Node Only)</li>
2023-04-19 14:00:45 +02:00
<li className="settings-tip">Optional folder path to create/resume the user and subplebbit databases.</li>
2023-04-19 13:56:38 +02:00
<div className="settings-input">
2023-04-21 10:00:01 +02:00
<textarea placeholder="Data Path (Node Only)"
2023-04-20 10:03:36 +02:00
ref={dataPathRef}
/>
2023-04-18 22:21:28 +02:00
</div>
</ul>
2023-04-20 10:03:36 +02:00
{/* <ul className="settings-cat" style={{ display: expanded.includes(2) ? ' block ' : ' none ' }} >
< li className = "settings-option disc" >
Chain Providers </ li >
< li className = "settings-tip" > Optional provider RPC URLs and chain IDs .</ li >
< ul >
< li className = "settings-option disc" > Ethereum </ li >
< li className = "settings-option disc" > Avalanche </ li >
< li className = "settings-option disc" > Polygon </ li >
</ ul >
</ ul > * /}
2023-04-18 22:21:28 +02:00
</ ul >
2023-04-19 13:56:38 +02:00
< div >
2023-04-19 16:00:31 +02:00
< button
className = "cache-button"
onClick = { async () => {
if ( window . confirm ( "Are you sure you want to clear the cache?" )) {
await deleteCaches ();
localStorage . setItem ( "cacheCleared" , "true" );
window . location . reload ();
}
}}
>
Clear Cache
</ button >
2023-04-19 13:56:38 +02:00
</ div >
2023-03-15 15:25:09 +01:00
</ div >
</ StyledModal >
);
}
Modal . setAppElement ( "#root" );
export default SettingsModal ;