mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 12:38:24 +00:00
Fix system dialog dismissed UX
This commit is contained in:
@@ -56,3 +56,5 @@ reference/*
|
|||||||
|
|
||||||
# FVM Version Cache
|
# FVM Version Cache
|
||||||
.fvm/
|
.fvm/
|
||||||
|
|
||||||
|
bugs/
|
||||||
+20
-3
@@ -353,10 +353,27 @@ class AndroidPackageManagerPlugin :
|
|||||||
Log.d(TAG, "App foregrounded")
|
Log.d(TAG, "App foregrounded")
|
||||||
|
|
||||||
if (!wasForeground) {
|
if (!wasForeground) {
|
||||||
// Re-launch any pending install dialogs
|
|
||||||
for ((packageName, intent) in pendingUserActionIntents.toMap()) {
|
for ((packageName, intent) in pendingUserActionIntents.toMap()) {
|
||||||
Log.d(TAG, "Re-launching pending dialog for $packageName")
|
val sessionActive = findExistingSession(packageName) != null
|
||||||
launchConfirmDialog(packageName, intent)
|
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 _methodChannel = MethodChannel('android_package_manager');
|
||||||
static const _eventChannel = EventChannel('android_package_manager/events');
|
static const _eventChannel = EventChannel('android_package_manager/events');
|
||||||
static const _pendingUserActionTimeout = Duration(seconds: 10);
|
|
||||||
|
|
||||||
bool _supportsSilentInstall = false;
|
bool _supportsSilentInstall = false;
|
||||||
int _syncGeneration = 0;
|
int _syncGeneration = 0;
|
||||||
StreamSubscription<dynamic>? _eventSubscription;
|
StreamSubscription<dynamic>? _eventSubscription;
|
||||||
@@ -230,29 +228,13 @@ final class AndroidPackageManager extends PackageManager {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case InstallStatus.pendingUserAction:
|
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
|
// User action required. Ensure we don't get stuck in Verifying if the
|
||||||
// STARTED event was missed; show Installing state.
|
// STARTED event was missed; show Installing state.
|
||||||
// Skip if already in Installing or SystemProcessing to preserve the
|
// Skip if already in Installing or SystemProcessing to preserve the
|
||||||
// original startedAt timestamp — otherwise the watchdog timeout resets
|
// original startedAt timestamp — otherwise the watchdog timeout resets
|
||||||
// on every pendingUserAction/systemProcessing bounce and never fires.
|
// 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 &&
|
if (filePath != null &&
|
||||||
existingOp is! Installing &&
|
existingOp is! Installing &&
|
||||||
existingOp is! SystemProcessing) {
|
existingOp is! SystemProcessing) {
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ class InstallButton extends ConsumerWidget {
|
|||||||
isSilent
|
isSilent
|
||||||
? (isInstalled ? 'Updating...' : 'Installing...')
|
? (isInstalled ? 'Updating...' : 'Installing...')
|
||||||
: (isInstalled ? 'Requesting update' : 'Requesting installation'),
|
: (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,
|
fontSize: fontSize,
|
||||||
showSpinner: true,
|
showSpinner: true,
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user