Skip to content
Snippets Groups Projects
Unverified Commit aad609f4 authored by Matiss Janis Aboltins's avatar Matiss Janis Aboltins Committed by GitHub
Browse files

:sparkles: added loading descriptions and lazy-loaded module retries (#2639)

parent 7313cf72
No related branches found
No related tags found
No related merge requests found
......@@ -21,6 +21,7 @@
"@swc/plugin-react-remove-properties": "^1.5.108",
"@testing-library/react": "14.1.2",
"@testing-library/user-event": "14.5.2",
"@types/promise-retry": "^1.1.6",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.1",
"@types/react-modal": "^3.16.0",
......@@ -43,6 +44,7 @@
"mdast-util-newline-to-break": "^2.0.0",
"memoize-one": "^6.0.0",
"pikaday": "1.8.2",
"promise-retry": "^2.0.1",
"react": "18.2.0",
"react-aria-components": "^1.1.1",
"react-dnd": "^16.0.1",
......
......@@ -38,24 +38,32 @@ type AppInnerProps = {
function AppInner({ budgetId, cloudFileId }: AppInnerProps) {
const [initializing, setInitializing] = useState(true);
const { showBoundary: showErrorBoundary } = useErrorBoundary();
const loadingText = useSelector((state: State) => state.app.loadingText);
const stateLoadingText = useSelector((state: State) => state.app.loadingText);
const [loadingText = stateLoadingText, setLoadingText] = useState<
string | null
>(null);
const { loadBudget, closeBudget, loadGlobalPrefs } = useActions();
async function init() {
const socketName = await global.Actual.getServerSocket();
setLoadingText('Initializing the connection to the local database...');
await initConnection(socketName);
// Load any global prefs
setLoadingText('Loading global preferences...');
await loadGlobalPrefs();
// Open the last opened budget, if any
setLoadingText('Opening last budget...');
const budgetId = await send('get-last-opened-backup');
if (budgetId) {
setLoadingText('Loading the last budget file...');
await loadBudget(budgetId);
// 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...');
send('get-remote-files').then(files => {
if (files) {
const remoteFile = files.find(f => f.fileId === cloudFileId);
......@@ -71,6 +79,7 @@ function AppInner({ budgetId, cloudFileId }: AppInnerProps) {
async function initAll() {
await Promise.all([installPolyfills(), init()]);
setInitializing(false);
setLoadingText(null);
}
initAll().catch(showErrorBoundary);
......
import React from 'react';
import { useTransition, animated } from 'react-spring';
import { css } from 'glamor';
......@@ -18,29 +19,39 @@ export function AppBackground({
initializing,
loadingText,
}: AppBackgroundProps) {
const transitions = useTransition(loadingText, {
from: { opacity: 0, transform: 'translateY(-100px)' },
enter: { opacity: 1, transform: 'translateY(0)' },
leave: { opacity: 0, transform: 'translateY(-100px)' },
unique: true,
});
return (
<>
<Background />
{(loadingText != null || initializing) && (
<View
className={`${css({
position: 'absolute',
top: 0,
left: 0,
right: 0,
padding: 50,
paddingTop: 200,
color: theme.pageText,
alignItems: 'center',
})}`}
>
<Block style={{ marginBottom: 20, fontSize: 18 }}>
{loadingText}
</Block>
<AnimatedLoading width={25} color={theme.pageText} />
</View>
)}
{(loadingText != null || initializing) &&
transitions((style, item) => (
<animated.div key={item} style={style}>
<View
className={`${css({
position: 'absolute',
top: 0,
left: 0,
right: 0,
padding: 50,
paddingTop: 200,
color: theme.pageText,
alignItems: 'center',
})}`}
>
<Block style={{ marginBottom: 20, fontSize: 18 }}>
{loadingText}
</Block>
<AnimatedLoading width={25} color={theme.pageText} />
</View>
</animated.div>
))}
</>
);
}
import { type ComponentType, useEffect, useState } from 'react';
import promiseRetry from 'promise-retry';
import { AnimatedLoading } from '../../icons/AnimatedLoading';
import { theme, styles } from '../../style';
import { Block } from '../common/Block';
......@@ -23,10 +25,29 @@ function LoadComponentInner<K extends string>({
importer,
}: LoadComponentProps<K>) {
const [Component, setComponent] = useState<ProplessComponent | null>(null);
const [failedToLoad, setFailedToLoad] = useState(false);
useEffect(() => {
importer().then(module => setComponent(() => module[name]));
setFailedToLoad(false);
// Load the module; if it fails - retry with exponential backoff
promiseRetry(
retry =>
importer()
.then(module => setComponent(() => module[name]))
.catch(retry),
{
retries: 5,
},
).catch(() => {
setFailedToLoad(true);
});
}, [name, importer]);
if (failedToLoad) {
throw new Error(`Failed loading the ${name} lazy module.`);
}
if (!Component) {
return (
<View
......@@ -46,8 +67,5 @@ function LoadComponentInner<K extends string>({
);
}
// console.log(
// `rendering <${Component.displayName || Component.name} /> as ${name}`,
// );
return <Component />;
}
---
category: Enhancements
authors: [MatissJanis]
---
Added app-loading stage description texts; also added exponential backoff in case a lazy-loaded module fails loading
......@@ -73,6 +73,7 @@ __metadata:
"@swc/plugin-react-remove-properties": "npm:^1.5.108"
"@testing-library/react": "npm:14.1.2"
"@testing-library/user-event": "npm:14.5.2"
"@types/promise-retry": "npm:^1.1.6"
"@types/react": "npm:^18.2.0"
"@types/react-dom": "npm:^18.2.1"
"@types/react-modal": "npm:^3.16.0"
......@@ -95,6 +96,7 @@ __metadata:
mdast-util-newline-to-break: "npm:^2.0.0"
memoize-one: "npm:^6.0.0"
pikaday: "npm:1.8.2"
promise-retry: "npm:^2.0.1"
react: "npm:18.2.0"
react-aria-components: "npm:^1.1.1"
react-dnd: "npm:^16.0.1"
......@@ -5524,6 +5526,15 @@ __metadata:
languageName: node
linkType: hard
 
"@types/promise-retry@npm:^1.1.6":
version: 1.1.6
resolution: "@types/promise-retry@npm:1.1.6"
dependencies:
"@types/retry": "npm:*"
checksum: 8834adbc77399329fafa4e07ada57fc49007802f81af42cd74b2c51e89a3cdd9aa4c09a05e3909aaea9d165bd2ff940ed309db21c21c373104e479b11e24435c
languageName: node
linkType: hard
"@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0":
version: 15.7.5
resolution: "@types/prop-types@npm:15.7.5"
......@@ -5590,6 +5601,13 @@ __metadata:
languageName: node
linkType: hard
 
"@types/retry@npm:*":
version: 0.12.5
resolution: "@types/retry@npm:0.12.5"
checksum: 3fb6bf91835ca0eb2987567d6977585235a7567f8aeb38b34a8bb7bbee57ac050ed6f04b9998cda29701b8c893f5dfe315869bc54ac17e536c9235637fe351a2
languageName: node
linkType: hard
"@types/scheduler@npm:*":
version: 0.16.3
resolution: "@types/scheduler@npm:0.16.3"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment