fix(refactor): Refactoring and restructuring

This commit is contained in:
Daniel Gonzalez
2025-01-23 17:42:28 -04:00
parent 941d14df36
commit 4ce02538e1
10 changed files with 140 additions and 143 deletions
+41 -137
View File
@@ -3,201 +3,105 @@
*/
// Global npm libraries
import React, { useState, useEffect } from 'react'
import { useQueryParam, StringParam } from 'use-query-params'
import React, { useEffect, useCallback } from 'react'
// Local libraries
import './App.css'
import LoadScripts from './components/load-scripts'
import WaitingModal from './components/waiting-modal'
import AsyncLoad from './services/async-load'
import SelectServerButton from './components/servers/select-server-button'
import Footer from './components/footer'
import NavMenu from './components/nav-menu'
import AppBody from './components/app-body'
import useAppState from './hooks/state'
import { UninitializedView, InitializedView } from './components/starter-views'
function App (props) {
// BEGIN STATE
// Get the CashStack URL from a query parameter, if it exists.
let [restURL] = useQueryParam('restURL', StringParam)
// Otherwise default to free-bch.fullstack.cash
if (!restURL) restURL = 'https://free-bch.fullstack.cash'
// console.log('restURL: ', restURL)
const [serverUrl, setServerUrl] = useState(restURL)
const [menuState, setMenuState] = useState(0)
const [wallet, setWallet] = useState(false)
const [servers, setServers] = useState([])
// Startup state
// When the page is loaded, it goes through a series of async network calls
// to initialize the app. These variables track the state of this startup
// process.
const [asyncInitStarted, setAsyncInitStarted] = useState(false)
const [asyncInitFinished, setAsyncInitFinished] = useState(false)
const [asyncInitSucceeded, setAsyncInitSucceeded] = useState(null)
// Startup Modal
const [showStartModal, setShowStartModal] = useState(true)
const [modalBody, setModalBody] = useState([])
const [hideSpinner, setHideSpinner] = useState(false)
const [denyClose, setDenyClose] = useState(false) // Deny modal to be closed
// Load all the app state into a single object that can be passed to child
// components.
const appData = {
wallet,
setWallet,
serverUrl,
setServerUrl,
servers,
setServers,
showStartModal,
setShowStartModal,
menuState,
setMenuState,
asyncInitFinished,
setAsyncInitFinished,
asyncInitSucceeded,
setAsyncInitSucceeded,
modalBody,
setModalBody,
hideSpinner,
setHideSpinner,
denyClose,
setDenyClose
}
const appData = useAppState()
// END STATE
// Encasulate dependencies
const asyncLoad = new AsyncLoad()
// Add a new line to the waiting modal.
const addToModal = useCallback((inStr, appData) => {
// console.log('addToModal() inStr: ', inStr)
appData.setModalBody(prevBody => {
// console.log('prevBody: ', prevBody)
prevBody.push(inStr)
return prevBody
})
}, [])
/** Load all required data before component start. */
useEffect(() => {
async function asyncEffect () {
// console.log('asyncInitStarted: ', asyncInitStarted)
if (!asyncInitStarted) {
console.log('asyncInitStarted: ', appData.asyncInitStarted)
if (!appData.asyncInitStarted) {
try {
setAsyncInitStarted(true)
// Instantiate the async load object.
const asyncLoad = new AsyncLoad()
appData.setAsyncInitStarted(true)
addToModal('Loading minimal-slp-wallet', appData)
setDenyClose(true)
appData.setDenyClose(true)
await asyncLoad.loadWalletLib()
// console.log('Wallet: ', Wallet)
addToModal('Getting alternative servers', appData)
const gistServers = await asyncLoad.getServers()
setServers(gistServers)
appData.setServers(gistServers)
// console.log('servers: ', servers)
// throw new Error('test error')
addToModal('Initializing wallet', appData)
console.log(`Initializing wallet with back end server ${serverUrl}`)
console.log(`Initializing wallet with back end server ${appData.serverUrl}`)
const walletTemp = await asyncLoad.initWallet(serverUrl)
setWallet(walletTemp)
const walletTemp = await asyncLoad.initWallet(appData.serverUrl)
appData.setWallet(walletTemp)
// Update state
setShowStartModal(false)
setDenyClose(false)
appData.setShowStartModal(false)
appData.setDenyClose(false)
// Update the startup state.
setAsyncInitFinished(true)
setAsyncInitSucceeded(true)
appData.setAsyncInitFinished(true)
appData.setAsyncInitSucceeded(true)
console.log('App.js useEffect() startup finished successfully')
} catch (err) {
const errModalBody = [
`Error: ${err.message}`,
'Try selecting a different back end server using the drop-down menu at the bottom of the app.'
]
setModalBody(errModalBody)
appData.setModalBody(errModalBody)
// Update Modal State
setHideSpinner(true)
setShowStartModal(true)
setDenyClose(false)
appData.setHideSpinner(true)
appData.setShowStartModal(true)
appData.setDenyClose(false)
// Update the startup state.
setAsyncInitFinished(true)
setAsyncInitSucceeded(false)
appData.setAsyncInitFinished(true)
appData.setAsyncInitSucceeded(false)
}
}
}
asyncEffect()
})
}, [appData, addToModal])
return (
<>
<LoadScripts />
<NavMenu menuHandler={onMenuClick} appData={appData} />
<NavMenu appData={appData} />
{/** Define View to show */}
{
showStartModal
appData.showStartModal
? (<UninitializedView appData={appData} />)
: (<InitializedView menuState={menuState} appData={appData} />)
: (<InitializedView menuState={appData.menuState} appData={appData} />)
}
<SelectServerButton menuHandler={onMenuClick} appData={appData} />
<SelectServerButton appData={appData} />
<Footer appData={appData} />
</>
)
}
// Add a new line to the waiting modal.
function addToModal (inStr, appData) {
// console.log('addToModal() inStr: ', inStr)
appData.setModalBody(prevBody => {
// console.log('prevBody: ', prevBody)
prevBody.push(inStr)
return prevBody
})
}
// This handler is passed into the child menu component. When an item in the
// nav menu is clicked, this handler will update the state. The state is
// used by the AppBody component to determine which View component to display.
function onMenuClick (menuState, appData) {
// console.log('onMenuClick() menuState: ', menuState)
appData.setMenuState(menuState)
}
// This is rendered *before* the BCH wallet is initialized.
function UninitializedView (props = {}) {
// console.log('UninitializedView props: ', props)
const heading = 'Connecting to BCH blockchain...'
return (
<>
<WaitingModal
heading={heading}
body={props.appData.modalBody}
hideSpinner={props.appData.hideSpinner}
denyClose={props.appData.denyClose}
/>
{
props.asyncInitFinished
? <AppBody menuState={100} wallet={props.appData.wallet} appData={props.appData} />
: null
}
</>
)
}
// This is rendered *after* the BCH wallet is initialized.
function InitializedView (props) {
return (
<>
<br />
<AppBody menuState={props.menuState} appData={props.appData} />
</>
)
}
export default App
+3 -3
View File
@@ -10,9 +10,9 @@
import React from 'react'
// Local libraries
import GetBalance from '../balance'
import Placeholder2 from '../placeholder2'
import Placeholder3 from '../placeholder3'
import GetBalance from './balance'
import Placeholder2 from './placeholder2'
import Placeholder3 from './placeholder3'
import ServerSelectView from '../servers/select-server-view'
function AppBody (props) {
+1 -1
View File
@@ -13,7 +13,7 @@ import Logo from './psf-logo.png'
function NavMenu (props) {
const handleClickEvent = (menuItem) => {
// Pass the selected menu item up to the parent component.
props.menuHandler(menuItem, props.appData)
props.appData.setMenuState(menuItem)
}
return (
@@ -47,7 +47,7 @@ class ServerSelect extends React.Component {
handleServerSelect () {
console.log('This function should navigate to the server selection view.')
this.state.menuHandler(100, this.state.appData)
this.state.appData.setMenuState(100)
}
}
+42
View File
@@ -0,0 +1,42 @@
/**
* This file contains the views that are displayed before and after the BCH wallet is initialized.
*/
import React from 'react'
import WaitingModal from './waiting-modal'
import AppBody from './app-body'
// This is rendered *before* the BCH wallet is initialized.
export function UninitializedView (props = {}) {
// console.log('UninitializedView props: ', props)
const { appData } = props
const heading = 'Connecting to BCH blockchain...'
return (
<>
<WaitingModal
heading={heading}
body={appData.modalBody}
hideSpinner={appData.hideSpinner}
denyClose={appData.denyClose}
/>
{
props.asyncInitFinished
? <AppBody menuState={100} wallet={appData.wallet} appData={appData} />
: null
}
</>
)
}
// This is rendered *after* the BCH wallet is initialized.
export function InitializedView (props) {
const { appData } = props
return (
<>
<br />
<AppBody menuState={appData.menuState} appData={appData} />
</>
)
}
+51
View File
@@ -0,0 +1,51 @@
import { useState } from 'react'
import { useQueryParam, StringParam } from 'use-query-params'
function useAppState () {
// Get the CashStack URL from query parameter or use default
let [restURL] = useQueryParam('restURL', StringParam)
if (!restURL) restURL = 'https://free-bch.fullstack.cash'
const [serverUrl, setServerUrl] = useState(restURL)
const [menuState, setMenuState] = useState(0)
const [wallet, setWallet] = useState(false)
const [servers, setServers] = useState([])
// Startup state management
const [asyncInitStarted, setAsyncInitStarted] = useState(false)
const [asyncInitFinished, setAsyncInitFinished] = useState(false)
const [asyncInitSucceeded, setAsyncInitSucceeded] = useState(null)
// Modal state management
const [showStartModal, setShowStartModal] = useState(true)
const [modalBody, setModalBody] = useState([])
const [hideSpinner, setHideSpinner] = useState(false)
const [denyClose, setDenyClose] = useState(false)
return {
serverUrl,
setServerUrl,
menuState,
setMenuState,
wallet,
setWallet,
servers,
setServers,
asyncInitStarted,
setAsyncInitStarted,
asyncInitFinished,
setAsyncInitFinished,
asyncInitSucceeded,
setAsyncInitSucceeded,
showStartModal,
setShowStartModal,
modalBody,
setModalBody,
hideSpinner,
setHideSpinner,
denyClose,
setDenyClose
}
}
export default useAppState
+1 -1
View File
@@ -19,7 +19,7 @@ class GistServers {
// Retrieve the gist from github.com.
const result = await this.axios.get(gistUrl)
console.log('result.data: ', result.data)
// console.log('result.data: ', result.data)
// Get the current content of the gist.
const content = result.data.servers