From d2739e2b4ab9b92a8498a7e5b8a8d38c9288cff0 Mon Sep 17 00:00:00 2001 From: jacob-xhio <163027616+jacob-xhio@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:31:00 -0700 Subject: [PATCH] New bindable `AppContainerModel.intializingLoadMaskMessage` (#3763) + Allow apps to customize the loading mask message shown during app initialization. --- CHANGELOG.md | 3 ++- appcontainer/AppContainerModel.ts | 9 ++++++++- desktop/appcontainer/AppContainer.ts | 8 +++++--- mobile/appcontainer/AppContainer.ts | 8 +++++--- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 012320f1f..4427b6937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,8 @@ * New property `FetchOptions.asJson` to instruct `FetchService` to decode an HTTP response as JSON. Note that `FetchService` methods suffixed with `Json` will set this property automatically. * `GridModel` will now accept `contextMenu: false` to omit context menus. -* Swapped locations of `primaryOnly` and `active` sliders in `MonitorEditorDialog`. +* New bindable `AppContainerModel.intializingLoadMaskMessage` property to allow apps to customize + the loading mask message shown during app initialization. ### 🐞 Bug Fixes diff --git a/appcontainer/AppContainerModel.ts b/appcontainer/AppContainerModel.ts index 30006a544..c895aeb19 100644 --- a/appcontainer/AppContainerModel.ts +++ b/appcontainer/AppContainerModel.ts @@ -16,9 +16,10 @@ import { XH } from '@xh/hoist/core'; import {Icon} from '@xh/hoist/icon'; -import {action, when as mobxWhen} from '@xh/hoist/mobx'; +import {action, bindable, when as mobxWhen} from '@xh/hoist/mobx'; import {never, wait} from '@xh/hoist/promise'; import numbro from 'numbro'; +import {ReactNode} from 'react'; import {createRoot} from 'react-dom/client'; import { AlertBannerService, @@ -97,6 +98,12 @@ export class AppContainerModel extends HoistModel { @managed themeModel = new ThemeModel(); @managed userAgentModel = new UserAgentModel(); + /** + * Message shown on spinner while the application is in the INITIALIZING state. + * Update within `AppModel.initAsync()` to relay app-specific initialization status. + */ + @bindable initializingLoadMaskMessage: ReactNode; + /** * Main entry point. Initialize and render application code. */ diff --git a/desktop/appcontainer/AppContainer.ts b/desktop/appcontainer/AppContainer.ts index 67f0ef326..c687e3e2e 100644 --- a/desktop/appcontainer/AppContainer.ts +++ b/desktop/appcontainer/AppContainer.ts @@ -87,7 +87,7 @@ export const AppContainer = hoistCmp({ }, errorRenderer: () => null }, - item: viewForState() + item: viewForState({model}) }), // Modal component helpers rendered here at top-level to support display of messages // and exceptions at any point during the app lifecycle. @@ -101,11 +101,13 @@ export const AppContainer = hoistCmp({ //----------------------------------------- // Implementation //----------------------------------------- -function viewForState() { +function viewForState({model}) { switch (XH.appState) { case 'PRE_AUTH': case 'INITIALIZING': - return viewport(mask({spinner: true, isDisplayed: true})); + return viewport( + mask({spinner: true, isDisplayed: true, message: model.initializingLoadMaskMessage}) + ); case 'LOGIN_REQUIRED': return loginPanel(); case 'ACCESS_DENIED': diff --git a/mobile/appcontainer/AppContainer.ts b/mobile/appcontainer/AppContainer.ts index 928c944a1..80e223ac1 100644 --- a/mobile/appcontainer/AppContainer.ts +++ b/mobile/appcontainer/AppContainer.ts @@ -72,7 +72,7 @@ export const AppContainer = hoistCmp({ }, errorRenderer: () => null }, - item: viewForState() + item: viewForState({model}) }), // Modal component helpers rendered here at top-level to support display of messages // and exceptions at any point during the app lifecycle. @@ -86,11 +86,13 @@ export const AppContainer = hoistCmp({ //------------------- // Implementation //------------------- -function viewForState() { +function viewForState({model}) { switch (XH.appState) { case 'PRE_AUTH': case 'INITIALIZING': - return viewport(mask({spinner: true, isDisplayed: true})); + return viewport( + mask({spinner: true, isDisplayed: true, message: model.initializingLoadMaskMessage}) + ); case 'LOGIN_REQUIRED': return loginPanel(); case 'ACCESS_DENIED':