From 4eb3b61c7a12db69a0339ca63868ef9137424b9e Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 4 Jun 2022 09:06:07 -0700 Subject: [PATCH] fix: Lazily polyfill `ResizeObserver` for old iOS (#3629) * fix: Lazily polyfill ResizeObserver for old iOS * fix: Prevent child rendering until polyfills are loaded * tsc --- app/components/LazyPolyfills.tsx | 23 +++++++++++++++++++++++ app/index.tsx | 27 +++++++++++++++------------ app/utils/polyfills.ts | 31 +++++++++++++++++++++++++++++++ package.json | 1 + yarn.lock | 5 +++++ 5 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 app/components/LazyPolyfills.tsx create mode 100644 app/utils/polyfills.ts diff --git a/app/components/LazyPolyfills.tsx b/app/components/LazyPolyfills.tsx new file mode 100644 index 000000000..20601c96d --- /dev/null +++ b/app/components/LazyPolyfills.tsx @@ -0,0 +1,23 @@ +import * as React from "react"; +import { loadPolyfills } from "~/utils/polyfills"; + +/** + * Asyncronously load required polyfills. Should wrap the React tree. + */ +export const LazyPolyfill: React.FC = ({ children }) => { + const [isLoaded, setIsLoaded] = React.useState(false); + + React.useEffect(() => { + loadPolyfills().then(() => { + setIsLoaded(true); + }); + }, []); + + if (!isLoaded) { + return null; + } + + return <>{children}; +}; + +export default LazyPolyfill; diff --git a/app/index.tsx b/app/index.tsx index 8252a4c91..1a9ec09ac 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -15,6 +15,7 @@ import ScrollToTop from "~/components/ScrollToTop"; import Theme from "~/components/Theme"; import Toasts from "~/components/Toasts"; import env from "~/env"; +import LazyPolyfill from "./components/LazyPolyfills"; import Routes from "./routes"; import Logger from "./utils/Logger"; import history from "./utils/history"; @@ -75,18 +76,20 @@ if (element) { - - - <> - - - - - - - - - + + + + <> + + + + + + + + + + diff --git a/app/utils/polyfills.ts b/app/utils/polyfills.ts new file mode 100644 index 000000000..4607d7354 --- /dev/null +++ b/app/utils/polyfills.ts @@ -0,0 +1,31 @@ +/** + * Loads required polyfills. + * + * @returns A promise that resolves when all required polyfills are loaded + */ +export async function loadPolyfills() { + const polyfills = []; + + if (!supportsResizeObserver()) { + polyfills.push( + import("@juggle/resize-observer").then((module) => { + window.ResizeObserver = module.ResizeObserver; + }) + ); + } + + return Promise.all(polyfills); +} + +/** + * Detect ResizeObserver compatability. + * + * @returns true if the current browser supports ResizeObserver + */ +function supportsResizeObserver() { + return ( + "ResizeObserver" in global && + "ResizeObserverEntry" in global && + "contentRect" in ResizeObserverEntry.prototype + ); +} diff --git a/package.json b/package.json index 305ac434c..be2f2dd45 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "@hocuspocus/provider": "^1.0.0-alpha.36", "@hocuspocus/server": "^1.0.0-alpha.102", "@joplin/turndown-plugin-gfm": "^1.0.44", + "@juggle/resize-observer": "^3.3.1", "@outlinewiki/koa-passport": "^4.1.4", "@outlinewiki/passport-azure-ad-oauth2": "^0.1.0", "@renderlesskit/react": "^0.6.0", diff --git a/yarn.lock b/yarn.lock index dad388065..4020acc71 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1818,6 +1818,11 @@ resolved "https://registry.yarnpkg.com/@joplin/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.44.tgz#028e4c56bf58e57a4d0d923bb7d10a21c30d5c7d" integrity sha512-lpVI/fpj0CKzWzpsOxsmqwjWlIrw+IZlIEz3h8Vqoviz8dCYbqSSY/4VxpiUDmBpxX/3Xk73R5BfzqiAHBmYqA== +"@juggle/resize-observer@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.3.1.tgz#b50a781709c81e10701004214340f25475a171a0" + integrity sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw== + "@lifeomic/attempt@^3.0.2": version "3.0.3" resolved "https://registry.yarnpkg.com/@lifeomic/attempt/-/attempt-3.0.3.tgz#e742a5b85eb673e2f1746b0f39cb932cbc6145bb"