Skip to content

Commit

Permalink
Fix loading screen not showing when opening a budget file (#2663)
Browse files Browse the repository at this point in the history
* Fix app loading screen

* Release note

* Code review feedback
  • Loading branch information
joel-jeremy authored Apr 26, 2024
1 parent 98a7aac commit f8af8f9
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 57 deletions.
73 changes: 45 additions & 28 deletions packages/desktop-client/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,22 @@ import {
type FallbackProps,
} from 'react-error-boundary';
import { HotkeysProvider } from 'react-hotkeys-hook';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';

import {
closeBudget,
loadBudget,
loadGlobalPrefs,
setAppState,
sync,
} from 'loot-core/client/actions';
import * as Platform from 'loot-core/src/client/platform';
import { type State } from 'loot-core/src/client/state-types';
import {
init as initConnection,
send,
} from 'loot-core/src/platform/client/fetch';

import { useActions } from '../hooks/useActions';
import { useLocalPref } from '../hooks/useLocalPref';
import { installPolyfills } from '../polyfills';
import { ResponsiveProvider } from '../ResponsiveProvider';
Expand All @@ -38,37 +44,49 @@ type AppInnerProps = {
function AppInner({ budgetId, cloudFileId }: AppInnerProps) {
const [initializing, setInitializing] = useState(true);
const { showBoundary: showErrorBoundary } = useErrorBoundary();
const stateLoadingText = useSelector((state: State) => state.app.loadingText);
const [loadingText = stateLoadingText, setLoadingText] = useState<
string | null
>(null);
const { loadBudget, closeBudget, loadGlobalPrefs } = useActions();
const loadingText = useSelector((state: State) => state.app.loadingText);
const dispatch = useDispatch();

async function init() {
const socketName = await global.Actual.getServerSocket();

setLoadingText('Initializing the connection to the local database...');
dispatch(
setAppState({
loadingText: 'Initializing the connection to the local database...',
}),
);
await initConnection(socketName);

// Load any global prefs
setLoadingText('Loading global preferences...');
await loadGlobalPrefs();
dispatch(
setAppState({
loadingText: 'Loading global preferences...',
}),
);
await dispatch(loadGlobalPrefs());

// Open the last opened budget, if any
setLoadingText('Opening last budget...');
dispatch(
setAppState({
loadingText: 'Opening last budget...',
}),
);
const budgetId = await send('get-last-opened-backup');
if (budgetId) {
setLoadingText('Loading the last budget file...');
await loadBudget(budgetId);
await dispatch(loadBudget(budgetId, 'Loading the last budget file...'));

// Check to see if this file has been remotely deleted (but
// don't block on this in case they are offline or something)
setLoadingText('Retrieving remote files...');
dispatch(
setAppState({
loadingText: 'Retrieving remote files...',
}),
);
send('get-remote-files').then(files => {
if (files) {
const remoteFile = files.find(f => f.fileId === cloudFileId);
if (remoteFile && remoteFile.deleted) {
closeBudget();
dispatch(closeBudget());
}
}
});
Expand All @@ -79,7 +97,11 @@ function AppInner({ budgetId, cloudFileId }: AppInnerProps) {
async function initAll() {
await Promise.all([installPolyfills(), init()]);
setInitializing(false);
setLoadingText(null);
dispatch(
setAppState({
loadingText: null,
}),
);
}

initAll().catch(showErrorBoundary);
Expand All @@ -91,18 +113,13 @@ function AppInner({ budgetId, cloudFileId }: AppInnerProps) {

return (
<>
{initializing ? (
{(initializing || !budgetId) && (
<AppBackground initializing={initializing} loadingText={loadingText} />
) : budgetId ? (
)}
{budgetId ? (
<FinancesApp />
) : (
<>
<AppBackground
initializing={initializing}
loadingText={loadingText}
/>
<ManagementApp isLoading={loadingText != null} />
</>
<ManagementApp isLoading={loadingText != null} />
)}

<UpdateNotification />
Expand All @@ -123,10 +140,10 @@ function ErrorFallback({ error }: FallbackProps) {
export function App() {
const [budgetId] = useLocalPref('id');
const [cloudFileId] = useLocalPref('cloudFileId');
const { sync } = useActions();
const [hiddenScrollbars, setHiddenScrollbars] = useState(
hasHiddenScrollbars(),
);
const dispatch = useDispatch();

useEffect(() => {
function checkScrollbars() {
Expand All @@ -141,7 +158,7 @@ export function App() {
if (!isSyncing) {
console.debug('triggering sync because of visibility change');
isSyncing = true;
await sync();
await dispatch(sync());
isSyncing = false;
}
}
Expand All @@ -153,7 +170,7 @@ export function App() {
window.removeEventListener('focus', checkScrollbars);
window.removeEventListener('visibilitychange', onVisibilityChange);
};
}, [sync]);
}, [dispatch]);

return (
<HotkeysProvider initiallyActiveScopes={['*']}>
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-client/src/components/AppBackground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function AppBackground({
const transitions = useTransition(loadingText, {
from: { opacity: 0, transform: 'translateY(-100px)' },
enter: { opacity: 1, transform: 'translateY(0)' },
leave: { opacity: 0, transform: 'translateY(-100px)' },
leave: { opacity: 0, transform: 'translateY(100px)' },
unique: true,
});

Expand Down
56 changes: 29 additions & 27 deletions packages/desktop-client/src/components/manager/BudgetList.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import React, { useState, useRef } from 'react';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';

import * as actions from 'loot-core/src/client/actions';
import {
createBudget,
downloadBudget,
getUserData,
loadAllFiles,
loadBudget,
pushModal,
} from 'loot-core/client/actions';
import { isNonProductionEnvironment } from 'loot-core/src/shared/environment';

import { useActions } from '../../hooks/useActions';
import { AnimatedLoading } from '../../icons/AnimatedLoading';
import {
SvgCloudCheck,
Expand All @@ -13,6 +19,7 @@ import {
SvgFileDouble,
} from '../../icons/v1';
import { SvgCloudUnknown, SvgKey, SvgRefreshArrow } from '../../icons/v2';
import { useResponsive } from '../../ResponsiveProvider';
import { styles, theme } from '../../style';
import { tokens } from '../../tokens';
import { Button } from '../common/Button';
Expand Down Expand Up @@ -247,22 +254,19 @@ function RefreshButton({ onRefresh }) {

export function BudgetList() {
const files = useSelector(state => state.budgets.allFiles || []);

const {
getUserData,
loadAllFiles,
pushModal,
loadBudget,
createBudget,
downloadBudget,
} = useActions();

const dispatch = useDispatch();
const [creating, setCreating] = useState(false);
const { isNarrowWidth } = useResponsive();
const narrowButtonStyle = isNarrowWidth
? {
height: styles.mobileMinHeight,
}
: {};

const onCreate = ({ testMode } = {}) => {
if (!creating) {
setCreating(true);
createBudget({ testMode });
dispatch(createBudget({ testMode }));
}
};

Expand Down Expand Up @@ -294,47 +298,45 @@ export function BudgetList() {
>
<RefreshButton
onRefresh={() => {
getUserData();
loadAllFiles();
dispatch(getUserData());
dispatch(loadAllFiles());
}}
/>
</View>
</View>
<BudgetTable
files={files}
actions={actions}
onSelect={file => {
if (file.state === 'remote') {
downloadBudget(file.cloudFileId);
dispatch(downloadBudget(file.cloudFileId));
} else {
loadBudget(file.id);
dispatch(loadBudget(file.id, `Loading ${file.name}...`));
}
}}
onDelete={file => pushModal('delete-budget', { file })}
onDelete={file => dispatch(pushModal('delete-budget', { file }))}
/>
<View
style={{
flexDirection: 'row',
justifyContent: 'flex-end',
padding: 25,
paddingLeft: 5,
gap: 15,
}}
>
<Button
type="bare"
style={{
marginLeft: 10,
...narrowButtonStyle,
color: theme.pageTextLight,
}}
onClick={e => {
e.preventDefault();
pushModal('import');
onClick={() => {
dispatch(pushModal('import'));
}}
>
Import file
</Button>

<Button type="primary" onClick={onCreate} style={{ marginLeft: 15 }}>
<Button type="primary" onClick={onCreate} style={narrowButtonStyle}>
Create new file
</Button>

Expand All @@ -343,7 +345,7 @@ export function BudgetList() {
type="primary"
isSubmit={false}
onClick={() => onCreate({ testMode: true })}
style={{ marginLeft: 15 }}
style={narrowButtonStyle}
>
Create test file
</Button>
Expand Down
2 changes: 1 addition & 1 deletion packages/loot-core/src/types/file.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export type RemoteFile = {
cloudFileId: string;
groupId: string;
name: string;
enccryptKeyId?: string;
encryptKeyId?: string;
hasKey: boolean;
state: 'remote';
};
Expand Down
6 changes: 6 additions & 0 deletions upcoming-release-notes/2663.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [joel-jeremy]
---

Fix app loading screen not showing when opening a budget file.

0 comments on commit f8af8f9

Please sign in to comment.