Skip to content

Commit

Permalink
Merge pull request Expensify#48772 from nkdengineer/feature/46611
Browse files Browse the repository at this point in the history
Feature: add loading indicator when ReconnectApp is running
  • Loading branch information
srikarparsi authored Nov 5, 2024
2 parents a42f0f3 + 31335cf commit 596671b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ const CONST = {
ANIMATED_HIGHLIGHT_END_DURATION: 2000,
ANIMATED_TRANSITION: 300,
ANIMATED_TRANSITION_FROM_VALUE: 100,
ANIMATED_PROGRESS_BAR_DELAY: 300,
ANIMATED_PROGRESS_BAR_OPACITY_DURATION: 300,
ANIMATED_PROGRESS_BAR_DURATION: 750,
ANIMATION_IN_TIMING: 100,
ANIMATION_DIRECTION: {
IN: 'in',
Expand Down
85 changes: 85 additions & 0 deletions src/components/LoadingBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React, {useEffect} from 'react';
import Animated, {cancelAnimation, Easing, runOnJS, useAnimatedStyle, useSharedValue, withDelay, withRepeat, withSequence, withTiming} from 'react-native-reanimated';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';

type LoadingBarProps = {
// Whether or not to show the loading bar
shouldShow: boolean;
};

function LoadingBar({shouldShow}: LoadingBarProps) {
const left = useSharedValue(0);
const width = useSharedValue(0);
const opacity = useSharedValue(0);
const isVisible = useSharedValue(false);
const styles = useThemeStyles();

useEffect(() => {
if (shouldShow) {
// eslint-disable-next-line react-compiler/react-compiler
isVisible.value = true;
left.value = 0;
width.value = 0;
opacity.value = withTiming(1, {duration: CONST.ANIMATED_PROGRESS_BAR_OPACITY_DURATION});
left.value = withDelay(
CONST.ANIMATED_PROGRESS_BAR_DELAY,
withRepeat(
withSequence(
withTiming(0, {duration: 0}),
withTiming(0, {duration: CONST.ANIMATED_PROGRESS_BAR_DURATION, easing: Easing.bezier(0.65, 0, 0.35, 1)}),
withTiming(100, {duration: CONST.ANIMATED_PROGRESS_BAR_DURATION, easing: Easing.bezier(0.65, 0, 0.35, 1)}),
),
-1,
false,
),
);

width.value = withDelay(
CONST.ANIMATED_PROGRESS_BAR_DELAY,
withRepeat(
withSequence(
withTiming(0, {duration: 0}),
withTiming(100, {duration: CONST.ANIMATED_PROGRESS_BAR_DURATION, easing: Easing.bezier(0.65, 0, 0.35, 1)}),
withTiming(0, {duration: CONST.ANIMATED_PROGRESS_BAR_DURATION, easing: Easing.bezier(0.65, 0, 0.35, 1)}),
),
-1,
false,
),
);
} else if (isVisible.value) {
opacity.value = withTiming(0, {duration: CONST.ANIMATED_PROGRESS_BAR_OPACITY_DURATION}, () => {
runOnJS(() => {
isVisible.value = false;
cancelAnimation(left);
cancelAnimation(width);
});
});
}
// we want to update only when shouldShow changes
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
}, [shouldShow]);

const animatedIndicatorStyle = useAnimatedStyle(() => {
return {
left: `${left.value}%`,
width: `${width.value}%`,
};
});

const animatedContainerStyle = useAnimatedStyle(() => {
return {
opacity: opacity.value,
};
});

return (
<Animated.View style={[styles.progressBarWrapper, animatedContainerStyle]}>
{isVisible.value ? <Animated.View style={[styles.progressBar, animatedIndicatorStyle]} /> : null}
</Animated.View>
);
}

LoadingBar.displayName = 'ProgressBar';

export default LoadingBar;
3 changes: 3 additions & 0 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {useOnyx} from 'react-native-onyx';
import Banner from '@components/Banner';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import DragAndDropProvider from '@components/DragAndDrop/Provider';
import LoadingBar from '@components/LoadingBar';
import MoneyReportHeader from '@components/MoneyReportHeader';
import MoneyRequestHeader from '@components/MoneyRequestHeader';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
Expand Down Expand Up @@ -129,6 +130,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro
const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP);
const [workspaceTooltip] = useOnyx(ONYXKEYS.NVP_WORKSPACE_TOOLTIP);
const wasLoadingApp = usePrevious(isLoadingApp);
const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA, {initialValue: true});
const finishedLoadingApp = wasLoadingApp && !isLoadingApp;
const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(parentReportAction);
const prevIsDeletedParentAction = usePrevious(isDeletedParentAction);
Expand Down Expand Up @@ -756,6 +758,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro
needsOffscreenAlphaCompositing
>
{headerView}
{shouldUseNarrowLayout && !!isLoadingReportData && <LoadingBar shouldShow={!!isLoadingReportData} />}
{!!report && ReportUtils.isTaskReport(report) && shouldUseNarrowLayout && ReportUtils.isOpenTaskReport(report, parentReportAction) && (
<View style={[styles.borderBottom]}>
<View style={[styles.appBG, styles.pl0]}>
Expand Down
4 changes: 4 additions & 0 deletions src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {useEffect} from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import LoadingBar from '@components/LoadingBar';
import ScreenWrapper from '@components/ScreenWrapper';
import useActiveWorkspaceFromNavigationState from '@hooks/useActiveWorkspaceFromNavigationState';
import useLocalize from '@hooks/useLocalize';
Expand Down Expand Up @@ -31,6 +32,8 @@ function BaseSidebarScreen() {
const {shouldUseNarrowLayout} = useResponsiveLayout();
const [activeWorkspace] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activeWorkspaceID ?? -1}`);

const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA, {initialValue: true});

useEffect(() => {
Performance.markStart(CONST.TIMING.SIDEBAR_LOADED);
Timing.start(CONST.TIMING.SIDEBAR_LOADED);
Expand Down Expand Up @@ -62,6 +65,7 @@ function BaseSidebarScreen() {
activeWorkspaceID={activeWorkspaceID}
shouldDisplaySearch={shouldDisplaySearch}
/>
<LoadingBar shouldShow={isLoadingReportData ?? false} />
<View style={[styles.flex1]}>
<SidebarLinksData
onLinkClick={startTimer}
Expand Down
14 changes: 14 additions & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5307,6 +5307,20 @@ const styles = (theme: ThemeColors) =>
left: 12,
},

progressBarWrapper: {
height: 2,
width: '100%',
backgroundColor: theme.border,
borderRadius: 5,
overflow: 'hidden',
},

progressBar: {
height: '100%',
backgroundColor: theme.success,
width: '100%',
},

qbdSetupLinkBox: {
backgroundColor: theme.hoverComponentBG,
borderRadius: variables.componentBorderRadiusMedium,
Expand Down

0 comments on commit 596671b

Please sign in to comment.