From daf66f33da6774876b95717fb272fe33c7b54cc8 Mon Sep 17 00:00:00 2001
From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
Date: Wed, 14 Dec 2022 15:59:09 -0800
Subject: [PATCH] Fix DisappearingTimerSelect on Windows
---
ts/components/DisappearingTimerSelect.tsx | 43 ++++++++++++++---------
ts/components/Select.tsx | 11 +++---
2 files changed, 33 insertions(+), 21 deletions(-)
diff --git a/ts/components/DisappearingTimerSelect.tsx b/ts/components/DisappearingTimerSelect.tsx
index 958579da019a..08711d987f54 100644
--- a/ts/components/DisappearingTimerSelect.tsx
+++ b/ts/components/DisappearingTimerSelect.tsx
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { ReactNode } from 'react';
-import React, { useState } from 'react';
+import React, { useCallback, useState, useMemo } from 'react';
import classNames from 'classnames';
import type { LocalizerType } from '../types/Util';
@@ -29,27 +29,36 @@ export function DisappearingTimerSelect(props: Props): JSX.Element {
let expirationTimerOptions: ReadonlyArray<{
readonly value: DurationInSeconds;
readonly text: string;
- }> = expirationTimer.DEFAULT_DURATIONS_IN_SECONDS.map(seconds => {
- const text = expirationTimer.format(i18n, seconds, {
- capitalizeOff: true,
+ }> = useMemo(() => {
+ return expirationTimer.DEFAULT_DURATIONS_IN_SECONDS.map(seconds => {
+ const text = expirationTimer.format(i18n, seconds, {
+ capitalizeOff: true,
+ });
+ return {
+ value: seconds,
+ text,
+ };
});
- return {
- value: seconds,
- text,
- };
- });
+ }, [i18n]);
const isCustomTimeSelected =
!expirationTimer.DEFAULT_DURATIONS_SET.has(value);
- const onSelectChange = (newValue: string) => {
- const intValue = DurationInSeconds.fromSeconds(parseInt(newValue, 10));
- if (intValue === -1) {
- setIsModalOpen(true);
- } else {
- onChange(intValue);
- }
- };
+ const onSelectChange = useCallback(
+ (newValue: string) => {
+ const intValue = DurationInSeconds.fromSeconds(parseInt(newValue, 10));
+ if (intValue === -1) {
+ // On Windows we get "change" event followed by "click" (even if
+ // the was selected with keyboard. This click unfortunately
+ // closes the modal so we need to delay opening it until after the
+ // "click" event.
+ setTimeout(() => setIsModalOpen(true), 0);
+ } else {
+ onChange(intValue);
+ }
+ },
+ [onChange]
+ );
// Custom time...
expirationTimerOptions = [
diff --git a/ts/components/Select.tsx b/ts/components/Select.tsx
index 5732a7918c27..aa79e40e67f4 100644
--- a/ts/components/Select.tsx
+++ b/ts/components/Select.tsx
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import type { ChangeEvent } from 'react';
-import React from 'react';
+import React, { useCallback } from 'react';
import classNames from 'classnames';
export type Option = Readonly<{
@@ -35,9 +35,12 @@ export const Select = React.forwardRef(function SelectInner(
}: PropsType,
ref: React.Ref
): JSX.Element {
- const onSelectChange = (event: ChangeEvent) => {
- onChange(event.target.value);
- };
+ const onSelectChange = useCallback(
+ (event: ChangeEvent) => {
+ onChange(event.target.value);
+ },
+ [onChange]
+ );
return (