From 7fad61272f83ba1c9646394cdd64e3f38586f296 Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Tue, 9 Jun 2026 10:22:59 -0700 Subject: [PATCH] Installer: replace confusing mount prompt with radio dialog The Yes/No/Cancel MsgBox shown when mounted repos are detected during install was confusing -- the Yes option meant "keep repos mounted" (the less-common, advanced staging case), which inverted user expectations and required reading the message body carefully to map button semantics to outcomes. Replace it with a custom modal containing two radio buttons and Continue/Cancel: (*) Remount repos as part of the installation They will be temporarily unavailable. ( ) Keep repos mounted The upgrade will complete automatically when all repos are unmounted, or at next reboot. The remount option is selected by default, matching the previous IDYES default's intent (proceed with the common path). Silent-mode STAGEIFMOUNTED=true|false behavior is unchanged. Assisted-by: Claude Opus 4.7 Signed-off-by: Tyrie Vella --- GVFS/GVFS.Installers/Setup.iss | 139 +++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 14 deletions(-) diff --git a/GVFS/GVFS.Installers/Setup.iss b/GVFS/GVFS.Installers/Setup.iss index 10765dddb..bda36b806 100644 --- a/GVFS/GVFS.Installers/Setup.iss +++ b/GVFS/GVFS.Installers/Setup.iss @@ -763,9 +763,129 @@ begin end; end; +// Shows a modal dialog letting the user choose how to handle mounted repos. +// Returns True if the user clicked Continue, False if Cancel. On Continue, +// KeepMounted is set to True if the user chose to stage the upgrade and +// leave repos mounted, or False to unmount and remount immediately. +function ShowMountChoiceDialog(Repos: String; var KeepMounted: Boolean): Boolean; +var + Form: TForm; + HeaderLbl, ReposLbl, RemountDescLbl, KeepDescLbl: TNewStaticText; + RemountRadio, KeepRadio: TNewRadioButton; + BtnContinue, BtnCancel: TNewButton; + ButtonWidth, ButtonHeight, ContentWidth, Margin, IndentMargin: Integer; + ModalResult, Y: Integer; +begin + Margin := ScaleX(15); + IndentMargin := ScaleX(34); + ButtonWidth := ScaleX(85); + ButtonHeight := ScaleY(25); + + Form := TForm.Create(nil); + try + Form.Caption := 'Setup'; + Form.BorderStyle := bsDialog; + Form.Position := poOwnerFormCenter; + Form.ClientWidth := ScaleX(520); + ContentWidth := Form.ClientWidth - (2 * Margin); + + Y := ScaleY(15); + + HeaderLbl := TNewStaticText.Create(Form); + HeaderLbl.Parent := Form; + HeaderLbl.Left := Margin; + HeaderLbl.Top := Y; + HeaderLbl.Caption := 'The following repos are currently mounted:'; + HeaderLbl.AutoSize := True; + Y := HeaderLbl.Top + HeaderLbl.Height + ScaleY(4); + + ReposLbl := TNewStaticText.Create(Form); + ReposLbl.Parent := Form; + ReposLbl.Left := IndentMargin; + ReposLbl.Top := Y; + ReposLbl.Width := Form.ClientWidth - IndentMargin - Margin; + ReposLbl.WordWrap := True; + ReposLbl.AutoSize := True; + ReposLbl.Caption := Trim(Repos); + Y := ReposLbl.Top + ReposLbl.Height + ScaleY(16); + + RemountRadio := TNewRadioButton.Create(Form); + RemountRadio.Parent := Form; + RemountRadio.Left := Margin; + RemountRadio.Top := Y; + RemountRadio.Width := ContentWidth; + RemountRadio.Caption := 'Remount repos as part of the installation'; + RemountRadio.Checked := True; + Y := RemountRadio.Top + RemountRadio.Height + ScaleY(2); + + RemountDescLbl := TNewStaticText.Create(Form); + RemountDescLbl.Parent := Form; + RemountDescLbl.Left := IndentMargin; + RemountDescLbl.Top := Y; + RemountDescLbl.Width := Form.ClientWidth - IndentMargin - Margin; + RemountDescLbl.WordWrap := True; + RemountDescLbl.AutoSize := True; + RemountDescLbl.Caption := 'They will be temporarily unavailable.'; + Y := RemountDescLbl.Top + RemountDescLbl.Height + ScaleY(14); + + KeepRadio := TNewRadioButton.Create(Form); + KeepRadio.Parent := Form; + KeepRadio.Left := Margin; + KeepRadio.Top := Y; + KeepRadio.Width := ContentWidth; + KeepRadio.Caption := 'Keep repos mounted'; + Y := KeepRadio.Top + KeepRadio.Height + ScaleY(2); + + KeepDescLbl := TNewStaticText.Create(Form); + KeepDescLbl.Parent := Form; + KeepDescLbl.Left := IndentMargin; + KeepDescLbl.Top := Y; + KeepDescLbl.Width := Form.ClientWidth - IndentMargin - Margin; + KeepDescLbl.WordWrap := True; + KeepDescLbl.AutoSize := True; + KeepDescLbl.Caption := 'The upgrade will complete automatically when all repos are unmounted, or at next reboot.'; + Y := KeepDescLbl.Top + KeepDescLbl.Height + ScaleY(20); + + BtnContinue := TNewButton.Create(Form); + BtnContinue.Parent := Form; + BtnContinue.Width := ButtonWidth; + BtnContinue.Height := ButtonHeight; + BtnContinue.Top := Y; + BtnContinue.Left := Form.ClientWidth - Margin - ButtonWidth - ScaleX(10) - ButtonWidth; + BtnContinue.Caption := '&Continue'; + BtnContinue.Default := True; + BtnContinue.ModalResult := mrOk; + + BtnCancel := TNewButton.Create(Form); + BtnCancel.Parent := Form; + BtnCancel.Width := ButtonWidth; + BtnCancel.Height := ButtonHeight; + BtnCancel.Top := Y; + BtnCancel.Left := Form.ClientWidth - Margin - ButtonWidth; + BtnCancel.Caption := '&Cancel'; + BtnCancel.Cancel := True; + BtnCancel.ModalResult := mrCancel; + + Form.ClientHeight := Y + ButtonHeight + ScaleY(15); + Form.ActiveControl := BtnContinue; + + ModalResult := Form.ShowModal(); + if ModalResult = mrOk then + begin + KeepMounted := KeepRadio.Checked; + Result := True; + end + else + begin + Result := False; + end; + finally + Form.Free(); + end; +end; + function PrepareToInstall(var NeedsRestart: Boolean): String; var - MsgBoxResult: integer; Repos: ansiString; ResultCode: integer; HasMounts: Boolean; @@ -805,19 +925,10 @@ begin end else begin - // Interactive mode: let user choose - MsgBoxResult := SuppressibleMsgBox( - 'The following repos are currently mounted:' + #13#10 + Repos + #13#10#13#10 + - 'Click Yes to keep repos mounted during the upgrade.' + #13#10 + - 'The upgrade will complete automatically when all repos are unmounted.' + #13#10#13#10 + - 'Click No to unmount all repos now and upgrade without restart.' + #13#10 + - 'Repos will be temporarily unavailable during the upgrade.', - mbConfirmation, MB_YESNOCANCEL, IDYES); - if MsgBoxResult = IDYES then - KeepMountsRunning := True - else if MsgBoxResult = IDNO then - KeepMountsRunning := False - else + // Interactive mode: show a radio-button modal so the user can pick + // between remounting (immediate but brief unavailability) and + // staging the upgrade (deferred until repos are unmounted). + if not ShowMountChoiceDialog(Repos, KeepMountsRunning) then begin Result := 'Installation cancelled.'; exit;