On most browsers, pressing Enter to end IME composition produces this sequence of events: * keydown (keycode 229, key Processing/Unidentified, isComposing true) * compositionend * keyup (keycode 13, key Enter, isComposing false) On Safari, the sequence is different: * compositionend * keydown (keycode 229, key Enter, isComposing false) * keyup (keycode 13, key Enter, isComposing false) This causes Safari users to mistakenly send their messages when they press Enter to confirm their choice in an IME. The workaround is to treat the next keydown with keycode 229 as if it were part of the IME composition period if it occurs within a short time of the compositionend event. Fixes #2103, but needs confirmation from a Safari user.
56 lines
2.2 KiB
TypeScript
56 lines
2.2 KiB
TypeScript
import React from 'react';
|
|
import { Provider as JotaiProvider } from 'jotai';
|
|
import { OverlayContainerProvider, PopOutContainerProvider, TooltipContainerProvider } from 'folds';
|
|
import { RouterProvider } from 'react-router-dom';
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
|
|
|
import { ClientConfigLoader } from '../components/ClientConfigLoader';
|
|
import { ClientConfigProvider } from '../hooks/useClientConfig';
|
|
import { ConfigConfigError, ConfigConfigLoading } from './ConfigConfig';
|
|
import { FeatureCheck } from './FeatureCheck';
|
|
import { createRouter } from './Router';
|
|
import { ScreenSizeProvider, useScreenSize } from '../hooks/useScreenSize';
|
|
import { useCompositionEndTracking } from '../hooks/useComposingCheck';
|
|
|
|
const queryClient = new QueryClient();
|
|
|
|
function App() {
|
|
const screenSize = useScreenSize();
|
|
useCompositionEndTracking();
|
|
|
|
const portalContainer = document.getElementById('portalContainer') ?? undefined;
|
|
|
|
return (
|
|
<TooltipContainerProvider value={portalContainer}>
|
|
<PopOutContainerProvider value={portalContainer}>
|
|
<OverlayContainerProvider value={portalContainer}>
|
|
<ScreenSizeProvider value={screenSize}>
|
|
<FeatureCheck>
|
|
<ClientConfigLoader
|
|
fallback={() => <ConfigConfigLoading />}
|
|
error={(err, retry, ignore) => (
|
|
<ConfigConfigError error={err} retry={retry} ignore={ignore} />
|
|
)}
|
|
>
|
|
{(clientConfig) => (
|
|
<ClientConfigProvider value={clientConfig}>
|
|
<QueryClientProvider client={queryClient}>
|
|
<JotaiProvider>
|
|
<RouterProvider router={createRouter(clientConfig, screenSize)} />
|
|
</JotaiProvider>
|
|
<ReactQueryDevtools initialIsOpen={false} />
|
|
</QueryClientProvider>
|
|
</ClientConfigProvider>
|
|
)}
|
|
</ClientConfigLoader>
|
|
</FeatureCheck>
|
|
</ScreenSizeProvider>
|
|
</OverlayContainerProvider>
|
|
</PopOutContainerProvider>
|
|
</TooltipContainerProvider>
|
|
);
|
|
}
|
|
|
|
export default App;
|