Fix update dialog: show errors, handle OpenFile result correctly

- Check OpenResult.type before resetting state — previously a failed
  open_file call (e.g. installer blocked on emulator) silently called
  state = const UpdateState(), nulling latestVersion and downloadUrl,
  causing "Version null" and a non-functional Download button
- Show errorMessage in dialog with error colour so failures are visible
- Guard Download button on downloadUrl != null (no button if URL lost)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 21:01:01 -04:00
parent fc1c7cade2
commit a337c3fda3
2 changed files with 22 additions and 6 deletions
+12 -2
View File
@@ -185,7 +185,7 @@ class _ShellState extends ConsumerState<_Shell> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('Version ${state.latestVersion} is ready to install.'), Text('Version ${state.latestVersion ?? '?'} is ready to install.'),
if (state.currentVersion != null) if (state.currentVersion != null)
Text( Text(
'Installed: v${state.currentVersion}', 'Installed: v${state.currentVersion}',
@@ -205,6 +205,16 @@ class _ShellState extends ConsumerState<_Shell> {
style: Theme.of(context).textTheme.bodySmall, style: Theme.of(context).textTheme.bodySmall,
), ),
], ],
if (state.status == UpdateStatus.error &&
state.errorMessage != null) ...[
const SizedBox(height: 12),
Text(
state.errorMessage!,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.error,
),
),
],
], ],
), ),
actions: [ actions: [
@@ -212,7 +222,7 @@ class _ShellState extends ConsumerState<_Shell> {
onPressed: () => Navigator.pop(dialogContext), onPressed: () => Navigator.pop(dialogContext),
child: const Text('Later'), child: const Text('Later'),
), ),
if (!isDownloading) if (!isDownloading && state.downloadUrl != null)
FilledButton( FilledButton(
onPressed: () => ref onPressed: () => ref
.read(updateProvider.notifier) .read(updateProvider.notifier)
+10 -4
View File
@@ -119,14 +119,20 @@ class UpdateNotifier extends Notifier<UpdateState> {
}, },
); );
await OpenFile.open( final result = await OpenFile.open(
path, path,
type: 'application/vnd.android.package-archive', type: 'application/vnd.android.package-archive',
); );
// Transition to idle — the system installer is now open. if (result.type == ResultType.done) {
// Going back to `available` would re-trigger the update dialog loop. // Installer launched — reset to idle so the dialog closes naturally.
state = const UpdateState(); state = const UpdateState();
} else {
state = state.copyWith(
status: UpdateStatus.error,
errorMessage: 'Could not open installer: ${result.message}',
);
}
} catch (e) { } catch (e) {
state = state.copyWith( state = state.copyWith(
status: UpdateStatus.error, status: UpdateStatus.error,