Singleton manager updates to handle retrieved and saved items independently

This commit is contained in:
Mo Bitar
2018-01-20 10:39:00 -06:00
parent af8cdf5a41
commit 02f77b67b0
5 changed files with 45 additions and 27 deletions

View File

@@ -90,7 +90,6 @@ class AccountMenu {
} }
$scope.submitAuthForm = function() { $scope.submitAuthForm = function() {
console.log("Submitting auth form");
if(!$scope.formData.email || !$scope.formData.user_password) { if(!$scope.formData.email || !$scope.formData.user_password) {
return; return;
} }
@@ -102,7 +101,6 @@ class AccountMenu {
} }
$scope.login = function(extraParams) { $scope.login = function(extraParams) {
console.log("Logging in");
$scope.formData.status = "Generating Login Keys..."; $scope.formData.status = "Generating Login Keys...";
$timeout(function(){ $timeout(function(){
authManager.login($scope.formData.url, $scope.formData.email, $scope.formData.user_password, $scope.formData.ephemeral, extraParams, authManager.login($scope.formData.url, $scope.formData.email, $scope.formData.user_password, $scope.formData.ephemeral, extraParams,

View File

@@ -79,7 +79,6 @@ class ComponentManager {
]; ];
this.runWithPermissions(observer.component, requiredPermissions, () => { this.runWithPermissions(observer.component, requiredPermissions, () => {
console.log("Stream observer, sending items", relevantItems);
this.sendItemsInReply(observer.component, relevantItems, observer.originalMessage); this.sendItemsInReply(observer.component, relevantItems, observer.originalMessage);
}) })
} }

View File

@@ -22,14 +22,15 @@ class SingletonManager {
$rootScope.$on("sync:completed", (event, data) => { $rootScope.$on("sync:completed", (event, data) => {
// The reason we also need to consider savedItems in consolidating singletons is in case of sync conflicts, // The reason we also need to consider savedItems in consolidating singletons is in case of sync conflicts,
// a new item can be created, but is never processed through "retrievedItems" since it is only created locally then saved. // a new item can be created, but is never processed through "retrievedItems" since it is only created locally then saved.
// HOWEVER, by considering savedItems, we are now ruining everything, especially during sign in. A singleton can be created
// offline, and upon sign in, will sync all items to the server, and by combining retrievedItems & savedItems, and only choosing
// the latest, you are now resolving to the most recent one, which is in the savedItems list and not retrieved items, defeating
// the whole purpose of this thing.
// Updated solution: resolveSingletons will now evaluate both of these arrays separately.
this.resolveSingletons(data.retrievedItems, data.savedItems); this.resolveSingletons(data.retrievedItems, data.savedItems);
}) })
// Testing code to make sure only 1 exists
// setTimeout(function () {
// var userPrefs = modelManager.itemsForContentType("SN|UserPreferences");
// console.assert(userPrefs.length == 1);
// }, 1000);
} }
registerSingleton(predicate, resolveCallback, createBlock) { registerSingleton(predicate, resolveCallback, createBlock) {
@@ -48,10 +49,16 @@ class SingletonManager {
resolveSingletons(retrievedItems, savedItems, initialLoad) { resolveSingletons(retrievedItems, savedItems, initialLoad) {
retrievedItems = retrievedItems || []; retrievedItems = retrievedItems || [];
savedItems = savedItems || []; savedItems = savedItems || [];
for(let singletonHandler of this.singletonHandlers) { for(let singletonHandler of this.singletonHandlers) {
var predicate = singletonHandler.predicate; var predicate = singletonHandler.predicate;
var singletonItems = this.filterItemsWithPredicate(_.uniq(retrievedItems.concat(savedItems)), predicate); let retrievedSingletonItems = this.filterItemsWithPredicate(retrievedItems, predicate);
if(singletonItems.length > 0) {
// We only want to consider saved items count to see if it's more than 0, and do nothing else with it.
// This way we know there was some action and things need to be resolved. The saved items will come up
// in filterItemsWithPredicate(this.modelManager.allItems) and be deleted anyway
let savedSingletonItemsCount = this.filterItemsWithPredicate(savedItems, predicate).length;
if(retrievedSingletonItems.length > 0 || savedSingletonItemsCount > 0) {
/* /*
Check local inventory and make sure only 1 similar item exists. If more than 1, delete oldest Check local inventory and make sure only 1 similar item exists. If more than 1, delete oldest
Note that this local inventory will also contain whatever is in retrievedItems. Note that this local inventory will also contain whatever is in retrievedItems.
@@ -61,22 +68,39 @@ class SingletonManager {
var allExtantItemsMatchingPredicate = this.filterItemsWithPredicate(this.modelManager.allItems, predicate); var allExtantItemsMatchingPredicate = this.filterItemsWithPredicate(this.modelManager.allItems, predicate);
/* /*
If there are more than 1 matches, delete everything not in `singletonItems`, If there are more than 1 matches, delete everything not in `retrievedSingletonItems`,
then delete all but the latest in `singletonItems` then delete all but the latest in `retrievedSingletonItems`
*/ */
if(allExtantItemsMatchingPredicate.length >= 2) { if(allExtantItemsMatchingPredicate.length >= 2) {
// Items that will be deleted
var toDelete = []; var toDelete = [];
for(let extantItem of allExtantItemsMatchingPredicate) { // The item that will be chosen to be kept
if(!singletonItems.includes(extantItem)) { var winningItem, sorted;
// Delete it
toDelete.push(extantItem); if(retrievedSingletonItems.length > 0) {
for(let extantItem of allExtantItemsMatchingPredicate) {
if(!retrievedSingletonItems.includes(extantItem)) {
// Delete it
toDelete.push(extantItem);
}
} }
// Sort incoming singleton items by most recently updated first, then delete all the rest
sorted = retrievedSingletonItems.sort((a, b) => {
return a.updated_at < b.updated_at;
})
} else {
// We're in here because of savedItems
// This can be the case if retrievedSingletonItems/retrievedItems length is 0, but savedSingletonItemsCount is non zero.
// In this case, we want to sort by date and delete all but the most recent one
sorted = allExtantItemsMatchingPredicate.sort((a, b) => {
return a.updated_at < b.updated_at;
});
} }
// Sort incoming singleton items by most recently updated first, then delete all the rest winningItem = sorted[0];
var sorted = singletonItems.sort((a, b) => {
return a.updated_at < b.updated_at;
})
// Delete everything but the first one // Delete everything but the first one
toDelete = toDelete.concat(sorted.slice(1, sorted.length)); toDelete = toDelete.concat(sorted.slice(1, sorted.length));
@@ -88,9 +112,8 @@ class SingletonManager {
this.$rootScope.sync(); this.$rootScope.sync();
// Send remaining item to callback // Send remaining item to callback
var singleton = sorted[0]; singletonHandler.singleton = winningItem;
singletonHandler.singleton = singleton; singletonHandler.resolutionCallback(winningItem);
singletonHandler.resolutionCallback(singleton);
} else if(allExtantItemsMatchingPredicate.length == 1) { } else if(allExtantItemsMatchingPredicate.length == 1) {
if(!singletonHandler.singleton) { if(!singletonHandler.singleton) {

View File

@@ -101,8 +101,6 @@ class StorageManager {
var storage = this.getVault(vaultKey); var storage = this.getVault(vaultKey);
storage.setItem(key, value); storage.setItem(key, value);
console.log(this.itemsStorageMode);
if(vaultKey === StorageManager.FixedEncrypted || (!vaultKey && this.itemsStorageMode === StorageManager.FixedEncrypted)) { if(vaultKey === StorageManager.FixedEncrypted || (!vaultKey && this.itemsStorageMode === StorageManager.FixedEncrypted)) {
this.writeEncryptedStorageToDisk(); this.writeEncryptedStorageToDisk();
} }

View File

@@ -22,7 +22,7 @@
{{formData.showLogin ? "Sign In" : "Register (free)"}} {{formData.showLogin ? "Sign In" : "Register (free)"}}
%form.panel-form{"ng-submit" => "submitAuthForm()"} %form.panel-form{"ng-submit" => "submitAuthForm()"}
%input{:placeholder => 'Email', :autofocus => 'autofocus', :name => 'email', :required => true, :type => 'email', 'ng-model' => 'formData.email'} %input{:placeholder => 'Email', "sn-autofocus" => 'true', "should-focus" => "true", :name => 'email', :required => true, :type => 'email', 'ng-model' => 'formData.email'}
%input{:placeholder => 'Password', :name => 'password', :required => true, :type => 'password', 'ng-model' => 'formData.user_password'} %input{:placeholder => 'Password', :name => 'password', :required => true, :type => 'password', 'ng-model' => 'formData.user_password'}
%input{:placeholder => 'Confirm Password', "ng-if" => "formData.showRegister", :name => 'password', :required => true, :type => 'password', 'ng-model' => 'formData.password_conf'} %input{:placeholder => 'Confirm Password', "ng-if" => "formData.showRegister", :name => 'password', :required => true, :type => 'password', 'ng-model' => 'formData.password_conf'}