diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index 2fa4a805e2..f4035de695 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -15,6 +15,7 @@ dependencies { implementation project(':capacitor-keyboard') implementation project(':capacitor-share') implementation project(':capacitor-status-bar') + implementation project(':capacitor-android-nav-mode') implementation project(':capacitor-application-context') implementation project(':capacitor-plugin-safe-area') implementation project(':capacitor-stash-media') diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index 5332cc0f6c..8e6511b596 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -20,6 +20,9 @@ project(':capacitor-share').projectDir = new File('../node_modules/.pnpm/@capaci include ':capacitor-status-bar' project(':capacitor-status-bar').projectDir = new File('../node_modules/.pnpm/@capacitor+status-bar@5.0.6_@capacitor+core@5.2.2/node_modules/@capacitor/status-bar/android') +include ':capacitor-android-nav-mode' +project(':capacitor-android-nav-mode').projectDir = new File('../node_modules/.pnpm/capacitor-android-nav-mode@0.0.1_@capacitor+core@5.2.2/node_modules/capacitor-android-nav-mode/android') + include ':capacitor-application-context' project(':capacitor-application-context').projectDir = new File('../node_modules/.pnpm/capacitor-application-context@0.0.1_@capacitor+core@5.2.2/node_modules/capacitor-application-context/android') diff --git a/ios/App/Podfile b/ios/App/Podfile index ccb7eee019..c45f9109c1 100644 --- a/ios/App/Podfile +++ b/ios/App/Podfile @@ -17,6 +17,7 @@ def capacitor_pods pod 'CapacitorKeyboard', :path => '../../node_modules/.pnpm/@capacitor+keyboard@5.0.6_@capacitor+core@5.2.2/node_modules/@capacitor/keyboard' pod 'CapacitorShare', :path => '../../node_modules/.pnpm/@capacitor+share@5.0.6_@capacitor+core@5.2.2/node_modules/@capacitor/share' pod 'CapacitorStatusBar', :path => '../../node_modules/.pnpm/@capacitor+status-bar@5.0.6_@capacitor+core@5.2.2/node_modules/@capacitor/status-bar' + pod 'CapacitorAndroidNavMode', :path => '../../node_modules/.pnpm/capacitor-android-nav-mode@0.0.1_@capacitor+core@5.2.2/node_modules/capacitor-android-nav-mode' pod 'CapacitorApplicationContext', :path => '../../node_modules/.pnpm/capacitor-application-context@0.0.1_@capacitor+core@5.2.2/node_modules/capacitor-application-context' pod 'CapacitorPluginSafeArea', :path => '../../node_modules/.pnpm/capacitor-plugin-safe-area@2.0.5_@capacitor+core@5.2.2/node_modules/capacitor-plugin-safe-area' pod 'CapacitorStashMedia', :path => '../../node_modules/.pnpm/capacitor-stash-media@0.0.3_@capacitor+core@5.2.2/node_modules/capacitor-stash-media' diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock index ff0f97773f..c84a926f7e 100644 --- a/ios/App/Podfile.lock +++ b/ios/App/Podfile.lock @@ -1,6 +1,8 @@ PODS: - Capacitor (5.2.2): - CapacitorCordova + - CapacitorAndroidNavMode (0.0.1): + - Capacitor - CapacitorApp (5.0.6): - Capacitor - CapacitorApplicationContext (0.0.1): @@ -27,6 +29,7 @@ PODS: DEPENDENCIES: - "Capacitor (from `../../node_modules/.pnpm/@capacitor+ios@5.2.2_@capacitor+core@5.2.2/node_modules/@capacitor/ios`)" + - "CapacitorAndroidNavMode (from `../../node_modules/.pnpm/capacitor-android-nav-mode@0.0.1_@capacitor+core@5.2.2/node_modules/capacitor-android-nav-mode`)" - "CapacitorApp (from `../../node_modules/.pnpm/@capacitor+app@5.0.6_@capacitor+core@5.2.2/node_modules/@capacitor/app`)" - "CapacitorApplicationContext (from `../../node_modules/.pnpm/capacitor-application-context@0.0.1_@capacitor+core@5.2.2/node_modules/capacitor-application-context`)" - "CapacitorBrowser (from `../../node_modules/.pnpm/@capacitor+browser@5.0.6_@capacitor+core@5.2.2/node_modules/@capacitor/browser`)" @@ -45,6 +48,8 @@ SPEC REPOS: EXTERNAL SOURCES: Capacitor: :path: "../../node_modules/.pnpm/@capacitor+ios@5.2.2_@capacitor+core@5.2.2/node_modules/@capacitor/ios" + CapacitorAndroidNavMode: + :path: "../../node_modules/.pnpm/capacitor-android-nav-mode@0.0.1_@capacitor+core@5.2.2/node_modules/capacitor-android-nav-mode" CapacitorApp: :path: "../../node_modules/.pnpm/@capacitor+app@5.0.6_@capacitor+core@5.2.2/node_modules/@capacitor/app" CapacitorApplicationContext: @@ -68,6 +73,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Capacitor: 070b18988e0f566728ae9a5eb3a7a974595f1626 + CapacitorAndroidNavMode: b7bc1b2505e8991bb71999565b9ef3124a42e414 CapacitorApp: 024e1b1bea5f883d79f6330d309bc441c88ad04a CapacitorApplicationContext: 487dced4aebde33c94a3bf8fd0e519ab59a17eb8 CapacitorBrowser: 6192948e0ce804fd72aaf77f4114a3ad2e08c760 @@ -80,6 +86,6 @@ SPEC CHECKSUMS: CapacitorStatusBar: 565c0a1ebd79bb40d797606a8992b4a105885309 SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9 -PODFILE CHECKSUM: 64aed244866097bf21833d6fbb682b5d31e29b18 +PODFILE CHECKSUM: b8e7c3f88041ca6d3a54b6d338c63b3d039cf987 COCOAPODS: 1.12.1 diff --git a/package.json b/package.json index 800c9d7e03..18a4c29ed2 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@typescript-eslint/parser": "^5.60.0", "@vitejs/plugin-legacy": "^4.0.5", "@vitejs/plugin-react": "^4.0.1", + "capacitor-android-nav-mode": "^0.0.1", "capacitor-application-context": "^0.0.1", "capacitor-plugin-safe-area": "^2.0.5", "capacitor-set-version": "^2.0.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index adf1753c4a..c2cb8f64b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -139,6 +139,9 @@ devDependencies: '@vitejs/plugin-react': specifier: ^4.0.1 version: 4.0.1(vite@4.3.9) + capacitor-android-nav-mode: + specifier: ^0.0.1 + version: 0.0.1(@capacitor/core@5.2.2) capacitor-application-context: specifier: ^0.0.1 version: 0.0.1(@capacitor/core@5.2.2) @@ -5276,6 +5279,14 @@ packages: resolution: {integrity: sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==} dev: true + /capacitor-android-nav-mode@0.0.1(@capacitor/core@5.2.2): + resolution: {integrity: sha512-cnEk7CqDCjNokhDr/DTY/w/qgZqUr/+tTqavjl5PIBCXNkqUCHAP/nBFebZN5wZfAwD9WaXJp67Q1MtfaQNpVw==} + peerDependencies: + '@capacitor/core': ^5.0.0 + dependencies: + '@capacitor/core': 5.2.2 + dev: true + /capacitor-application-context@0.0.1(@capacitor/core@5.2.2): resolution: {integrity: sha512-XYHvn01l3VxbGh/fs77aBTyEW54TOoEDlXYkAEeRe7PQCwU8EfVCX5MLvuWVCoIzpRlEWYNCFCS1TvLkmV7IsQ==} peerDependencies: diff --git a/src/App.tsx b/src/App.tsx index d24e38c05a..d01b9940ff 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,7 +17,12 @@ import "@ionic/react/css/flex-utils.css"; import "@ionic/react/css/display.css"; import { StoreProvider } from "./store"; -import { isAndroid, isInstalled, isNative } from "./helpers/device"; +import { + getAndroidNavMode, + isAndroid, + isInstalled, + isNative, +} from "./helpers/device"; import TabbedRoutes from "./TabbedRoutes"; import Auth from "./Auth"; import { AppContextProvider } from "./features/auth/AppContext"; @@ -31,12 +36,26 @@ import { SafeArea, SafeAreaInsets } from "capacitor-plugin-safe-area"; import { StatusBar } from "@capacitor/status-bar"; import { Keyboard } from "@capacitor/keyboard"; import { TabContextProvider } from "./TabContext"; +import { NavModes } from "capacitor-android-nav-mode"; -setupIonicReact({ - rippleEffect: false, - mode: getDeviceMode(), - swipeBackEnabled: isInstalled() && getDeviceMode() === "ios", -}); +// index.tsx ensurxes android nav mode resolves before app is rendered +(async () => { + let navMode; + try { + navMode = await getAndroidNavMode(); + } catch (e) { + // ignore errors + } + + setupIonicReact({ + rippleEffect: false, + mode: getDeviceMode(), + swipeBackEnabled: + isInstalled() && + getDeviceMode() === "ios" && + navMode !== NavModes.Gesture, + }); +})(); // Android safe area inset management is bad, we have to do it manually if (isNative() && isAndroid()) { diff --git a/src/helpers/device.ts b/src/helpers/device.ts index 4c6a0d0b7e..7449c09749 100644 --- a/src/helpers/device.ts +++ b/src/helpers/device.ts @@ -1,5 +1,6 @@ import UAParser from "ua-parser-js"; import { Capacitor } from "@capacitor/core"; +import { NavMode, NavModes } from "capacitor-android-nav-mode"; export function isNative() { return Capacitor.isNativePlatform(); @@ -50,3 +51,14 @@ export function supportsWebp() { return name !== "iOS" || (version && +version >= 14); } + +export let androidNavMode: Promise | undefined; + +export function getAndroidNavMode() { + if (androidNavMode !== undefined) return androidNavMode; + if (!isAndroid() || !isNative()) return; + + const promise = NavMode.getNavigationMode().then(({ mode }) => mode); + androidNavMode = promise; + return promise; +} diff --git a/src/index.tsx b/src/index.tsx index 3f968c2e5d..a251b3b8a4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,15 +2,22 @@ import React from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; import "./index.css"; -import { isNative } from "./helpers/device"; +import { getAndroidNavMode, isNative } from "./helpers/device"; -const container = document.getElementById("root"); -const root = createRoot(container as HTMLElement); -root.render( - - - -); +(async () => { + try { + await getAndroidNavMode(); + } finally { + const container = document.getElementById("root"); + const root = createRoot(container as HTMLElement); + + root.render( + + + + ); + } +})(); (async () => { // Native apps should silently accept without user prompt