Skip to content

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

Open
tomerqodo wants to merge 2 commits intocoderabbit_combined_20260121_augment_sentry_coderabbit_1_base_featcore_back_button_event_on_android_closes_8142_pr162from
coderabbit_combined_20260121_augment_sentry_coderabbit_1_head_featcore_back_button_event_on_android_closes_8142_pr162
Open

feat(core): back button event on Android, closes #8142#19
tomerqodo wants to merge 2 commits intocoderabbit_combined_20260121_augment_sentry_coderabbit_1_base_featcore_back_button_event_on_android_closes_8142_pr162from
coderabbit_combined_20260121_augment_sentry_coderabbit_1_head_featcore_back_button_event_on_android_closes_8142_pr162

Conversation

@tomerqodo
Copy link
Copy Markdown

@tomerqodo tomerqodo commented Jan 22, 2026

Benchmark PR from qodo-benchmark#162

Summary by CodeRabbit

  • New Features

    • Added Android app plugin with support for exit command and back button press event handling
    • Introduced onBackButtonPress API to listen for Android back button interactions
    • Added register/remove listener commands for event management
  • Chores

    • Updated wry dependency to version 0.53.4
    • Cleaned up unused imports and formatting adjustments

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 22, 2026

Walkthrough

The PR introduces Android back button press event handling by adding a new AppPlugin that detects back button presses, emits corresponding events to JavaScript listeners, and provides an exit command. Supporting changes include TypeScript APIs, new permissions, updated build configuration, and a minor dependency version bump.

Changes

Cohort / File(s) Summary
Changelog Documentation
.changes/android-app-plugin.md, .changes/back-button-press-api.md
New changelog entries documenting the mobile app plugin addition and back button handling API feature.
Dependency Updates
crates/tauri-runtime-wry/Cargo.toml
Bumped wry dependency from 0.53.2 to 0.53.4.
Build Configuration
crates/tauri/build.rs
Added register_listener and remove_listener commands to core:app plugin in PLUGINS constant.
Android Plugin Implementation
crates/tauri/mobile/android-codegen/TauriActivity.kt, crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt, crates/tauri/mobile/android/src/main/java/app/tauri/plugin/Plugin.kt
New AppPlugin Kotlin class implementing back button handling via OnBackPressedCallback; triggers back-button event to JavaScript listeners or delegates to WebView. Added exit() command and load() override. Added hasListener() helper method to Plugin base class. TauriActivity enables handleBackNavigation by default.
Rust Plugin Integration
crates/tauri/src/app/plugin.rs
Android-specific setup block registering AppPlugin and wrapping handle in new AppPlugin struct.
TypeScript API
packages/api/src/app.ts
New onBackButtonPress() function and OnBackButtonPressPayload type for registering back button listeners from JavaScript.
Permissions
crates/tauri/permissions/app/autogenerated/reference.md
Added allow/deny permission entries for register_listener and remove_listener commands.
Miscellaneous
crates/tauri/scripts/bundle.global.js, crates/tauri/src/path/android.rs
Formatting adjustments and unused import cleanup.

Sequence Diagram

sequenceDiagram
    actor User
    participant Android as Android System
    participant Plugin as AppPlugin
    participant WebView as WebView
    participant JS as JavaScript Handler

    User->>Android: Press back button
    Android->>Plugin: OnBackPressedCallback invoked
    Plugin->>Plugin: Check for back-button listener
    
    alt Listener registered
        Plugin->>Plugin: Build JSObject with canGoBack
        Plugin->>JS: Emit BACK_BUTTON_EVENT
        JS->>JS: Execute onBackButtonPress handler
    else No listener registered
        Plugin->>WebView: goBack() if canGoBack
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A button pressed, the back we go,
Android hops with Kotlin flow,
Listeners wake, JavaScript knows,
Exit graceful, forward close!
Permissions blessed, events bestow! 🔙✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(core): back button event on Android, closes #8142' accurately describes the main change: adding back button event handling for Android, following conventional commit format.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt`:
- Line 46: The current direct cast (activity as AppCompatActivity) before
calling onBackPressedDispatcher.addCallback is unsafe and can throw
ClassCastException; update AppPlugin.kt to perform a safe type check (e.g., use
an instanceof/is-check or a safe cast) against AppCompatActivity before calling
onBackPressedDispatcher.addCallback(activity, callback) and only register the
callback when the activity is an AppCompatActivity (otherwise skip registration
or log/handle gracefully) so the back-button behavior falls back to the system
when the activity is not AppCompatActivity.
- Around line 33-37: Replace the deprecated call to Activity.onBackPressed() in
AppPlugin with the Activity's OnBackPressedDispatcher by invoking
activity.onBackPressedDispatcher.onBackPressed(); keep the existing
disable/re-enable pattern around the call (this.isEnabled = false ...
this.isEnabled = true) to avoid recursion; locate the call site referencing
this@AppPlugin.activity.onBackPressed() and swap it to use
this@AppPlugin.activity.onBackPressedDispatcher.onBackPressed() while preserving
surrounding logic in the AppPlugin class.

In `@crates/tauri/src/app/plugin.rs`:
- Around line 135-143: The setup closure is attempting to dereference a
reference to a PluginHandle which is not Copy; remove the intermediate reference
and pass the owned handle (or clone it) directly into AppPlugin. Locate the call
to register_android_plugin and the AppPlugin construction inside the .setup
closure and replace the pattern let handle = _api.register_android_plugin(...)?;
let handle_ref = &handle; _app.manage(AppPlugin(*handle_ref)); with a direct
move or clone into _app.manage (e.g., _app.manage(AppPlugin(handle)) or
_app.manage(AppPlugin(handle.clone()))), since PluginHandle implements Clone but
not Copy.
🧹 Nitpick comments (1)
packages/api/src/app.ts (1)

255-275: Add @since and @example tags to match API documentation conventions.

Other functions in this file include @since version tags and @example code blocks. The new onBackButtonPress function should follow the same convention for consistency.

📝 Suggested documentation improvement
 /**
  * Listens to the backButton event on Android.
- * `@param` handler
+ *
+ * `@example`
+ * ```typescript
+ * import { onBackButtonPress } from '@tauri-apps/api/app';
+ * const unlisten = await onBackButtonPress((payload) => {
+ *   if (payload.canGoBack) {
+ *     // handle back navigation
+ *   }
+ * });
+ * // later, to stop listening
+ * unlisten.unregister();
+ * ```
+ *
+ * `@param` handler - The callback function to handle back button press events.
+ * `@returns` A promise resolving to a listener that can be used to unregister.
+ *
+ * `@since` 2.x.0
  */
 async function onBackButtonPress(
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37afddf and 55a5c9a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • .changes/android-app-plugin.md
  • .changes/back-button-press-api.md
  • crates/tauri-runtime-wry/Cargo.toml
  • crates/tauri/build.rs
  • crates/tauri/mobile/android-codegen/TauriActivity.kt
  • crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt
  • crates/tauri/mobile/android/src/main/java/app/tauri/plugin/Plugin.kt
  • crates/tauri/permissions/app/autogenerated/reference.md
  • crates/tauri/scripts/bundle.global.js
  • crates/tauri/src/app/plugin.rs
  • crates/tauri/src/path/android.rs
  • packages/api/src/app.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/api/src/app.ts (1)
packages/api/src/core.ts (2)
  • PluginListener (347-347)
  • addPluginListener (348-348)
crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt (1)
crates/tauri/mobile/android/src/main/java/app/tauri/plugin/Plugin.kt (2)
  • hasListener (149-151)
  • trigger (129-137)
🔇 Additional comments (14)
crates/tauri/scripts/bundle.global.js (1)

1-1: LGTM!

The minified bundle correctly includes the new onBackButtonPress API for Android back button handling. As this is auto-generated build output, the changes align with the PR's feature additions.

crates/tauri/mobile/android/src/main/java/app/tauri/plugin/Plugin.kt (1)

149-151: LGTM!

The hasListener helper method is cleanly implemented using idiomatic Kotlin with isNullOrEmpty(). This enables AppPlugin to check for registered back-button listeners before deciding whether to emit events or trigger system back behavior.

crates/tauri/src/path/android.rs (1)

7-7: LGTM!

Clean removal of unused OsStr import. The remaining Path and PathBuf imports are properly utilized in the file.

.changes/back-button-press-api.md (1)

1-5: LGTM!

The changeset correctly documents the new back button API as a minor feature addition to @tauri-apps/api. The description accurately reflects the PR's changes.

crates/tauri/mobile/android-codegen/TauriActivity.kt (1)

15-15: Back navigation fallback is properly implemented—no breaking change risk.

The handleBackNavigation = true default is safe. When no JavaScript listener is registered for the back-button event, AppPlugin gracefully falls back to standard behavior: it calls webView.goBack() if the web view can navigate back, or otherwise triggers the system's default onBackPressed(). Only when a JavaScript listener is registered does the event get emitted. This maintains backward compatibility with existing apps.

crates/tauri-runtime-wry/Cargo.toml (1)

20-25: The wry 0.53.4 version bump is justified and appropriate.

The version exists and includes Android back-navigation handling improvements (added flag to opt out of automatic back navigation handling via WryActivity#handleBackNavigation), which directly supports the Android runtime requirements. The update also includes Linux improvements for WebKitGTK compatibility.

.changes/android-app-plugin.md (1)

1-5: LGTM!

The changelog entry correctly documents the new mobile app plugin feature as a minor feature addition.

crates/tauri/build.rs (1)

167-168: LGTM!

The new register_listener and remove_listener commands are correctly added to the core:app plugin with default enabled, following the existing pattern for command registration.

crates/tauri/permissions/app/autogenerated/reference.md (2)

12-13: LGTM!

The new default permissions for allow-register-listener and allow-remove-listener are correctly added, aligning with the command registrations in build.rs.


209-282: LGTM!

The permission table entries for the new listener commands follow the existing documentation structure consistently.

crates/tauri/src/app/plugin.rs (1)

147-148: LGTM!

The Android-only AppPlugin wrapper struct is appropriately scoped with #[cfg(target_os = "android")] and provides the necessary type to manage the plugin handle.

packages/api/src/app.ts (2)

5-5: LGTM!

The imports for addPluginListener and PluginListener from ./core are correctly added to support the new back button listener functionality.


289-291: LGTM!

The exports correctly include both the OnBackButtonPressPayload type and the onBackButtonPress function.

crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt (1)

49-53: LGTM!

The exit command correctly finishes the activity and resolves the invoke.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +33 to +37
} else {
this.isEnabled = false
this@AppPlugin.activity.onBackPressed()
this.isEnabled = true
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Android onBackPressed deprecated API level Android 13 OnBackPressedDispatcher

💡 Result:

Short answer

  • ComponentActivity.onBackPressed() is deprecated (AndroidX) — use OnBackPressedDispatcher with OnBackPressedCallback instead. [1][2][3]

Details

  • The Activity API was updated to route back events through an OnBackPressedDispatcher that invokes one or more OnBackPressedCallback instances; ComponentActivity.onBackPressed() is marked deprecated in favor of that dispatcher. [1][2]
  • On Android 13 (API 33) the activity support libraries also expose integration with the platform’s predictive back (OnBackInvokedDispatcher) via setOnBackInvokedDispatcher for proper behavior on SDK 33+. Use the androidx OnBackPressedDispatcher APIs (addCallback with a LifecycleOwner) to handle back navigation and lifecycle automatically. [2][1][3]

Example (Kotlin)

  • requireActivity().onBackPressedDispatcher.addCallback(this) { /* handle back */ } . [2][3]

Sources
[1] ComponentActivity (AndroidX) — deprecation note.
[2] OnBackPressedDispatcher (AndroidX) — usage and addCallback.
[3] Android Developers guide: Provide custom back navigation (recommendation to replace onBackPressed with OnBackPressedCallback).


🌐 Web query:

Android Activity onBackPressed() deprecated replacement best practices

💡 Result:

Short answer

  • Don’t override Activity.onBackPressed() (deprecated). Use the Jetpack OnBackPressedDispatcher + OnBackPressedCallback for most apps, and for Android 13+ (API 33+) use the platform OnBackInvokedDispatcher/OnBackInvokedCallback or the AndroidX bridge. Register callbacks lifecycle‑aware and enable/disable them instead of removing. [1][2][3]

Why and when

  • OnBackPressedDispatcher (androidx.activity) is lifecycle‑aware and is the recommended cross‑API solution (works with Fragments, ViewModels, avoids leaks). Use it by default. [1]
  • OnBackInvokedDispatcher / OnBackInvokedCallback (platform, API 33+) replaces Activity.onBackPressed at the OS level and provides priority/animation hooks; AndroidX can be wired to it so your code works across API levels. [2][3]

Best practices (concise)

  • Use OnBackPressedDispatcher.addCallback(owner, callback) so the callback follows the LifecycleOwner (use viewLifecycleOwner in Fragments). [1]
  • Prefer enabling/disabling an OnBackPressedCallback rather than removing it. [1]
  • If you target API 33+, either register an OnBackInvokedCallback for platform behavior or rely on the AndroidX dispatcher which can be set to use the platform dispatcher (AndroidX 1.6+). [1][2]
  • Keep back handling focused: let UI overlays (dialogs, drawers) register higher‑priority callbacks and return control to the default flow when appropriate. [2]

Minimal examples

  • Activity (Kotlin, Jetpack):
    val callback = object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() { /* custom */ }
    }
    onBackPressedDispatcher.addCallback(this, callback) // lifecycle-aware. [1]

  • Fragment (Kotlin):
    val cb = object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() { /* handle or call requireActivity().onBackPressedDispatcher.onBackPressed() */ }
    }
    requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, cb) // use viewLifecycleOwner. [1]

Docs / references

  • OnBackPressedDispatcher / OnBackPressedCallback (AndroidX). [1]
  • OnBackInvokedDispatcher (platform API level 33+) — priority and window-level callbacks. [2]
  • OnBackInvokedCallback (platform replacement for Activity.onBackPressed()). [3]

If you want, I can paste a copy‑pasteable Kotlin sample showing AndroidX + API‑33 bridging (setOnBackInvokedDispatcher) and explain version checks.


🏁 Script executed:

# Let's examine the full context of the code in question
cd /tmp && git clone --depth 1 https://github.com/tauri-apps/tauri.git 2>/dev/null || true
find . -name "AppPlugin.kt" -type f 2>/dev/null | head -5

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 156


🏁 Script executed:

# Get the full context of AppPlugin.kt around lines 33-37
cat -n /tmp/tauri/crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt | head -60

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 2002


🏁 Script executed:

# Let's check if there are other methods or patterns used in the codebase for back press handling
rg "onBackPressed|OnBackPressedDispatcher|OnBackPressedCallback" crates/tauri/mobile/android --type kotlin -B2 -A2

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 2002


Replace deprecated onBackPressed() with OnBackPressedDispatcher.onBackPressed().

The Activity.onBackPressed() method is deprecated in AndroidX. The modern approach is to call onBackPressedDispatcher.onBackPressed(), which properly delegates to the next callback in the dispatcher queue or the system's default back handling. The disable/re-enable pattern is still needed here to prevent callback recursion.

🔧 Suggested fix
          } else {
            this.isEnabled = false
-           this@AppPlugin.activity.onBackPressed()
+           (this@AppPlugin.activity as AppCompatActivity).onBackPressedDispatcher.onBackPressed()
            this.isEnabled = true
          }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else {
this.isEnabled = false
this@AppPlugin.activity.onBackPressed()
this.isEnabled = true
}
} else {
this.isEnabled = false
(this@AppPlugin.activity as AppCompatActivity).onBackPressedDispatcher.onBackPressed()
this.isEnabled = true
}
🤖 Prompt for AI Agents
In `@crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt` around
lines 33 - 37, Replace the deprecated call to Activity.onBackPressed() in
AppPlugin with the Activity's OnBackPressedDispatcher by invoking
activity.onBackPressedDispatcher.onBackPressed(); keep the existing
disable/re-enable pattern around the call (this.isEnabled = false ...
this.isEnabled = true) to avoid recursion; locate the call site referencing
this@AppPlugin.activity.onBackPressed() and swap it to use
this@AppPlugin.activity.onBackPressedDispatcher.onBackPressed() while preserving
surrounding logic in the AppPlugin class.

}
}
}
(activity as AppCompatActivity).onBackPressedDispatcher.addCallback(activity, callback)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Unsafe cast to AppCompatActivity may crash at runtime.

The cast (activity as AppCompatActivity) will throw ClassCastException if the activity is not an AppCompatActivity. Consider adding a type check or documenting this requirement.

🔧 Suggested defensive check
-    (activity as AppCompatActivity).onBackPressedDispatcher.addCallback(activity, callback)
+    if (activity is AppCompatActivity) {
+      activity.onBackPressedDispatcher.addCallback(activity, callback)
+    }

Note: If the callback isn't registered when activity is not AppCompatActivity, the back button behavior will fall back to the default system handling, which may be acceptable depending on the use case.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(activity as AppCompatActivity).onBackPressedDispatcher.addCallback(activity, callback)
if (activity is AppCompatActivity) {
activity.onBackPressedDispatcher.addCallback(activity, callback)
}
🤖 Prompt for AI Agents
In `@crates/tauri/mobile/android/src/main/java/app/tauri/AppPlugin.kt` at line 46,
The current direct cast (activity as AppCompatActivity) before calling
onBackPressedDispatcher.addCallback is unsafe and can throw ClassCastException;
update AppPlugin.kt to perform a safe type check (e.g., use an
instanceof/is-check or a safe cast) against AppCompatActivity before calling
onBackPressedDispatcher.addCallback(activity, callback) and only register the
callback when the activity is an AppCompatActivity (otherwise skip registration
or log/handle gracefully) so the back-button behavior falls back to the system
when the activity is not AppCompatActivity.

Comment on lines +135 to +143
.setup(|_app, _api| {
#[cfg(target_os = "android")]
{
let handle = _api.register_android_plugin("app.tauri", "AppPlugin")?;
let handle_ref = &handle;
_app.manage(AppPlugin(*handle_ref));
}
Ok(())
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for PluginHandle definition
fd "\.rs$" -x rg -l "PluginHandle" {} \; | head -10

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 224


🏁 Script executed:

#!/bin/bash
# Get the structure and trait impls for PluginHandle
rg -n "struct PluginHandle|enum PluginHandle" --type rust -A 10 | head -50

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 843


🏁 Script executed:

#!/bin/bash
# Search for Copy/Clone implementations for PluginHandle
rg -n "impl.*Copy.*PluginHandle|impl.*Clone.*PluginHandle|#\[derive\(.*Copy.*\)|#\[derive\(.*Clone.*\)" --type rust -B 3 -A 5 | grep -A 5 -B 5 "PluginHandle"

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 816


🏁 Script executed:

#!/bin/bash
# Read the specific lines mentioned in the review
sed -n '135,143p' crates/tauri/src/app/plugin.rs

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 338


🏁 Script executed:

#!/bin/bash
# Get more context around those lines
sed -n '130,150p' crates/tauri/src/app/plugin.rs

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 562


🏁 Script executed:

#!/bin/bash
# Search for AppPlugin struct definition
rg -n "struct AppPlugin|impl.*AppPlugin" --type rust -A 5 | head -30

Repository: qodo-benchmark/tauri-combined-coderabbit

Length of output: 379


This code does not compile as written.

PluginHandle implements Clone but not Copy. The pattern let handle_ref = &handle; _app.manage(AppPlugin(*handle_ref)); violates Rust's move semantics—you cannot move a non-Copy value out of a reference. This is a compilation error that must be fixed.

Remove the intermediate reference and pass the owned handle directly:

♻️ Corrected code
     .setup(|_app, _api| {
       #[cfg(target_os = "android")]
       {
         let handle = _api.register_android_plugin("app.tauri", "AppPlugin")?;
-        let handle_ref = &handle;
-        _app.manage(AppPlugin(*handle_ref));
+        _app.manage(AppPlugin(handle));
       }
       Ok(())
     })
🤖 Prompt for AI Agents
In `@crates/tauri/src/app/plugin.rs` around lines 135 - 143, The setup closure is
attempting to dereference a reference to a PluginHandle which is not Copy;
remove the intermediate reference and pass the owned handle (or clone it)
directly into AppPlugin. Locate the call to register_android_plugin and the
AppPlugin construction inside the .setup closure and replace the pattern let
handle = _api.register_android_plugin(...)?; let handle_ref = &handle;
_app.manage(AppPlugin(*handle_ref)); with a direct move or clone into
_app.manage (e.g., _app.manage(AppPlugin(handle)) or
_app.manage(AppPlugin(handle.clone()))), since PluginHandle implements Clone but
not Copy.

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.

1 participant