From c5f9dd086b78319d5e8170b62ae854a8e9d625c0 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Tue, 12 Aug 2014 17:43:01 -0400 Subject: [PATCH 1/9] Possibility to collapsed threads with persistance --- UI/MailerUI/UIxMailActions.m | 79 +++++++++++++++++++++ UI/MailerUI/product.plist | 10 +++ UI/WebServerResources/MailerUI.js | 48 +++++++++++-- UI/WebServerResources/SOGoDataTable.js | 1 - UI/WebServerResources/SOGoMailDataSource.js | 9 ++- 5 files changed, 139 insertions(+), 8 deletions(-) diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index b21cd160f..27e5e9a8f 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -145,6 +145,85 @@ return response; } +- (id) markMessageCollapseAction +{ + NSMutableDictionary *moduleSettings, *threadsCollapsed; + NSMutableArray *mailboxThreadsCollapsed; + NSString *msguid, *currentMailbox, *currentAccount, *keyForMsgUIDs; + SOGoUserSettings *us; + us = [[context activeUser] userSettings]; + moduleSettings = [us objectForKey: @"Mail"]; + + msguid = [[self clientObject] nameInContainer]; + currentMailbox = [[[self clientObject] container] nameInContainer]; + currentAccount = [[[[self clientObject] container] container] nameInContainer]; + keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; + + // Check if the module threadsCollapsed is created in the userSettings + if ([moduleSettings objectForKey:@"threadsCollapsed"]) + { + // Check if the currentMailbox already have other threads saved and add the new collapsed thread + threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; + if ([threadsCollapsed objectForKey:keyForMsgUIDs]) + { + mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; + if (![mailboxThreadsCollapsed containsObject:msguid]) + [mailboxThreadsCollapsed addObject:msguid]; + } + else + { + mailboxThreadsCollapsed = [NSMutableArray arrayWithObject:msguid]; + [threadsCollapsed setObject:mailboxThreadsCollapsed forKey:keyForMsgUIDs]; + } + } + else + { + // Created the module threadsCollapsed and add the new collapsed thread + mailboxThreadsCollapsed = [NSMutableArray arrayWithObject:msguid]; + threadsCollapsed = [NSMutableDictionary dictionaryWithObject:mailboxThreadsCollapsed forKey:keyForMsgUIDs]; + [moduleSettings setObject:threadsCollapsed forKey: @"threadsCollapsed"]; + } + + [us synchronize]; + + return [self responseWith204]; +} + +- (id) markMessageUncollapseAction +{ + NSMutableDictionary *moduleSettings, *threadsCollapsed; + NSMutableArray *mailboxThreadsCollapsed; + NSString *msguid, *currentMailbox, *currentAccount, *keyForMsgUIDs; + SOGoUserSettings *us; + us = [[context activeUser] userSettings]; + moduleSettings = [us objectForKey: @"Mail"]; + + msguid = [[self clientObject] nameInContainer]; + currentMailbox = [[[self clientObject] container] nameInContainer]; + currentAccount = [[[[self clientObject] container] container] nameInContainer]; + keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; + + // Check if the module threadsCollapsed is created in the userSettings + if ([moduleSettings objectForKey:@"threadsCollapsed"]) + { + // Check if the currentMailbox already have other threads saved and remove the uncollapsed thread + threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; + if ([threadsCollapsed objectForKey:keyForMsgUIDs]) + { + mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; + [mailboxThreadsCollapsed removeObject:msguid]; + + if ([mailboxThreadsCollapsed count] == 0) + [threadsCollapsed removeObjectForKey:keyForMsgUIDs]; + + [us synchronize]; + } + } + // TODO : Manage errors + + return [self responseWith204]; +} + /* SOGoDraftObject */ - (WOResponse *) editAction { diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index 4956cf286..3060fe3ec 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -252,6 +252,16 @@ actionClass = "UIxMailActions"; actionName = "forward"; }; + markMessageUncollapse = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "markMessageUncollapse"; + }; + markMessageCollapse = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "markMessageCollapse"; + }; markMessageUnflagged = { protectedBy = "View"; actionClass = "UIxMailActions"; diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 3ce06319c..d80268e24 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -219,13 +219,16 @@ function openMessageWindowsForSelection(action, firstOnly) { return false; } -/* + function mailListToggleMessageThread(row, cell) { var show = row.hasClassName('closedThread'); + var msguid = row.id.split("_")[1]; + var action = "markMessageCollapse"; $(cell).down('img').remove(); if (show) { row.removeClassName('closedThread'); row.addClassName('openedThread'); + action = "markMessageUncollapse"; var img = createElement("img", null, null, { src: ResourcesURL + '/arrow-down.png' }); cell.insertBefore(img, cell.firstChild); } @@ -241,8 +244,23 @@ function mailListToggleMessageThread(row, cell) { else row.hide(); } + + // Update the dictionnary of the collapsed threads + var mailbox = Mailer.currentMailbox; + var url = ApplicationBaseURL + encodeURI(mailbox) + "/" + msguid + "/" + action; + var data = { "currentMailbox": Mailer.currentMailbox, "msguid": msguid }; + + triggerAjaxRequest(url, mailListToggleMessageCollapseCallback); } -*/ + +function mailListToggleMessageCollapseCallback(http) { + var data = http.callbackData; + if (!isHttpStatus204(http.status)) { + log("Message Collapse Failed (" + http.status + "): " + http.statusText); + } + //Mailer.dataTable.invalidate(data["msguid"], true); +} + /* Triggered when clicking on the read/unread dot of a message row or * through the contextual menu. */ @@ -929,6 +947,8 @@ function openMailbox(mailbox, reload) { /* * Called from SOGoDataTable.render() */ +var show = false; + function messageListCallback(row, data, isNew) { var currentMessage = Mailer.currentMessages[Mailer.currentMailbox]; row.id = data['rowID']; @@ -940,13 +960,31 @@ function messageListCallback(row, data, isNew) { if (data['uid'] == currentMessage) row.addClassName('_selected'); - if (data['Thread']) - row.addClassName('openedThread'); + if (data['Thread']) { + if (UserSettings.Mail.threadsCollapsed) { + var mailbox = Mailer.currentMailbox; + var collapsedList = UserSettings.Mail.threadsCollapsed[mailbox]; + if (collapsedList != undefined && collapsedList.indexOf(row.id.split("_")[1]) != -1) { + row.addClassName('closedThread'); + show = true; + } + else { + row.addClassName('openedThread'); + } + } + } + else if (data['ThreadLevel'] > 0) { if (data['ThreadLevel'] > 10) data['ThreadLevel'] = 10; row.addClassName('thread'); row.addClassName('thread' + data['ThreadLevel']); + + if (show) + row.hide(); } + + else + show = false; var cells = row.childElements(); for (var j = 0; j < cells.length; j++) { @@ -1222,7 +1260,7 @@ function onMessageSelectionChange(event) { t = t.parentNode; if (t.tagName == 'TD') { if (t.className == 'messageThreadColumn') { - //mailListToggleMessageThread(t.parentNode, t); Disable thread collapsing + mailListToggleMessageThread(t.parentNode, t); } else if (t.className == 'messageUnreadColumn') { mailListToggleMessagesRead(t.parentNode); diff --git a/UI/WebServerResources/SOGoDataTable.js b/UI/WebServerResources/SOGoDataTable.js index ee04b19f7..8cb0a94f0 100644 --- a/UI/WebServerResources/SOGoDataTable.js +++ b/UI/WebServerResources/SOGoDataTable.js @@ -248,7 +248,6 @@ var SOGoDataTableInterface = { j++, i++) { var row = this.rowModel.cloneNode(true); this.rowRenderCallback(row, data[j], true); - row.show(); this.body.insertBefore(row, this.rowBottom); } } diff --git a/UI/WebServerResources/SOGoMailDataSource.js b/UI/WebServerResources/SOGoMailDataSource.js index 7826ffe32..6535f57ff 100644 --- a/UI/WebServerResources/SOGoMailDataSource.js +++ b/UI/WebServerResources/SOGoMailDataSource.js @@ -196,8 +196,13 @@ SOGoMailDataSource = Class.create({ data[j] = this.cache.get(this.uids[i][0]); // Add thread-related data - if (parseInt(this.uids[i][2]) > 0) - data[j]['Thread'] = ' '; //''; + if (parseInt(this.uids[i][2]) > 0) { + var mailbox = Mailer.currentMailbox; + if ((UserSettings.Mail.threadsCollapsed[Mailer.currentMailbox] != undefined) && (UserSettings.Mail.threadsCollapsed[Mailer.currentMailbox].indexOf((this.uids[i][0]).toString())) != -1) + data[j]['Thread'] = ''; + else + data[j]['Thread'] = ''; + } else if (data[j]['Thread']) delete data[j]['Thread']; if (parseInt(this.uids[i][1]) > -1) From 59023da7f00010c44ff026019d93009ff908d13e Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Wed, 13 Aug 2014 18:39:33 -0400 Subject: [PATCH 2/9] applied comments and fix bug where the folded threads were saved only after refreshing the entire page --- UI/MailerUI/UIxMailActions.m | 76 ++++++++++++++----------------- UI/WebServerResources/MailerUI.js | 24 +++++++--- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index 27e5e9a8f..3ff8832f3 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -145,7 +145,7 @@ return response; } -- (id) markMessageCollapseAction +- (void) collapseAction: (BOOL) isCollapsing { NSMutableDictionary *moduleSettings, *threadsCollapsed; NSMutableArray *mailboxThreadsCollapsed; @@ -159,67 +159,59 @@ currentAccount = [[[[self clientObject] container] container] nameInContainer]; keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; - // Check if the module threadsCollapsed is created in the userSettings - if ([moduleSettings objectForKey:@"threadsCollapsed"]) + if (isCollapsing) { - // Check if the currentMailbox already have other threads saved and add the new collapsed thread - threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; - if ([threadsCollapsed objectForKey:keyForMsgUIDs]) + // Check if the module threadsCollapsed is created in the userSettings + if ((threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"])) { - mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; - if (![mailboxThreadsCollapsed containsObject:msguid]) + // Check if the currentMailbox already have other threads saved and add the new collapsed thread + if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) + if (![mailboxThreadsCollapsed containsObject:msguid]) [mailboxThreadsCollapsed addObject:msguid]; + else + { + mailboxThreadsCollapsed = [NSMutableArray arrayWithObject:msguid]; + [threadsCollapsed setObject:mailboxThreadsCollapsed forKey:keyForMsgUIDs]; + } } else { + // Created the module threadsCollapsed and add the new collapsed thread mailboxThreadsCollapsed = [NSMutableArray arrayWithObject:msguid]; - [threadsCollapsed setObject:mailboxThreadsCollapsed forKey:keyForMsgUIDs]; + threadsCollapsed = [NSMutableDictionary dictionaryWithObject:mailboxThreadsCollapsed forKey:keyForMsgUIDs]; + [moduleSettings setObject:threadsCollapsed forKey: @"threadsCollapsed"]; } } else { - // Created the module threadsCollapsed and add the new collapsed thread - mailboxThreadsCollapsed = [NSMutableArray arrayWithObject:msguid]; - threadsCollapsed = [NSMutableDictionary dictionaryWithObject:mailboxThreadsCollapsed forKey:keyForMsgUIDs]; - [moduleSettings setObject:threadsCollapsed forKey: @"threadsCollapsed"]; + // Check if the module threadsCollapsed is created in the userSettings + if ((threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"])) + { + // Check if the currentMailbox already have other threads saved and remove the uncollapsed thread + if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) + { + [mailboxThreadsCollapsed removeObject:msguid]; + + if ([mailboxThreadsCollapsed count] == 0) + [threadsCollapsed removeObjectForKey:keyForMsgUIDs]; + } + } + // TODO : Manage errors } [us synchronize]; +} + +- (id) markMessageCollapseAction +{ + [self collapseAction: YES]; return [self responseWith204]; } - (id) markMessageUncollapseAction { - NSMutableDictionary *moduleSettings, *threadsCollapsed; - NSMutableArray *mailboxThreadsCollapsed; - NSString *msguid, *currentMailbox, *currentAccount, *keyForMsgUIDs; - SOGoUserSettings *us; - us = [[context activeUser] userSettings]; - moduleSettings = [us objectForKey: @"Mail"]; - - msguid = [[self clientObject] nameInContainer]; - currentMailbox = [[[self clientObject] container] nameInContainer]; - currentAccount = [[[[self clientObject] container] container] nameInContainer]; - keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; - - // Check if the module threadsCollapsed is created in the userSettings - if ([moduleSettings objectForKey:@"threadsCollapsed"]) - { - // Check if the currentMailbox already have other threads saved and remove the uncollapsed thread - threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; - if ([threadsCollapsed objectForKey:keyForMsgUIDs]) - { - mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; - [mailboxThreadsCollapsed removeObject:msguid]; - - if ([mailboxThreadsCollapsed count] == 0) - [threadsCollapsed removeObjectForKey:keyForMsgUIDs]; - - [us synchronize]; - } - } - // TODO : Manage errors + [self collapseAction: NO]; return [self responseWith204]; } diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index d80268e24..d28d92c99 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -248,17 +248,28 @@ function mailListToggleMessageThread(row, cell) { // Update the dictionnary of the collapsed threads var mailbox = Mailer.currentMailbox; var url = ApplicationBaseURL + encodeURI(mailbox) + "/" + msguid + "/" + action; - var data = { "currentMailbox": Mailer.currentMailbox, "msguid": msguid }; + var callbackData = { "currentMailbox": Mailer.currentMailbox, "msguid": msguid, "action": action}; - triggerAjaxRequest(url, mailListToggleMessageCollapseCallback); + triggerAjaxRequest(url, mailListToggleMessageCollapseCallback, callbackData); } function mailListToggleMessageCollapseCallback(http) { var data = http.callbackData; - if (!isHttpStatus204(http.status)) { + if (isHttpStatus204(http.status)) { + if (data.action == "markMessageCollapse") { + if (cachedThreadsCollapsed[data.currentMailbox]) + cachedThreadsCollapsed[data.currentMailbox].push(data.msguid); + else + cachedThreadsCollapsed[data.currentMailbox] = [data.msguid]; + } + else { + var index = cachedThreadsCollapsed[data.currentMailbox].indexOf(data.msguid); + cachedThreadsCollapsed[data.currentMailbox].splice(index, 1); + } + } + else { log("Message Collapse Failed (" + http.status + "): " + http.statusText); } - //Mailer.dataTable.invalidate(data["msguid"], true); } @@ -948,6 +959,7 @@ function openMailbox(mailbox, reload) { * Called from SOGoDataTable.render() */ var show = false; +var cachedThreadsCollapsed = UserSettings.Mail.threadsCollapsed; function messageListCallback(row, data, isNew) { var currentMessage = Mailer.currentMessages[Mailer.currentMailbox]; @@ -961,9 +973,9 @@ function messageListCallback(row, data, isNew) { row.addClassName('_selected'); if (data['Thread']) { - if (UserSettings.Mail.threadsCollapsed) { + if (cachedThreadsCollapsed) { var mailbox = Mailer.currentMailbox; - var collapsedList = UserSettings.Mail.threadsCollapsed[mailbox]; + var collapsedList = cachedThreadsCollapsed[mailbox]; if (collapsedList != undefined && collapsedList.indexOf(row.id.split("_")[1]) != -1) { row.addClassName('closedThread'); show = true; From c9d1294a8aca4e66c8ef59595035e9f8b3dd35ac Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Thu, 28 Aug 2014 17:55:35 -0400 Subject: [PATCH 3/9] Manage the collapse UIDs save in the user settings --- UI/MailerUI/UIxMailActions.m | 30 +++++--- UI/MailerUI/UIxMailFolderActions.m | 110 +++++++++++++++++++++++++++-- 2 files changed, 122 insertions(+), 18 deletions(-) diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index 3ff8832f3..d14c17031 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -147,27 +147,33 @@ - (void) collapseAction: (BOOL) isCollapsing { + SOGoMailObject *co; NSMutableDictionary *moduleSettings, *threadsCollapsed; NSMutableArray *mailboxThreadsCollapsed; NSString *msguid, *currentMailbox, *currentAccount, *keyForMsgUIDs; SOGoUserSettings *us; + + co = [self clientObject]; us = [[context activeUser] userSettings]; moduleSettings = [us objectForKey: @"Mail"]; - - msguid = [[self clientObject] nameInContainer]; - currentMailbox = [[[self clientObject] container] nameInContainer]; - currentAccount = [[[[self clientObject] container] container] nameInContainer]; + msguid = [co nameInContainer]; + currentMailbox = [[co container] nameInContainer]; + currentAccount = [[[co container] container] nameInContainer]; keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; - + if (isCollapsing) { // Check if the module threadsCollapsed is created in the userSettings - if ((threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"])) + if ([[moduleSettings objectForKey:@"threadsCollapsed"] boolValue]) { + threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; // Check if the currentMailbox already have other threads saved and add the new collapsed thread - if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) - if (![mailboxThreadsCollapsed containsObject:msguid]) - [mailboxThreadsCollapsed addObject:msguid]; + if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + { + mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; + if (![mailboxThreadsCollapsed containsObject:msguid]) + [mailboxThreadsCollapsed addObject:msguid]; + } else { mailboxThreadsCollapsed = [NSMutableArray arrayWithObject:msguid]; @@ -185,11 +191,13 @@ else { // Check if the module threadsCollapsed is created in the userSettings - if ((threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"])) + if ([[moduleSettings objectForKey:@"threadsCollapsed"] boolValue]) { + threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; // Check if the currentMailbox already have other threads saved and remove the uncollapsed thread - if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) + if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) { + mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; [mailboxThreadsCollapsed removeObject:msguid]; if ([mailboxThreadsCollapsed count] == 0) diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index 0e1ca9123..9427d8d5c 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -89,22 +89,45 @@ - (WOResponse *) renameFolderAction { SOGoMailFolder *co; + SOGoUserSettings *us; WOResponse *response; NSException *error; - NSString *folderName; + NSString *newFolderName, *oldFolderName, *currentMailbox, *currentAccount, *keyForMsgUIDs, *newKeyForMsgUIDs; + NSMutableDictionary *moduleSettings, *threadsCollapsed; + NSArray *values; co = [self clientObject]; + //Prepare the variables need to verify if the current folder have any collapsed threads saved in userSettings + us = [[context activeUser] userSettings]; + moduleSettings = [us objectForKey: @"Mail"]; + threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; + currentMailbox = [co nameInContainer]; + currentAccount = [[co container] nameInContainer]; + keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; - folderName = [[context request] formValueForKey: @"name"]; - error = [co renameTo: folderName]; + newFolderName = [[context request] formValueForKey: @"name"]; + newKeyForMsgUIDs = [NSString stringWithFormat:@"/%@/folder%@", currentAccount, newFolderName]; + error = [co renameTo: newFolderName]; if (error) { response = [self responseWithStatus: 500]; [response appendContentString: @"Unable to rename folder."]; } else - response = [self responseWith204]; - + { + // Verify if the current folder have any collapsed threads save under it old name and adjust the folderName + if ([threadsCollapsed boolValue]) + { + if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + { + values = [NSArray arrayWithArray:[threadsCollapsed objectForKey:keyForMsgUIDs]]; + [threadsCollapsed setObject:values forKey:newKeyForMsgUIDs]; + [threadsCollapsed removeObjectForKey:keyForMsgUIDs]; + [us synchronize]; + } + } + response = [self responseWith204]; + } return response; } @@ -149,10 +172,13 @@ - (WOResponse *) deleteAction { SOGoMailFolder *co, *inbox; + SOGoUserSettings *us; WOResponse *response; NGImap4Connection *connection; NSException *error; NSURL *srcURL, *destURL; + NSMutableDictionary *moduleSettings, *threadsCollapsed; + NSString *currentMailbox, *currentAccount, *keyForMsgUIDs; co = [self clientObject]; if ([co ensureTrashFolder]) @@ -174,7 +200,23 @@ // We unsubscribe to the old one, and subscribe back to the new one [[connection client] subscribe: [destURL path]]; [[connection client] unsubscribe: [srcURL path]]; - + + // Verify if the current folder have any collapsed threads save under it name and erase it + us = [[context activeUser] userSettings]; + moduleSettings = [us objectForKey: @"Mail"]; + threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; + currentMailbox = [co nameInContainer]; + currentAccount = [[co container] nameInContainer]; + keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; + + if ([threadsCollapsed boolValue]) + { + if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + { + [threadsCollapsed removeObjectForKey:keyForMsgUIDs]; + [us synchronize]; + } + } response = [self responseWith204]; } } @@ -191,11 +233,16 @@ { SOGoMailFolder *co; SOGoMailAccount *account; + SOGoUserSettings *us; WOResponse *response; NSArray *uids; NSString *value; NSDictionary *data; BOOL withTrash; + NSMutableDictionary *moduleSettings, *threadsCollapsed; + NSString *currentMailbox, *currentAccount, *keyForMsgUIDs; + NSMutableArray *mailboxThreadsCollapsed; + int i; co = [self clientObject]; value = [[context request] formValueForKey: @"uid"]; @@ -217,7 +264,30 @@ andString: [data jsonRepresentation]]; } else - response = [self responseWith204]; + { + // Verify if the message beeing delete is saved as the root of a collapsed thread + us = [[context activeUser] userSettings]; + moduleSettings = [us objectForKey: @"Mail"]; + threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; + currentMailbox = [co nameInContainer]; + currentAccount = [[co container] nameInContainer]; + keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; + + if ([threadsCollapsed boolValue]) + { + if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + { + mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; + for (i = 0; i < [uids count]; i++) + { + if ([mailboxThreadsCollapsed containsObject:[uids objectAtIndex:i]]) + [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; + } + [us synchronize]; + } + } + response = [self responseWith204]; + } } } else @@ -317,9 +387,14 @@ - (WOResponse *) moveMessagesAction { SOGoMailFolder *co; + SOGoUserSettings *us; WOResponse *response; NSArray *uids; NSString *value, *destinationFolder; + NSMutableDictionary *moduleSettings, *threadsCollapsed; + NSString *currentMailbox, *currentAccount, *keyForMsgUIDs; + NSMutableArray *mailboxThreadsCollapsed; + int i; co = [self clientObject]; value = [[context request] formValueForKey: @"uid"]; @@ -331,6 +406,27 @@ uids = [value componentsSeparatedByString: @","]; response = [co moveUIDs: uids toFolder: destinationFolder inContext: context]; if (!response) + // Verify if the message beeing delete is saved as the root of a collapsed thread + us = [[context activeUser] userSettings]; + moduleSettings = [us objectForKey: @"Mail"]; + threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; + currentMailbox = [co nameInContainer]; + currentAccount = [[co container] nameInContainer]; + keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; + + if ([threadsCollapsed boolValue]) + { + if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + { + mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; + for (i = 0; i < [uids count]; i++) + { + if ([mailboxThreadsCollapsed containsObject:[uids objectAtIndex:i]]) + [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; + } + [us synchronize]; + } + } response = [self responseWith204]; } else From 267a689683dd435fde53dc7f442a9e9853b91305 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Fri, 29 Aug 2014 09:30:40 -0400 Subject: [PATCH 4/9] Applied comments --- UI/MailerUI/UIxMailFolderActions.m | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index 9427d8d5c..becfbad5d 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -279,10 +279,7 @@ { mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; for (i = 0; i < [uids count]; i++) - { - if ([mailboxThreadsCollapsed containsObject:[uids objectAtIndex:i]]) - [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; - } + [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; [us synchronize]; } } @@ -420,10 +417,7 @@ { mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; for (i = 0; i < [uids count]; i++) - { - if ([mailboxThreadsCollapsed containsObject:[uids objectAtIndex:i]]) - [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; - } + [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; [us synchronize]; } } From 0c88edc61b788c5a33de2ab85fda9680deb80bc2 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Thu, 4 Sep 2014 11:09:04 -0400 Subject: [PATCH 5/9] bugfix where an exception was raised if threadsCollapsed is undefined --- UI/WebServerResources/SOGoMailDataSource.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/UI/WebServerResources/SOGoMailDataSource.js b/UI/WebServerResources/SOGoMailDataSource.js index 6535f57ff..b6758e559 100644 --- a/UI/WebServerResources/SOGoMailDataSource.js +++ b/UI/WebServerResources/SOGoMailDataSource.js @@ -198,8 +198,11 @@ SOGoMailDataSource = Class.create({ // Add thread-related data if (parseInt(this.uids[i][2]) > 0) { var mailbox = Mailer.currentMailbox; - if ((UserSettings.Mail.threadsCollapsed[Mailer.currentMailbox] != undefined) && (UserSettings.Mail.threadsCollapsed[Mailer.currentMailbox].indexOf((this.uids[i][0]).toString())) != -1) - data[j]['Thread'] = ''; + if ((UserSettings.Mail.threadsCollapsed != undefined) && + (UserSettings.Mail.threadsCollapsed[Mailer.currentMailbox] != undefined) && + (UserSettings.Mail.threadsCollapsed[Mailer.currentMailbox].indexOf((this.uids[i][0]).toString())) != -1) { + data[j]['Thread'] = ''; + } else data[j]['Thread'] = ''; } From e6002c9b2a419dd12f543990fed588a07b0a88df Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Mon, 8 Sep 2014 12:39:55 -0400 Subject: [PATCH 6/9] applied comments --- UI/MailerUI/UIxMailActions.m | 13 +++++-------- UI/MailerUI/UIxMailFolderActions.m | 20 +++++++++----------- UI/WebServerResources/MailerUI.js | 25 ++++++++++++++++++------- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index d14c17031..3da8b7540 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -34,6 +34,7 @@ #import #import #import +#import #import #import "../Common/WODirectAction+SOGo.h" @@ -164,13 +165,11 @@ if (isCollapsing) { // Check if the module threadsCollapsed is created in the userSettings - if ([[moduleSettings objectForKey:@"threadsCollapsed"] boolValue]) + if ((threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"])) { - threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; // Check if the currentMailbox already have other threads saved and add the new collapsed thread - if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) { - mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; if (![mailboxThreadsCollapsed containsObject:msguid]) [mailboxThreadsCollapsed addObject:msguid]; } @@ -191,13 +190,11 @@ else { // Check if the module threadsCollapsed is created in the userSettings - if ([[moduleSettings objectForKey:@"threadsCollapsed"] boolValue]) + if ((threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"])) { - threadsCollapsed = [moduleSettings objectForKey:@"threadsCollapsed"]; // Check if the currentMailbox already have other threads saved and remove the uncollapsed thread - if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) { - mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; [mailboxThreadsCollapsed removeObject:msguid]; if ([mailboxThreadsCollapsed count] == 0) diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index becfbad5d..30f1816cd 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -92,7 +92,7 @@ SOGoUserSettings *us; WOResponse *response; NSException *error; - NSString *newFolderName, *oldFolderName, *currentMailbox, *currentAccount, *keyForMsgUIDs, *newKeyForMsgUIDs; + NSString *newFolderName, *currentMailbox, *currentAccount, *keyForMsgUIDs, *newKeyForMsgUIDs; NSMutableDictionary *moduleSettings, *threadsCollapsed; NSArray *values; @@ -116,9 +116,9 @@ else { // Verify if the current folder have any collapsed threads save under it old name and adjust the folderName - if ([threadsCollapsed boolValue]) + if (threadsCollapsed) { - if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + if ([threadsCollapsed objectForKey:keyForMsgUIDs]) { values = [NSArray arrayWithArray:[threadsCollapsed objectForKey:keyForMsgUIDs]]; [threadsCollapsed setObject:values forKey:newKeyForMsgUIDs]; @@ -209,9 +209,9 @@ currentAccount = [[co container] nameInContainer]; keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; - if ([threadsCollapsed boolValue]) + if (threadsCollapsed) { - if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + if ([threadsCollapsed objectForKey:keyForMsgUIDs]) { [threadsCollapsed removeObjectForKey:keyForMsgUIDs]; [us synchronize]; @@ -273,11 +273,10 @@ currentAccount = [[co container] nameInContainer]; keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; - if ([threadsCollapsed boolValue]) + if (threadsCollapsed) { - if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) { - mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; for (i = 0; i < [uids count]; i++) [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; [us synchronize]; @@ -411,11 +410,10 @@ currentAccount = [[co container] nameInContainer]; keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; - if ([threadsCollapsed boolValue]) + if (threadsCollapsed) { - if ([[threadsCollapsed objectForKey:keyForMsgUIDs] boolValue]) + if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) { - mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs]; for (i = 0; i < [uids count]; i++) [mailboxThreadsCollapsed removeObject:[uids objectAtIndex:i]]; [us synchronize]; diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index d28d92c99..395cebbd0 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -33,6 +33,10 @@ var deleteMessageRequestCount = 0; var messageCheckTimer; +// Variables for feature threadsCollapsing +var displayThreadElement = false; +var cachedThreadsCollapsed = UserSettings.Mail.threadsCollapsed; + /* We need to override this method since it is adapted to GCS-based folder references, which we do not use here */ function URLForFolderID(folderID, application) { @@ -958,8 +962,6 @@ function openMailbox(mailbox, reload) { /* * Called from SOGoDataTable.render() */ -var show = false; -var cachedThreadsCollapsed = UserSettings.Mail.threadsCollapsed; function messageListCallback(row, data, isNew) { var currentMessage = Mailer.currentMessages[Mailer.currentMailbox]; @@ -978,7 +980,7 @@ function messageListCallback(row, data, isNew) { var collapsedList = cachedThreadsCollapsed[mailbox]; if (collapsedList != undefined && collapsedList.indexOf(row.id.split("_")[1]) != -1) { row.addClassName('closedThread'); - show = true; + displayThreadElement = true; } else { row.addClassName('openedThread'); @@ -991,12 +993,12 @@ function messageListCallback(row, data, isNew) { row.addClassName('thread'); row.addClassName('thread' + data['ThreadLevel']); - if (show) + if (displayThreadElement) row.hide(); } else - show = false; + displayThreadElement = false; var cells = row.childElements(); for (var j = 0; j < cells.length; j++) { @@ -2604,10 +2606,19 @@ function onMenuToggleMessageFlag(event) { mailListToggleMessagesFlagged(); } +function refreshUserSettingsCallback(http) { + var allUserSettings = http.response.evalJSON(); + UserSettings.Mail = allUserSettings.Mail; + cachedThreadsCollapsed = UserSettings.Mail.threadsCollapsed; + refreshMailbox(); +} + function folderOperationCallback(http) { - if (http.readyState == 4 - && isHttpStatus204(http.status)) + if (http.readyState == 4 && isHttpStatus204(http.status)) { initMailboxTree(); + var url = ApplicationBaseURL.split("Mail")[0]; + triggerAjaxRequest(url + "/jsonSettings", refreshUserSettingsCallback); + } else showAlertDialog(http.callbackData); } From df42c31618611f41856bc5a2427e7b59cc899bda Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Mon, 8 Sep 2014 12:43:29 -0400 Subject: [PATCH 7/9] Update NEWS file --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 80bd1a16c..4ab0dfbbb 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,7 @@ ------------------ New features - - +- new user settings for threads collapsing Enchancements - major refactoring of the GCS component saving code (dropped OGoContentStore) From 06f81a032cafe6017e328f8c8b4215119cc502a0 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Tue, 9 Sep 2014 12:44:23 -0400 Subject: [PATCH 8/9] applied comments --- UI/WebServerResources/MailerUI.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 395cebbd0..64f864a3d 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -2616,8 +2616,7 @@ function refreshUserSettingsCallback(http) { function folderOperationCallback(http) { if (http.readyState == 4 && isHttpStatus204(http.status)) { initMailboxTree(); - var url = ApplicationBaseURL.split("Mail")[0]; - triggerAjaxRequest(url + "/jsonSettings", refreshUserSettingsCallback); + triggerAjaxRequest(UserFolderURL + "/preferences/jsonSettings", refreshUserSettingsCallback); } else showAlertDialog(http.callbackData); From 7db526a5d968e0f0c7ad0782f8449220df722359 Mon Sep 17 00:00:00 2001 From: Alexandre Cloutier Date: Tue, 9 Sep 2014 13:50:42 -0400 Subject: [PATCH 9/9] bugfix for new user without userSettings.mail --- UI/MailerUI/UIxMailActions.m | 9 ++++----- UI/WebServerResources/MailerUI.js | 8 +++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index 3da8b7540..6d1439176 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -156,12 +156,13 @@ co = [self clientObject]; us = [[context activeUser] userSettings]; - moduleSettings = [us objectForKey: @"Mail"]; + if (!(moduleSettings = [us objectForKey: @"Mail"])) + [us setObject:[NSMutableDictionary dictionnary] forKey: @"Mail"]; msguid = [co nameInContainer]; currentMailbox = [[co container] nameInContainer]; currentAccount = [[[co container] container] nameInContainer]; keyForMsgUIDs = [NSString stringWithFormat:@"/%@/%@", currentAccount, currentMailbox]; - + if (isCollapsing) { // Check if the module threadsCollapsed is created in the userSettings @@ -196,14 +197,12 @@ if ((mailboxThreadsCollapsed = [threadsCollapsed objectForKey:keyForMsgUIDs])) { [mailboxThreadsCollapsed removeObject:msguid]; - if ([mailboxThreadsCollapsed count] == 0) [threadsCollapsed removeObjectForKey:keyForMsgUIDs]; } } - // TODO : Manage errors + // TODO : Manage errors } - [us synchronize]; } diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 64f864a3d..b30926591 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -35,7 +35,7 @@ var messageCheckTimer; // Variables for feature threadsCollapsing var displayThreadElement = false; -var cachedThreadsCollapsed = UserSettings.Mail.threadsCollapsed; +var cachedThreadsCollapsed = (UserSettings.Mail ? UserSettings.Mail.threadsCollapsed: []); /* We need to override this method since it is adapted to GCS-based folder references, which we do not use here */ @@ -2608,8 +2608,10 @@ function onMenuToggleMessageFlag(event) { function refreshUserSettingsCallback(http) { var allUserSettings = http.response.evalJSON(); - UserSettings.Mail = allUserSettings.Mail; - cachedThreadsCollapsed = UserSettings.Mail.threadsCollapsed; + if (UserSettings.Mail) { + UserSettings.Mail = allUserSettings.Mail; + cachedThreadsCollapsed = UserSettings.Mail.threadsCollapsed; + } refreshMailbox(); }