Change:
We should push the update UI we were running on insiders to stable. Since the new update notification UI is less invasive, there is the concern that users might forget to update and ignore the notification. Therefore we should add an update reminder, when a user did not update after a period of time. The proposal is to show the existing Update Available message box, when the user did not update after 5 days since the notification has appeared.
Will be fixed by
Fixed.

Discussion:
import * as nls from 'vs/nls'; import 'vs/css!./media/update.contribution'; import { Registry } from 'vs/platform/registry/common/platform'; <del> import { isMacintosh } from 'vs/base/common/platform'; import product from 'vs/platform/node/product'; </del> import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { ReleaseNotesEditor } from 'vs/workbench/parts/update/electron-browser/releaseNotesEditor'; import { ReleaseNotesInput } from 'vs/workbench/parts/update/electron-browser/releaseNotesInput';

import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actionRegistry'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; <del> import { ShowCurrentReleaseNotesAction, ProductContribution, UpdateContribution, LightUpdateContribution } from './update'; </del> <ins> import { ShowCurrentReleaseNotesAction, ProductContribution, UpdateContribution } from './update'; </ins> Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(ProductContribution); <del> if (isMacintosh || product.quality !== 'stable') { Registry.as<IGlobalActivityRegistry>(GlobalActivityExtensions) .registerActivity(LightUpdateContribution); } else { Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench) .registerWorkbenchContribution(UpdateContribution); } </del> <ins> Registry.as<IGlobalActivityRegistry>(GlobalActivityExtensions) .registerActivity(UpdateContribution); </ins> // Editor const editorDescriptor = new EditorDescriptor(

import severity from 'vs/base/common/severity'; import { TPromise } from 'vs/base/common/winjs.base'; import { IAction, Action } from 'vs/base/common/actions'; <ins> import { mapEvent } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; </ins> import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IMessageService, CloseAction, Severity } from 'vs/platform/message/common/message'; import pkg from 'vs/platform/node/package';

} } <del> export class UpdateContribution implements IWorkbenchContribution { getId() { return 'vs.update'; } </del> <ins> class CommandAction extends Action { </ins> constructor( <del> @IInstantiationService instantiationService: IInstantiationService, @IMessageService messageService: IMessageService, @IUpdateService updateService: IUpdateService </del> <ins> commandId: string, label: string, @ICommandService private commandService: ICommandService </ins> ) { <del> updateService.onUpdateReady(update => { const applyUpdateAction = instantiationService.createInstance(ApplyUpdateAction); const releaseNotesAction = instantiationService.createInstance(ShowReleaseNotesAction, false, update.version); messageService.show(severity.Info, { message: nls.localize('updateAvailable', "{0} will be updated after it restarts.", product.nameLong), actions: [applyUpdateAction, NotNowAction, releaseNotesAction] }); }); updateService.onUpdateAvailable(update => { const downloadAction = instantiationService.createInstance(DownloadAction, update.version); const releaseNotesAction = instantiationService.createInstance(ShowReleaseNotesAction, false, update.version); messageService.show(severity.Info, { message: nls.localize('thereIsUpdateAvailable', "There is an available update."), actions: [downloadAction, NotNowAction, releaseNotesAction] }); }); updateService.onUpdateNotAvailable(explicit => { if (!explicit) { return; } messageService.show(severity.Info, nls.localize('noUpdatesAvailable', "There are no updates currently available.")); }); updateService.onError(err => messageService.show(severity.Error, err)); </del> <ins> super(`command-action:${commandId}`, label, undefined, true, () => commandService.executeCommand(commandId)); </ins> } } <del> export class LightUpdateContribution implements IGlobalActivity { </del> <ins> export class UpdateContribution implements IGlobalActivity { </ins> private static readonly showCommandsId = 'workbench.action.showCommands'; private static readonly openSettingsId = 'workbench.action.openGlobalSettings';

get id() { return 'vs.update'; } get name() { return ''; } get cssClass() { return 'update-activity'; } <ins> private disposables: IDisposable[] = []; </ins> constructor( <del> @IStorageService storageService: IStorageService, </del> <ins> @IStorageService private storageService: IStorageService, </ins> @ICommandService private commandService: ICommandService, <del> @IInstantiationService instantiationService: IInstantiationService, @IMessageService messageService: IMessageService, </del> <ins> @IInstantiationService private instantiationService: IInstantiationService, @IMessageService private messageService: IMessageService, </ins> @IUpdateService private updateService: IUpdateService, @IWorkbenchEditorService editorService: IWorkbenchEditorService, <del> @IActivityBarService activityBarService: IActivityBarService </del> <ins> @IActivityBarService private activityBarService: IActivityBarService </ins> ) { <del> const addBadge = () => { const badge = new NumberBadge(1, () => nls.localize('updateIsReady', "New update available.")); activityBarService.showGlobalActivity(this.id, badge); }; </del> <ins> const onUpdateAvailable = isLinux ? mapEvent(updateService.onUpdateAvailable, e => e.version) : mapEvent(updateService.onUpdateReady, e => e.version); onUpdateAvailable(this.onUpdateAvailable, this, this.disposables); updateService.onError(this.onError, this, this.disposables); updateService.onUpdateNotAvailable(this.onUpdateNotAvailable, this, this.disposables); /* The `update/lastKnownVersion` and `update/updateNotificationTime` storage keys are used in combination to figure out when to show a message to the user that he should update. This message should appear if the user has received an update notification but hasn't updated since 5 days. */ const currentVersion = product.commit; const lastKnownVersion = this.storageService.get('update/lastKnownVersion', StorageScope.GLOBAL); // if current version != stored version, clear both fields if (currentVersion !== lastKnownVersion) { this.storageService.remove('update/lastKnownVersion', StorageScope.GLOBAL); this.storageService.remove('update/updateNotificationTime', StorageScope.GLOBAL); } } private onUpdateAvailable(version: string): void { const badge = new NumberBadge(1, () => nls.localize('updateIsReady', "New update available.")); this.activityBarService.showGlobalActivity(this.id, badge); const currentVersion = product.commit; const currentMillis = new Date().getTime(); const lastKnownVersion = this.storageService.get('update/lastKnownVersion', StorageScope.GLOBAL); // if version != stored version, save version and date if (currentVersion !== lastKnownVersion) { this.storageService.store('update/lastKnownVersion', currentVersion, StorageScope.GLOBAL); this.storageService.store('update/updateNotificationTime', currentMillis, StorageScope.GLOBAL); } const updateNotificationMillis = this.storageService.getInteger('update/updateNotificationTime', StorageScope.GLOBAL, currentMillis); const diffDays = (currentMillis - updateNotificationMillis) / (1000 * 60 * 60 * 24); // if 5 days have passed from stored date, show message service if (diffDays > 5) { this.showUpdateNotification(version); } } private showUpdateNotification(version: string): void { const releaseNotesAction = this.instantiationService.createInstance(ShowReleaseNotesAction, false, version); </ins> if (isLinux) { <del> this.updateService.onUpdateAvailable(() => addBadge()); </del> <ins> const downloadAction = this.instantiationService.createInstance(DownloadAction, version); this.messageService.show(severity.Info, { message: nls.localize('thereIsUpdateAvailable', "There is an available update."), actions: [downloadAction, NotNowAction, releaseNotesAction] }); </ins> } else { <del> this.updateService.onUpdateReady(() => addBadge()); </del> <ins> const applyUpdateAction = this.instantiationService.createInstance(ApplyUpdateAction); this.messageService.show(severity.Info, { message: nls.localize('updateAvailable', "{0} will be updated after it restarts.", product.nameLong), actions: [applyUpdateAction, NotNowAction, releaseNotesAction] }); </ins> } <ins> } </ins> <del> this.updateService.onError(err => messageService.show(severity.Error, err)); </del> <ins> private onUpdateNotAvailable(explicit: boolean): void { if (!explicit) { return; } </ins> <del> this.updateService.onUpdateNotAvailable(explicit => { if (!explicit) { return; } </del> <ins> this.messageService.show(severity.Info, nls.localize('noUpdatesAvailable', "There are no updates currently available.")); } </ins> <del> messageService.show(severity.Info, nls.localize('noUpdatesAvailable', "There are no updates currently available.")); }); </del> <ins> private onError(err: any): void { this.messageService.show(severity.Error, err); </ins> } getActions(): IAction[] { <ins> const updateAction = this.getUpdateAction(); </ins> return [ <del> new Action(LightUpdateContribution.showCommandsId, nls.localize('commandPalette', "Command Palette..."), undefined, true, () => this.commandService.executeCommand(LightUpdateContribution.showCommandsId)), </del> <ins> new CommandAction(UpdateContribution.showCommandsId, nls.localize('commandPalette', "Command Palette..."), this.commandService), </ins> new Separator(), <del> new Action(LightUpdateContribution.openSettingsId, nls.localize('settings', "Settings"), null, true, () => this.commandService.executeCommand(LightUpdateContribution.openSettingsId)), new Action(LightUpdateContribution.openKeybindingsId, nls.localize('keyboardShortcuts', "Keyboard Shortcuts"), null, true, () => this.commandService.executeCommand(LightUpdateContribution.openKeybindingsId)), </del> <ins> new CommandAction(UpdateContribution.openSettingsId, nls.localize('settings', "Settings"), this.commandService), new CommandAction(UpdateContribution.openKeybindingsId, nls.localize('keyboardShortcuts', "Keyboard Shortcuts"), this.commandService), </ins> new Separator(), <del> new Action(LightUpdateContribution.selectColorThemeId, nls.localize('selectTheme.label', "Color Theme"), null, true, () => this.commandService.executeCommand(LightUpdateContribution.selectColorThemeId)), new Action(LightUpdateContribution.selectIconThemeId, nls.localize('themes.selectIconTheme.label', "File Icon Theme"), null, true, () => this.commandService.executeCommand(LightUpdateContribution.selectIconThemeId)), </del> <ins> new CommandAction(UpdateContribution.selectColorThemeId, nls.localize('selectTheme.label', "Color Theme"), this.commandService), new CommandAction(UpdateContribution.selectIconThemeId, nls.localize('themes.selectIconTheme.label', "File Icon Theme"), this.commandService), </ins> new Separator(), <del> this.getUpdateAction() </del> <ins> updateAction </ins> ]; }

this.updateService.checkForUpdates(true)); } } <ins> dispose(): void { this.disposables = dispose(this.disposables); } </ins> }  No newline at end of file