diff --git a/app/README.md b/app/README.md index aa136f6ae..a90390bf3 100644 --- a/app/README.md +++ b/app/README.md @@ -67,6 +67,49 @@ const checkAppLaunchUrl = async () => { }; ``` +## Configuration + + + + +| Prop | Type | Description | Default | Since | +| ------------------------------ | -------------------- | ------------------------------------------------------------------------------ | ------------------ | ----- | +| **`disableBackButtonHandler`** | boolean | Disable the plugin's default back button handling. Only available for Android. | false | 7.1.0 | + +### Examples + +In `capacitor.config.json`: + +```json +{ + "plugins": { + "App": { + "disableBackButtonHandler": true + } + } +} +``` + +In `capacitor.config.ts`: + +```ts +/// + +import { CapacitorConfig } from '@capacitor/cli'; + +const config: CapacitorConfig = { + plugins: { + App: { + disableBackButtonHandler: true, + }, + }, +}; + +export default config; +``` + + + ## API @@ -76,6 +119,7 @@ const checkAppLaunchUrl = async () => { * [`getState()`](#getstate) * [`getLaunchUrl()`](#getlaunchurl) * [`minimizeApp()`](#minimizeapp) +* [`toggleBackButtonHandler(...)`](#togglebackbuttonhandler) * [`addListener('appStateChange', ...)`](#addlistenerappstatechange-) * [`addListener('pause', ...)`](#addlistenerpause-) * [`addListener('resume', ...)`](#addlistenerresume-) @@ -167,6 +211,25 @@ Only available for Android. -------------------- +### toggleBackButtonHandler(...) + +```typescript +toggleBackButtonHandler(options: ToggleBackButtonHandlerOptions) => Promise +``` + +Enables or disables the plugin's back button handling during runtime. + +Only available for Android. + +| Param | Type | +| ------------- | ----------------------------------------------------------------------------------------- | +| **`options`** | ToggleBackButtonHandlerOptions | + +**Since:** 7.1.0 + +-------------------- + + ### addListener('appStateChange', ...) ```typescript @@ -364,6 +427,13 @@ Remove all native listeners for this plugin | **`url`** | string | The url used to open the app. | 1.0.0 | +#### ToggleBackButtonHandlerOptions + +| Prop | Type | Description | Since | +| ------------- | -------------------- | -------------------------------------------------------------------- | ----- | +| **`enabled`** | boolean | Indicates whether to enable or disable default back button handling. | 7.1.0 | + + #### PluginListenerHandle | Prop | Type | diff --git a/app/android/src/main/java/com/capacitorjs/plugins/app/AppPlugin.java b/app/android/src/main/java/com/capacitorjs/plugins/app/AppPlugin.java index 0ca7fa152..0b6295b5f 100644 --- a/app/android/src/main/java/com/capacitorjs/plugins/app/AppPlugin.java +++ b/app/android/src/main/java/com/capacitorjs/plugins/app/AppPlugin.java @@ -25,7 +25,11 @@ public class AppPlugin extends Plugin { private static final String EVENT_RESUME = "resume"; private boolean hasPausedEver = false; + private OnBackPressedCallback onBackPressedCallback; + public void load() { + boolean disableBackButtonHandler = getConfig().getBoolean("disableBackButtonHandler", false); + bridge .getApp() .setStatusChangeListener( @@ -44,22 +48,24 @@ public void load() { notifyListeners(EVENT_RESTORED_RESULT, result.getWrappedResult(), true); } ); - OnBackPressedCallback callback = new OnBackPressedCallback(true) { - @Override - public void handleOnBackPressed() { - if (!hasListeners(EVENT_BACK_BUTTON)) { - if (bridge.getWebView().canGoBack()) { - bridge.getWebView().goBack(); + this.onBackPressedCallback = + new OnBackPressedCallback(!disableBackButtonHandler) { + @Override + public void handleOnBackPressed() { + if (!hasListeners(EVENT_BACK_BUTTON)) { + if (bridge.getWebView().canGoBack()) { + bridge.getWebView().goBack(); + } + } else { + JSObject data = new JSObject(); + data.put("canGoBack", bridge.getWebView().canGoBack()); + notifyListeners(EVENT_BACK_BUTTON, data, true); + bridge.triggerJSEvent("backbutton", "document"); } - } else { - JSObject data = new JSObject(); - data.put("canGoBack", bridge.getWebView().canGoBack()); - notifyListeners(EVENT_BACK_BUTTON, data, true); - bridge.triggerJSEvent("backbutton", "document"); } - } - }; - getActivity().getOnBackPressedDispatcher().addCallback(getActivity(), callback); + }; + + getActivity().getOnBackPressedDispatcher().addCallback(getActivity(), this.onBackPressedCallback); } @PluginMethod @@ -112,6 +118,19 @@ public void minimizeApp(PluginCall call) { call.resolve(); } + @PluginMethod + public void toggleBackButtonHandler(PluginCall call) { + if (this.onBackPressedCallback == null) { + call.reject("onBackPressedCallback is not set"); + return; + } + + Boolean enabled = call.getBoolean("enabled"); + + this.onBackPressedCallback.setEnabled(enabled); + call.resolve(); + } + /** * Handle ACTION_VIEW intents to store a URL that was used to open the app * @param intent diff --git a/app/ios/Sources/AppPlugin/AppPlugin.swift b/app/ios/Sources/AppPlugin/AppPlugin.swift index 0f6086507..a6c4451fd 100644 --- a/app/ios/Sources/AppPlugin/AppPlugin.swift +++ b/app/ios/Sources/AppPlugin/AppPlugin.swift @@ -10,7 +10,8 @@ public class AppPlugin: CAPPlugin, CAPBridgedPlugin { CAPPluginMethod(name: "getInfo", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "getLaunchUrl", returnType: CAPPluginReturnPromise), CAPPluginMethod(name: "getState", returnType: CAPPluginReturnPromise), - CAPPluginMethod(name: "minimizeApp", returnType: CAPPluginReturnPromise) + CAPPluginMethod(name: "minimizeApp", returnType: CAPPluginReturnPromise), + CAPPluginMethod(name: "toggleBackButtonHandler", returnType: CAPPluginReturnPromise) ] private var observers: [NSObjectProtocol] = [] @@ -113,4 +114,8 @@ public class AppPlugin: CAPPlugin, CAPBridgedPlugin { @objc func minimizeApp(_ call: CAPPluginCall) { call.unimplemented() } + + @objc func toggleBackButtonHandler(_ call: CAPPluginCall) { + call.unimplemented() + } } diff --git a/app/package.json b/app/package.json index 7d81824c3..296169c05 100644 --- a/app/package.json +++ b/app/package.json @@ -48,6 +48,7 @@ }, "devDependencies": { "@capacitor/android": "^7.0.0", + "@capacitor/cli": "^7.0.0", "@capacitor/core": "^7.0.0", "@capacitor/docgen": "0.2.2", "@capacitor/ios": "^7.0.0", diff --git a/app/src/definitions.ts b/app/src/definitions.ts index ff8324896..5745a1d66 100644 --- a/app/src/definitions.ts +++ b/app/src/definitions.ts @@ -1,5 +1,24 @@ +/// + import type { PluginListenerHandle } from '@capacitor/core'; +declare module '@capacitor/cli' { + export interface PluginsConfig { + App?: { + /** + * Disable the plugin's default back button handling. + * + * Only available for Android. + * + * @since 7.1.0 + * @default false + * @example true + */ + disableBackButtonHandler?: boolean; + }; + } +} + export interface AppInfo { /** * The name of the app. @@ -125,6 +144,15 @@ export interface BackButtonListenerEvent { canGoBack: boolean; } +export interface ToggleBackButtonHandlerOptions { + /** + * Indicates whether to enable or disable default back button handling. + * + * @since 7.1.0 + */ + enabled: boolean; +} + export type StateChangeListener = (state: AppState) => void; export type URLOpenListener = (event: URLOpenListenerEvent) => void; export type RestoredListener = (event: RestoredListenerEvent) => void; @@ -171,6 +199,17 @@ export interface AppPlugin { */ minimizeApp(): Promise; + /** + * Enables or disables the plugin's back button handling during runtime. + * + * Only available for Android. + * + * @since 7.1.0 + */ + toggleBackButtonHandler( + options: ToggleBackButtonHandlerOptions, + ): Promise; + /** * Listen for changes in the app or the activity states. * diff --git a/app/src/web.ts b/app/src/web.ts index 1db1ff356..62288cc07 100644 --- a/app/src/web.ts +++ b/app/src/web.ts @@ -32,6 +32,10 @@ export class AppWeb extends WebPlugin implements AppPlugin { throw this.unimplemented('Not implemented on web.'); } + async toggleBackButtonHandler(): Promise { + throw this.unimplemented('Not implemented on web.'); + } + private handleVisibilityChange = () => { const data = { isActive: document.hidden !== true,