fluttercommunity / fluttercommunity/plus_plugins

[share_plus] iOS: sourceView set unconditionally on iPhone — on iOS 26 swipe-dismissing the sheet can hang the share() Future and break touch delivery

Abierto Apto para principiantes
#3,943 0 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Dart
Estrellas
1.9k
Forks
1.3k
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

## Platform

- `share_plus`: 13.2.0 (same code present in 12.x)
- iOS 26.3 – 26.5.2, iPhone (reproduced on iPhone 16e / 17 Pro / 17 Pro Max, simulator and physical devices)
- Flutter 3.44.4

## Description

In `FPPSharePlusPlugin.m`, `popoverPresentationController.sourceView` is assigned **unconditionally**, regardless of `UIUserInterfaceIdiom`:

```objc
activityViewController.popoverPresentationController.sourceView = topViewController.view;
if (!CGRectIsEmpty(origin)) {
activityViewController.popoverPresentationController.sourceRect = origin;
}
```

There is no way to opt out from Dart: even when the caller passes no `sharePositionOrigin`, `sourceView` is still set.

On iPhone this used to be harmless, but on **iOS 26** a non-nil `sourceView` routes `UIActivityViewController` into the popover/anchored presentation path (compact sheet anchored to the Flutter view). When the user dismisses that sheet **interactively** (swipe down — most reliably after visiting a sub-screen such as AirDrop and coming back), the dismissal can end up in a broken state:

1. `completionWithItemsHandler` is **never called** → the `Future` returned by `SharePlus.share()` never completes, and any `await`/`finally` after it is dead.
2. The `UIActivityViewController` can stay `presented` with `isBeingDismissed == true` indefinitely (interrupted interactive dismissal never finishes), or stay presented with its view already detached from the window.
3. Touch delivery inside the app degrades: taps in part of the Flutter UI (in our case the bottom sheet under the share origin) stop being delivered until the presentation stack is rebuilt (e.g., by pushing/popping any route). Instrumentation shows events dying before reaching gesture handlers while the widget tree is healthy.

## Steps to reproduce

1. iPhone with iOS 26.x, any app calling `SharePlus.instance.share(ShareParams(uri: ...))` (no `sharePositionOrigin`).
2. Open the share sheet, optionally enter the AirDrop sub-screen and come back.
3. Dismiss the sheet with a swipe-down gesture.
4. Observe: the `share()` Future often never completes; in a fraction of runs taps around the share origin stop working.

The race is timing-sensitive (roughly 1 in 3 attempts in our testing), the AirDrop detour makes it much more reliable.

## Expected

- `sourceView`/popover configuration only applies on iPad (where `sharePositionOrigin` is genuinely required), or is at least skippable from Dart.
- `completionWithItemsHandler` fires (with `completed == false`) for interrupted interactive dismissals so the returned Future always completes.

## Workaround we ship (vendored fork)

Wrapping the popover configuration in an idiom check fixes the iPhone path while keeping iPad behavior intact:

```objc
BOOL isIpad = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
if (isIpad) {
activityViewController.popoverPresentationController.sourceView =
topViewController.view;
if (!CGRectIsEmpty(origin)) {
activityViewController.popoverPresentationController.sourceRect = origin;
}
}
```

The hung-completion part still needs an app-level watchdog on iOS 26 even with this patch (the OS sometimes drops the completion for interrupted dismissals), but the touch-delivery breakage no longer reproduces with `sourceView` unset on iPhone.

Happy to send a PR with the idiom guard if that direction works for the maintainers.

Guía de contribución

Abrir la guía de contribución

Línea de trabajo

Comienza en FPPSharePlusPlugin.m, en la configuración del popover de UIActivityViewController, y compara el comportamiento informado en iPhone y iPad. Reproduce el cierre mediante deslizamiento en iOS 26 si está disponible y, después, verifica que sourceView/sourceRect solo se configuren para iPad y que el comportamiento existente en iPad se mantenga intacto.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
dart, ios, objective-c
Área
mobile-dev
Tipo de issue
Error
Dificultad
2/5
Tiempo estimado
1-3 horas
Estado de actividad
Tranquilo
Claridad
Bien especificado
Aptitud para principiantes
78/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.