Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion src/features/shared/DynamicDismissableModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { noop } from "es-toolkit";
import React, { createContext, useEffect, useRef, useState } from "react";
import { Prompt, useLocation } from "react-router";

import { isNative } from "#/helpers/device";
import { isAndroid, isIosTheme, isNative } from "#/helpers/device";
import useStateRef from "#/helpers/useStateRef";
import { clearRecoveredText } from "#/helpers/useTextRecovery";
import { useAppDispatch } from "#/store";
Expand Down Expand Up @@ -153,6 +153,8 @@ export function DynamicDismissableModal({
setIsOpen(false);
setPresentingElement(undefined);

performAndroidModalBugWorkaroundIfNeeded();

// in case onDidDismiss incorrectly called by Ionic, don't clear data
if (textRecovery && canDismissRef_.current) clearRecoveredText();

Expand Down Expand Up @@ -189,3 +191,32 @@ export const DynamicDismissableModalContext = createContext<{
dismiss: () => void;
setCanDismiss: (canDismiss: boolean) => void;
}>({ dismiss: noop, setCanDismiss: noop });

/**
* Ionic and/or Android has an inconsistent bug
* specific to Android+iOS modal animations.
*
* On those devices, check if the transform failed
* to be applied, and if so, reset it manually.
*
* @see https://github.com/aeharding/voyager/issues/2183
*/
function performAndroidModalBugWorkaroundIfNeeded() {
if (!isAndroid()) return; // only Android is affected
if (!isIosTheme()) return; // only iOS theme is affected

queueMicrotask(() => {
const tabs = document.querySelector("ion-tabs")!;

// If the transform was successfully reset by Ionic, return
if (!tabs.style.transform) return;

tabs.style.transform = "";
tabs.style.overflow = "";

const app = document.querySelector("ion-app")!;
app.style.backgroundColor = "";

document.body.classList.remove("backdrop-no-scroll");
});
}