refactor: move Clock from class component to functional component (#31964)
This commit is contained in:
@@ -5,13 +5,16 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { type HTMLProps } from "react";
|
import React, { type JSX, type HTMLProps, useMemo } from "react";
|
||||||
import { Temporal } from "temporal-polyfill";
|
import { Temporal } from "temporal-polyfill";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import { formatSeconds } from "../../utils/DateUtils";
|
import { formatSeconds } from "../../utils/DateUtils";
|
||||||
|
|
||||||
export interface Props extends Pick<HTMLProps<HTMLSpanElement>, "aria-live" | "role" | "className"> {
|
export interface Props extends Pick<HTMLProps<HTMLSpanElement>, "aria-live" | "role" | "className"> {
|
||||||
|
/**
|
||||||
|
* The number of seconds to display.
|
||||||
|
*/
|
||||||
seconds: number;
|
seconds: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,33 +22,39 @@ export interface Props extends Pick<HTMLProps<HTMLSpanElement>, "aria-live" | "r
|
|||||||
* Clock which represents time periods rather than absolute time.
|
* Clock which represents time periods rather than absolute time.
|
||||||
* Simply converts seconds using formatSeconds().
|
* Simply converts seconds using formatSeconds().
|
||||||
* Note that in this case hours will not be displayed, making it possible to see "82:29".
|
* Note that in this case hours will not be displayed, making it possible to see "82:29".
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```tsx
|
||||||
|
* <Clock seconds={125} />
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
export class Clock extends React.Component<Props> {
|
export function Clock({ seconds, className, ...rest }: Props): JSX.Element {
|
||||||
public shouldComponentUpdate(nextProps: Readonly<Props>): boolean {
|
// Memoize current second to avoid recalculating the duration when seconds changes slightly (e.g. 1.2 -> 1.3)
|
||||||
const currentFloor = Math.floor(this.props.seconds);
|
const currentSecond = useMemo(() => Math.floor(seconds), [seconds]);
|
||||||
const nextFloor = Math.floor(nextProps.seconds);
|
const duration = useMemo(() => calculateDuration(currentSecond), [currentSecond]);
|
||||||
return currentFloor !== nextFloor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private calculateDuration(seconds: number): string | undefined {
|
return (
|
||||||
if (isNaN(seconds)) return undefined;
|
<time
|
||||||
return new Temporal.Duration(0, 0, 0, 0, 0, 0, Math.round(seconds))
|
dateTime={duration}
|
||||||
.round({ smallestUnit: "seconds", largestUnit: "hours" })
|
/* Keep class for backward compatibility with parent component */
|
||||||
.toString();
|
className={classNames("mx_Clock", className)}
|
||||||
}
|
{...rest}
|
||||||
|
>
|
||||||
|
{formatSeconds(seconds)}
|
||||||
|
</time>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
/**
|
||||||
const { seconds, role } = this.props;
|
* Calculates an ISO 8601 duration string from seconds.
|
||||||
return (
|
* @param seconds
|
||||||
<time
|
* @returns ISO 8601 duration string or undefined if input is NaN
|
||||||
dateTime={this.calculateDuration(seconds)}
|
*/
|
||||||
aria-live={this.props["aria-live"]}
|
function calculateDuration(seconds: number): string | undefined {
|
||||||
role={role}
|
// This shouldn't happen but it's in the original implementation
|
||||||
/* Keep class for backward compatibility with parent component */
|
if (isNaN(seconds)) return undefined;
|
||||||
className={classNames("mx_Clock", this.props.className)}
|
|
||||||
>
|
return new Temporal.Duration(0, 0, 0, 0, 0, 0, Math.round(seconds))
|
||||||
{formatSeconds(seconds)}
|
.round({ smallestUnit: "seconds", largestUnit: "hours" })
|
||||||
</time>
|
.toString();
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user