diff --git a/src/App.js b/src/App.js
index 53d545d..3d9d912 100644
--- a/src/App.js
+++ b/src/App.js
@@ -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 (
<>
-
-
+
+ {/** Define View to show */}
{
- showStartModal
+ appData.showStartModal
? ()
- : ()
+ : ()
}
-
+
>
)
}
-// 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 (
- <>
-
- {
- props.asyncInitFinished
- ?
- : null
- }
- >
- )
-}
-
-// This is rendered *after* the BCH wallet is initialized.
-function InitializedView (props) {
- return (
- <>
-
-
- >
- )
-}
-
export default App
diff --git a/src/components/balance.js b/src/components/app-body/balance.js
similarity index 100%
rename from src/components/balance.js
rename to src/components/app-body/balance.js
diff --git a/src/components/app-body/index.js b/src/components/app-body/index.js
index ed4a35d..11808df 100644
--- a/src/components/app-body/index.js
+++ b/src/components/app-body/index.js
@@ -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) {
diff --git a/src/components/placeholder2.js b/src/components/app-body/placeholder2.js
similarity index 100%
rename from src/components/placeholder2.js
rename to src/components/app-body/placeholder2.js
diff --git a/src/components/placeholder3.js b/src/components/app-body/placeholder3.js
similarity index 100%
rename from src/components/placeholder3.js
rename to src/components/app-body/placeholder3.js
diff --git a/src/components/nav-menu/index.js b/src/components/nav-menu/index.js
index 4844975..7b91099 100644
--- a/src/components/nav-menu/index.js
+++ b/src/components/nav-menu/index.js
@@ -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 (
diff --git a/src/components/servers/select-server-button.js b/src/components/servers/select-server-button.js
index b9601e3..e6aef80 100644
--- a/src/components/servers/select-server-button.js
+++ b/src/components/servers/select-server-button.js
@@ -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)
}
}
diff --git a/src/components/starter-views.js b/src/components/starter-views.js
new file mode 100644
index 0000000..bb63664
--- /dev/null
+++ b/src/components/starter-views.js
@@ -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 (
+ <>
+
+ {
+ props.asyncInitFinished
+ ?
+ : null
+ }
+ >
+ )
+}
+
+// This is rendered *after* the BCH wallet is initialized.
+export function InitializedView (props) {
+ const { appData } = props
+
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/src/hooks/state.js b/src/hooks/state.js
new file mode 100644
index 0000000..56c2843
--- /dev/null
+++ b/src/hooks/state.js
@@ -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
diff --git a/src/services/gist-servers.js b/src/services/gist-servers.js
index 39e9e33..78f5736 100644
--- a/src/services/gist-servers.js
+++ b/src/services/gist-servers.js
@@ -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