Skip to content

Introduse the ability to postpone a downloaded update #4263#6355

Merged
michaelDCurran merged 29 commits into
nvaccess:masterfrom
BabbageCom:t4263
Mar 28, 2018
Merged

Introduse the ability to postpone a downloaded update #4263#6355
michaelDCurran merged 29 commits into
nvaccess:masterfrom
BabbageCom:t4263

Conversation

@LeonarddeR

@LeonarddeR LeonarddeR commented Sep 6, 2016

Copy link
Copy Markdown
Collaborator

Closes #4263
closes #6281
closes #4020

First of all, many thanks to @zahyur who actually did the major work for this.
This pull request introduces the possibility to postpone a downloaded update. Comment and discussion in #4263 has been processed in this request. Also, I decided to make installing postponed updates from the menu possible regardless of showing the exit dialog has been disabled.

This code still needs testing in real live, which is quite hard from source, without real updatable builds.

Changelog entry

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

I wonder, is there still desire to leave this open? I initially found this a quite interesting idea and the code was already there for the most part.

cc @feerrenrut

@feerrenrut

Copy link
Copy Markdown
Contributor

Yes, I think so. I will review it shortly. Unless it has been obsoleted by some other change?

@feerrenrut feerrenrut self-requested a review August 30, 2017 08:42

@feerrenrut feerrenrut left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it's taken a while for this to be looked at. I think I will need to go over this again, but hopefully we can start by agreeing on the UX for this change.

Comment thread source/updateCheck.py Outdated
message = _("NVDA version {version} is available.").format(**updateInfo)
if isPendingUpdate() and state["pendingUpdateVersion"] == updateInfo["version"]:
# Translators: A message indicating that an updated version of NVDA is already pending to be installed.
message = _("The latest update is already pending to be installed.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the wording of this could be better, first I want to double check I understand correctly that this message will be shown after NVDA has confirmed that the pending installation is in fact the latest available update? If so, I think the # Translators: comment could be clearer also, perhaps A message indicating that the latest version of NVDA has been downloaded and is waiting to be installed

Since we specify the version when we specify that the availability of the update, I think we should do this here also, so perhaps something like NVDA version {version} is pending installation or NVDA version {version} is ready to be installed

Comment thread source/updateCheck.py Outdated
message=_("You can install it now, or install it later from the NVDA menu or the exit dialog, if enabled.\n")
mainSizer.Add(wx.StaticText(self, label=
# Translators: A message indicating that an updated version of NVDA is ready to be installed.
_("Update is ready to install.\n")+message+

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This building up of messages has a risk that it won't make sense once translated. I also think these labels could be simplified. I think it is adequate to simply set the label as "Update is ready to install" and rely on the presence of the buttons to indicate what options are available.

Comment thread source/updateCheck.py Outdated
except:
gui.messageBox(
# Translators: The message when a downloaded update file could not be preserved.
_("The downloaded file could not be postponed properly."),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would word this "Unable to postpone update"

Comment thread source/updateCheck.py Outdated
gui.messageBox(
# Translators: The message when a downloaded update file could not be preserved.
_("The downloaded file could not be postponed properly."),
_("Error"), wx.OK | wx.ICON_ERROR)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing a translator comment. I think there is an automated test that would catch this, you can run this with scons checkPot

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

It seems that when I reviewed this code earlier and made it ready for a pr, I missed some major things that really need to be fixed before this even works. The major downside with this code is that it is very difficult to test, at least when running from source. @feerrenrut, I've addressed your review comments although not yet pushed. However, let me do some additional testing before I ask you to come back to this again.

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

I've been able to test this to some extend, however as pointed out, it requires some ugly hacking as NVDA only allows itself to be updated in official snapshot or release cases. I'd also like to incorporate support for portable copy updating while at it.

@feerrenrut

Copy link
Copy Markdown
Contributor

Ok, please request a review again when you are ready for me to take another look at it.

@feerrenrut feerrenrut self-requested a review January 15, 2018 00:38
Comment thread source/gui/__init__.py
try:
self.sysTrayIcon.menu.RemoveItem(self.sysTrayIcon.runPendingUpdateMenuItem)
except:
pass

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth logging something here at debug level.

Comment thread source/gui/__init__.py Outdated
except:
pass
if updateCheck and updateCheck.isPendingUpdate():
self.sysTrayIcon.menu.InsertItem(self.sysTrayIcon.menu.GetMenuItemCount()-2,self.sysTrayIcon.runPendingUpdateMenuItem)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with the -2. Is this the position. Might be clearer to put this in a pendingUpdateMenuItemPosition variable. Is it important for it to be second from the bottom? I am concerned that because this positioning is separated from the rest of that menu filing that the order might change, and this code wont be considered. The index of the position for this item could be saved at the point where the rest of the menu is populated.

Comment thread source/config/__init__.py
if not os.path.isdir(curDestDir):
os.makedirs(curDestDir)
for f in files:
if f.endswith(".exe"):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps a comment to say why exe files should be skipped?

Comment thread source/updateCheck.py Outdated
state["removeFile"] = destPath
saveState()
if config.isInstalledCopy():
exeCuteParams = u"--install -m"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like a bug, here exeCuteParams has a capital C, and where it is passed to ShellExecute it does not.

Comment thread source/updateCheck.py
saveState()
self.Close()

class UpdateAskInstallDialog(wx.Dialog):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a feeling that this dialog wont have the visual spacing expected between labels and buttons. What is the easiest way to test this, so I can inspect it?

@LeonarddeR LeonarddeR Jan 24, 2018

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some guiHelper stuff to it now. Here is a code snippet to make it show up:

import versionInfo, gui
versionInfo.updateVersionType="snapshot:next"
import updateCheck
updateCheck.initialize()
updateCheck.UpdateAskInstallDialog(gui.mainFrame, "dummy_path", "2018.3")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the snippet. It looks ok to me.

Comment thread source/updateCheck.py Outdated
wx.OK | wx.ICON_ERROR)

def _downloadSuccess(self):
# global storeUpdatesDir

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this can be removed?

Comment thread source/updateCheck.py Outdated
wx.OK | wx.ICON_ERROR)

def _downloadSuccess(self):
# global storeUpdatesDir

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be uncommented / removed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has already been removed. Probably legacy code from the initial author, but storeUpdatesDir doesn't have to be changed inside this function.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry I must have misread this line.

Comment thread source/gui/__init__.py Outdated
]
if updateCheck and updateCheck.isPendingUpdate():
# Translators: An option in the combo box to choose exit action.
self.actions.append(_("Run pending update"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elsewhere we say "Install update" rather than "run update", I think "Install pending update" would be more consistent.

Comment thread source/updateCheck.py Outdated
sHelper = guiHelper.BoxSizerHelper(self, orientation=wx.VERTICAL)

# Translators: A message indicating that an updated version of NVDA is ready to be installed.
sHelper.addItem(wx.StaticText(self, label=_("Update is ready to install.\n")))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this dialog should tell you the updates version information? To be consistent with the other download update dialog?

Comment thread user_docs/en/userGuide.t2t Outdated
==== Show exit options when exiting NVDA ====[GeneralSettingsShowExitOptions]
This option is a checkbox that allows you to choose whether or not a dialog appears when you exit NVDA that asks what action you want to perform.
When checked, a dialog will appear when you attempt to exit NVDA asking whether you want to exit, restart or restart with add-ons disabled.
When checked, a dialog will appear when you attempt to exit NVDA asking whether you want to exit, restart, restart with addons disabled or Run pending updates (if any).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few places here that still refer to "run pending updates"

Comment thread user_docs/en/userGuide.t2t Outdated

==== Notify for pending updates on startup ====[GeneralSettingsNotifyPendingUpdates]
If this is enabled, NVDA will inform you when there is a pending update on startup, offering you the possibility to install it.
You can also manually run the pending update from the Exit NVDA dialog (if enabled), from the NVDA menu, or when you perform a new check from the Hel pmenu.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also refers to "run the pending update"

There is also a typo, a space needs to move one character over in Hel pmenu

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

Note that with my most recent change, the behavior of the "Notify for pending update on startup" option has changed a little. As this functionality now resides in the AutoUpdateChecker, a pending update will be ignored if there is a version available that is newer than the pending update. I think this behavior is desirable, it does not make sense to install a pending update and notice afterwards that it wasn't the most recent update available. As a side effect, the pending update notification won't show up if the update check fails due to no internet connection available. People will still be able to install the postponed update from the menu or using the exit dialog, though.

@Brian1Gaff

Brian1Gaff commented Feb 7, 2018 via email

Copy link
Copy Markdown

@feerrenrut feerrenrut self-requested a review February 8, 2018 06:56
Comment thread source/updateCheck.py Outdated
mainSizer.Fit(self)
self.Center(wx.BOTH | wx.CENTER_ON_SCREEN)
self.Show()
gui.mainFrame.prePopup()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's this about?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you call this, I think you also need to call postPopup().

@LeonarddeR LeonarddeR Feb 9, 2018

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you'd think so. The use of prePopup and postPopup inside updateCheck really puzzles me.

  1. prePopup is only used in the UpdateDownloader, not for the other dialogs. It was called for the old update installation message box, so that's why I belief it should be called in the UpdateAskInstallDialog as well.
  2. postPopup is even more confusing given it is being called in a wx.CallLater with a not very descriptive comment. A git blame points at @jcsteh, so may be he knows more?
  3. In several places in the gui module, you see the following code:
mainFrame.prePopup()
dialog.Show()
mainFrame.postPopup()

However, this doesn't seem to make much sense, as Show doesn't block the caller. For ShowModal, it does make sense as ShowModal blocks the caller until the dialog is dismissed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps its better to use def runScriptModalDialog in source/gui/__init__

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR: The general rule is that if you're popping up a window (as opposed to a window which appears as a result of some action performed while our GUI was already visible), you must call prePopup. If you call prePopup, there must be a corresponding call to postPopup. Ideally, this postPopup call would occur once the window is dismissed, but for windows that aren't modal, it's enough in most cases to just call it after Show.

prePopup and postPopup have two major functions:

  1. To force Windows to bring us to the foreground (prePopup) and to return to the previous foreground (postPopup). The way foreground stuff works in Windows is really obscure. prePopup mostly makes sense; we ask Windows to bring us to the foreground. However, we were seeing cases where the user would just be stuck in limbo when our pop-ups were dismissed. I still don't really understand why this is the case, but the show/hide in postPopup seemed to fix it. (Obviously, that doesn't actually get applied at the right tie for dialogs that aren't modal, but it seems to behave regardless.) This code is very old, wx has been updated and Windows XP is no longer a factor, so you could consider re-assessing to see whether we can get rid of this ugliness. However, note that installed versus portable is still a factor, since uiAccess gives the app special privileges regarding the foreground window.
  2. These methods also set things up so that NVDA is aware of what the focus was before the pop-up. This is important for input gestures, for example, so it knows which object to get gestures for. postPopup does the necessary teardown of this state. The fact that it gets called immediately after Show is fine in this case because the dialog should already have done what it needs to do with this state.

@LeonarddeR

LeonarddeR commented Feb 9, 2018 via email

Copy link
Copy Markdown
Collaborator Author

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

@feerrenrut: IN 20407fb I started to use scriptRunModalDialog

@feerrenrut

Copy link
Copy Markdown
Contributor

Ok, looks good. I will incubate this again.

feerrenrut added a commit that referenced this pull request Feb 14, 2018
Merge remote-tracking branch 'origin/pr/6355' into next
…t do this, a user will never be reminded about a postponed update automatically at all
@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

@feerrenrut: Three cheers for broken code. Just tried to fix another small bug, namely that postponing an update does not clear the don't remind version. This means that the don't remind version and the pending version are equal, in which case the AutoUpdateChecker would never pop up a reminder.

@Brian1Gaff

Brian1Gaff commented Feb 15, 2018 via email

Copy link
Copy Markdown

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

@feerrenrut: Could you please review 4a4f7c4?

@feerrenrut feerrenrut left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest commit makes sense. I think it would be handy to have a manual test plan for this feature. Outline all the possible paths that one can take, and what is expected to happen. It might help to highlight some case that has not yet been explored.

feerrenrut added a commit that referenced this pull request Mar 7, 2018
Merge remote-tracking branch 'origin/pr/6355' into next
michaelDCurran added a commit that referenced this pull request Mar 14, 2018
@michaelDCurran michaelDCurran merged commit b3daebb into nvaccess:master Mar 28, 2018
@nvaccessAuto nvaccessAuto added this to the 2018.2 milestone Mar 28, 2018
@LeonarddeR LeonarddeR added the BabbageWork Pull requests filed on behalf of Babbage B.V. label Oct 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BabbageWork Pull requests filed on behalf of Babbage B.V.

Projects

None yet

10 participants