mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 20:48:24 +00:00
fix: handle terminal install ops in install button
- Show uninstall (delete) actions immediately after install by treating Completed as not busy on the detail screen. - Ignore stale Completed when the app is no longer installed so the primary CTA returns to Install. - Allow install → uninstall → install again by clearing stale terminal ops (Completed/OperationFailed) in PackageManager.startDownload() (keeps batch progress UX intact).
This commit is contained in:
@@ -330,7 +330,18 @@ abstract class PackageManager extends StateNotifier<PackageManagerState> {
|
|||||||
String? displayName,
|
String? displayName,
|
||||||
}) async {
|
}) async {
|
||||||
await _ensureDownloaderReady();
|
await _ensureDownloaderReady();
|
||||||
if (hasOperation(appId)) return false;
|
final existing = getOperation(appId);
|
||||||
|
if (existing != null) {
|
||||||
|
// We keep terminal states (Completed/Failed) in the operations map briefly so
|
||||||
|
// batch progress UI can derive totals. However, starting a new download for the
|
||||||
|
// same app should not be blocked by a stale terminal op (e.g. install -> uninstall
|
||||||
|
// -> install again). Only in-flight operations should block.
|
||||||
|
if (existing is Completed || existing is OperationFailed) {
|
||||||
|
clearOperation(appId);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final downloadUrl = target.urls.firstOrNull;
|
final downloadUrl = target.urls.firstOrNull;
|
||||||
if (downloadUrl == null || downloadUrl.isEmpty) {
|
if (downloadUrl == null || downloadUrl.isEmpty) {
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ class InstallButton extends ConsumerWidget {
|
|||||||
|
|
||||||
// Derive what to display
|
// Derive what to display
|
||||||
final isInstalled = installedPkg != null;
|
final isInstalled = installedPkg != null;
|
||||||
|
// Note: PackageManager keeps terminal operations (e.g. Completed) in the
|
||||||
|
// operations map for a while so batch UX (e.g. "All done") can derive counts.
|
||||||
|
// For the detail screen action row, Completed should be treated as "not busy"
|
||||||
|
// so the user can immediately Open/Delete after install.
|
||||||
|
final canShowActionButtons =
|
||||||
|
isInstalled && (operation == null || operation is Completed);
|
||||||
final hasUpdate = app.hasUpdate;
|
final hasUpdate = app.hasUpdate;
|
||||||
final hasDowngrade = app.hasDowngrade;
|
final hasDowngrade = app.hasDowngrade;
|
||||||
final hasRelease = release != null;
|
final hasRelease = release != null;
|
||||||
@@ -76,7 +82,7 @@ class InstallButton extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(child: SizedBox(height: 48, child: button)),
|
Expanded(child: SizedBox(height: 48, child: button)),
|
||||||
// Show action buttons only for installed apps with no active operation
|
// Show action buttons only for installed apps with no active operation
|
||||||
if (isInstalled && operation == null) ...[
|
if (canShowActionButtons) ...[
|
||||||
if (hasUpdate) ...[
|
if (hasUpdate) ...[
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
_buildOpenIconButton(context, ref),
|
_buildOpenIconButton(context, ref),
|
||||||
@@ -101,9 +107,15 @@ class InstallButton extends ConsumerWidget {
|
|||||||
required FileMetadata? fileMetadata,
|
required FileMetadata? fileMetadata,
|
||||||
required double fontSize,
|
required double fontSize,
|
||||||
}) {
|
}) {
|
||||||
|
// Completed is a terminal "result" state and may linger for batch progress UX.
|
||||||
|
// If the app is no longer installed (e.g. user uninstalled right after install),
|
||||||
|
// ignore a stale Completed op so we fall back to the normal "Install" UI.
|
||||||
|
final effectiveOperation =
|
||||||
|
(!isInstalled && operation is Completed) ? null : operation;
|
||||||
|
|
||||||
// Handle operation states first
|
// Handle operation states first
|
||||||
if (operation != null) {
|
if (effectiveOperation != null) {
|
||||||
return switch (operation) {
|
return switch (effectiveOperation) {
|
||||||
DownloadQueued() => _buildSimpleButton(
|
DownloadQueued() => _buildSimpleButton(
|
||||||
context,
|
context,
|
||||||
'Queued for download',
|
'Queued for download',
|
||||||
|
|||||||
Reference in New Issue
Block a user