Fix system dialog dismissed UX

This commit is contained in:
franzap
2026-04-01 20:09:43 -03:00
parent d3c07ac797
commit 4d1b6b2656
4 changed files with 26 additions and 25 deletions
+2
View File
@@ -56,3 +56,5 @@ reference/*
# FVM Version Cache
.fvm/
bugs/
@@ -353,10 +353,27 @@ class AndroidPackageManagerPlugin :
Log.d(TAG, "App foregrounded")
if (!wasForeground) {
// Re-launch any pending install dialogs
for ((packageName, intent) in pendingUserActionIntents.toMap()) {
Log.d(TAG, "Re-launching pending dialog for $packageName")
val sessionActive = findExistingSession(packageName) != null
if (sessionActive) {
// Session still alive — user was in another app, dialog is still pending.
// Re-show it so the user can act on it without hunting for it.
Log.d(TAG, "Re-launching pending dialog for $packageName (session active)")
launchConfirmDialog(packageName, intent)
} else {
// Session is gone — dialog was dismissed without confirming.
// Emit CANCELLED so Dart transitions to InstallCancelled immediately.
Log.d(TAG, "Session gone for $packageName on foreground — emitting cancelled")
pendingUserActionIntents.remove(packageName)
val sessionId = sessionToPackage.entries.find { it.value == packageName }?.key ?: -1
clearWatchdog(packageName)
onInstallResult(
sessionId = sessionId,
status = InstallStatus.CANCELLED,
packageName = packageName,
message = "Install dialog dismissed"
)
}
}
}
}
@@ -71,8 +71,6 @@ final class AndroidPackageManager extends PackageManager {
static const _methodChannel = MethodChannel('android_package_manager');
static const _eventChannel = EventChannel('android_package_manager/events');
static const _pendingUserActionTimeout = Duration(seconds: 10);
bool _supportsSilentInstall = false;
int _syncGeneration = 0;
StreamSubscription<dynamic>? _eventSubscription;
@@ -230,29 +228,13 @@ final class AndroidPackageManager extends PackageManager {
break;
case InstallStatus.pendingUserAction:
// If pending user action lingers too long, treat it like dismiss/cancel
// and surface "Install (retry)" instead of staying stuck requesting.
if (existingOp is Installing &&
!existingOp.isSilent &&
DateTime.now().difference(existingOp.startedAt) >=
_pendingUserActionTimeout) {
if (filePath != null) {
setOperation(
appId,
InstallCancelled(target: target, filePath: filePath),
);
} else {
clearOperation(appId);
}
clearInstallSlot(appId);
break;
}
// User action required. Ensure we don't get stuck in Verifying if the
// STARTED event was missed; show Installing state.
// Skip if already in Installing or SystemProcessing to preserve the
// original startedAt timestamp — otherwise the watchdog timeout resets
// on every pendingUserAction/systemProcessing bounce and never fires.
// Dialog dismiss is detected on the Kotlin side via onStart +
// findExistingSession, which emits CANCELLED when the session is gone.
if (filePath != null &&
existingOp is! Installing &&
existingOp is! SystemProcessing) {
+1 -1
View File
@@ -175,7 +175,7 @@ class InstallButton extends ConsumerWidget {
isSilent
? (isInstalled ? 'Updating...' : 'Installing...')
: (isInstalled ? 'Requesting update' : 'Requesting installation'),
null, // Not tappable - auto-transitions to retry after 10s if no response
null, // Not tappable - transitions to retry when Kotlin detects dialog dismissed
fontSize: fontSize,
showSpinner: true,
),