diff options
Diffstat (limited to 'packages/instant/src/components')
-rw-r--r-- | packages/instant/src/components/simulated_progress_bar.tsx | 194 | ||||
-rw-r--r-- | packages/instant/src/components/timed_progress_bar.tsx | 9 |
2 files changed, 5 insertions, 198 deletions
diff --git a/packages/instant/src/components/simulated_progress_bar.tsx b/packages/instant/src/components/simulated_progress_bar.tsx deleted file mode 100644 index 067f4093e..000000000 --- a/packages/instant/src/components/simulated_progress_bar.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; - -import { PROGRESS_STALL_AT_PERCENTAGE, PROGRESS_TICK_INTERVAL_MS } from '../constants'; -import { ColorOption, styled } from '../style/theme'; -import { timeUtil } from '../util/time'; - -import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text } from './ui/text'; - -const TICKS_PER_SECOND = 1000 / PROGRESS_TICK_INTERVAL_MS; - -const curTimeUnix = () => { - return new Date().getTime(); -}; - -export interface SimulatedProgressBarProps { - startTimeUnix: number; - expectedEndTimeUnix: number; - ended: boolean; -} -enum TickingRunState { - None = 'None', - Running = 'Running', - Finishing = 'Finishing', -} -interface TickingNoneStatus { - runState: TickingRunState.None; -} -interface TickingRunningStatus { - runState: TickingRunState.Running; -} -interface TickingFinishingStatus { - runState: TickingRunState.Finishing; - increasePercentageEveryTick: number; -} -type TickingStatus = TickingNoneStatus | TickingRunningStatus | TickingFinishingStatus; - -export interface SimulatedProgressState { - percentageDone: number; - intervalId?: number; - tickingStatus: TickingStatus; - elapsedTimeMs: number; -} -export class SimulatedProgressBar extends React.Component<SimulatedProgressBarProps, SimulatedProgressState> { - public constructor(props: SimulatedProgressBarProps) { - super(props); - - // TODO: look into using assert library here? - if (props.expectedEndTimeUnix <= props.startTimeUnix) { - throw new Error('End time before start time'); - } - - // TODO: use getFreshState here - const intervalId = window.setInterval(this._tick.bind(this), PROGRESS_TICK_INTERVAL_MS); - this.state = { - percentageDone: 0, - intervalId, - tickingStatus: { runState: TickingRunState.Running }, - elapsedTimeMs: 0, - }; - } - - public componentDidUpdate(prevProps: SimulatedProgressBarProps, prevState: SimulatedProgressState): void { - const percentLeft = 100 - this.state.percentageDone; - const increasePercentageEveryTick = percentLeft / TICKS_PER_SECOND; - - // if we just switched to ending, having animate to end - if (prevProps.ended === false && this.props.ended === true) { - this.setState({ - tickingStatus: { - runState: TickingRunState.Finishing, - increasePercentageEveryTick, - }, - }); - return; - } - - // later TODO: the new state could be for the wrong order, attach to order state or add concurrency checking - - // if anything else changes, reset internal state - if ( - prevProps.startTimeUnix !== this.props.startTimeUnix || - prevProps.expectedEndTimeUnix !== this.props.expectedEndTimeUnix || - prevProps.ended !== this.props.ended - ) { - this.setState(this._getFreshState()); - } - } - - public componentWillUnmount(): void { - console.log('unmount'); - this._clearTimer(); - } - - public render(): React.ReactNode { - // TODO: Consider moving to seperate component - - const estimatedTimeSeconds = Math.ceil((this.props.expectedEndTimeUnix - this.props.startTimeUnix) / 1000); - const elapsedTimeSeconds = Math.floor(this.state.elapsedTimeMs / 1000); - return ( - <Container padding="20px 20px 0px 20px" width="100%"> - <Container marginBottom="5px"> - {/* TODO: consider moving to separate component */} - <Flex justify="space-between"> - <Text>Est. Time ({timeUtil.secondsToHumanDescription(estimatedTimeSeconds)})</Text> - <Text>Time: {timeUtil.secondsToStopwatchTime(elapsedTimeSeconds)}</Text> - </Flex> - </Container> - <Container width="100%" backgroundColor={ColorOption.lightGrey} borderRadius="6px"> - <InnerProgressBarElement - percentageDone={this.state.percentageDone} - backgroundColor={ColorOption.primaryColor} - borderRadius="6px" - height="6px" - transitionTimeMs={200} - /> - </Container> - </Container> - ); - } - - private _getFreshState(): SimulatedProgressState { - this._clearTimer(); - const intervalId = window.setInterval(this._tick.bind(this), PROGRESS_TICK_INTERVAL_MS); - return { - percentageDone: 0, - intervalId, - tickingStatus: { runState: TickingRunState.Running }, - elapsedTimeMs: 0, - }; - } - - private _tick(): void { - const rawPercentageDone = - this.state.tickingStatus.runState === TickingRunState.Finishing - ? this._getNewPercentageFinishing(this.state.tickingStatus) - : this._getNewPercentageNormal(); - const maxPercentage = - this.state.tickingStatus.runState === TickingRunState.Finishing ? 100 : PROGRESS_STALL_AT_PERCENTAGE; - const percentageDone = Math.min(rawPercentageDone, maxPercentage); - - const elapsedTimeMs = Math.max(curTimeUnix() - this.props.startTimeUnix, 0); - - this.setState({ - percentageDone, - elapsedTimeMs, - }); - - if (percentageDone >= 100) { - this._clearTimer(); - } - } - - private _clearTimer(): void { - if (this.state.intervalId) { - window.clearTimeout(this.state.intervalId); - } - } - - // TODO: consider not taking in a parameter here, might be confusing - private _getNewPercentageFinishing(tickingStatus: TickingFinishingStatus): number { - return this.state.percentageDone + tickingStatus.increasePercentageEveryTick; - } - - private _getNewPercentageNormal(): number { - const elapsedTimeMs = curTimeUnix() - this.props.startTimeUnix; - const safeElapsedTimeMs = Math.max(elapsedTimeMs, 1); - - const expectedAmountOfTimeMs = this.props.expectedEndTimeUnix - this.props.startTimeUnix; - const percentageDone = safeElapsedTimeMs / expectedAmountOfTimeMs * 100; - return percentageDone; - } -} - -interface InnerProgressBarElementProps { - percentageDone: number; - backgroundColor: ColorOption; - borderRadius: string; - height: string; - transitionTimeMs: number; -} - -export const InnerProgressBarElement = - styled.div < - InnerProgressBarElementProps > - ` - width: ${props => props.percentageDone}%; - background-color: ${props => props.theme[props.backgroundColor]}; - border-radius: ${props => props.borderRadius}; - height: ${props => props.height}; - transition: width ${props => props.transitionTimeMs}ms ease-in-out; - `; diff --git a/packages/instant/src/components/timed_progress_bar.tsx b/packages/instant/src/components/timed_progress_bar.tsx index 7fdfe1a25..a4bb2eabd 100644 --- a/packages/instant/src/components/timed_progress_bar.tsx +++ b/packages/instant/src/components/timed_progress_bar.tsx @@ -1,14 +1,10 @@ import * as _ from 'lodash'; import * as React from 'react'; -import { Keyframes } from 'styled-components'; import { PROGRESS_FINISH_ANIMATION_TIME_MS, PROGRESS_STALL_AT_PERCENTAGE } from '../constants'; import { ColorOption, keyframes, styled } from '../style/theme'; -import { timeUtil } from '../util/time'; import { Container } from './ui/container'; -import { Flex } from './ui/flex'; -import { Text } from './ui/text'; export interface TimedProgressBarProps { expectedTimeMs: number; @@ -29,6 +25,11 @@ export const beginningState = (props: TimedProgressBarProps): TimedProgressBarSt }; }; +/** + * Timed Progress Bar + * Goes from 0% -> PROGRESS_STALL_AT_PERCENTAGE% over time of expectedTimeMs + * When ended set to true, goes to 100% through animation of PROGRESS_FINISH_ANIMATION_TIME_MS length + */ export class TimedProgressBar extends React.Component<TimedProgressBarProps, TimedProgressBarState> { private readonly _barRef = React.createRef<HTMLDivElement>(); |