Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit 180e4cc

Browse files
committed
Merge pull request #7330 from adobe/zaggino/check-for-update
Check for extensions updates
2 parents a2ce391 + 5560bc2 commit 180e4cc

9 files changed

Lines changed: 239 additions & 73 deletions

src/brackets.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,13 +296,9 @@ define(function (require, exports, module) {
296296

297297
// Check for updates
298298
if (!params.get("skipUpdateCheck") && !brackets.inBrowser) {
299-
// check once a day, plus 2 minutes,
300-
// as the check will skip if the last check was not -24h ago
301-
window.setInterval(UpdateNotification.checkForUpdate, 86520000);
302-
303-
// Check for updates on App Ready
304299
AppInit.appReady(function () {
305-
UpdateNotification.checkForUpdate();
300+
// launches periodic checks for updates cca every 24 hours
301+
UpdateNotification.launchAutomaticUpdate();
306302
});
307303
}
308304
}

src/extensibility/ExtensionManager.js

Lines changed: 105 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
define(function (require, exports, module) {
4040
"use strict";
4141

42-
var FileUtils = require("file/FileUtils"),
42+
var _ = require("thirdparty/lodash"),
43+
FileUtils = require("file/FileUtils"),
4344
Package = require("extensibility/Package"),
4445
Async = require("utils/Async"),
4546
ExtensionLoader = require("utils/ExtensionLoader"),
@@ -105,13 +106,28 @@ define(function (require, exports, module) {
105106
}
106107

107108
entry.installInfo.owner = entry.registryInfo.owner;
108-
if (entry.installInfo.metadata && entry.installInfo.metadata.version && semver.lt(entry.installInfo.metadata.version, entry.registryInfo.metadata.version)) {
109+
110+
// Assume false
111+
entry.installInfo.updateAvailable = false;
112+
entry.registryInfo.updateAvailable = false;
113+
entry.installInfo.updateCompatible = false;
114+
entry.registryInfo.updateCompatible = false;
115+
116+
var currentVersion = entry.installInfo.metadata ? entry.installInfo.metadata.version : null;
117+
if (currentVersion && semver.lt(currentVersion, entry.registryInfo.metadata.version)) {
109118
// Note: available update may still be incompatible; we check for this when rendering the Update button in ExtensionManagerView._renderItem()
110-
entry.registryInfo.updateAvailable = true;
111-
entry.installInfo.updateAvailable = true;
112-
} else {
113-
entry.installInfo.updateAvailable = false;
114-
entry.registryInfo.updateAvailable = false;
119+
entry.registryInfo.updateAvailable = true;
120+
entry.installInfo.updateAvailable = true;
121+
// Calculate updateCompatible to check if there's an update for current version of Brackets
122+
var lastCompatibleVersionInfo = _.findLast(entry.registryInfo.versions, function (versionInfo) {
123+
return semver.satisfies(brackets.metadata.apiVersion, versionInfo.brackets);
124+
});
125+
if (lastCompatibleVersionInfo && lastCompatibleVersionInfo.version && semver.lt(currentVersion, lastCompatibleVersionInfo.version)) {
126+
entry.installInfo.updateCompatible = true;
127+
entry.registryInfo.updateCompatible = true;
128+
entry.installInfo.lastCompatibleVersion = lastCompatibleVersionInfo.version;
129+
entry.registryInfo.lastCompatibleVersion = lastCompatibleVersionInfo.version;
130+
}
115131
}
116132

117133
$(exports).triggerHandler("registryUpdate", [id]);
@@ -160,6 +176,7 @@ define(function (require, exports, module) {
160176
extensions[id].registryInfo = data[id];
161177
synchronizeEntry(id);
162178
});
179+
$(exports).triggerHandler("registryDownload");
163180
result.resolve();
164181
})
165182
.fail(function () {
@@ -506,39 +523,94 @@ define(function (require, exports, module) {
506523
);
507524
}
508525

526+
/**
527+
* Gets an array of extensions that are currently installed and can be updated to a new version
528+
* @return {Array.<{id: string, installVersion: string, registryVersion: string}>}
529+
* where id = extensionId
530+
* installVersion = currently installed version of extension
531+
* registryVersion = latest version compatible with current Brackets
532+
*/
533+
function getAvailableUpdates() {
534+
var result = [];
535+
Object.keys(extensions).forEach(function (extensionId) {
536+
var extensionInfo = extensions[extensionId];
537+
// skip extensions that are not installed or are not in the registry
538+
if (!extensionInfo.installInfo || !extensionInfo.registryInfo) {
539+
return;
540+
}
541+
if (extensionInfo.registryInfo.updateCompatible) {
542+
result.push({
543+
id: extensionId,
544+
installVersion: extensionInfo.installInfo.metadata.version,
545+
registryVersion: extensionInfo.registryInfo.lastCompatibleVersion
546+
});
547+
}
548+
});
549+
return result;
550+
}
551+
552+
/**
553+
* Takes the array returned from getAvailableUpdates() as an input and removes those entries
554+
* that are no longer current - when currently installed version of an extension
555+
* is equal or newer than registryVersion returned by getAvailableUpdates().
556+
* This function is designed to work without the necessity to download extension registry
557+
* @param {Array.<{id: string, installVersion: string, registryVersion: string}>} updates
558+
* previous output of getAvailableUpdates()
559+
* @return {Array.<{id: string, installVersion: string, registryVersion: string}>}
560+
* filtered input as function description
561+
*/
562+
function cleanAvailableUpdates(updates) {
563+
return updates.reduce(function (arr, updateInfo) {
564+
var extDefinition = extensions[updateInfo.id];
565+
if (!extDefinition || !extDefinition.installInfo) {
566+
// extension has been uninstalled in the meantime
567+
return arr;
568+
}
569+
570+
var installedVersion = extDefinition.installInfo.metadata.version;
571+
if (semver.lt(installedVersion, updateInfo.registryVersion)) {
572+
arr.push(updateInfo);
573+
}
574+
575+
return arr;
576+
}, []);
577+
}
578+
509579
// Listen to extension load and loadFailed events
510580
$(ExtensionLoader)
511581
.on("load", _handleExtensionLoad)
512582
.on("loadFailed", _handleExtensionLoad);
513583

514584
// Public exports
515-
exports.downloadRegistry = downloadRegistry;
516-
exports.getCompatibilityInfo = getCompatibilityInfo;
517-
exports.getExtensionURL = getExtensionURL;
518-
exports.remove = remove;
519-
exports.update = update;
520-
exports.extensions = extensions;
521-
exports.cleanupUpdates = cleanupUpdates;
522-
exports.markForRemoval = markForRemoval;
523-
exports.isMarkedForRemoval = isMarkedForRemoval;
524-
exports.unmarkAllForRemoval = unmarkAllForRemoval;
525-
exports.hasExtensionsToRemove = hasExtensionsToRemove;
526-
exports.updateFromDownload = updateFromDownload;
527-
exports.removeUpdate = removeUpdate;
528-
exports.isMarkedForUpdate = isMarkedForUpdate;
529-
exports.hasExtensionsToUpdate = hasExtensionsToUpdate;
530-
exports.removeMarkedExtensions = removeMarkedExtensions;
531-
exports.updateExtensions = updateExtensions;
585+
exports.downloadRegistry = downloadRegistry;
586+
exports.getCompatibilityInfo = getCompatibilityInfo;
587+
exports.getExtensionURL = getExtensionURL;
588+
exports.remove = remove;
589+
exports.update = update;
590+
exports.extensions = extensions;
591+
exports.cleanupUpdates = cleanupUpdates;
592+
exports.markForRemoval = markForRemoval;
593+
exports.isMarkedForRemoval = isMarkedForRemoval;
594+
exports.unmarkAllForRemoval = unmarkAllForRemoval;
595+
exports.hasExtensionsToRemove = hasExtensionsToRemove;
596+
exports.updateFromDownload = updateFromDownload;
597+
exports.removeUpdate = removeUpdate;
598+
exports.isMarkedForUpdate = isMarkedForUpdate;
599+
exports.hasExtensionsToUpdate = hasExtensionsToUpdate;
600+
exports.removeMarkedExtensions = removeMarkedExtensions;
601+
exports.updateExtensions = updateExtensions;
602+
exports.getAvailableUpdates = getAvailableUpdates;
603+
exports.cleanAvailableUpdates = cleanAvailableUpdates;
532604

533-
exports.ENABLED = ENABLED;
534-
exports.START_FAILED = START_FAILED;
605+
exports.ENABLED = ENABLED;
606+
exports.START_FAILED = START_FAILED;
535607

536-
exports.LOCATION_DEFAULT = LOCATION_DEFAULT;
537-
exports.LOCATION_DEV = LOCATION_DEV;
538-
exports.LOCATION_USER = LOCATION_USER;
539-
exports.LOCATION_UNKNOWN = LOCATION_UNKNOWN;
608+
exports.LOCATION_DEFAULT = LOCATION_DEFAULT;
609+
exports.LOCATION_DEV = LOCATION_DEV;
610+
exports.LOCATION_USER = LOCATION_USER;
611+
exports.LOCATION_UNKNOWN = LOCATION_UNKNOWN;
540612

541613
// For unit testing only
542-
exports._reset = _reset;
543-
exports._setExtensions = _setExtensions;
544-
});
614+
exports._reset = _reset;
615+
exports._setExtensions = _setExtensions;
616+
});

src/extensibility/ExtensionManagerView.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ define(function (require, exports, module) {
219219

220220
var isInstalledInUserFolder = (entry.installInfo && entry.installInfo.locationType === ExtensionManager.LOCATION_USER);
221221
context.allowRemove = isInstalledInUserFolder;
222-
context.allowUpdate = context.showUpdateButton && context.isCompatible && context.isCompatibleLatest && isInstalledInUserFolder;
222+
context.allowUpdate = context.showUpdateButton && context.isCompatible && context.updateCompatible && isInstalledInUserFolder;
223223
if (!context.allowUpdate) {
224224
context.updateNotAllowedReason = isInstalledInUserFolder ? Strings.CANT_UPDATE : Strings.CANT_UPDATE_DEV;
225225
}
@@ -310,4 +310,4 @@ define(function (require, exports, module) {
310310
};
311311

312312
exports.ExtensionManagerView = ExtensionManagerView;
313-
});
313+
});

src/extensibility/ExtensionManagerViewModel.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,13 @@ define(function (require, exports, module) {
366366
*/
367367
function InstalledViewModel() {
368368
ExtensionManagerViewModel.call(this);
369+
370+
// when registry is downloaded, sort extensions again - those with updates will be before others
371+
var self = this;
372+
$(ExtensionManager).on("registryDownload", function () {
373+
self._sortFullSet();
374+
self._setInitialFilter();
375+
});
369376
}
370377

371378
InstalledViewModel.prototype = Object.create(ExtensionManagerViewModel.prototype);
@@ -405,17 +412,22 @@ define(function (require, exports, module) {
405412
var self = this;
406413

407414
this.sortedFullSet = this.sortedFullSet.sort(function (key1, key2) {
408-
var metadata1 = self.extensions[key1].installInfo.metadata,
409-
metadata2 = self.extensions[key2].installInfo.metadata,
410-
id1 = (metadata1.title || metadata1.name).toLowerCase(),
411-
id2 = (metadata2.title || metadata2.name).toLowerCase();
412-
if (id1 < id2) {
415+
// before sorting by name, put first extensions that have updates
416+
var ua1 = self.extensions[key1].installInfo.updateAvailable,
417+
ua2 = self.extensions[key2].installInfo.updateAvailable;
418+
419+
if (ua1 && !ua2) {
413420
return -1;
414-
} else if (id1 === id2) {
415-
return 0;
416-
} else {
421+
} else if (!ua1 && ua2) {
417422
return 1;
418423
}
424+
425+
var metadata1 = self.extensions[key1].installInfo.metadata,
426+
metadata2 = self.extensions[key2].installInfo.metadata,
427+
id1 = (metadata1.title || metadata1.name).toLocaleLowerCase(),
428+
id2 = (metadata2.title || metadata2.name).toLocaleLowerCase();
429+
430+
return id1.localeCompare(id2);
419431
});
420432
};
421433

@@ -427,7 +439,7 @@ define(function (require, exports, module) {
427439
var self = this;
428440
this.notifyCount = 0;
429441
this.sortedFullSet.forEach(function (key) {
430-
if (self.extensions[key].installInfo.updateAvailable) {
442+
if (self.extensions[key].installInfo.updateCompatible) {
431443
self.notifyCount++;
432444
}
433445
});
@@ -483,4 +495,4 @@ define(function (require, exports, module) {
483495

484496
exports.RegistryViewModel = RegistryViewModel;
485497
exports.InstalledViewModel = InstalledViewModel;
486-
});
498+
});

src/styles/brackets.less

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,10 @@ a, img {
500500
}
501501

502502
#toolbar-extension-manager {
503-
.sprite-icon(0, 0, 24px, 24px, "images/topcoat-plugin-20.svg");
503+
.sprite-icon(0, 0, 24px, 24px, "images/extension-manager-sprite.svg");
504+
&.updatesAvailable {
505+
.sprite-icon(0, 24px, 24px, 24px, "images/extension-manager-sprite.svg");
506+
}
504507
}
505508

506509
/* Project panel */
Lines changed: 9 additions & 0 deletions
Loading

src/styles/images/topcoat-plugin-20.svg

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)