See ChangeLog
Monotone-Parent: ede90c4ec21ca642e49b4287679877bd02717ed6 Monotone-Revision: ae2c5342363a3fa87101fa6840e1c1e1f7a819c0 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-06-01T21:10:25 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
624172fe92
commit
53a01edee4
36
ChangeLog
36
ChangeLog
|
@ -1,9 +1,45 @@
|
||||||
2011-06-01 Francis Lachapelle <flachapelle@inverse.ca>
|
2011-06-01 Francis Lachapelle <flachapelle@inverse.ca>
|
||||||
|
|
||||||
|
* SoObjects/SOGo/SOGoUserDefaults.m (-setMailSortByThreads)
|
||||||
|
(-mailSortByThreads): new accessors for the "SOGoMailSortByThreads"
|
||||||
|
user defaults.
|
||||||
|
|
||||||
|
* UI/PreferencesUI/UIxPreferences.m (-setSortByThreads)
|
||||||
|
(sortByThreads): idem.
|
||||||
|
|
||||||
|
* SoObjects/Mailer/SOGoMailFolder.m
|
||||||
|
(-fetchUIDsMatchingQualifier:sortOrdering:threaded:): new method
|
||||||
|
to fetch a threaded-view of the folder.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/NSArray+Utilities.m (-flattenedArray): added
|
||||||
|
recurrence to flatten interleaved arrays.
|
||||||
|
|
||||||
* SoObjects/Mailer/SOGoMailAccount.m (-updateFilters): write
|
* SoObjects/Mailer/SOGoMailAccount.m (-updateFilters): write
|
||||||
multiple 'redirect' directives when forwarding to multiple email
|
multiple 'redirect' directives when forwarding to multiple email
|
||||||
addresses.
|
addresses.
|
||||||
|
|
||||||
|
* UI/MailerUI/UIxMailListActions.m (-threadedUIDs): new method
|
||||||
|
that returns a flatten representation of messages threads.
|
||||||
|
|
||||||
|
* UI/MailerUI/UIxMailMainFrame.m (-columnsMetaData): added CSS
|
||||||
|
classnames for the thread column.
|
||||||
|
(-columnsDisplayOrder): add or remove the thread column depending
|
||||||
|
on the user's defaults.
|
||||||
|
|
||||||
|
* UI/MailerUI/UIxMailListActions.m (-getUIDsAndHeadersInFolder)
|
||||||
|
(-getSortedUIDsAction): added support for threads.
|
||||||
|
|
||||||
|
* UI/WebServerResources/ContactsUI.js (onContactContextMenu):
|
||||||
|
select row at pointer position when not already selected.
|
||||||
|
|
||||||
|
* UI/WebServerResources/MailerUI.js: added support for the
|
||||||
|
threaded view.
|
||||||
|
(onMessageContextMenu): select row at pointer position when not
|
||||||
|
already selected.
|
||||||
|
|
||||||
|
* UI/WebServerResources/SOGoMailDataSource.js: added support for
|
||||||
|
the threaded view.
|
||||||
|
|
||||||
2011-05-31 Francis Lachapelle <flachapelle@inverse.ca>
|
2011-05-31 Francis Lachapelle <flachapelle@inverse.ca>
|
||||||
|
|
||||||
* UI/WebServerResources/SchedulerUI.js (initCalendarSelector): use
|
* UI/WebServerResources/SchedulerUI.js (initCalendarSelector): use
|
||||||
|
|
10
NEWS
10
NEWS
|
@ -1,3 +1,13 @@
|
||||||
|
1.3-2011MMDD (1.3.8)
|
||||||
|
---------------------
|
||||||
|
New Features
|
||||||
|
- initial support for threaded-view in the webmail interface
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
- improved list selection and contextual menu behavior in all web modules
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
|
||||||
1.3-20110503 (1.3.7)
|
1.3-20110503 (1.3.7)
|
||||||
---------------------
|
---------------------
|
||||||
New Features
|
New Features
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2009-2010 Inverse inc.
|
Copyright (C) 2009-2011 Inverse inc.
|
||||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||||
|
|
||||||
This file is part of OpenGroupware.org.
|
This file is part of OpenGroupware.org.
|
||||||
|
@ -60,7 +60,8 @@
|
||||||
inContext: (id) context;
|
inContext: (id) context;
|
||||||
- (WOResponse *) archiveAllMessagesInContext: (id) localContext;
|
- (WOResponse *) archiveAllMessagesInContext: (id) localContext;
|
||||||
|
|
||||||
- (NSArray *) fetchUIDsMatchingQualifier: (id)_q sortOrdering: (id) _so;
|
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q sortOrdering: (id) _so;
|
||||||
|
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q sortOrdering: (id) _so threaded: (BOOL) _threaded;
|
||||||
- (NSArray *) fetchUIDs: (NSArray *) _uids parts: (NSArray *) _parts;
|
- (NSArray *) fetchUIDs: (NSArray *) _uids parts: (NSArray *) _parts;
|
||||||
|
|
||||||
- (WOResponse *) copyUIDs: (NSArray *) uids
|
- (WOResponse *) copyUIDs: (NSArray *) uids
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2009-2010 Inverse inc.
|
Copyright (C) 2009-2011 Inverse inc.
|
||||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||||
|
|
||||||
This file is part of OpenGroupware.org.
|
This file is part of OpenGroupware.org.
|
||||||
|
@ -315,8 +315,8 @@ static NSString *defaultUserID = @"anyone";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
error = [NSException exceptionWithHTTPStatus: 500
|
error = [NSException exceptionWithHTTPStatus: 500
|
||||||
reason: @"Did not find Trash folder!"];
|
reason: @"Did not find Trash folder!"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b)
|
if (b)
|
||||||
|
@ -544,9 +544,27 @@ static NSString *defaultUserID = @"anyone";
|
||||||
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q
|
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q
|
||||||
sortOrdering: (id) _so
|
sortOrdering: (id) _so
|
||||||
{
|
{
|
||||||
/* seems to return an NSArray of NSNumber's */
|
return [self fetchUIDsMatchingQualifier: _q
|
||||||
return [[self imap4Connection] fetchUIDsInURL: [self imap4URL]
|
sortOrdering: _so
|
||||||
qualifier: _q sortOrdering: _so];
|
threaded: NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q
|
||||||
|
sortOrdering: (id) _so
|
||||||
|
threaded: (BOOL) _threaded
|
||||||
|
{
|
||||||
|
if (_threaded)
|
||||||
|
{
|
||||||
|
return [[self imap4Connection] fetchThreadedUIDsInURL: [self imap4URL]
|
||||||
|
qualifier: _q
|
||||||
|
sortOrdering: _so];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return [[self imap4Connection] fetchUIDsInURL: [self imap4URL]
|
||||||
|
qualifier: _q
|
||||||
|
sortOrdering: _so];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) fetchUIDs: (NSArray *) _uids
|
- (NSArray *) fetchUIDs: (NSArray *) _uids
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* NSArray+Utilities.m - this file is part of SOGo
|
/* NSArray+Utilities.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006-2009 Inverse inc.
|
* Copyright (C) 2006-2011 Inverse inc.
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -129,7 +129,10 @@
|
||||||
flattenedArray = [NSMutableArray array];
|
flattenedArray = [NSMutableArray array];
|
||||||
objects = [self objectEnumerator];
|
objects = [self objectEnumerator];
|
||||||
while ((currentObject = [objects nextObject]))
|
while ((currentObject = [objects nextObject]))
|
||||||
[flattenedArray addObjectsFromArray: currentObject];
|
if ([currentObject isKindOfClass: [NSArray class]])
|
||||||
|
[flattenedArray addObjectsFromArray: [(NSArray *)currentObject flattenedArray]];
|
||||||
|
else
|
||||||
|
[flattenedArray addObject: currentObject];
|
||||||
|
|
||||||
return flattenedArray;
|
return flattenedArray;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
SOGoMailSignaturePlacement = "below";
|
SOGoMailSignaturePlacement = "below";
|
||||||
SOGoMailPollingIntervals = ( 1, 2, 5, 10, 20, 30, 60 );
|
SOGoMailPollingIntervals = ( 1, 2, 5, 10, 20, 30, 60 );
|
||||||
SOGoMailComposeMessageType = "text";
|
SOGoMailComposeMessageType = "text";
|
||||||
SOGoMailListViewColumnsOrder = ( "Flagged", "Attachment", "Subject",
|
SOGoMailListViewColumnsOrder = ( "Thread", "Flagged", "Attachment", "Subject",
|
||||||
"From", "Unread", "Date", "Priority",
|
"From", "Unread", "Date", "Priority",
|
||||||
"Size" );
|
"Size" );
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* SOGoUserDefaults.h - this file is part of SOGo
|
/* SOGoUserDefaults.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Inverse inc.
|
* Copyright (C) 2011 Inverse inc.
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -85,6 +85,9 @@ extern NSString *SOGoWeekStartFirstFullWeek;
|
||||||
- (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue;
|
- (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue;
|
||||||
- (BOOL) mailShowSubscribedFoldersOnly;
|
- (BOOL) mailShowSubscribedFoldersOnly;
|
||||||
|
|
||||||
|
- (void) setMailSortByThreads: (BOOL) newValue;
|
||||||
|
- (BOOL) mailSortByThreads;
|
||||||
|
|
||||||
- (void) setDraftsFolderName: (NSString *) newValue;
|
- (void) setDraftsFolderName: (NSString *) newValue;
|
||||||
- (NSString *) draftsFolderName;
|
- (NSString *) draftsFolderName;
|
||||||
|
|
||||||
|
|
|
@ -372,6 +372,16 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
return [self boolForKey: @"SOGoMailShowSubscribedFoldersOnly"];
|
return [self boolForKey: @"SOGoMailShowSubscribedFoldersOnly"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setMailSortByThreads: (BOOL) newValue
|
||||||
|
{
|
||||||
|
[self setBool: newValue forKey: @"SOGoMailSortByThreads"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) mailSortByThreads
|
||||||
|
{
|
||||||
|
return [self boolForKey: @"SOGoMailSortByThreads"];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setDraftsFolderName: (NSString *) newValue
|
- (void) setDraftsFolderName: (NSString *) newValue
|
||||||
{
|
{
|
||||||
[self setObject: newValue forKey: @"SOGoDraftsFolderName"];
|
[self setObject: newValue forKey: @"SOGoDraftsFolderName"];
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
id message;
|
id message;
|
||||||
SOGoDateFormatter *dateFormatter;
|
SOGoDateFormatter *dateFormatter;
|
||||||
NSTimeZone *userTimeZone;
|
NSTimeZone *userTimeZone;
|
||||||
|
BOOL sortByThread;
|
||||||
int folderType;
|
int folderType;
|
||||||
int specificMessageNumber;
|
int specificMessageNumber;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
user = [[self context] activeUser];
|
user = [[self context] activeUser];
|
||||||
ASSIGN (dateFormatter, [user dateFormatterInContext: context]);
|
ASSIGN (dateFormatter, [user dateFormatterInContext: context]);
|
||||||
ASSIGN (userTimeZone, [[user userDefaults] timeZone]);
|
ASSIGN (userTimeZone, [[user userDefaults] timeZone]);
|
||||||
|
sortByThread = [[user userDefaults] mailSortByThreads];
|
||||||
folderType = 0;
|
folderType = 0;
|
||||||
specificMessageNumber = 0;
|
specificMessageNumber = 0;
|
||||||
}
|
}
|
||||||
|
@ -458,13 +459,115 @@
|
||||||
|
|
||||||
sortedUIDs
|
sortedUIDs
|
||||||
= [mailFolder fetchUIDsMatchingQualifier: fetchQualifier
|
= [mailFolder fetchUIDsMatchingQualifier: fetchQualifier
|
||||||
sortOrdering: [self imap4SortOrdering]];
|
sortOrdering: [self imap4SortOrdering]
|
||||||
|
threaded: sortByThread];
|
||||||
|
|
||||||
[sortedUIDs retain];
|
[sortedUIDs retain];
|
||||||
}
|
}
|
||||||
|
|
||||||
return sortedUIDs;
|
return sortedUIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a flatten representation of the messages threads as triples of
|
||||||
|
* metadata, including the message UID, thread level and root position.
|
||||||
|
* @param _sortedUIDs the interleaved arrays representation of the messages UIDs
|
||||||
|
* @return an flatten array representation of the messages UIDs
|
||||||
|
*/
|
||||||
|
- (NSArray *) threadedUIDs: (NSArray *) _sortedUIDs
|
||||||
|
{
|
||||||
|
NSMutableArray *threads;
|
||||||
|
NSMutableArray *currentThreads;
|
||||||
|
NSEnumerator *rootThreads;
|
||||||
|
id thread;
|
||||||
|
int count;
|
||||||
|
int i;
|
||||||
|
BOOL first;
|
||||||
|
BOOL expected;
|
||||||
|
int previousLevel;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
i = 0;
|
||||||
|
previousLevel = 0;
|
||||||
|
expected = YES;
|
||||||
|
threads = [NSMutableArray arrayWithObject: [NSArray arrayWithObjects: @"uid", @"level", @"first", nil]];
|
||||||
|
rootThreads = [_sortedUIDs objectEnumerator];
|
||||||
|
thread = [rootThreads nextObject];
|
||||||
|
|
||||||
|
// Make sure rootThreads starts with an NSArray
|
||||||
|
if (![thread respondsToSelector: @selector(objectEnumerator)])
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
first = [thread count] > 1;
|
||||||
|
thread = [thread objectEnumerator];
|
||||||
|
|
||||||
|
currentThreads = [NSMutableArray array];
|
||||||
|
|
||||||
|
while (thread)
|
||||||
|
{
|
||||||
|
unsigned int ecount = 0;
|
||||||
|
id t;
|
||||||
|
|
||||||
|
if ([thread isKindOfClass: [NSEnumerator class]])
|
||||||
|
{
|
||||||
|
t = [thread nextObject];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
t = thread; // never happen?
|
||||||
|
while (t && ![t isKindOfClass: [NSArray class]])
|
||||||
|
{
|
||||||
|
BOOL currentFirst;
|
||||||
|
int currentLevel;
|
||||||
|
NSArray *currentThread;
|
||||||
|
|
||||||
|
currentFirst = (first && ecount == 0) || (i == 0 && count > 0) || (count > 0 && previousLevel < 0);
|
||||||
|
currentLevel = (first && ecount == 0)? 0 : (count > 0? count : -1);
|
||||||
|
currentThread = [NSArray arrayWithObjects: t,
|
||||||
|
[NSNumber numberWithInt: currentLevel],
|
||||||
|
[NSNumber numberWithInt: currentFirst], nil];
|
||||||
|
[threads addObject: currentThread];
|
||||||
|
i++;
|
||||||
|
count++;
|
||||||
|
ecount++;
|
||||||
|
expected = NO;
|
||||||
|
previousLevel = currentLevel;
|
||||||
|
t = [thread nextObject];
|
||||||
|
}
|
||||||
|
if (t)
|
||||||
|
{
|
||||||
|
// If t is defined, it has to be an NSArray
|
||||||
|
if (expected)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
expected = NO;
|
||||||
|
}
|
||||||
|
thread = [thread allObjects];
|
||||||
|
if ([thread count] > 0)
|
||||||
|
[currentThreads addObject: [thread objectEnumerator]];
|
||||||
|
thread = [t objectEnumerator];
|
||||||
|
}
|
||||||
|
else if ([currentThreads count] > 0)
|
||||||
|
{
|
||||||
|
thread = [currentThreads objectAtIndex: 0];
|
||||||
|
[currentThreads removeObjectAtIndex: 0];
|
||||||
|
count -= ecount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread = [[rootThreads nextObject] objectEnumerator]; // assume all objects of rootThreads are NSArrays
|
||||||
|
count = 0;
|
||||||
|
expected = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare next iteration
|
||||||
|
thread = [thread allObjects];
|
||||||
|
first = !first && (thread != nil) && [thread count] > 1;
|
||||||
|
thread = [thread objectEnumerator];
|
||||||
|
}
|
||||||
|
|
||||||
|
return threads;
|
||||||
|
}
|
||||||
|
|
||||||
- (int) indexOfMessageUID: (int) messageNbr
|
- (int) indexOfMessageUID: (int) messageNbr
|
||||||
{
|
{
|
||||||
NSArray *messageNbrs;
|
NSArray *messageNbrs;
|
||||||
|
@ -521,11 +624,9 @@
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* actions */
|
|
||||||
|
|
||||||
- (NSDictionary *) getUIDsAndHeadersInFolder: (SOGoMailFolder *) mailFolder
|
- (NSDictionary *) getUIDsAndHeadersInFolder: (SOGoMailFolder *) mailFolder
|
||||||
{
|
{
|
||||||
NSArray *uids, *headers;
|
NSArray *uids, *threadedUids, *headers;
|
||||||
NSDictionary *data;
|
NSDictionary *data;
|
||||||
NSRange r;
|
NSRange r;
|
||||||
int count;
|
int count;
|
||||||
|
@ -536,18 +637,31 @@
|
||||||
count = [uids count];
|
count = [uids count];
|
||||||
if (count > headersPrefetchMaxSize) count = headersPrefetchMaxSize;
|
if (count > headersPrefetchMaxSize) count = headersPrefetchMaxSize;
|
||||||
r = NSMakeRange(0, count);
|
r = NSMakeRange(0, count);
|
||||||
headers = [self getHeadersForUIDs: [uids subarrayWithRange: r]
|
headers = [self getHeadersForUIDs: [[uids flattenedArray] subarrayWithRange: r]
|
||||||
inFolder: mailFolder];
|
inFolder: mailFolder];
|
||||||
|
|
||||||
|
if (sortByThread)
|
||||||
|
{
|
||||||
|
threadedUids = [self threadedUIDs: uids];
|
||||||
|
if (threadedUids != nil)
|
||||||
|
uids = threadedUids;
|
||||||
|
else
|
||||||
|
sortByThread = NO;
|
||||||
|
}
|
||||||
|
|
||||||
data = [NSDictionary dictionaryWithObjectsAndKeys: uids, @"uids",
|
data = [NSDictionary dictionaryWithObjectsAndKeys: uids, @"uids",
|
||||||
headers, @"headers", nil];
|
headers, @"headers",
|
||||||
|
[NSNumber numberWithBool: sortByThread], @"threaded", nil];
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Module actions */
|
||||||
|
|
||||||
- (id <WOActionResults>) getSortedUIDsAction
|
- (id <WOActionResults>) getSortedUIDsAction
|
||||||
{
|
{
|
||||||
id data;
|
NSDictionary *data;
|
||||||
|
NSArray *uids, *threadedUids;
|
||||||
NSString *noHeaders;
|
NSString *noHeaders;
|
||||||
SOGoMailFolder *folder;
|
SOGoMailFolder *folder;
|
||||||
WORequest *request;
|
WORequest *request;
|
||||||
|
@ -563,10 +677,22 @@
|
||||||
[folder expungeLastMarkedFolder];
|
[folder expungeLastMarkedFolder];
|
||||||
noHeaders = [request formValueForKey: @"no_headers"];
|
noHeaders = [request formValueForKey: @"no_headers"];
|
||||||
if ([noHeaders length])
|
if ([noHeaders length])
|
||||||
data = [self getSortedUIDsInFolder: folder];
|
{
|
||||||
|
uids = [self getSortedUIDsInFolder: folder];
|
||||||
|
if (sortByThread)
|
||||||
|
{
|
||||||
|
threadedUids = [self threadedUIDs: uids];
|
||||||
|
if (threadedUids != nil)
|
||||||
|
uids = threadedUids;
|
||||||
|
else
|
||||||
|
sortByThread = NO;
|
||||||
|
}
|
||||||
|
data = [NSDictionary dictionaryWithObjectsAndKeys: uids, @"uids",
|
||||||
|
[NSNumber numberWithBool: sortByThread], @"threaded", nil];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
data = [self getUIDsAndHeadersInFolder: folder];
|
data = [self getUIDsAndHeadersInFolder: folder];
|
||||||
|
|
||||||
[response appendContentString: [data jsonRepresentation]];
|
[response appendContentString: [data jsonRepresentation]];
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|
|
@ -471,13 +471,20 @@
|
||||||
columnsMetaData = [NSMutableDictionary dictionaryWithCapacity: 8];
|
columnsMetaData = [NSMutableDictionary dictionaryWithCapacity: 8];
|
||||||
|
|
||||||
tmpKeys = [NSArray arrayWithObjects: @"headerClass", @"headerId", @"value",
|
tmpKeys = [NSArray arrayWithObjects: @"headerClass", @"headerId", @"value",
|
||||||
nil];
|
nil];
|
||||||
tmpColumns
|
tmpColumns
|
||||||
= [NSArray arrayWithObjects: @"messageSubjectColumn tbtv_headercell sortableTableHeader resizable",
|
= [NSArray arrayWithObjects: @"messageSubjectColumn tbtv_headercell sortableTableHeader resizable",
|
||||||
@"subjectHeader", @"Subject", nil];
|
@"subjectHeader", @"Subject", nil];
|
||||||
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
||||||
forKeys: tmpKeys]
|
forKeys: tmpKeys]
|
||||||
forKey: @"Subject"];
|
forKey: @"Subject"];
|
||||||
|
|
||||||
|
tmpColumns
|
||||||
|
= [NSArray arrayWithObjects: @"messageThreadColumn tbtv_headercell",
|
||||||
|
@"invisibleHeader", @"Thread", nil];
|
||||||
|
[columnsMetaData setObject: [NSDictionary dictionaryWithObjects: tmpColumns
|
||||||
|
forKeys: tmpKeys]
|
||||||
|
forKey: @"Thread"];
|
||||||
|
|
||||||
tmpColumns
|
tmpColumns
|
||||||
= [NSArray arrayWithObjects: @"messageFlagColumn tbtv_headercell",
|
= [NSArray arrayWithObjects: @"messageFlagColumn tbtv_headercell",
|
||||||
|
@ -566,6 +573,16 @@
|
||||||
|
|
||||||
finalOrder = [columnsOrder mutableCopy];
|
finalOrder = [columnsOrder mutableCopy];
|
||||||
[finalOrder autorelease];
|
[finalOrder autorelease];
|
||||||
|
|
||||||
|
if (![ud mailSortByThreads])
|
||||||
|
[finalOrder removeObject: @"Thread"];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = [finalOrder indexOfObject: @"Thread"];
|
||||||
|
if (i == NSNotFound)
|
||||||
|
[finalOrder insertObject: @"Thread" atIndex: 0];
|
||||||
|
}
|
||||||
|
|
||||||
if ([self showToAddress])
|
if ([self showToAddress])
|
||||||
{
|
{
|
||||||
i = [finalOrder indexOfObject: @"From"];
|
i = [finalOrder indexOfObject: @"From"];
|
||||||
|
|
|
@ -547,6 +547,16 @@
|
||||||
return [userDefaults mailShowSubscribedFoldersOnly];
|
return [userDefaults mailShowSubscribedFoldersOnly];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setSortByThreads: (BOOL) sortByThreads
|
||||||
|
{
|
||||||
|
[userDefaults setMailSortByThreads: sortByThreads];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) sortByThreads
|
||||||
|
{
|
||||||
|
return [userDefaults mailSortByThreads];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray *) messageCheckList
|
- (NSArray *) messageCheckList
|
||||||
{
|
{
|
||||||
NSArray *intervalsList;
|
NSArray *intervalsList;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
xmlns:label="OGo:label"
|
xmlns:label="OGo:label"
|
||||||
className="UIxPageFrame"
|
className="UIxPageFrame"
|
||||||
title="title"
|
title="title"
|
||||||
const:userDefaultsKeys="SOGoMailMessageCheck,SOGoMailListViewColumnsOrder"
|
const:userDefaultsKeys="SOGoMailMessageCheck,SOGoMailSortByThreads,SOGoMailListViewColumnsOrder"
|
||||||
const:userSettingsKeys="Mail"
|
const:userSettingsKeys="Mail"
|
||||||
const:jsFiles="dtree.js,MailerUIdTree.js,SOGoAutoCompletion.js,SOGoResizableTable.js,SOGoMailDataSource.js,SOGoDataTable.js">
|
const:jsFiles="dtree.js,MailerUIdTree.js,SOGoAutoCompletion.js,SOGoResizableTable.js,SOGoMailDataSource.js,SOGoDataTable.js">
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -222,6 +222,9 @@
|
||||||
<tr class="tableview"
|
<tr class="tableview"
|
||||||
><var:foreach list="columnsDisplayOrder" item="currentColumn">
|
><var:foreach list="columnsDisplayOrder" item="currentColumn">
|
||||||
<th var:class="currentColumn.headerClass" var:id="currentColumn.headerId">
|
<th var:class="currentColumn.headerClass" var:id="currentColumn.headerId">
|
||||||
|
<var:if condition="currentColumn.value" const:value="Thread">
|
||||||
|
<entity name="nbsp"/>
|
||||||
|
</var:if>
|
||||||
<var:if condition="currentColumn.value" const:value="Flagged">
|
<var:if condition="currentColumn.value" const:value="Flagged">
|
||||||
<entity name="nbsp"/>
|
<entity name="nbsp"/>
|
||||||
</var:if>
|
</var:if>
|
||||||
|
@ -232,10 +235,12 @@
|
||||||
<var:if condition="currentColumn.value" const:value="Unread">
|
<var:if condition="currentColumn.value" const:value="Unread">
|
||||||
<img rsrc:src="title_read_14x14.png" label:title="$currentColumn.value" />
|
<img rsrc:src="title_read_14x14.png" label:title="$currentColumn.value" />
|
||||||
</var:if>
|
</var:if>
|
||||||
<var:if condition="currentColumn.value" const:value="Flagged" const:negate="YES">
|
<var:if condition="currentColumn.value" const:value="Thread" const:negate="YES">
|
||||||
<var:if condition="currentColumn.value" const:value="Attachment" const:negate="YES">
|
<var:if condition="currentColumn.value" const:value="Flagged" const:negate="YES">
|
||||||
<var:if condition="currentColumn.value" const:value="Unread" const:negate="YES">
|
<var:if condition="currentColumn.value" const:value="Attachment" const:negate="YES">
|
||||||
<var:string var:value="columnTitle" />
|
<var:if condition="currentColumn.value" const:value="Unread" const:negate="YES">
|
||||||
|
<var:string var:value="columnTitle" />
|
||||||
|
</var:if>
|
||||||
</var:if>
|
</var:if>
|
||||||
</var:if>
|
</var:if>
|
||||||
</var:if>
|
</var:if>
|
||||||
|
@ -255,6 +260,10 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr const:style="display: none;"
|
<tr const:style="display: none;"
|
||||||
><var:foreach list="columnsDisplayOrder" item="currentColumn"
|
><var:foreach list="columnsDisplayOrder" item="currentColumn"
|
||||||
|
><var:if condition="currentColumn.value" const:value="Thread"
|
||||||
|
><td class="messageThreadColumn"
|
||||||
|
><!-- thread --></td
|
||||||
|
></var:if
|
||||||
><var:if condition="currentColumn.value" const:value="Flagged"
|
><var:if condition="currentColumn.value" const:value="Flagged"
|
||||||
><td class="messageFlagColumn"
|
><td class="messageFlagColumn"
|
||||||
><!-- flagged --></td
|
><!-- flagged --></td
|
||||||
|
|
|
@ -176,6 +176,11 @@
|
||||||
const:id="subscribedFoldersOnly"
|
const:id="subscribedFoldersOnly"
|
||||||
var:checked="showSubscribedFoldersOnly" />
|
var:checked="showSubscribedFoldersOnly" />
|
||||||
<var:string label:value="Show subscribed mailboxes only"/></label><br/>
|
<var:string label:value="Show subscribed mailboxes only"/></label><br/>
|
||||||
|
<label><input type="checkbox"
|
||||||
|
const:name="sortByThreads"
|
||||||
|
const:id="sortByThreads"
|
||||||
|
var:checked="sortByThreads" />
|
||||||
|
<var:string label:value="Sort messages by threads"/></label><br/>
|
||||||
<label><var:string label:value="Check for new mail:"/>
|
<label><var:string label:value="Check for new mail:"/>
|
||||||
<var:popup list="messageCheckList" item="item"
|
<var:popup list="messageCheckList" item="item"
|
||||||
const:id="messageCheck"
|
const:id="messageCheck"
|
||||||
|
|
|
@ -40,7 +40,9 @@ DIV#contactsListContent
|
||||||
height: 15.5em;
|
height: 15.5em;
|
||||||
border-left: 1px solid #9B9B9B;
|
border-left: 1px solid #9B9B9B;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-x: hidden; }
|
overflow-x: hidden;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-khtml-user-select: none; }
|
||||||
|
|
||||||
.aptview_text
|
.aptview_text
|
||||||
{
|
{
|
||||||
|
|
|
@ -215,11 +215,20 @@ function contactsListCallback(http) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onContactContextMenu(event) {
|
function onContactContextMenu(event) {
|
||||||
|
var target = Event.element(event);
|
||||||
|
var contact = target.up('TR');
|
||||||
var contactsList = $("contactsList");
|
var contactsList = $("contactsList");
|
||||||
|
var contacts = contactsList.getSelectedRows();
|
||||||
|
|
||||||
|
if (contacts.indexOf(contact) < 0) {
|
||||||
|
onRowClick(event, target);
|
||||||
|
contacts = contactsList.getSelectedRows();
|
||||||
|
}
|
||||||
|
|
||||||
var menu = $("contactMenu");
|
var menu = $("contactMenu");
|
||||||
menu.observe("hideMenu", onContactContextMenuHide);
|
menu.observe("hideMenu", onContactContextMenuHide);
|
||||||
if (contactsList)
|
if (contactsList)
|
||||||
popupMenu(event, "contactMenu", contactsList.getSelectedRows());
|
popupMenu(event, "contactMenu", contacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onContactContextMenuHide(event) {
|
function onContactContextMenuHide(event) {
|
||||||
|
@ -1285,7 +1294,7 @@ function initContacts(event) {
|
||||||
// Initialize event delegation on contacts table
|
// Initialize event delegation on contacts table
|
||||||
table.multiselect = true;
|
table.multiselect = true;
|
||||||
var tbody = $(table.tBodies[0]);
|
var tbody = $(table.tBodies[0]);
|
||||||
tbody.on("mousedown", onContactSelectionChange);
|
tbody.on("click", onContactSelectionChange);
|
||||||
tbody.on("dblclick", onContactRowDblClick);
|
tbody.on("dblclick", onContactRowDblClick);
|
||||||
tbody.on("selectstart", listRowMouseDownHandler);
|
tbody.on("selectstart", listRowMouseDownHandler);
|
||||||
tbody.on("contextmenu", onContactContextMenu);
|
tbody.on("contextmenu", onContactContextMenu);
|
||||||
|
@ -1470,12 +1479,19 @@ function startDragging (itm, e) {
|
||||||
var handle = $("dragDropVisual");
|
var handle = $("dragDropVisual");
|
||||||
var contacts = $('contactsList').getSelectedRowsId();
|
var contacts = $('contactsList').getSelectedRowsId();
|
||||||
var count = contacts.length;
|
var count = contacts.length;
|
||||||
|
var row = target.up('TR');
|
||||||
|
|
||||||
handle.show();
|
if (count == 0 || contacts.indexOf(row.id) < 0) {
|
||||||
handle.update (count);
|
onRowClick(e, target);
|
||||||
if (e.shiftKey || currentFolderIsRemote ()) {
|
contacts = $("contactsList").getSelectedRowsId();
|
||||||
handle.addClassName ("copy");
|
count = contacts.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle.update (count);
|
||||||
|
if (e.shiftKey || currentFolderIsRemote()) {
|
||||||
|
handle.addClassName("copy");
|
||||||
|
}
|
||||||
|
handle.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function whileDragging (itm, e) {
|
function whileDragging (itm, e) {
|
||||||
|
|
|
@ -256,6 +256,7 @@ TR#messageCountHeader TH
|
||||||
TABLE.messageList TD
|
TABLE.messageList TD
|
||||||
{ border-right: 1px solid transparent; }
|
{ border-right: 1px solid transparent; }
|
||||||
|
|
||||||
|
TABLE.messageList .messageThreadColumn,
|
||||||
TABLE.messageList .messageFlagColumn,
|
TABLE.messageList .messageFlagColumn,
|
||||||
TABLE.messageList .messageAttachmentColumn,
|
TABLE.messageList .messageAttachmentColumn,
|
||||||
TABLE.messageList .messageUnreadColumn
|
TABLE.messageList .messageUnreadColumn
|
||||||
|
@ -270,6 +271,45 @@ TABLE.messageList .messageSubjectColumn
|
||||||
TABLE.messageList .messageSubjectColumn SPAN
|
TABLE.messageList .messageSubjectColumn SPAN
|
||||||
{ padding-left: 20px; }
|
{ padding-left: 20px; }
|
||||||
|
|
||||||
|
TABLE.messageList TR.openedThread TD,
|
||||||
|
TABLE.messageList TR.closedThread TD,
|
||||||
|
TABLE.messageList TR.thread .messageThreadColumn
|
||||||
|
{ background-color: #DDD; }
|
||||||
|
|
||||||
|
TABLE.messageList TR.thread TD
|
||||||
|
{ background-color: #EEE; }
|
||||||
|
|
||||||
|
TABLE.messageList TR.thread1 .messageSubjectColumn
|
||||||
|
{ background-position: 20px 0px !important;
|
||||||
|
padding-left: 20px; }
|
||||||
|
TABLE.messageList TR.thread2 .messageSubjectColumn
|
||||||
|
{ background-position: 40px 0px !important;
|
||||||
|
padding-left: 40px; }
|
||||||
|
TABLE.messageList TR.thread3 .messageSubjectColumn
|
||||||
|
{ background-position: 60px 0px !important;
|
||||||
|
padding-left: 60px; }
|
||||||
|
TABLE.messageList TR.thread4 .messageSubjectColumn
|
||||||
|
{ background-position: 80px 0px !important;
|
||||||
|
padding-left: 80px; }
|
||||||
|
TABLE.messageList TR.thread5 .messageSubjectColumn
|
||||||
|
{ background-position: 100px 0px !important;
|
||||||
|
padding-left: 100px; }
|
||||||
|
TABLE.messageList TR.thread6 .messageSubjectColumn
|
||||||
|
{ background-position: 120px 0px !important;
|
||||||
|
padding-left: 120px; }
|
||||||
|
TABLE.messageList TR.thread7 .messageSubjectColumn
|
||||||
|
{ background-position: 140px 0px !important;
|
||||||
|
padding-left: 140px; }
|
||||||
|
TABLE.messageList TR.thread8 .messageSubjectColumn
|
||||||
|
{ background-position: 160px 0px !important;
|
||||||
|
padding-left: 160px; }
|
||||||
|
TABLE.messageList TR.thread9 .messageSubjectColumn
|
||||||
|
{ background-position: 180px 0px !important;
|
||||||
|
padding-left: 180px; }
|
||||||
|
TABLE.messageList TR.thread10 .messageSubjectColumn
|
||||||
|
{ background-position: 200px 0px !important;
|
||||||
|
padding-left: 200px; }
|
||||||
|
|
||||||
TABLE.messageList .messageAddressColumn
|
TABLE.messageList .messageAddressColumn
|
||||||
{ max-width: 18%;
|
{ max-width: 18%;
|
||||||
width: 18%; }
|
width: 18%; }
|
||||||
|
|
|
@ -17,7 +17,10 @@ var Mailer = {
|
||||||
quotas: null,
|
quotas: null,
|
||||||
|
|
||||||
dataTable: null,
|
dataTable: null,
|
||||||
dataSources: new Hash()
|
dataSources: new Hash(),
|
||||||
|
|
||||||
|
columnsOrder: null,
|
||||||
|
sortByThread: false
|
||||||
};
|
};
|
||||||
|
|
||||||
var usersRightsWindowHeight = 320;
|
var usersRightsWindowHeight = 320;
|
||||||
|
@ -169,8 +172,10 @@ function markMailInWindow(win, msguid, markread) {
|
||||||
return (unseenCount != 0);
|
return (unseenCount != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is called by UIxMailView with window.opener.
|
||||||
|
*/
|
||||||
function markMailReadInWindow(win, msguid) {
|
function markMailReadInWindow(win, msguid) {
|
||||||
/* this is called by UIxMailView with window.opener */
|
|
||||||
return markMailInWindow(win, msguid, true);
|
return markMailInWindow(win, msguid, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,6 +208,31 @@ function openMessageWindowsForSelection(action, firstOnly) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
function mailListToggleMessageThread(row, cell) {
|
||||||
|
var show = row.hasClassName('closedThread');
|
||||||
|
$(cell).down('img').remove();
|
||||||
|
if (show) {
|
||||||
|
row.removeClassName('closedThread');
|
||||||
|
row.addClassName('openedThread');
|
||||||
|
var img = createElement("img", null, null, { src: ResourcesURL + '/arrow-down.png' });
|
||||||
|
cell.insertBefore(img, cell.firstChild);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
row.removeClassName('openedThread');
|
||||||
|
row.addClassName('closedThread');
|
||||||
|
var img = createElement("img", null, null, { src: ResourcesURL + '/arrow-right.png' });
|
||||||
|
cell.insertBefore(img, cell.firstChild);
|
||||||
|
}
|
||||||
|
while ((row = row.next()) && row.hasClassName('thread')) {
|
||||||
|
if (show)
|
||||||
|
row.show();
|
||||||
|
else
|
||||||
|
row.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* Triggered when clicking on the read/unread dot of a message row or
|
/* Triggered when clicking on the read/unread dot of a message row or
|
||||||
* through the contextual menu. */
|
* through the contextual menu. */
|
||||||
function mailListToggleMessagesRead(row) {
|
function mailListToggleMessagesRead(row) {
|
||||||
|
@ -399,6 +429,7 @@ function deleteSelectedMessages(sender) {
|
||||||
var uids = new Array(); // message IDs
|
var uids = new Array(); // message IDs
|
||||||
var paths = new Array(); // row IDs
|
var paths = new Array(); // row IDs
|
||||||
var unseenCount = 0;
|
var unseenCount = 0;
|
||||||
|
var refreshFolder = false;
|
||||||
|
|
||||||
if (rowIds && rowIds.length > 0) {
|
if (rowIds && rowIds.length > 0) {
|
||||||
messageList.deselectAll();
|
messageList.deselectAll();
|
||||||
|
@ -432,15 +463,26 @@ function deleteSelectedMessages(sender) {
|
||||||
var row = $("row_" + uid);
|
var row = $("row_" + uid);
|
||||||
var nextRow = false;
|
var nextRow = false;
|
||||||
if (row) {
|
if (row) {
|
||||||
|
//row.addClassName("deleted"); // when we'll offer "mark as deleted"
|
||||||
nextRow = row.next("tr");
|
nextRow = row.next("tr");
|
||||||
if (!nextRow.id.startsWith('row_'))
|
if (!nextRow.id.startsWith('row_'))
|
||||||
nextRow = row.previous("tr");
|
nextRow = row.previous("tr");
|
||||||
// row.addClassName("deleted"); // when we'll offer "mark as deleted"
|
else if (row.hasClassName('openedThread') || row.hasClassName('closedThread')) {
|
||||||
|
// Thread root deleted -- must refresh folder
|
||||||
|
refreshFolder = true;
|
||||||
|
// New row will be the new thread root -- mark it as first mail of the thread
|
||||||
|
var nextUid = nextRow.id.substr(4);
|
||||||
|
var nextIndex = Mailer.dataTable.dataSource.indexOf(nextUid);
|
||||||
|
Mailer.dataTable.dataSource.uids[nextIndex][2] = 1; // mark it as "first"
|
||||||
|
Mailer.dataTable.invalidate(nextUid, true);
|
||||||
|
}
|
||||||
if (nextRow.id.startsWith('row_')) {
|
if (nextRow.id.startsWith('row_')) {
|
||||||
Mailer.currentMessages[Mailer.currentMailbox] = nextRow.id.substr(4);
|
Mailer.currentMessages[Mailer.currentMailbox] = nextRow.id.substr(4);
|
||||||
nextRow.selectElement();
|
nextRow.selectElement();
|
||||||
if (loadMessage(Mailer.currentMessages[Mailer.currentMailbox]))
|
if (loadMessage(Mailer.currentMessages[Mailer.currentMailbox]) && !refreshFolder)
|
||||||
|
// Seen state has changed
|
||||||
Mailer.dataTable.invalidate(Mailer.currentMessages[Mailer.currentMailbox], true);
|
Mailer.dataTable.invalidate(Mailer.currentMessages[Mailer.currentMailbox], true);
|
||||||
|
refreshFolder = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -452,7 +494,6 @@ function deleteSelectedMessages(sender) {
|
||||||
lastClickedRow = nextRow.rowIndex;
|
lastClickedRow = nextRow.rowIndex;
|
||||||
lastClickedRowId = nextRow.id;
|
lastClickedRowId = nextRow.id;
|
||||||
}
|
}
|
||||||
Mailer.dataTable.refresh();
|
|
||||||
deleteCachedMailboxByType("trash");
|
deleteCachedMailboxByType("trash");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -468,7 +509,7 @@ function deleteSelectedMessages(sender) {
|
||||||
}
|
}
|
||||||
var url = ApplicationBaseURL + encodeURI(Mailer.currentMailbox) + "/batchDelete";
|
var url = ApplicationBaseURL + encodeURI(Mailer.currentMailbox) + "/batchDelete";
|
||||||
var parameters = "uid=" + uids.join(",");
|
var parameters = "uid=" + uids.join(",");
|
||||||
var data = { "id": uids, "mailbox": Mailer.currentMailbox, "path": paths, "refreshUnseenCount": (unseenCount > 0) };
|
var data = { "id": uids, "mailbox": Mailer.currentMailbox, "path": paths, "refreshUnseenCount": (unseenCount > 0), "refreshFolder": refreshFolder };
|
||||||
triggerAjaxRequest(url, deleteSelectedMessagesCallback, data, parameters,
|
triggerAjaxRequest(url, deleteSelectedMessagesCallback, data, parameters,
|
||||||
{ "Content-type": "application/x-www-form-urlencoded" });
|
{ "Content-type": "application/x-www-form-urlencoded" });
|
||||||
}
|
}
|
||||||
|
@ -485,6 +526,8 @@ function deleteSelectedMessagesCallback(http) {
|
||||||
// TODO : the unseen count should be returned when calling the batchDelete remote action,
|
// TODO : the unseen count should be returned when calling the batchDelete remote action,
|
||||||
// in order to avoid this extra AJAX call.
|
// in order to avoid this extra AJAX call.
|
||||||
getUnseenCountForFolder(data["mailbox"]);
|
getUnseenCountForFolder(data["mailbox"]);
|
||||||
|
if (data["refreshFolder"])
|
||||||
|
Mailer.dataTable.refresh();
|
||||||
}
|
}
|
||||||
else if (!http.callbackData["withoutTrash"]) {
|
else if (!http.callbackData["withoutTrash"]) {
|
||||||
showConfirmDialog(_("Warning"),
|
showConfirmDialog(_("Warning"),
|
||||||
|
@ -514,16 +557,11 @@ function onMenuDeleteMessage(event) {
|
||||||
preventDefault(event);
|
preventDefault(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteMessage(url, id, mailbox, messageId) {
|
/**
|
||||||
var data = { "id": new Array(id), "mailbox": mailbox, "path": new Array(messageId) };
|
* The following two functions are called from UIxMailPopupView
|
||||||
var parameters = "uid=" + id;
|
* with window.opener.
|
||||||
deleteMessageRequestCount++;
|
*/
|
||||||
triggerAjaxRequest(url, deleteSelectedMessagesCallback, data, parameters,
|
|
||||||
{ "Content-type": "application/x-www-form-urlencoded" });
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteMessageWithDelay(url, id, mailbox, messageId) {
|
function deleteMessageWithDelay(url, id, mailbox, messageId) {
|
||||||
/* this is called by UIxMailPopupView with window.opener */
|
|
||||||
var row = $("row_" + id);
|
var row = $("row_" + id);
|
||||||
if (row) row.hide();
|
if (row) row.hide();
|
||||||
setTimeout("deleteMessage('" +
|
setTimeout("deleteMessage('" +
|
||||||
|
@ -534,6 +572,14 @@ function deleteMessageWithDelay(url, id, mailbox, messageId) {
|
||||||
50);
|
50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteMessage(url, id, mailbox, messageId) {
|
||||||
|
var data = { "id": new Array(id), "mailbox": mailbox, "path": new Array(messageId) };
|
||||||
|
var parameters = "uid=" + id;
|
||||||
|
deleteMessageRequestCount++;
|
||||||
|
triggerAjaxRequest(url, deleteSelectedMessagesCallback, data, parameters,
|
||||||
|
{ "Content-type": "application/x-www-form-urlencoded" });
|
||||||
|
}
|
||||||
|
|
||||||
function onPrintCurrentMessage(event) {
|
function onPrintCurrentMessage(event) {
|
||||||
var messageList = $("messageListBody").down("TBODY");
|
var messageList = $("messageListBody").down("TBODY");
|
||||||
var rows = messageList.getSelectedNodesId();
|
var rows = messageList.getSelectedNodesId();
|
||||||
|
@ -588,9 +634,9 @@ function toggleAddressColumn(search, replace) {
|
||||||
if (header) {
|
if (header) {
|
||||||
header.id = replace + "Header";
|
header.id = replace + "Header";
|
||||||
header.update(_(replace.capitalize()));
|
header.update(_(replace.capitalize()));
|
||||||
var i = UserDefaults["SOGoMailListViewColumnsOrder"].indexOf(search.capitalize());
|
var i = Mailer.columnsOrder.indexOf(search.capitalize());
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
UserDefaults["SOGoMailListViewColumnsOrder"][i] = replace.capitalize();
|
Mailer.columnsOrder[i] = replace.capitalize();
|
||||||
}
|
}
|
||||||
if (sorting["attribute"] == search)
|
if (sorting["attribute"] == search)
|
||||||
sorting["attribute"] = replace;
|
sorting["attribute"] = replace;
|
||||||
|
@ -767,7 +813,7 @@ function openMailbox(mailbox, reload) {
|
||||||
if (inboxData) {
|
if (inboxData) {
|
||||||
// Use UIDs and headers from the WOX template; this only
|
// Use UIDs and headers from the WOX template; this only
|
||||||
// happens once and only with the inbox
|
// happens once and only with the inbox
|
||||||
dataSource.init(inboxData['uids'], inboxData['headers']);
|
dataSource.init(inboxData['uids'], inboxData['threaded'], inboxData['headers']);
|
||||||
inboxData = null; // invalidate this initial lookup
|
inboxData = null; // invalidate this initial lookup
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -813,12 +859,20 @@ function messageListCallback(row, data, isNew) {
|
||||||
row.id = data['rowID'];
|
row.id = data['rowID'];
|
||||||
row.writeAttribute('labels', (data['labels']?data['labels']:""));
|
row.writeAttribute('labels', (data['labels']?data['labels']:""));
|
||||||
row.className = data['rowClasses'];
|
row.className = data['rowClasses'];
|
||||||
|
row.show(); // make sure the row is visible
|
||||||
|
|
||||||
// Restore previous selection
|
// Restore previous selection
|
||||||
if (data['uid'] == currentMessage)
|
if (data['uid'] == currentMessage)
|
||||||
row.addClassName('_selected');
|
row.addClassName('_selected');
|
||||||
|
|
||||||
var columnsOrder = UserDefaults["SOGoMailListViewColumnsOrder"];
|
if (data['Thread'])
|
||||||
|
row.addClassName('openedThread');
|
||||||
|
else if (data['ThreadLevel'] > 0) {
|
||||||
|
if (data['ThreadLevel'] > 10) data['ThreadLevel'] = 10;
|
||||||
|
row.addClassName('thread');
|
||||||
|
row.addClassName('thread' + data['ThreadLevel']);
|
||||||
|
}
|
||||||
|
|
||||||
var cells;
|
var cells;
|
||||||
if (Prototype.Browser.IE)
|
if (Prototype.Browser.IE)
|
||||||
cells = row.childNodes;
|
cells = row.childNodes;
|
||||||
|
@ -827,7 +881,7 @@ function messageListCallback(row, data, isNew) {
|
||||||
|
|
||||||
for (var j = 0; j < cells.length; j++) {
|
for (var j = 0; j < cells.length; j++) {
|
||||||
var cell = $(cells[j]);
|
var cell = $(cells[j]);
|
||||||
var cellType = columnsOrder[j];
|
var cellType = Mailer.columnsOrder[j];
|
||||||
|
|
||||||
if (data[cellType]) cell.innerHTML = data[cellType];
|
if (data[cellType]) cell.innerHTML = data[cellType];
|
||||||
else cell.innerHTML = ' ';
|
else cell.innerHTML = ' ';
|
||||||
|
@ -957,21 +1011,26 @@ function onMessageListRender(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMessageContextMenu(event) {
|
function onMessageContextMenu(event) {
|
||||||
var row = getTarget(event);
|
var target = Event.element(event);
|
||||||
var menu = $('messageListMenu');
|
var menu = $('messageListMenu');
|
||||||
var topNode = $('messageListBody');
|
var topNode = $('messageListBody');
|
||||||
var selectedNodes = topNode.getSelectedRows();
|
var selectedNodes = topNode.getSelectedRowsId();
|
||||||
if (row.tagName != 'TR')
|
var row = target.up('TR');
|
||||||
row = row.parentNode;
|
|
||||||
if (row.tagName != 'TR')
|
|
||||||
row = row.parentNode;
|
|
||||||
|
|
||||||
|
if (selectedNodes.indexOf(row.id) < 0) {
|
||||||
|
if (target.tagName != 'TD')
|
||||||
|
target = target.up('TD');
|
||||||
|
onRowClick(event, target);
|
||||||
|
selectedNodes = topNode.getSelectedRowsId();
|
||||||
|
}
|
||||||
|
|
||||||
menu.observe("hideMenu", onMessageContextMenuHide);
|
menu.observe("hideMenu", onMessageContextMenuHide);
|
||||||
|
|
||||||
if (selectedNodes.length > 1)
|
if (selectedNodes.length > 1)
|
||||||
popupMenu(event, "messagesListMenu", selectedNodes);
|
popupMenu(event, "messagesListMenu", selectedNodes);
|
||||||
else
|
else if (selectedNodes.length == 1)
|
||||||
popupMenu(event, "messageListMenu", row);
|
popupMenu(event, "messageListMenu", row);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMessageContextMenuHide(event) {
|
function onMessageContextMenuHide(event) {
|
||||||
|
@ -1110,7 +1169,10 @@ function onMessageSelectionChange(event) {
|
||||||
if (t.tagName == 'IMG') {
|
if (t.tagName == 'IMG') {
|
||||||
t = t.parentNode;
|
t = t.parentNode;
|
||||||
if (t.tagName == 'TD') {
|
if (t.tagName == 'TD') {
|
||||||
if (t.className == 'messageUnreadColumn') {
|
if (t.className == 'messageThreadColumn') {
|
||||||
|
//mailListToggleMessageThread(t.parentNode, t); Disable thread collapsing
|
||||||
|
}
|
||||||
|
else if (t.className == 'messageUnreadColumn') {
|
||||||
mailListToggleMessagesRead(t.parentNode);
|
mailListToggleMessagesRead(t.parentNode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1781,15 +1843,17 @@ function refreshMessage(mailbox, messageUID) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function configureMessageListEvents(headerTable, dataTable) {
|
function configureMessageListEvents() {
|
||||||
|
var headerTable = $("messageListHeader");
|
||||||
|
var dataTable = $("messageListBody");
|
||||||
|
|
||||||
if (headerTable)
|
if (headerTable)
|
||||||
// Sortable columns
|
// Sortable columns
|
||||||
configureSortableTableHeaders(headerTable);
|
configureSortableTableHeaders(headerTable);
|
||||||
|
|
||||||
if (dataTable) {
|
if (dataTable) {
|
||||||
dataTable.multiselect = true;
|
dataTable.multiselect = true;
|
||||||
// Each body row can load a message
|
dataTable.observe("click", onMessageSelectionChange);
|
||||||
dataTable.observe("mouseup", onMessageSelectionChange);
|
|
||||||
dataTable.observe("dblclick", onMessageDoubleClick);
|
dataTable.observe("dblclick", onMessageDoubleClick);
|
||||||
dataTable.observe("selectstart", listRowMouseDownHandler);
|
dataTable.observe("selectstart", listRowMouseDownHandler);
|
||||||
dataTable.observe("contextmenu", onMessageContextMenu);
|
dataTable.observe("contextmenu", onMessageContextMenu);
|
||||||
|
@ -1844,6 +1908,11 @@ function openInbox(node) {
|
||||||
|
|
||||||
function initMailer(event) {
|
function initMailer(event) {
|
||||||
if (!$(document.body).hasClassName("popup")) {
|
if (!$(document.body).hasClassName("popup")) {
|
||||||
|
Mailer.columnsOrder = UserDefaults["SOGoMailListViewColumnsOrder"];
|
||||||
|
Mailer.sortByThread = UserDefaults["SOGoMailSortByThreads"] != null && parseInt(UserDefaults["SOGoMailSortByThreads"]) > 0;
|
||||||
|
if (!Mailer.sortByThread && Mailer.columnsOrder[0] == "Thread")
|
||||||
|
Mailer.columnsOrder.shift(); // drop the thread column
|
||||||
|
|
||||||
// Restore sorting from user settings
|
// Restore sorting from user settings
|
||||||
if (UserSettings && UserSettings["Mail"] && UserSettings["Mail"]["SortingState"]) {
|
if (UserSettings && UserSettings["Mail"] && UserSettings["Mail"]["SortingState"]) {
|
||||||
sorting["attribute"] = UserSettings["Mail"]["SortingState"][0];
|
sorting["attribute"] = UserSettings["Mail"]["SortingState"][0];
|
||||||
|
@ -1866,7 +1935,7 @@ function initMailer(event) {
|
||||||
messageListHeader.restore($H(UserSettings["Mail"]["ColumnsState"]));
|
messageListHeader.restore($H(UserSettings["Mail"]["ColumnsState"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
configureMessageListEvents($("messageListHeader"), $("messageListBody"));
|
configureMessageListEvents();
|
||||||
|
|
||||||
initMailboxTree();
|
initMailboxTree();
|
||||||
initMessageCheckTimer();
|
initMessageCheckTimer();
|
||||||
|
@ -2589,15 +2658,16 @@ function onLabelMenuPrepareVisibility() {
|
||||||
function onMarkMenuPrepareVisibility() {
|
function onMarkMenuPrepareVisibility() {
|
||||||
var messageList = $("messageListBody");
|
var messageList = $("messageListBody");
|
||||||
if (messageList) {
|
if (messageList) {
|
||||||
var nodes = messageList.down("TBODY").getSelectedNodes();
|
var nodes = messageList.down("TBODY").getSelectedNodesId();
|
||||||
|
|
||||||
var isRead = false;
|
var isRead = false;
|
||||||
var isFlagged = false;
|
var isFlagged = false;
|
||||||
|
|
||||||
if (nodes.length > 0) {
|
if (nodes.length > 0) {
|
||||||
var row = nodes[0];
|
var row = null;
|
||||||
var firstTd = row.childElements().first();
|
for (var i = 0; row == null && i < nodes.length; i++)
|
||||||
var img = firstTd.childElements().first();
|
row = $(nodes[i]);
|
||||||
|
var img = row.down('img');
|
||||||
isFlagged = img.hasClassName ("messageIsFlagged");
|
isFlagged = img.hasClassName ("messageIsFlagged");
|
||||||
isRead = !row.hasClassName("mailer_unreadmail");
|
isRead = !row.hasClassName("mailer_unreadmail");
|
||||||
}
|
}
|
||||||
|
@ -2685,7 +2755,7 @@ function getMenus() {
|
||||||
"-", "moveMailboxMenu",
|
"-", "moveMailboxMenu",
|
||||||
"copyMailboxMenu", "label-menu",
|
"copyMailboxMenu", "label-menu",
|
||||||
"mark-menu", "-",
|
"mark-menu", "-",
|
||||||
saveAs, null,
|
saveAs, null, null,
|
||||||
onMenuDeleteMessage ],
|
onMenuDeleteMessage ],
|
||||||
imageMenu: [ saveImage ],
|
imageMenu: [ saveImage ],
|
||||||
attachmentMenu: [ saveAttachment ],
|
attachmentMenu: [ saveAttachment ],
|
||||||
|
@ -2857,16 +2927,15 @@ function startDragging (itm, e) {
|
||||||
if (target.up('TBODY') == undefined)
|
if (target.up('TBODY') == undefined)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (target.tagName != 'TD')
|
|
||||||
target = target.up('TD');
|
|
||||||
var row = target.up('TR');
|
var row = target.up('TR');
|
||||||
|
|
||||||
var handle = $("dragDropVisual");
|
var handle = $("dragDropVisual");
|
||||||
var selectedIds = $("messageListBody").getSelectedRowsId();
|
var selectedIds = $("messageListBody").getSelectedRowsId();
|
||||||
var count = selectedIds.length;
|
var count = selectedIds.length;
|
||||||
var rowId = row.id;
|
var rowId = row.id;
|
||||||
|
|
||||||
if (count == 0 || selectedIds.indexOf(rowId) < 0) {
|
if (count == 0 || selectedIds.indexOf(rowId) < 0) {
|
||||||
|
if (target.tagName != 'TD')
|
||||||
|
target = target.up('TD');
|
||||||
onRowClick(e, target);
|
onRowClick(e, target);
|
||||||
selectedIds = $("messageListBody").getSelectedRowsId();
|
selectedIds = $("messageListBody").getSelectedRowsId();
|
||||||
count = selectedIds.length;
|
count = selectedIds.length;
|
||||||
|
|
|
@ -57,9 +57,9 @@ var SOGoDataTableInterface = {
|
||||||
s = startIndex;
|
s = startIndex;
|
||||||
e = endIndex;
|
e = endIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (s <= e) {
|
while (s <= e) {
|
||||||
uid = "row_" + div.dataSource.uids[s];
|
uid = "row_" + div.dataSource.uidAtIndex(s);
|
||||||
if (this.selectedIds.indexOf(uid) < 0)
|
if (this.selectedIds.indexOf(uid) < 0)
|
||||||
this.selectedIds.push(uid);
|
this.selectedIds.push(uid);
|
||||||
s++;
|
s++;
|
||||||
|
@ -71,7 +71,7 @@ var SOGoDataTableInterface = {
|
||||||
var div = this.up('div');
|
var div = this.up('div');
|
||||||
this.selectedIds = new Array();
|
this.selectedIds = new Array();
|
||||||
for (var i = 0; i < div.dataSource.uids.length; i++)
|
for (var i = 0; i < div.dataSource.uids.length; i++)
|
||||||
this.selectedIds.push("row_" + div.dataSource.uids[i]);
|
this.selectedIds.push("row_" + div.dataSource.uidAtIndex(i));
|
||||||
this.refreshSelectionByIds();
|
this.refreshSelectionByIds();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ SOGoMailDataSource = Class.create({
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
|
||||||
this.uids = new Array();
|
this.uids = new Array();
|
||||||
|
this.threaded = false;
|
||||||
this.cache = new Hash();
|
this.cache = new Hash();
|
||||||
|
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
|
@ -27,7 +28,7 @@ SOGoMailDataSource = Class.create({
|
||||||
|
|
||||||
invalidate: function(uid) {
|
invalidate: function(uid) {
|
||||||
this.cache.unset(uid);
|
this.cache.unset(uid);
|
||||||
var index = this.uids.indexOf(parseInt(uid));
|
var index = this.indexOf(uid);
|
||||||
// log ("MailDataSource.invalidate(" + uid + ") at index " + index);
|
// log ("MailDataSource.invalidate(" + uid + ") at index " + index);
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
|
@ -41,10 +42,16 @@ SOGoMailDataSource = Class.create({
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
},
|
},
|
||||||
|
|
||||||
init: function(uids, headers) {
|
init: function(uids, threaded, headers) {
|
||||||
this.uids = uids;
|
this.uids = uids;
|
||||||
|
if (typeof threaded != "undefined") {
|
||||||
|
this.threaded = threaded;
|
||||||
|
if (threaded)
|
||||||
|
this.uids.shift(); // drop key fields
|
||||||
|
}
|
||||||
|
// log ("MailDataSource.init() " + this.uids.length + " uids loaded");
|
||||||
|
|
||||||
if (headers) {
|
if (headers) {
|
||||||
var keys = headers[0];
|
var keys = headers[0];
|
||||||
for (var i = 1; i < headers.length; i++) {
|
for (var i = 1; i < headers.length; i++) {
|
||||||
|
@ -53,6 +60,7 @@ SOGoMailDataSource = Class.create({
|
||||||
header[keys[j]] = headers[i][j];
|
header[keys[j]] = headers[i][j];
|
||||||
this.cache.set(header["uid"], header);
|
this.cache.set(header["uid"], header);
|
||||||
}
|
}
|
||||||
|
// log ("MailDataSource.init() " + this.cache.keys().length + " headers loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
|
@ -81,7 +89,7 @@ SOGoMailDataSource = Class.create({
|
||||||
if (http.responseText.length > 0) {
|
if (http.responseText.length > 0) {
|
||||||
var data = http.responseText.evalJSON(true);
|
var data = http.responseText.evalJSON(true);
|
||||||
if (data.uids)
|
if (data.uids)
|
||||||
this.init(data.uids, data.headers);
|
this.init(data.uids, data.threaded, data.headers);
|
||||||
else
|
else
|
||||||
this.init(data);
|
this.init(data);
|
||||||
if (this.delayedGetData) {
|
if (this.delayedGetData) {
|
||||||
|
@ -136,8 +144,9 @@ SOGoMailDataSource = Class.create({
|
||||||
// log ("MailDataSource._getData() from " + index + " to " + (index + count) + " boosted from " + start + " to " + end);
|
// log ("MailDataSource._getData() from " + index + " to " + (index + count) + " boosted from " + start + " to " + end);
|
||||||
|
|
||||||
for (i = 0, j = start; j < end; j++) {
|
for (i = 0, j = start; j < end; j++) {
|
||||||
if (!this.cache.get(this.uids[j])) {
|
var uid = this.threaded? this.uids[j][0] : this.uids[j];
|
||||||
missingUids[i] = this.uids[j];
|
if (!this.cache.get(uid)) {
|
||||||
|
missingUids[i] = uid;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,12 +205,45 @@ SOGoMailDataSource = Class.create({
|
||||||
var i, j;
|
var i, j;
|
||||||
var data = new Array();
|
var data = new Array();
|
||||||
for (i = start, j = 0; i < end; i++, j++) {
|
for (i = start, j = 0; i < end; i++, j++) {
|
||||||
data[j] = this.cache.get(this.uids[i]);
|
if (this.threaded) {
|
||||||
|
data[j] = this.cache.get(this.uids[i][0]);
|
||||||
|
|
||||||
|
// Add thread-related data
|
||||||
|
if (parseInt(this.uids[i][2]) > 0)
|
||||||
|
data[j]['Thread'] = ' '; //'<img class="messageThread" src="' + ResourcesURL + '/arrow-down.png">';
|
||||||
|
else
|
||||||
|
delete data[j]['Thread'];
|
||||||
|
if (parseInt(this.uids[i][1]) > -1)
|
||||||
|
data[j]['ThreadLevel'] = this.uids[i][1];
|
||||||
|
else
|
||||||
|
delete data[j]['ThreadLevel'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data[j] = this.cache.get(this.uids[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
callbackFunction(id, start, this.uids.length, data);
|
callbackFunction(id, start, this.uids.length, data);
|
||||||
},
|
},
|
||||||
|
|
||||||
indexOf: function(uid) {
|
indexOf: function(uid) {
|
||||||
return this.uids.indexOf(parseInt(uid));
|
var index = -1;
|
||||||
|
if (this.threaded) {
|
||||||
|
for (var i = 0; i < this.uids.length; i++)
|
||||||
|
if (this.uids[i][0] == uid) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
index = this.uids.indexOf(parseInt(uid));
|
||||||
|
|
||||||
|
return index;
|
||||||
|
},
|
||||||
|
|
||||||
|
uidAtIndex: function(index) {
|
||||||
|
if (this.threaded)
|
||||||
|
return this.uids[index][0];
|
||||||
|
else
|
||||||
|
return this.uids[index];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -93,7 +93,7 @@ div#headerArea div.addressList
|
||||||
div#attachmentsArea
|
div#attachmentsArea
|
||||||
{ display: none;
|
{ display: none;
|
||||||
float: right;
|
float: right;
|
||||||
width: 120px;
|
width: 200px;
|
||||||
padding: 2px 5px 0;
|
padding: 2px 5px 0;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
border-left: 1px solid #888; }
|
border-left: 1px solid #888; }
|
||||||
|
@ -144,7 +144,9 @@ UL#attachments
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
list-style-image: none;
|
list-style-image: none;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-x: hidden; }
|
overflow-x: hidden;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-khtml-user-select: none; }
|
||||||
|
|
||||||
UL#attachments LI
|
UL#attachments LI
|
||||||
{ white-space: nowrap;
|
{ white-space: nowrap;
|
||||||
|
|
|
@ -361,6 +361,7 @@ function initMailEditor() {
|
||||||
|
|
||||||
var list = $("attachments");
|
var list = $("attachments");
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
|
list.multiselect = true;
|
||||||
list.on("click", onRowClick);
|
list.on("click", onRowClick);
|
||||||
list.attachMenu("attachmentsMenu");
|
list.attachMenu("attachmentsMenu");
|
||||||
var elements = $(list).childNodesWithTag("li");
|
var elements = $(list).childNodesWithTag("li");
|
||||||
|
|
|
@ -89,7 +89,7 @@ DIV.listWrapper
|
||||||
DIV#filtersListWrapper
|
DIV#filtersListWrapper
|
||||||
{ bottom: 30px;
|
{ bottom: 30px;
|
||||||
right: 2em;
|
right: 2em;
|
||||||
top: 164px;
|
top: 174px;
|
||||||
left: 2em; }
|
left: 2em; }
|
||||||
|
|
||||||
TABLE#filtersList
|
TABLE#filtersList
|
||||||
|
|
|
@ -605,14 +605,6 @@ function onRowClick(event, target) {
|
||||||
// Single line selection
|
// Single line selection
|
||||||
$(node.parentNode).deselectAll();
|
$(node.parentNode).deselectAll();
|
||||||
$(node).selectElement();
|
$(node).selectElement();
|
||||||
|
|
||||||
if (initialSelection != $(node.parentNode).getSelectedNodesId()) {
|
|
||||||
// Selection has changed; fire mousedown event
|
|
||||||
var parentNode = node.parentNode;
|
|
||||||
if (parentNode.tagName == 'TBODY')
|
|
||||||
parentNode = parentNode.parentNode;
|
|
||||||
parentNode.fire("mousedown");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (rowIndex != null) {
|
if (rowIndex != null) {
|
||||||
lastClickedRow = rowIndex;
|
lastClickedRow = rowIndex;
|
||||||
|
@ -735,8 +727,6 @@ function hideMenu(menuNode) {
|
||||||
menuNode.parentMenu.submenu = null;
|
menuNode.parentMenu.submenu = null;
|
||||||
menuNode.parentMenu = null;
|
menuNode.parentMenu = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$(menuNode).fire("mousedown");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMenuEntryClick(event) {
|
function onMenuEntryClick(event) {
|
||||||
|
|
|
@ -50,7 +50,15 @@ TABLE.messageList TD
|
||||||
{ white-space: pre; }
|
{ white-space: pre; }
|
||||||
|
|
||||||
TABLE.messageList TR._selected TD
|
TABLE.messageList TR._selected TD
|
||||||
{ border-right: 1px solid #9ABCD8; }
|
{ border-right: 1px solid #9ABCD8 !important; }
|
||||||
|
|
||||||
|
TABLE.messageList TR.openedThread TD,
|
||||||
|
TABLE.messageList TR.closedThread TD,
|
||||||
|
TABLE.messageList TR.thread .messageThreadColumn
|
||||||
|
{ border-right: 1px solid #DDD; }
|
||||||
|
|
||||||
|
TABLE.messageList TR.thread TD
|
||||||
|
{ border-right: 1px solid #EEE; }
|
||||||
|
|
||||||
/* ContactsUI */
|
/* ContactsUI */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue