mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 06:30:59 +01:00
WIP push for mail (currently only Dovecot with further configuration!)
This commit is contained in:
parent
6d9dfc6364
commit
bf44ee753a
@ -210,25 +210,67 @@ var AppJS = (function(){ "use strict"; return Class.extend(
|
||||
},
|
||||
|
||||
/**
|
||||
* Push method receives push notification about updates to entries from the application
|
||||
* Handle a push notification about entry changes from the websocket
|
||||
*
|
||||
* It can use the extra _data parameter to determine if the client has read access to
|
||||
* the entry - if an update of the list is necessary.
|
||||
* Get's called for data of all apps, but should only handle data of apps it displays,
|
||||
* which is by default only it's own, but can be for multiple apps eg. for calendar.
|
||||
*
|
||||
* @param {string} _type either 'update', 'edit', 'delete', 'add' or null
|
||||
* @param pushData
|
||||
* @param {string} pushData.app application name
|
||||
* @param {(string|number)} pushData.id id of entry to refresh or null
|
||||
* @param {string} pushData.type either 'update', 'edit', 'delete', 'add' or null
|
||||
* - update: request just modified data from given rows. Sorting is not considered,
|
||||
* so if the sort field is changed, the row will not be moved.
|
||||
* - edit: rows changed, but sorting may be affected. Requires full reload.
|
||||
* - delete: just delete the given rows clientside (no server interaction neccessary)
|
||||
* - add: requires full reload for proper sorting
|
||||
* @param {string} _app application name
|
||||
* @param {(string|number)} _id id of entry to refresh or null
|
||||
* @param {mixed} _data eg. owner or responsible to decide if update is necessary
|
||||
* @returns {undefined}
|
||||
* @param {object|null} pushData.acl Extra data for determining relevance. eg: owner or responsible to decide if update is necessary
|
||||
* @param {number} pushData.account_id User that caused the notification
|
||||
*/
|
||||
push: function(_type, _app, _id, _data)
|
||||
push: function(pushData)
|
||||
{
|
||||
// don't care about other apps data, reimplement if your app does care eg. calendar
|
||||
if (pushData.app !== this.appname) return;
|
||||
|
||||
// only handle delete by default, for simple case of uid === "$app::$id"
|
||||
if (pushData.type === 'delete')
|
||||
{
|
||||
egw.dataStoreUID(this.uid(pushData), null);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get (possible) app-specific uid
|
||||
*
|
||||
* @param {object} pushData see push method for individual attributes
|
||||
*/
|
||||
uid(pushData)
|
||||
{
|
||||
return pushData.app + '::' + pushData.id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method called after apps push implementation checked visibility
|
||||
*
|
||||
* @param {et2_nextmatch} nm
|
||||
* @param pushData see push method for individual attributes
|
||||
* @todo implement better way to update nextmatch widget without disturbing the user / state
|
||||
* @todo show indicator that an update has happend
|
||||
* @todo rate-limit update frequency
|
||||
*/
|
||||
updateList: function(nm, pushData)
|
||||
{
|
||||
switch (pushData.type)
|
||||
{
|
||||
case 'add':
|
||||
case 'unknown':
|
||||
nm.applyFilters();
|
||||
break;
|
||||
|
||||
default:
|
||||
egw.dataRefreshUID(this.uid(pushData));
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -243,7 +285,7 @@ var AppJS = (function(){ "use strict"; return Class.extend(
|
||||
open: function(_action, _senders) {
|
||||
var id_app = _senders[0].id.split('::');
|
||||
egw.open(id_app[1], this.appname);
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* A generic method to action to server asynchronously
|
||||
|
@ -14,6 +14,7 @@ namespace EGroupware\Api\Mail\Imap;
|
||||
|
||||
use EGroupware\Api;
|
||||
use EGroupware\Api\Mail;
|
||||
use EGroupware\SwoolePush\Tokens;
|
||||
|
||||
/**
|
||||
* Manages connection to Dovecot IMAP server
|
||||
@ -24,7 +25,7 @@ use EGroupware\Api\Mail;
|
||||
* --> require by webserver writable user_home to be configured, otherwise deleting get ignored like with defaultimap
|
||||
* - quota can be read, but not set
|
||||
*/
|
||||
class Dovecot extends Mail\Imap
|
||||
class Dovecot extends Mail\Imap implements Mail\Imap\PushIface
|
||||
{
|
||||
/**
|
||||
* Label shown in EMailAdmin
|
||||
@ -281,4 +282,49 @@ class Dovecot extends Mail\Imap
|
||||
// mailbox get's automatic created with full rights for user
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata name to enable push notifications
|
||||
*/
|
||||
const METADATA_NAME = '/private/vendor/vendor.dovecot/http-notify';
|
||||
const METADATA_MAILBOX = '';
|
||||
const METADATA_PREFIX = 'user=';
|
||||
|
||||
/**
|
||||
* Enable push notifictions for current connection and given account_id
|
||||
*
|
||||
* @param int $account_id =null 0=everyone on the instance
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
function enablePush($account_id=null)
|
||||
{
|
||||
if (!class_exists(Tokens::class))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$this->setMetadata(self::METADATA_MAILBOX, [
|
||||
self::METADATA_NAME => self::METADATA_PREFIX.$GLOBALS['egw_info']['user']['account_id'].'::'.$this->acc_id.';'.
|
||||
$this->getMailBoxUserName($GLOBALS['egw_info']['user']['account_lid']) . ';' .
|
||||
((string)$account_id === '0' ? Tokens::instance() : Tokens::user($account_id)) . '@' .
|
||||
Api\Header\Http::host(),
|
||||
]);
|
||||
}
|
||||
catch (Horde_Imap_Client_Exception $e) {
|
||||
_egw_log_exception($e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if push is available / konfigured for given server
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function pushAvailable()
|
||||
{
|
||||
return in_array($this->acc_imap_host, ['imap.egroupware.org', 'mail.egroupware.org']) ||
|
||||
$this->acc_imap_host === 'mail' && $this->acc_imap_port == 10143;
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,9 @@
|
||||
* @link http://www.stylite.de
|
||||
* @package api
|
||||
* @subpackage mail
|
||||
* @author Ralf Becker <rb@stylite.de>
|
||||
* @author Stylite AG <info@stylite.de>
|
||||
* @author Ralf Becker <rb@egroupware.org>
|
||||
* @author EGroupware GmbH <info@egroupware.org>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Mail\Imap;
|
||||
|
38
api/src/Mail/Imap/PushIface.php
Normal file
38
api/src/Mail/Imap/PushIface.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* EGroupware Api: Push Interface for IMAP
|
||||
*
|
||||
* @link http://www.stylite.de
|
||||
* @package api
|
||||
* @subpackage mail
|
||||
* @author Ralf Becker <rb@egroupware.org>
|
||||
* @author EGroupware GmbH <info@egroupware.org>
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
*/
|
||||
|
||||
namespace EGroupware\Api\Mail\Imap;
|
||||
|
||||
/**
|
||||
* This class holds all information about the imap connection.
|
||||
* This is the base class for all other imap classes.
|
||||
*
|
||||
* Also proxies Sieve calls to Mail\Sieve (eg. it behaves like the former felamimail bosieve),
|
||||
* to allow IMAP plugins to also manage Sieve connection.
|
||||
*/
|
||||
interface PushIface
|
||||
{
|
||||
/**
|
||||
* Check if push is available / konfigured for given server
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function pushAvailable();
|
||||
|
||||
/**
|
||||
* Enable push notifictions for current connection and given account_id
|
||||
*
|
||||
* @param int $account_id =null 0=everyone on the instance
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
function enablePush($account_id=null);
|
||||
}
|
@ -248,7 +248,16 @@ class mail_ui
|
||||
|
||||
// save session varchar
|
||||
$oldicServerID =& Api\Cache::getSession('mail','activeProfileID');
|
||||
if ($oldicServerID <> self::$icServerID) $this->mail_bo->openConnection(self::$icServerID);
|
||||
if ($oldicServerID != self::$icServerID)
|
||||
{
|
||||
$this->mail_bo->openConnection(self::$icServerID);
|
||||
// enable push notifications, if supported (and konfigured) by the server
|
||||
if ($this->mail_bo->icServer instanceof Api\Mail\Imap\PushIface &&
|
||||
$this->mail_bo->icServer->pushAvailable())
|
||||
{
|
||||
$this->mail_bo->icServer->enablePush();
|
||||
}
|
||||
}
|
||||
if (true) $oldicServerID = self::$icServerID;
|
||||
if (!Mail::storeActiveProfileIDToPref($this->mail_bo->icServer, self::$icServerID, true ))
|
||||
{
|
||||
|
@ -5,10 +5,9 @@
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @author EGroupware GmbH [info@egroupware.org]
|
||||
* @copyright (c) 2013-2014 by EGroupware GmbH <info-AT-egroupware.org>
|
||||
* @copyright (c) 2013-2020 by EGroupware GmbH <info-AT-egroupware.org>
|
||||
* @package mail
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/*egw:uses
|
||||
@ -367,6 +366,54 @@ app.classes.mail = AppJS.extend(
|
||||
this.preSetToggledOnActions ();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle a push notification about entry changes from the websocket
|
||||
*
|
||||
* Get's called for data of all apps, but should only handle data of apps it displays,
|
||||
* which is by default only it's own, but can be for multiple apps eg. for calendar.
|
||||
*
|
||||
* @param pushData
|
||||
* @param {string} pushData.app application name
|
||||
* @param {(string|number)} pushData.id id of entry to refresh or null
|
||||
* @param {string} pushData.type either 'update', 'edit', 'delete', 'add' or null
|
||||
* - update: request just modified data from given rows. Sorting is not considered,
|
||||
* so if the sort field is changed, the row will not be moved.
|
||||
* - edit: rows changed, but sorting may be affected. Requires full reload.
|
||||
* - delete: just delete the given rows clientside (no server interaction neccessary)
|
||||
* - add: requires full reload for proper sorting
|
||||
* @param {object|null} pushData.acl Extra data for determining relevance. eg: owner or responsible to decide if update is necessary
|
||||
* @param {number} pushData.account_id User that caused the notification
|
||||
*/
|
||||
push: function(pushData)
|
||||
{
|
||||
// don't care about other apps data, reimplement if your app does care eg. calendar
|
||||
if (pushData.app !== this.appname) return;
|
||||
|
||||
// only handle delete by default, for simple case of uid === "$app::$id"
|
||||
if (pushData.type === 'delete')
|
||||
{
|
||||
return this._super.call(this, pushData);
|
||||
}
|
||||
|
||||
// notify user a new mail arrived
|
||||
if (pushData.type === 'add')
|
||||
{
|
||||
this.egw.message(this.egw.lang('New mail from %1', pushData.acl.from)+'\n'+pushData.acl.subject+'\n'+pushData.acl.snippet, 'success');
|
||||
}
|
||||
// check if we might not see it because we are on a different mail account or folder
|
||||
let nm = this.et2 ? this.et2.getWidgetById('nm') : null;
|
||||
let nm_value = nm ? nm.getValue() : null;
|
||||
if (nm_value && nm_value.col_filter)
|
||||
{
|
||||
this.updateList(nm, pushData);
|
||||
}
|
||||
// update unseen counter in folder-tree
|
||||
if (pushData.type === 'add' && pushData.acl.folder && pushData.acl.unseen)
|
||||
{
|
||||
// todo: pushData.id contains acc_id
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Observer method receives update notifications from all applications
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user