diff --git a/apps/voting/app/package.json b/apps/voting/app/package.json index 7fa36c969c..b6958e061e 100644 --- a/apps/voting/app/package.json +++ b/apps/voting/app/package.json @@ -4,9 +4,9 @@ "private": true, "license": "AGPL-3.0-or-later", "dependencies": { - "@aragon/api": "^1.0.0", - "@aragon/api-react": "^1.0.0-beta.2", - "@aragon/ui": "^0.39.0", + "@aragon/api": "^2.0.0-beta.2", + "@aragon/api-react": "^2.0.0-beta.1", + "@aragon/ui": "^0.40.1", "bn.js": "^4.11.8", "date-fns": "2.0.0-alpha.22", "onecolor": "^3.1.0", diff --git a/apps/voting/app/src/App.js b/apps/voting/app/src/App.js index 6b24b19403..bdebd0f4c5 100644 --- a/apps/voting/app/src/App.js +++ b/apps/voting/app/src/App.js @@ -1,5 +1,5 @@ import React from 'react' -import { Main } from '@aragon/ui' +import { SyncIndicator, Main } from '@aragon/ui' import EmptyState from './screens/EmptyState' import Votes from './screens/Votes' @@ -14,6 +14,7 @@ import { AppLogicProvider, useAppLogic } from './app-logic' function App() { const { + isSyncing, votes, selectedVote, actions, @@ -25,6 +26,7 @@ function App() { return (
+ 0 ? ( ) : ( - + !isSyncing && )} diff --git a/apps/voting/app/src/app-logic.js b/apps/voting/app/src/app-logic.js index d76d704d91..9b084b8dd3 100644 --- a/apps/voting/app/src/app-logic.js +++ b/apps/voting/app/src/app-logic.js @@ -99,6 +99,8 @@ export function useSelectedVotePanel(selectedVote, selectVote) { // Handles the main logic of the app. export function useAppLogic() { + const { isSyncing, ready } = useAppState() + const votes = useVotes() const [selectedVote, selectVote] = useSelectedVote(votes) const newVotePanel = usePanelState() @@ -111,6 +113,7 @@ export function useAppLogic() { } return { + isSyncing: isSyncing || !ready, votes, selectVote, selectedVote, diff --git a/apps/voting/app/src/script.js b/apps/voting/app/src/script.js index f22d233c84..93b738661c 100644 --- a/apps/voting/app/src/script.js +++ b/apps/voting/app/src/script.js @@ -1,16 +1,11 @@ -import Aragon from '@aragon/api' -import { of } from 'rxjs' -import { map, publishReplay } from 'rxjs/operators' +import Aragon, { events } from '@aragon/api' import { addressesEqual } from './web3-utils' -import voteSettings, { hasLoadedVoteSettings } from './vote-settings' +import voteSettings from './vote-settings' import { voteTypeFromContractEnum } from './vote-utils' import { EMPTY_CALLSCRIPT } from './evmscript-utils' import tokenDecimalsAbi from './abi/token-decimals.json' import tokenSymbolAbi from './abi/token-symbol.json' -const INITIALIZATION_TRIGGER = Symbol('INITIALIZATION_TRIGGER') -const ACCOUNTS_TRIGGER = Symbol('ACCOUNTS_TRIGGER') - const tokenAbi = [].concat(tokenDecimalsAbi, tokenSymbolAbi) const app = new Aragon() @@ -61,6 +56,34 @@ retryEvery(retry => { }) async function initialize(tokenAddr) { + return app.store( + async (state, { event, returnValues }) => { + let nextState = { + ...state, + } + + switch (event) { + case events.ACCOUNTS_TRIGGER: + return updateConnectedAccount(nextState, returnValues) + case events.SYNC_STATUS_SYNCING: + return { ...nextState, isSyncing: true } + case events.SYNC_STATUS_SYNCED: + return { ...nextState, isSyncing: false } + case 'CastVote': + return castVote(nextState, returnValues) + case 'ExecuteVote': + return executeVote(nextState, returnValues) + case 'StartVote': + return startVote(nextState, returnValues) + default: + return nextState + } + }, + { init: initState(tokenAddr) } + ) +} + +const initState = tokenAddr => async cachedState => { const token = app.external(tokenAddr, tokenAbi) let tokenSymbol @@ -84,76 +107,23 @@ async function initialize(tokenAddr) { try { tokenDecimals = (await token.decimals().toPromise()) || '0' } catch (err) { - console.err( + console.error( `Failed to load token decimals for token at ${tokenAddr} due to:`, err ) - console.err('Defaulting to 0...') + console.error('Defaulting to 0...') tokenDecimals = '0' } - return createStore(token, { decimals: tokenDecimals, symbol: tokenSymbol }) -} + const voteSettings = await loadVoteSettings() -// Hook up the script as an aragon.js store -async function createStore(token, tokenSettings) { - const { decimals: tokenDecimals, symbol: tokenSymbol } = tokenSettings - - // Hot observable which emits an web3.js event-like object with an account string of the current active account. - const accounts$ = app.accounts().pipe( - map(accounts => { - return { - event: ACCOUNTS_TRIGGER, - returnValues: { - account: accounts[0], - }, - } - }), - publishReplay(1) - ) - - accounts$.connect() - - return app.store( - async (state, { event, returnValues }) => { - let nextState = { - ...state, - // Fetch the app's settings, if we haven't already - ...(!hasLoadedVoteSettings(state) ? await loadVoteSettings() : {}), - } - - if (event === INITIALIZATION_TRIGGER) { - nextState = { - ...nextState, - tokenDecimals, - tokenSymbol, - } - } else { - switch (event) { - case ACCOUNTS_TRIGGER: - nextState = await updateConnectedAccount(nextState, returnValues) - break - case 'CastVote': - nextState = await castVote(nextState, returnValues) - break - case 'ExecuteVote': - nextState = await executeVote(nextState, returnValues) - break - case 'StartVote': - nextState = await startVote(nextState, returnValues) - break - default: - break - } - } - return nextState - }, - [ - // Always initialize the store with our own home-made event - of({ event: INITIALIZATION_TRIGGER }), - accounts$, - ] - ) + return { + ...cachedState, + isSyncing: true, + tokenDecimals, + tokenSymbol, + ...voteSettings, + } } /***********************