Skip to content

feat(core): back button event on Android, closes #8142 - #10

Open
tomerqodo wants to merge 11 commits into
greptile_only-issues-20260113-qodo-grep-copilot_base_featcore_back_button_event_on_android_closes_8142_pr30from
greptile_only-issues-20260113-qodo-grep-copilot_head_featcore_back_button_event_on_android_closes_8142_pr30
Open

tomerqodo wants to merge 11 commits into
greptile_only-issues-20260113-qodo-grep-copilot_base_featcore_back_button_event_on_android_closes_8142_pr30from
greptile_only-issues-20260113-qodo-grep-copilot_head_featcore_back_button_event_on_android_closes_8142_pr30

Conversation

@tomerqodo

Copy link
Copy Markdown

Benchmark PR from qodo-benchmark#30

@greptile-apps

greptile-apps Bot commented Jan 14, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds Android back button event handling to Tauri, allowing developers to intercept back button presses and implement custom behavior. The implementation spans Android (Kotlin), Rust, and TypeScript layers.

Key Changes

  • New AppPlugin.kt registers an OnBackPressedCallback to intercept Android back button events
  • Added hasListener() and removeListener() cleanup in Plugin.kt for event listener management
  • New TypeScript API onBackButtonPress() for registering event handlers
  • Rust integration registers the Android plugin and exposes listener registration commands

Critical Issue Found

  • Logic Error in AppPlugin.kt:30-43: The conditional logic is inverted - when a listener exists (hasListener() returns true), the code performs default navigation instead of triggering the event. When no listener exists, it triggers the event. This will cause the feature to behave opposite to its intended design.

Confidence Score: 0/5

  • This PR contains a critical logic error that completely inverts the back button handling behavior
  • The inverted conditional in AppPlugin.kt means the feature will not work as designed - listeners won't receive events when registered, and default behavior won't execute when no listeners exist. This is a blocking issue that requires fixing before merge.
  • Critical attention needed for crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt - the conditional logic must be fixed before merging

Important Files Changed

Filename Overview
crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt New Android plugin for back button handling with critical logic error in hasListener check (inverted conditional)
crates/tauri/mobile/android/src/main/java/app/tauri/plugin/Plugin.kt Added hasListener() helper method and cleanup logic for empty event listener lists
packages/api/src/app.ts Added onBackButtonPress TypeScript API with proper typing and documentation
crates/tauri/src/app/plugin.rs Registered Android AppPlugin during setup phase for Android targets

Sequence Diagram

sequenceDiagram
    participant User
    participant Android as Android System
    participant AppPlugin as AppPlugin.kt
    participant Plugin as Plugin.kt
    participant WebView
    participant JS as JavaScript/TypeScript
    
    User->>Android: Press Back Button
    Android->>AppPlugin: handleOnBackPressed()
    
    alt Has Listener Registered
        AppPlugin->>Plugin: hasListener("back-button")
        Plugin-->>AppPlugin: true
        AppPlugin->>Plugin: trigger("back-button", {canGoBack})
        Plugin->>JS: Send event to registered listeners
        JS->>JS: onBackButtonPress handler executes
    else No Listener
        AppPlugin->>Plugin: hasListener("back-button")
        Plugin-->>AppPlugin: false
        alt WebView can go back
            AppPlugin->>WebView: canGoBack()
            WebView-->>AppPlugin: true
            AppPlugin->>WebView: goBack()
        else WebView cannot go back
            AppPlugin->>WebView: canGoBack()
            WebView-->>AppPlugin: false
            AppPlugin->>AppPlugin: Disable callback
            AppPlugin->>Android: onBackPressed()
            AppPlugin->>AppPlugin: Re-enable callback
            Android->>User: Exit app/go to previous activity
        end
    end
Loading

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +30 to +43
if (hasListener(BACK_BUTTON_EVENT)) {
if (this@AppPlugin.webView?.canGoBack() == true) {
this@AppPlugin.webView!!.goBack()
} else {
this.isEnabled = false
this@AppPlugin.activity.onBackPressed()
this.isEnabled = true
}
} else {
val data = JSObject().apply {
put("canGoBack", this@AppPlugin.webView?.canGoBack() ?: false)
}
trigger(BACK_BUTTON_EVENT, data)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Logic inverted: when hasListener() is true, the event should be triggered for the listener. When false, the default behavior (webview back navigation) should execute.

Suggested change
if (hasListener(BACK_BUTTON_EVENT)) {
if (this@AppPlugin.webView?.canGoBack() == true) {
this@AppPlugin.webView!!.goBack()
} else {
this.isEnabled = false
this@AppPlugin.activity.onBackPressed()
this.isEnabled = true
}
} else {
val data = JSObject().apply {
put("canGoBack", this@AppPlugin.webView?.canGoBack() ?: false)
}
trigger(BACK_BUTTON_EVENT, data)
}
if (!hasListener(BACK_BUTTON_EVENT)) {
if (this@AppPlugin.webView?.canGoBack() == true) {
this@AppPlugin.webView!!.goBack()
} else {
this.isEnabled = false
this@AppPlugin.activity.onBackPressed()
this.isEnabled = true
}
} else {
val data = JSObject().apply {
put("canGoBack", this@AppPlugin.webView?.canGoBack() ?: false)
}
trigger(BACK_BUTTON_EVENT, data)
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt
Line: 30:43

Comment:
**logic:** Logic inverted: when `hasListener()` is true, the event should be triggered for the listener. When false, the default behavior (webview back navigation) should execute.

```suggestion
        if (!hasListener(BACK_BUTTON_EVENT)) {
          if (this@AppPlugin.webView?.canGoBack() == true) {
            this@AppPlugin.webView!!.goBack()
          } else {
            this.isEnabled = false
            this@AppPlugin.activity.onBackPressed()
            this.isEnabled = true
          }
        } else {
          val data = JSObject().apply {
            put("canGoBack", this@AppPlugin.webView?.canGoBack() ?: false)
          }
          trigger(BACK_BUTTON_EVENT, data)
        }
```

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants