(feat) added IMAP folders subscriptions management (fixes #255)
parent
49d58b436e
commit
42127c51ab
|
@ -813,7 +813,7 @@ void handle_eas_terminate(int signum)
|
|||
}
|
||||
|
||||
allFoldersMetadata = [NSMutableArray array];
|
||||
[self _flattenFolders: [accountFolder allFoldersMetadata] into: allFoldersMetadata parent: nil parentType: nil];
|
||||
[self _flattenFolders: [accountFolder allFoldersMetadata: SOGoMailStandardListing] into: allFoldersMetadata parent: nil parentType: nil];
|
||||
|
||||
// Get GUIDs of folder (IMAP)
|
||||
// e.g. {folderINBOX = folder6b93c528176f1151c7260000aef6df92}
|
||||
|
|
2
NEWS
2
NEWS
|
@ -2,7 +2,7 @@
|
|||
------------------
|
||||
|
||||
New features
|
||||
-
|
||||
- [web] added IMAP folder subscriptions management (#255)
|
||||
|
||||
Enhancements
|
||||
- [web] don't allow a recurrence rule to end before the first occurrence
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2009-2014 Inverse inc.
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
Copyright (C) 2009-2016 Inverse inc.
|
||||
|
||||
This file is part of SOGo.
|
||||
|
||||
|
@ -35,6 +34,7 @@
|
|||
*/
|
||||
|
||||
@class NSArray;
|
||||
@class NSMutableDictionary;
|
||||
@class NSMutableArray;
|
||||
@class NSString;
|
||||
|
||||
|
@ -50,6 +50,11 @@ typedef enum {
|
|||
rfc4314
|
||||
} SOGoIMAPAclStyle;
|
||||
|
||||
typedef enum {
|
||||
SOGoMailStandardListing = 0,
|
||||
SOGoMailSubscriptionsManagementListing = 1
|
||||
} SOGoMailListingMode;
|
||||
|
||||
@interface SOGoMailAccount : SOGoMailBaseObject
|
||||
{
|
||||
SOGoMailFolder *inboxFolder;
|
||||
|
@ -61,6 +66,7 @@ typedef enum {
|
|||
NSMutableArray *identities;
|
||||
NSString *otherUsersFolderName;
|
||||
NSString *sharedFoldersName;
|
||||
NSMutableDictionary *subscribedFolders;
|
||||
}
|
||||
|
||||
- (SOGoIMAPAclStyle) imapAclStyle;
|
||||
|
@ -83,8 +89,8 @@ typedef enum {
|
|||
/* folder pathes */
|
||||
- (NSArray *) toManyRelationshipKeysWithNamespaces: (BOOL) withNSs;
|
||||
|
||||
- (NSArray *) allFolderPaths;
|
||||
- (NSArray *) allFoldersMetadata;
|
||||
- (NSArray *) allFolderPaths: (SOGoMailListingMode) theListingMode;
|
||||
- (NSArray *) allFoldersMetadata: (SOGoMailListingMode) theListingMode;
|
||||
|
||||
- (NSDictionary *) imapFolderGUIDs;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
Copyright (C) 2007-2016 Inverse inc.
|
||||
|
||||
This file is part of SOGo.
|
||||
|
@ -25,7 +24,6 @@
|
|||
#import <Foundation/NSURL.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
|
||||
#import <NGObjWeb/NSException+HTTP.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
|
@ -73,6 +71,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
identities = nil;
|
||||
otherUsersFolderName = nil;
|
||||
sharedFoldersName = nil;
|
||||
subscribedFolders = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -88,11 +87,10 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
[identities release];
|
||||
[otherUsersFolderName release];
|
||||
[sharedFoldersName release];
|
||||
[subscribedFolders release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* listing the available folders */
|
||||
|
||||
- (BOOL) isInDraftsFolder
|
||||
{
|
||||
return NO;
|
||||
|
@ -116,8 +114,6 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
}
|
||||
}
|
||||
|
||||
/* namespaces */
|
||||
|
||||
- (void) _appendNamespaces: (NSMutableArray *) folders
|
||||
{
|
||||
NSDictionary *namespaceDict;
|
||||
|
@ -342,30 +338,45 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
//
|
||||
//
|
||||
//
|
||||
- (NSArray *) allFolderPaths
|
||||
- (NSArray *) allFolderPaths: (SOGoMailListingMode) theListingMode
|
||||
{
|
||||
NSMutableArray *folderPaths, *namespaces;
|
||||
NSArray *folders, *mainFolders;
|
||||
SOGoUserDefaults *ud;
|
||||
NSString *namespace;
|
||||
|
||||
BOOL subscribedOnly;
|
||||
int count, max;
|
||||
|
||||
ud = [[context activeUser] userDefaults];
|
||||
subscribedOnly = [ud mailShowSubscribedFoldersOnly];
|
||||
if (theListingMode == SOGoMailStandardListing)
|
||||
subscribedOnly = [[[context activeUser] userDefaults] mailShowSubscribedFoldersOnly];
|
||||
else
|
||||
{
|
||||
subscribedOnly = NO;
|
||||
DESTROY(subscribedFolders);
|
||||
subscribedFolders = [[NSMutableDictionary alloc] init];
|
||||
folders = [[self imap4Connection] allFoldersForURL: [self imap4URL]
|
||||
onlySubscribedFolders: YES];
|
||||
max = [folders count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
[subscribedFolders setObject: [NSNull null]
|
||||
forKey: [folders objectAtIndex: count]];
|
||||
}
|
||||
[[self imap4Connection] flushFolderHierarchyCache];
|
||||
}
|
||||
|
||||
mainFolders = [[NSArray arrayWithObjects:
|
||||
[self inboxFolderNameInContext: context],
|
||||
[self draftsFolderNameInContext: context],
|
||||
[self sentFolderNameInContext: context],
|
||||
[self trashFolderNameInContext: context],
|
||||
[self junkFolderNameInContext: context],
|
||||
nil] stringsWithFormat: @"/%@"];
|
||||
[self junkFolderNameInContext: context],
|
||||
nil] stringsWithFormat: @"/%@"];
|
||||
folders = [[self imap4Connection] allFoldersForURL: [self imap4URL]
|
||||
onlySubscribedFolders: subscribedOnly];
|
||||
onlySubscribedFolders: subscribedOnly];
|
||||
folderPaths = [folders mutableCopy];
|
||||
[folderPaths autorelease];
|
||||
|
||||
[folderPaths removeObjectsInArray: mainFolders];
|
||||
namespaces = [NSMutableArray arrayWithCapacity: 10];
|
||||
[self _appendNamespaces: namespaces];
|
||||
|
@ -441,6 +452,9 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
return folderType;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
- (NSMutableDictionary *) _insertFolder: (NSString *) folderPath
|
||||
foldersList: (NSMutableArray *) theFolders
|
||||
{
|
||||
|
@ -449,8 +463,9 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
NSMutableDictionary *currentFolder, *parentFolder, *folder;
|
||||
NSString *currentFolderName, *currentPath, *fullName, *folderType;
|
||||
SOGoUserManager *userManager;
|
||||
|
||||
BOOL last, isOtherUsersFolder, parentIsOtherUsersFolder, isSubscribed;
|
||||
int i, j, count;
|
||||
BOOL last, isOtherUsersFolder, parentIsOtherUsersFolder;
|
||||
|
||||
parentFolder = nil;
|
||||
parentIsOtherUsersFolder = NO;
|
||||
|
@ -469,13 +484,9 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
// Search for the current path in the children of the parent folder.
|
||||
// For the first iteration, take the parent folder passed as argument.
|
||||
if (parentFolder)
|
||||
{
|
||||
folders = [parentFolder objectForKey: @"children"];
|
||||
}
|
||||
folders = [parentFolder objectForKey: @"children"];
|
||||
else
|
||||
{
|
||||
folders = theFolders;
|
||||
}
|
||||
folders = theFolders;
|
||||
|
||||
for (j = 0; j < [folders count]; j++)
|
||||
{
|
||||
|
@ -485,10 +496,9 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
folder = currentFolder;
|
||||
// Make sure all branches are ready to receive children
|
||||
if (!last && ![folder objectForKey: @"children"])
|
||||
{
|
||||
[folder setObject: [NSMutableArray array] forKey: @"children"];
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,18 +506,13 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
currentFolderName = [[pathComponents objectAtIndex: i] stringByDecodingImap4FolderName];
|
||||
if (otherUsersFolderName
|
||||
&& [currentFolderName caseInsensitiveCompare: otherUsersFolderName] == NSOrderedSame)
|
||||
{
|
||||
isOtherUsersFolder = YES;
|
||||
}
|
||||
isOtherUsersFolder = YES;
|
||||
else
|
||||
{
|
||||
isOtherUsersFolder = NO;
|
||||
}
|
||||
isOtherUsersFolder = NO;
|
||||
|
||||
if (folder == nil)
|
||||
{
|
||||
// Folder was not found; create it and add it to the folders list
|
||||
|
||||
if (parentIsOtherUsersFolder)
|
||||
{
|
||||
// Parent folder is the "Other users" folder; translate the user's mailbox name
|
||||
|
@ -519,14 +524,10 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
currentFolderName = fullName;
|
||||
}
|
||||
else if (isOtherUsersFolder)
|
||||
{
|
||||
currentFolderName = [self labelForKey: @"OtherUsersFolderName"];
|
||||
}
|
||||
currentFolderName = [self labelForKey: @"OtherUsersFolderName"];
|
||||
else if (sharedFoldersName
|
||||
&& [currentFolderName caseInsensitiveCompare: sharedFoldersName] == NSOrderedSame)
|
||||
{
|
||||
currentFolderName = [self labelForKey: @"SharedFoldersName"];
|
||||
}
|
||||
currentFolderName = [self labelForKey: @"SharedFoldersName"];
|
||||
|
||||
flags = [NSMutableArray array];;
|
||||
|
||||
|
@ -536,13 +537,19 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
else
|
||||
folderType = @"additional";
|
||||
|
||||
if ([subscribedFolders objectForKey: folderPath])
|
||||
isSubscribed = YES;
|
||||
else
|
||||
isSubscribed = NO;
|
||||
|
||||
folder = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
currentPath, @"path",
|
||||
folderType, @"type",
|
||||
currentFolderName, @"name",
|
||||
[NSMutableArray array], @"children",
|
||||
flags, @"flags",
|
||||
nil];
|
||||
folderType, @"type",
|
||||
currentFolderName, @"name",
|
||||
[NSMutableArray array], @"children",
|
||||
flags, @"flags",
|
||||
[NSNumber numberWithBool: isSubscribed], @"subscribed",
|
||||
nil];
|
||||
// Either add this new folder to its parent or the list of root folders
|
||||
[folders addObject: folder];
|
||||
}
|
||||
|
@ -557,7 +564,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
//
|
||||
// Return a tree representation of the mailboxes
|
||||
//
|
||||
- (NSArray *) allFoldersMetadata
|
||||
- (NSArray *) allFoldersMetadata: (SOGoMailListingMode) theListingMode
|
||||
{
|
||||
NSString *currentFolder;
|
||||
NSMutableArray *folders;
|
||||
|
@ -565,7 +572,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
NSAutoreleasePool *pool;
|
||||
NSArray *allFolderPaths;
|
||||
|
||||
allFolderPaths = [self allFolderPaths];
|
||||
allFolderPaths = [self allFolderPaths: theListingMode];
|
||||
rawFolders = [allFolderPaths objectEnumerator];
|
||||
folders = [NSMutableArray array];
|
||||
|
||||
|
@ -587,8 +594,6 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
return folders;
|
||||
}
|
||||
|
||||
|
||||
/* IMAP4 */
|
||||
- (NSDictionary *) _mailAccount
|
||||
{
|
||||
NSDictionary *mailAccount;
|
||||
|
@ -761,7 +766,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
[self trashFolderNameInContext: context],
|
||||
nil] stringsWithFormat: @"/%@"];
|
||||
else
|
||||
folderList = [self allFolderPaths];
|
||||
folderList = [self allFolderPaths: SOGoMailStandardListing];
|
||||
|
||||
folders = [NSMutableDictionary dictionary];
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
|||
|
||||
prefix = [self absoluteImap4Name];
|
||||
|
||||
result = [[self mailAccountFolder] allFolderPaths];
|
||||
result = [[self mailAccountFolder] allFolderPaths: SOGoMailStandardListing];
|
||||
folderNames = [result objectEnumerator];
|
||||
while ((currentFolderName = [folderNames nextObject]))
|
||||
if ([currentFolderName hasPrefix: prefix])
|
||||
|
|
|
@ -361,4 +361,7 @@
|
|||
"Folder compacted" = "Folder compacted";
|
||||
|
||||
/* Aria label for scope of search on messages */
|
||||
"Search scope" = "Search scope";
|
||||
"Search scope" = "Search scope";
|
||||
|
||||
/* Subscriptions Dialog */
|
||||
"Manage Subscriptions" = "Manage Subscriptions";
|
|
@ -23,10 +23,11 @@ MailerUI_OBJC_FILES += \
|
|||
UIxMailPopupView.m \
|
||||
UIxMailMoveToPopUp.m \
|
||||
UIxMailFilterPanel.m \
|
||||
UIxMailSearch.m \
|
||||
UIxMailSearch.m \
|
||||
\
|
||||
UIxMailAccountActions.m \
|
||||
UIxMailFolderActions.m \
|
||||
UIxMailFolderSubscriptions.m \
|
||||
UIxMailActions.m \
|
||||
UIxMailEditor.m \
|
||||
UIxMailToSelection.m \
|
||||
|
|
|
@ -46,14 +46,33 @@
|
|||
|
||||
co = [self clientObject];
|
||||
|
||||
folders = [co allFoldersMetadata];
|
||||
folders = [co allFoldersMetadata: SOGoMailStandardListing];
|
||||
|
||||
data = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
folders, @"mailboxes",
|
||||
[co getInboxQuota], @"quotas",
|
||||
nil];
|
||||
|
||||
return [self responseWithStatus: 200 andJSONRepresentation: data];
|
||||
return [self responseWithStatus: 200
|
||||
andJSONRepresentation: data];
|
||||
}
|
||||
|
||||
- (WOResponse *) listAllMailboxesAction
|
||||
{
|
||||
SOGoMailAccount *co;
|
||||
NSArray *folders;
|
||||
NSDictionary *data;
|
||||
|
||||
co = [self clientObject];
|
||||
|
||||
folders = [co allFoldersMetadata: SOGoMailSubscriptionsManagementListing];
|
||||
|
||||
data = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
folders, @"mailboxes",
|
||||
nil];
|
||||
|
||||
return [self responseWithStatus: 200
|
||||
andJSONRepresentation: data];
|
||||
}
|
||||
|
||||
/* compose */
|
||||
|
|
|
@ -743,42 +743,62 @@
|
|||
return response;
|
||||
}
|
||||
|
||||
#warning here should be done what should be done: IMAP subscription
|
||||
- (WOResponse *) _subscriptionStubAction
|
||||
// - (WOResponse *) _subscriptionStubAction
|
||||
// {
|
||||
// NSString *mailInvitationParam, *mailInvitationURL;
|
||||
// WOResponse *response;
|
||||
// SOGoMailFolder *clientObject;
|
||||
|
||||
// mailInvitationParam
|
||||
// = [[context request] formValueForKey: @"mail-invitation"];
|
||||
// if ([mailInvitationParam boolValue])
|
||||
// {
|
||||
// clientObject = [self clientObject];
|
||||
// mailInvitationURL
|
||||
// = [[clientObject soURLToBaseContainerForCurrentUser]
|
||||
// absoluteString];
|
||||
// response = [self responseWithStatus: 302];
|
||||
// [response setHeader: mailInvitationURL
|
||||
// forKey: @"location"];
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// response = [self responseWithStatus: 500];
|
||||
// [response appendContentString: @"How did you end up here?"];
|
||||
// }
|
||||
|
||||
// return response;
|
||||
// }
|
||||
|
||||
- (WOResponse *) _subscribeOrUnsubscribeAction: (BOOL) subscribing
|
||||
{
|
||||
NSString *mailInvitationParam, *mailInvitationURL;
|
||||
NGImap4Client *client;
|
||||
WOResponse *response;
|
||||
SOGoMailFolder *clientObject;
|
||||
SOGoMailFolder *co;
|
||||
NSDictionary *d;
|
||||
|
||||
mailInvitationParam
|
||||
= [[context request] formValueForKey: @"mail-invitation"];
|
||||
if ([mailInvitationParam boolValue])
|
||||
{
|
||||
clientObject = [self clientObject];
|
||||
mailInvitationURL
|
||||
= [[clientObject soURLToBaseContainerForCurrentUser]
|
||||
absoluteString];
|
||||
response = [self responseWithStatus: 302];
|
||||
[response setHeader: mailInvitationURL
|
||||
forKey: @"location"];
|
||||
}
|
||||
co = [self clientObject];
|
||||
client = [[co imap4Connection] client];
|
||||
|
||||
if (subscribing)
|
||||
d = [client subscribe: [[co imap4URL] path]];
|
||||
else
|
||||
{
|
||||
response = [self responseWithStatus: 500];
|
||||
[response appendContentString: @"How did you end up here?"];
|
||||
}
|
||||
d = [client unsubscribe: [[co imap4URL] path]];
|
||||
|
||||
return response;
|
||||
if ([[[[d objectForKey: @"RawResponse"] objectForKey: @"ResponseResult"] objectForKey: @"result"] isEqualToString: @"ok"])
|
||||
return [self responseWith204];
|
||||
|
||||
return [self responseWithStatus: 200];
|
||||
}
|
||||
|
||||
- (WOResponse *) subscribeAction
|
||||
{
|
||||
return [self _subscriptionStubAction];
|
||||
return [self _subscribeOrUnsubscribeAction: YES];
|
||||
}
|
||||
|
||||
- (WOResponse *) unsubscribeAction
|
||||
{
|
||||
return [self _subscriptionStubAction];
|
||||
return [self _subscribeOrUnsubscribeAction: NO];
|
||||
}
|
||||
|
||||
- (WOResponse *) addOrRemoveLabelAction
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* UIxMailFolderSubscriptions.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2016 Inverse inc.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
|
||||
@interface UIxMailFolderSubscriptions : UIxComponent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,42 @@
|
|||
/* UIxMailFolderSubscriptions.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2016 Inverse inc.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <NGObjWeb/WORequest.h>
|
||||
|
||||
#import "UIxMailFolderSubscriptions.h"
|
||||
|
||||
@implementation UIxMailFolderSubscriptions
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
|
@ -400,6 +400,15 @@
|
|||
actionClass = "UIxMailAccountActions";
|
||||
actionName = "listMailboxes";
|
||||
};
|
||||
viewAll = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxMailAccountActions";
|
||||
actionName = "listAllMailboxes";
|
||||
};
|
||||
subscribe = {
|
||||
protectedBy = "Access Contents Information";
|
||||
pageName = "UIxMailFolderSubscriptions";
|
||||
};
|
||||
createFolder = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxMailFolderActions";
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" standalone="yes"?>
|
||||
<!DOCTYPE container>
|
||||
<container
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label"
|
||||
>
|
||||
<md-dialog flex="50" flex-sm="80" flex-xs="100">
|
||||
|
||||
<md-toolbar>
|
||||
<div class="md-toolbar-tools">
|
||||
<md-icon class="material-icons sg-icon-toolbar-bg">folder</md-icon>
|
||||
<div class="pseudo-input-container md-flex">
|
||||
<label class="pseudo-input-label"><var:string label:value="Manage Subscriptions"/></label>
|
||||
<div class="sg-md-title">{{subscriptions.account.name}}</div>
|
||||
</div>
|
||||
<md-button class="md-icon-button" ng-click="subscriptions.close()">
|
||||
<md-icon aria-label="Close dialog">close</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
|
||||
<md-dialog-content class="md-dialog-content" layout="column">
|
||||
<md-list>
|
||||
<md-list-item ng-repeat="folder in subscriptions.account.$flattenMailboxes({all: true })"
|
||||
md-item-size="48"
|
||||
ng-hide="subscriptions.app.metadataForFolder(folder).special">
|
||||
<div ng-class="'sg-child-level-' + folder.level">
|
||||
<md-icon>{{subscriptions.app.metadataForFolder(folder).icon}}</md-icon>
|
||||
</div>
|
||||
<p class="sg-item-name">
|
||||
{{subscriptions.app.metadataForFolder(folder).name}}
|
||||
</p>
|
||||
<md-checkbox class="md-secondary"
|
||||
ng-model="folder.subscribed"
|
||||
ng-click="folder.$toggleSubscribe()"
|
||||
ng-true-value="1"
|
||||
ng-false-value="0">
|
||||
</md-checkbox>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
</md-dialog-content>
|
||||
|
||||
<md-dialog-actions>
|
||||
<md-button type="button" ng-click="subscriptions.close()"><var:string label:value="Close"/></md-button>
|
||||
</md-dialog-actions>
|
||||
|
||||
</md-dialog>
|
||||
</container>
|
|
@ -40,21 +40,35 @@
|
|||
<md-list>
|
||||
<md-list-item ng-click="app.toggleAccountState(account)">
|
||||
<div class="sg-no-wrap">{{account.name}}</div>
|
||||
<div class="md-flex"><!-- spacer --></div>
|
||||
<md-button class="md-icon-button md-secondary"
|
||||
ng-show="account.id == 0"
|
||||
label:aria-label="Delegation..."
|
||||
ng-click="app.delegate(account)">
|
||||
<md-tooltip md-delay="300"><var:string label:value="Delegation..."/></md-tooltip>
|
||||
<md-icon>people</md-icon>
|
||||
</md-button>
|
||||
<md-button class="md-icon-button md-secondary"
|
||||
label:aria-label="New Folder..."
|
||||
ng-click="app.newFolder(account)">
|
||||
<md-tooltip md-delay="300"><var:string label:value="New Folder..."/></md-tooltip>
|
||||
<md-icon>add_circle_outline</md-icon>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
<md-menu class="md-secondary">
|
||||
<md-icon label:aria-label="Options"
|
||||
ng-click="$mdOpenMenu($event)"
|
||||
md-menu-origin="md-menu-origin">more_vert</md-icon>
|
||||
<md-menu-content width="3">
|
||||
<md-menu-item ng-show="account.id == 0">
|
||||
<md-button
|
||||
label:aria-label="Delegation..."
|
||||
ng-click="app.delegate(account)">
|
||||
<var:string label:value="Delegation..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="app.showSubscribedOnly == 1">
|
||||
<md-button
|
||||
label:aria-label="Subscribe..."
|
||||
ng-click="app.subscribe(account)">
|
||||
<var:string label:value="Subscribe..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button
|
||||
label:aria-label="New Folder..."
|
||||
ng-click="app.newFolder(account)">
|
||||
<var:string label:value="New Folder..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
<div class="sg-quota ng-hide" ng-show="account.$quota">
|
||||
<md-progress-linear md-mode="determinate"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* @constructor
|
||||
* @param {object} futureAccountData
|
||||
*/
|
||||
function Account(futureAccountData) {
|
||||
function Account(futureAccountData, fetchAll) {
|
||||
// Data is immediately available
|
||||
if (typeof futureAccountData.then !== 'function') {
|
||||
angular.extend(this, futureAccountData);
|
||||
|
@ -24,6 +24,14 @@
|
|||
// The promise will be unwrapped first
|
||||
//this.$unwrap(futureAccountData);
|
||||
}
|
||||
|
||||
this.fetchAll = false;
|
||||
|
||||
// Check if we're displaying the IMAP subscription management dialog
|
||||
if (angular.isDefined(fetchAll) && fetchAll) {
|
||||
this.fetchAll = true;
|
||||
this.$getMailboxes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,7 +84,10 @@
|
|||
Mailbox.$find = function(account) {
|
||||
var path, futureMailboxData;
|
||||
|
||||
futureMailboxData = this.$$resource.fetch(account.id.toString(), 'view');
|
||||
if (account.fetchAll)
|
||||
futureMailboxData = this.$$resource.fetch(account.id.toString(), 'viewAll');
|
||||
else
|
||||
futureMailboxData = this.$$resource.fetch(account.id.toString(), 'view');
|
||||
|
||||
return Mailbox.$unwrapCollection(account, futureMailboxData); // a collection of mailboxes
|
||||
};
|
||||
|
@ -890,4 +893,15 @@
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $toggleSubscribe
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Subscribe or unsubscribe to a mailbox
|
||||
*/
|
||||
Mailbox.prototype.$toggleSubscribe = function() {
|
||||
if (this.subscribed)
|
||||
return Mailbox.$$resource.post(this.id, 'subscribe');
|
||||
|
||||
return Mailbox.$$resource.post(this.id, 'unsubscribe');
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
vm.service = Mailbox;
|
||||
vm.accounts = stateAccounts;
|
||||
vm.toggleAccountState = toggleAccountState;
|
||||
vm.subscribe = subscribe;
|
||||
vm.newFolder = newFolder;
|
||||
vm.delegate = delegate;
|
||||
vm.editFolder = editFolder;
|
||||
|
@ -54,6 +55,10 @@
|
|||
params: []
|
||||
};
|
||||
|
||||
Preferences.ready().then(function() {
|
||||
vm.showSubscribedOnly = Preferences.defaults.SOGoMailShowSubscribedFoldersOnly;
|
||||
});
|
||||
|
||||
vm.refreshUnseenCount();
|
||||
|
||||
function showAdvancedSearch(path) {
|
||||
|
@ -146,6 +151,40 @@
|
|||
}, 150);
|
||||
}
|
||||
|
||||
function subscribe(account) {
|
||||
$mdDialog.show({
|
||||
templateUrl: account.id + '/subscribe',
|
||||
controller: SubscriptionsDialogController,
|
||||
controllerAs: 'subscriptions',
|
||||
clickOutsideToClose: true,
|
||||
escapeToClose: true,
|
||||
locals: {
|
||||
srcApp: vm,
|
||||
srcAccount: account
|
||||
}
|
||||
}).finally(function() {
|
||||
account.$getMailboxes({reload: true});
|
||||
});
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
SubscriptionsDialogController.$inject = ['$scope', '$mdDialog', 'srcApp', 'srcAccount'];
|
||||
function SubscriptionsDialogController($scope, $mdDialog, srcApp, srcAccount) {
|
||||
var vm = this;
|
||||
|
||||
vm.app = srcApp;
|
||||
vm.account = new Account({id: srcAccount.id,
|
||||
name: srcAccount.name},
|
||||
true);
|
||||
vm.close = close;
|
||||
|
||||
function close() {
|
||||
$mdDialog.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function newFolder(parentFolder) {
|
||||
Dialog.prompt(l('New folder'),
|
||||
l('Enter the new name of your folder :'))
|
||||
|
@ -305,19 +344,19 @@
|
|||
|
||||
function metadataForFolder(folder) {
|
||||
if (folder.type == 'inbox')
|
||||
return {name: folder.name, icon:'inbox'};
|
||||
return {name: folder.name, icon:'inbox', special: true};
|
||||
else if (folder.type == 'draft')
|
||||
return {name: l('DraftsFolderName'), icon: 'drafts'};
|
||||
return {name: l('DraftsFolderName'), icon: 'drafts', special: true};
|
||||
else if (folder.type == 'sent')
|
||||
return {name: l('SentFolderName'), icon: 'send'};
|
||||
return {name: l('SentFolderName'), icon: 'send', special: true};
|
||||
else if (folder.type == 'trash')
|
||||
return {name: l('TrashFolderName'), icon: 'delete'};
|
||||
return {name: l('TrashFolderName'), icon: 'delete', special: true};
|
||||
else if (folder.type == 'junk')
|
||||
return {name: l('JunkFolderName'), icon: 'thumb_down'};
|
||||
return {name: l('JunkFolderName'), icon: 'thumb_down', special: true};
|
||||
else if (folder.type == 'additional')
|
||||
return {name: folder.name, icon: 'folder_shared'};
|
||||
return {name: folder.name, icon: 'folder_shared', special: true};
|
||||
|
||||
return {name: folder.name, icon: 'folder_open'};
|
||||
return {name: folder.name, icon: 'folder_open', special: false};
|
||||
}
|
||||
|
||||
function setFolderAs(folder, type) {
|
||||
|
|
Loading…
Reference in New Issue