feat(mail): delay or disable automatic mark message as read

Fixes #1585
This commit is contained in:
Francis Lachapelle
2021-12-07 09:55:13 -05:00
parent 30040ba590
commit 4eed98d58d
14 changed files with 129 additions and 12 deletions

View File

@@ -119,6 +119,7 @@
SOGoMailDisplayRemoteInlineImages = "never";
SOGoMailCertificateEnabled = YES;
SOGoMailAutoMarkAsReadDelay = "0";
SOGoMailAutoSave = "5";
SOGoCalendarShouldDisplayWeekend = YES;

View File

@@ -148,6 +148,10 @@ extern NSString *SOGoWeekStartFirstFullWeek;
- (void) setMailDisplayRemoteInlineImages: (NSString *) newValue;
- (NSString *) mailDisplayRemoteInlineImages;
- (void) setMailAutoMarkAsReadDelay: (int) newValue;
- (int) mailAutoMarkAsReadDelay;
- (void) setMailAutoSave: (NSString *) newValue;
- (NSString *) mailAutoSave;

View File

@@ -18,10 +18,12 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSTimeZone.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NGBase64Coding.h>
#import <NGImap4/NSString+Imap4.h>
#import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WOContext+SoObjects.h>
@@ -618,6 +620,16 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
return [self stringForKey: @"SOGoMailDisplayRemoteInlineImages"];
}
- (void) setMailAutoMarkAsReadDelay: (int) newValue
{
[self setInteger: newValue forKey: @"SOGoMailAutoMarkAsReadDelay"];
}
- (int) mailAutoMarkAsReadDelay
{
return [self integerForKey: @"SOGoMailAutoMarkAsReadDelay"];
}
- (void) setMailAutoSave: (NSString *) newValue
{
[self setObject: newValue forKey: @"SOGoMailAutoSave"];

View File

@@ -272,11 +272,13 @@ static NSString *mailETag = nil;
NSMutableDictionary *data;
NSArray *addresses;
SOGoMailObject *co;
SOGoUserDefaults *ud;
UIxEnvelopeAddressFormatter *addressFormatter;
UIxMailRenderingContext *mctx;
id viewer, renderedPart;
co = [self clientObject];
ud = [[context activeUser] userDefaults];
addressFormatter = [context mailEnvelopeAddressFormatter];
mctx = [[UIxMailRenderingContext alloc] initWithViewer: self context: context];
@@ -349,8 +351,11 @@ static NSString *mailETag = nil;
if ((addresses = [addressFormatter dictionariesForArray: [co replyToEnvelopeAddresses]]))
[data setObject: addresses forKey: @"reply-to"];
// Mark message as read
[co addFlags: @"seen"];
if ([ud mailAutoMarkAsReadDelay] == 0)
// Mark message as read
[co addFlags: @"seen"];
[data setObject: [NSNumber numberWithBool: [co read]] forKey: @"isRead"];
response = [self responseWithStatus: 200
andJSONRepresentation: data];

View File

@@ -201,6 +201,10 @@
"displayremoteinlineimages_always" = "Always";
"Auto save every" = "Auto save every";
"minutes" = "minutes";
"Automatically mark messages as read" = "Automatically mark messages as read";
"Immediately on display" = "Immediately on display";
"After displaying for" = "After displaying for";
"seconds" = "seconds";
/* Contact */
"Personal Address Book" = "Personal Address Book";

View File

@@ -342,6 +342,9 @@ static SoProduct *preferencesProduct = nil;
if (![[defaults source] objectForKey: @"SOGoMailDisplayRemoteInlineImages"])
[[defaults source] setObject: [defaults mailDisplayRemoteInlineImages] forKey: @"SOGoMailDisplayRemoteInlineImages"];
if ([[defaults source] objectForKey: @"SOGoMailAutoMarkAsReadDelay"] == nil)
[[defaults source] setObject: [NSNumber numberWithInt: [defaults mailAutoMarkAsReadDelay]] forKey: @"SOGoMailAutoMarkAsReadDelay"];
if (![[defaults source] objectForKey: @"SOGoMailAutoSave"])
[[defaults source] setObject: [defaults mailAutoSave] forKey: @"SOGoMailAutoSave"];

View File

@@ -35,6 +35,12 @@
<md-button class="sg-icon-button" label:aria-label="Flagged" ng-click="viewer.message.toggleFlag()">
<md-icon ng-class="{ 'sg-icon-star': viewer.message.isflagged }">{{ viewer.message.isflagged ? 'star' : 'star_border' }}</md-icon>
</md-button>
<md-button class="sg-icon-button" label:aria-label="Mark as read"
ng-click="viewer.message.toggleRead()"
ng-switch="viewer.message.isread">
<md-icon class="ng-animate-disabled" ng-switch-when="true" rsrc:md-svg-src="img/mark_email_unread.svg"><!-- mark as unread --></md-icon>
<md-icon class="ng-animate-disabled" ng-switch-default="true" rsrc:md-svg-src="img/mark_email_read.svg"><!-- mark as read --></md-icon>
</md-button>
<md-button class="sg-icon-button"
ng-hide="::viewer.message.isDraft"
ng-click="viewer.reply($event)"

View File

@@ -638,12 +638,28 @@
<div>
<md-checkbox
ng-model="app.preferences.defaults.SOGoMailMarkAsReadDelay"
ng-true-value="1"
ng-false-value="0"
ng-model="app.preferences.defaults.SOGoMailAutoMarkAsReadEnabled"
label:aria-label="Automatically mark messages as read">
<var:string label:value="Automatically mark messages as read"/>
</md-checkbox>
<div flex-offset="5">
<md-radio-group
layout="row" layout-align="start center"
ng-model="app.preferences.defaults.SOGoMailAutoMarkAsReadMode"
ng-disabled="!app.preferences.defaults.SOGoMailAutoMarkAsReadEnabled">
<md-radio-button value="immediate"><var:string label:value="Immediately on display"/></md-radio-button>
<md-radio-button value="delay" style="padding-right: 0">
<var:string label:value="After displaying for"/>
</md-radio-button>
<md-input-container class="md-input-number" style="margin: 0" md-no-float="md-no-float">
<input type="number" min="1" label:aria-label="seconds"
ng-disabled="!app.preferences.defaults.SOGoMailAutoMarkAsReadEnabled"
ng-change="app.onMailAutoMarkAsReadDelay()"
ng-model="app.mailAutoMarkAsReadDelay"/>
</md-input-container>
<var:string label:value="seconds"/>
</md-radio-group>
</div>
</div>
<div class="hide-xs" layout="row" layout-align="start center" flex="50">

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px"><g><rect fill="none" height="24" width="24" x="0"/><path d="M12,19c0-3.87,3.13-7,7-7c1.08,0,2.09,0.25,3,0.68V6c0-1.1-0.9-2-2-2H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h8.08 C12.03,19.67,12,19.34,12,19z M4,6l8,5l8-5v2l-8,5L4,8V6z M17.34,22l-3.54-3.54l1.41-1.41l2.12,2.12l4.24-4.24L23,16.34L17.34,22z"/></g></svg>

After

Width:  |  Height:  |  Size: 429 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px"><g><rect fill="none" height="24" width="24"/><path d="M22,8.98V18c0,1.1-0.9,2-2,2H4c-1.1,0-2-0.9-2-2V6c0-1.1,0.9-2,2-2h10.1C14.04,4.32,14,4.66,14,5 c0,1.48,0.65,2.79,1.67,3.71L12,11L4,6v2l8,5l5.3-3.32C17.84,9.88,18.4,10,19,10C20.13,10,21.16,9.61,22,8.98z M16,5 c0,1.66,1.34,3,3,3s3-1.34,3-3s-1.34-3-3-3S16,3.34,16,5z"/></g></svg>

After

Width:  |  Height:  |  Size: 451 B

View File

@@ -132,6 +132,7 @@
_this.flags.splice(i, 1,'_' + flag);
}
});
this.isread = !!this.isread;
};
/**
@@ -540,6 +541,31 @@
return Message.$$resource.post(this.$mailbox.$id(), 'addOrRemoveLabel', data);
};
/**
* @function toggleRead
* @memberof Message.prototype
* @desc Toggle message unseen status
* @returns a promise of the HTTP operation
*/
Message.prototype.toggleRead = function() {
var _this = this;
if (this.isread)
return Message.$$resource.fetch(this.$absolutePath(), 'markMessageUnread').then(function() {
Message.$timeout(function() {
_this.isread = false;
_this.$mailbox.unseenCount++;
});
});
else
return Message.$$resource.fetch(this.$absolutePath(), 'markMessageRead').then(function() {
Message.$timeout(function() {
_this.isread = true;
_this.$mailbox.unseenCount--;
});
});
};
/**
* @function $imipAction
* @memberof Message.prototype
@@ -664,13 +690,16 @@
var _this = this, futureMessageData;
if (options && options.useCache && this.$futureMessageData) {
// The message has already been fetched.
if (!this.isread) {
Message.$$resource.fetch(this.$absolutePath(), 'markMessageRead').then(function() {
Message.$timeout(function() {
_this.isread = true;
_this.$mailbox.unseenCount--;
});
});
if (Message.$Preferences.defaults.SOGoMailAutoMarkAsReadDelay > -1)
// Automatically mark message as read
_this.$markAsReadPromise = Message.$timeout(function() {
Message.$$resource.fetch(_this.$absolutePath(), 'markMessageRead').then(function() {
_this.isread = true;
_this.$mailbox.unseenCount--;
});
}, Message.$Preferences.defaults.SOGoMailAutoMarkAsReadDelay * 1000);
}
return this;
}
@@ -865,7 +894,18 @@
// Resolve and expose the promise
this.$futureMessageData = futureMessageData.then(function(data) {
// Calling $timeout will force Angular to refresh the view
if (_this.isread === 0) {
if (!data.isRead) {
if (Message.$Preferences.defaults.SOGoMailAutoMarkAsReadDelay > -1)
// Automatically mark message as read
_this.$markAsReadPromise = Message.$timeout(function() {
Message.$$resource.fetch(_this.$absolutePath(), 'markMessageRead').then(function() {
_this.isread = true;
_this.$mailbox.unseenCount--;
});
}, Message.$Preferences.defaults.SOGoMailAutoMarkAsReadDelay * 1000);
}
else if (!_this.isread) {
// Message as already been marked read on the server
_this.isread = true;
_this.$mailbox.unseenCount--;
}

View File

@@ -98,6 +98,9 @@
_.forEach(hotkeys, function(key) {
sgHotkeys.deregisterHotkey(key);
});
// Cancel automatic mark as read
if (vm.message.$markAsReadPromise)
vm.service.$timeout.cancel(vm.message.$markAsReadPromise);
});
}; // $onInit

View File

@@ -53,6 +53,13 @@
if (data.SOGoRememberLastModule)
data.SOGoLoginModule = "Last";
data.SOGoMailAutoMarkAsReadDelay = parseInt(data.SOGoMailAutoMarkAsReadDelay) || 0;
data.SOGoMailAutoMarkAsReadEnabled = (data.SOGoMailAutoMarkAsReadDelay >= 0);
if (data.SOGoMailAutoMarkAsReadDelay > 0)
data.SOGoMailAutoMarkAsReadMode = 'delay';
else
data.SOGoMailAutoMarkAsReadMode = 'immediate';
// Mail editor autosave is a number of minutes or 0 if disabled
data.SOGoMailAutoSave = parseInt(data.SOGoMailAutoSave) || 0;
@@ -724,6 +731,15 @@
// Don't push locale definition
delete preferences.defaults.locale;
if (preferences.defaults.SOGoMailAutoMarkAsReadEnabled) {
if (preferences.defaults.SOGoMailAutoMarkAsReadMode == 'immediate')
preferences.defaults.SOGoMailAutoMarkAsReadDelay = 0;
} else {
preferences.defaults.SOGoMailAutoMarkAsReadDelay = -1;
}
delete preferences.defaults.SOGoMailAutoMarkAsReadEnabled;
delete preferences.defaults.SOGoMailAutoMarkAsReadMode;
// Merge back mail labels keys and values
preferences.defaults.SOGoMailLabelsColors = {};
_.forEach(preferences.defaults.SOGoMailLabelsColorsKeys, function(key, i) {

View File

@@ -25,6 +25,7 @@
$mdConstant.KEY_CODE.COMMA,
$mdConstant.KEY_CODE.SEMICOLON
];
this.mailAutoMarkAsReadDelay = Preferences.defaults.SOGoMailAutoMarkAsReadEnabled ? Preferences.defaults.SOGoMailAutoMarkAsReadDelay : 5;
// Set alternate avatar in User service
if (Preferences.defaults.SOGoAlternateAvatar)
@@ -107,6 +108,10 @@
form.$setDirty();
};
this.onMailAutoMarkAsReadDelay = function() {
this.preferences.defaults.SOGoMailAutoMarkAsReadDelay = this.mailAutoMarkAsReadDelay;
};
this.addMailAccount = function(ev, form) {
var account, index;