Added functionality to share contacts

Added setting "Automatically add recipients to your address beech"
Further development of editing screen contact
This commit is contained in:
RainLoop Team 2013-12-19 04:53:42 +04:00
parent 026839d864
commit 2d9ff7d63f
63 changed files with 1229 additions and 1919 deletions

View file

@ -9,6 +9,7 @@ function AdminContacts()
this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; this.defautOptionsAfterRender = Utils.defautOptionsAfterRender;
this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable')); this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable'));
this.contactsSharing = ko.observable(!!RL.settingsGet('ContactsSharing'));
var var
aTypes = ['sqlite', 'mysql', 'pgsql'], aTypes = ['sqlite', 'mysql', 'pgsql'],
@ -177,6 +178,12 @@ AdminContacts.prototype.onBuild = function ()
}); });
}); });
self.contactsSharing.subscribe(function (bValue) {
RL.remote().saveAdminConfig(null, {
'ContactsSharing': bValue ? '1' : '0'
});
});
self.contactsType.subscribe(function (sValue) { self.contactsType.subscribe(function (sValue) {
RL.remote().saveAdminConfig(f5, { RL.remote().saveAdminConfig(f5, {
'ContactsPdoType': sValue 'ContactsPdoType': sValue

View file

@ -238,12 +238,7 @@ Enums.InterfaceAnimation = {
Enums.ContactScopeType = { Enums.ContactScopeType = {
'Default': 0, 'Default': 0,
'ShareAll': 2
'Auto': 1,
'ShareAll': 2,
'ShareDomain': 3,
'ShareEmail': 4
}; };
/** /**

View file

@ -719,6 +719,7 @@ Utils.initDataConstructorBySettings = function (oData)
oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html); oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html);
oData.showImages = ko.observable(false); oData.showImages = ko.observable(false);
oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full); oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full);
oData.contactsAutosave = ko.observable(false);
Globals.sAnimationType = Enums.InterfaceAnimation.Full; Globals.sAnimationType = Enums.InterfaceAnimation.Full;

View file

@ -10,7 +10,6 @@ function ContactModel()
this.properties = []; this.properties = [];
this.readOnly = false; this.readOnly = false;
this.scopeType = Enums.ContactScopeType.Default; this.scopeType = Enums.ContactScopeType.Default;
this.scopeValue = '';
this.checked = ko.observable(false); this.checked = ko.observable(false);
this.selected = ko.observable(false); this.selected = ko.observable(false);
@ -61,7 +60,6 @@ ContactModel.prototype.parse = function (oItem)
this.display = Utils.pString(oItem['Display']); this.display = Utils.pString(oItem['Display']);
this.readOnly = !!oItem['ReadOnly']; this.readOnly = !!oItem['ReadOnly'];
this.scopeType = Utils.pInt(oItem['ScopeType']); this.scopeType = Utils.pInt(oItem['ScopeType']);
this.scopeValue = Utils.pString(oItem['ScopeValue']);
if (Utils.isNonEmptyArray(oItem['Properties'])) if (Utils.isNonEmptyArray(oItem['Properties']))
{ {
@ -73,10 +71,7 @@ ContactModel.prototype.parse = function (oItem)
}, this); }, this);
} }
this.shared(-1 < Utils.inArray(this.scopeType, [ this.shared(Enums.ContactScopeType.ShareAll === this.scopeType);
Enums.ContactScopeType.ShareAll, Enums.ContactScopeType.ShareDomain, Enums.ContactScopeType.ShareEmail
]));
bResult = true; bResult = true;
} }

View file

@ -4,12 +4,20 @@
* @param {number=} iType = Enums.ContactPropertyType.Unknown * @param {number=} iType = Enums.ContactPropertyType.Unknown
* @param {string=} sValue = '' * @param {string=} sValue = ''
* @param {boolean=} bFocused = false * @param {boolean=} bFocused = false
* @param {string=} sPlaceholder = ''
* *
* @constructor * @constructor
*/ */
function ContactPropertyModel(iType, sValue, bFocused) function ContactPropertyModel(iType, sValue, bFocused, sPlaceholder)
{ {
this.type = ko.observable(Utils.isUnd(iType) ? Enums.ContactPropertyType.Unknown : iType); this.type = ko.observable(Utils.isUnd(iType) ? Enums.ContactPropertyType.Unknown : iType);
this.focused = ko.observable(Utils.isUnd(bFocused) ? false : !!bFocused); this.focused = ko.observable(Utils.isUnd(bFocused) ? false : !!bFocused);
this.value = ko.observable(Utils.pString(sValue)); this.value = ko.observable(Utils.pString(sValue));
this.placeholder = ko.observable(sPlaceholder || '');
this.placeholderValue = ko.computed(function () {
var sPlaceholder = this.placeholder();
return sPlaceholder ? Utils.i18n(sPlaceholder) : '';
}, this);
} }

View file

@ -12,6 +12,7 @@ function SettingsGeneral()
this.mainMessagesPerPageArray = Consts.Defaults.MessagesPerPageArray; this.mainMessagesPerPageArray = Consts.Defaults.MessagesPerPageArray;
this.editorDefaultType = oData.editorDefaultType; this.editorDefaultType = oData.editorDefaultType;
this.showImages = oData.showImages; this.showImages = oData.showImages;
this.contactsAutosave = oData.contactsAutosave;
this.interfaceAnimation = oData.interfaceAnimation; this.interfaceAnimation = oData.interfaceAnimation;
this.useDesktopNotifications = oData.useDesktopNotifications; this.useDesktopNotifications = oData.useDesktopNotifications;
this.threading = oData.threading; this.threading = oData.threading;
@ -95,6 +96,12 @@ SettingsGeneral.prototype.onBuild = function ()
}); });
}); });
oData.contactsAutosave.subscribe(function (bValue) {
RL.remote().saveSettings(Utils.emptyFunction, {
'ContactsAutosave': bValue ? '1' : '0'
});
});
oData.interfaceAnimation.subscribe(function (sValue) { oData.interfaceAnimation.subscribe(function (sValue) {
RL.remote().saveSettings(Utils.emptyFunction, { RL.remote().saveSettings(Utils.emptyFunction, {
'InterfaceAnimation': sValue 'InterfaceAnimation': sValue

View file

@ -40,6 +40,7 @@ AbstractData.prototype.populateDataOnStart = function()
this.editorDefaultType(RL.settingsGet('EditorDefaultType')); this.editorDefaultType(RL.settingsGet('EditorDefaultType'));
this.showImages(!!RL.settingsGet('ShowImages')); this.showImages(!!RL.settingsGet('ShowImages'));
this.contactsAutosave(!!RL.settingsGet('ContactsAutosave'));
this.interfaceAnimation(RL.settingsGet('InterfaceAnimation')); this.interfaceAnimation(RL.settingsGet('InterfaceAnimation'));
this.mainMessagesPerPage(RL.settingsGet('MPP')); this.mainMessagesPerPage(RL.settingsGet('MPP'));

View file

@ -570,11 +570,12 @@ WebMailAjaxRemoteStorage.prototype.contacts = function (fCallback, iOffset, iLim
/** /**
* @param {?Function} fCallback * @param {?Function} fCallback
*/ */
WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, aProperties) WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, nScopeType, aProperties)
{ {
this.defaultRequest(fCallback, 'ContactSave', { this.defaultRequest(fCallback, 'ContactSave', {
'RequestUid': sRequestUid, 'RequestUid': sRequestUid,
'Uid': Utils.trim(sUid), 'Uid': Utils.trim(sUid),
'ScopeType': nScopeType,
'Properties': aProperties 'Properties': aProperties
}); });
}; };

View file

@ -5,10 +5,10 @@
.control-group { .control-group {
.control-label.fix-width { .control-label.fix-width {
width: 110px; width: 90px;
} }
.controls.fix-width { .controls.fix-width {
margin-left: 135px; margin-left: 110px;
} }
} }
@ -319,6 +319,12 @@
} }
} }
.e-save-trigger {
position: absolute;
top: 25px;
left: 10px;
}
.e-read-only-sign { .e-read-only-sign {
display: none; display: none;
position: absolute; position: absolute;
@ -328,14 +334,14 @@
.e-share-sign { .e-share-sign {
position: absolute; position: absolute;
top: 60px; top: 20px;
right: 20px; right: 20px;
cursor: pointer; cursor: pointer;
} }
.button-save-contact { .button-save-contact {
position: absolute; position: absolute;
top: 20px; top: 100px;
right: 20px; right: 20px;
} }

View file

@ -46,6 +46,10 @@
cursor: pointer; cursor: pointer;
} }
.e-item.selected > .e-link {
background-color: #eee;
}
.e-item > .e-link:hover { .e-item > .e-link:hover {
background-color: #555; background-color: #555;
background-image: none; background-image: none;

View file

@ -9,8 +9,8 @@ function PopupsContactsViewModel()
KnoinAbstractViewModel.call(this, 'Popups', 'PopupsContacts'); KnoinAbstractViewModel.call(this, 'Popups', 'PopupsContacts');
var var
oT = Enums.ContactPropertyType,
self = this, self = this,
oT = Enums.ContactPropertyType,
aNameTypes = [oT.FullName, oT.FirstName, oT.SurName, oT.MiddleName], aNameTypes = [oT.FullName, oT.FirstName, oT.SurName, oT.MiddleName],
aEmailTypes = [oT.EmailPersonal, oT.EmailBussines, oT.EmailOther], aEmailTypes = [oT.EmailPersonal, oT.EmailBussines, oT.EmailOther],
aPhonesTypes = [ aPhonesTypes = [
@ -34,6 +34,8 @@ function PopupsContactsViewModel()
this.contacts.loading = ko.observable(false).extend({'throttle': 200}); this.contacts.loading = ko.observable(false).extend({'throttle': 200});
this.currentContact = ko.observable(null); this.currentContact = ko.observable(null);
this.contactsSharingIsAllowed = !!RL.settingsGet('ContactsSharingIsAllowed');
this.contactsPage = ko.observable(1); this.contactsPage = ko.observable(1);
this.contactsPageCount = ko.computed(function () { this.contactsPageCount = ko.computed(function () {
var iPage = Math.ceil(this.contactsCount() / Consts.Defaults.ContactsPerPage); var iPage = Math.ceil(this.contactsCount() / Consts.Defaults.ContactsPerPage);
@ -48,9 +50,10 @@ function PopupsContactsViewModel()
this.viewID = ko.observable(''); this.viewID = ko.observable('');
this.viewReadOnly = ko.observable(false); this.viewReadOnly = ko.observable(false);
this.viewScopeType = ko.observable(Enums.ContactScopeType.Default); this.viewScopeType = ko.observable(Enums.ContactScopeType.Default);
this.viewScopeValue = ko.observable('');
this.viewProperties = ko.observableArray([]); this.viewProperties = ko.observableArray([]);
this.viewSaveTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
this.viewPropertiesNames = this.viewProperties.filter(function(oProperty) { this.viewPropertiesNames = this.viewProperties.filter(function(oProperty) {
return -1 < Utils.inArray(oProperty.type(), aNameTypes); return -1 < Utils.inArray(oProperty.type(), aNameTypes);
}); });
@ -59,24 +62,18 @@ function PopupsContactsViewModel()
return -1 < Utils.inArray(oProperty.type(), aEmailTypes); return -1 < Utils.inArray(oProperty.type(), aEmailTypes);
}); });
this.shareIcon = ko.computed(function() {
return Enums.ContactScopeType.ShareAll === this.viewScopeType() ? 'icon-earth' : 'icon-share';
}, this);
this.shareToNone = ko.computed(function() { this.shareToNone = ko.computed(function() {
return -1 === Utils.inArray(this.viewScopeType(), [ return Enums.ContactScopeType.ShareAll !== this.viewScopeType();
Enums.ContactScopeType.ShareAll, Enums.ContactScopeType.ShareDomain, Enums.ContactScopeType.ShareEmail
]);
}, this); }, this);
this.shareToAll = ko.computed(function() { this.shareToAll = ko.computed(function() {
return Enums.ContactScopeType.ShareAll === this.viewScopeType(); return Enums.ContactScopeType.ShareAll === this.viewScopeType();
}, this); }, this);
this.shareToDomain = ko.computed(function() {
return Enums.ContactScopeType.ShareDomain === this.viewScopeType();
}, this);
this.shareToEmail = ko.computed(function() {
return Enums.ContactScopeType.ShareEmail === this.viewScopeType();
}, this);
this.viewHasNonEmptyRequaredProperties = ko.computed(function() { this.viewHasNonEmptyRequaredProperties = ko.computed(function() {
var var
@ -98,6 +95,10 @@ function PopupsContactsViewModel()
return -1 < Utils.inArray(oProperty.type(), aOtherTypes); return -1 < Utils.inArray(oProperty.type(), aOtherTypes);
}); });
this.viewPropertiesEmailsNonEmpty = this.viewPropertiesNames.filter(function(oProperty) {
return '' !== Utils.trim(oProperty.value());
});
this.viewPropertiesEmailsEmptyAndOnFocused = this.viewPropertiesEmails.filter(function(oProperty) { this.viewPropertiesEmailsEmptyAndOnFocused = this.viewPropertiesEmails.filter(function(oProperty) {
var bF = oProperty.focused(); var bF = oProperty.focused();
return '' === Utils.trim(oProperty.value()) && !bF; return '' === Utils.trim(oProperty.value()) && !bF;
@ -223,6 +224,7 @@ function PopupsContactsViewModel()
this.saveCommand = Utils.createCommand(this, function () { this.saveCommand = Utils.createCommand(this, function () {
this.viewSaving(true); this.viewSaving(true);
this.viewSaveTrigger(Enums.SaveSettingsStep.Animate);
var var
sRequestUid = Utils.fakeMd5(), sRequestUid = Utils.fakeMd5(),
@ -238,7 +240,9 @@ function PopupsContactsViewModel()
RL.remote().contactSave(function (sResult, oData) { RL.remote().contactSave(function (sResult, oData) {
var bRes = false;
self.viewSaving(false); self.viewSaving(false);
if (Enums.StorageResultType.Success === sResult && oData && oData.Result && if (Enums.StorageResultType.Success === sResult && oData && oData.Result &&
oData.Result.RequestUid === sRequestUid && 0 < Utils.pInt(oData.Result.ResultID)) oData.Result.RequestUid === sRequestUid && 0 < Utils.pInt(oData.Result.ResultID))
{ {
@ -248,13 +252,25 @@ function PopupsContactsViewModel()
} }
self.reloadContactList(); self.reloadContactList();
bRes = true;
} }
// else // else
// { // {
// // TODO // // TODO
// } // }
}, sRequestUid, this.viewID(), aProperties); _.delay(function () {
self.viewSaveTrigger(bRes ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult);
}, 300);
if (bRes)
{
_.delay(function () {
self.viewSaveTrigger(Enums.SaveSettingsStep.Idle);
}, 1000);
}
}, sRequestUid, this.viewID(), this.viewScopeType(), aProperties);
}, function () { }, function () {
var var
@ -266,11 +282,36 @@ function PopupsContactsViewModel()
this.bDropPageAfterDelete = false; this.bDropPageAfterDelete = false;
this.watchHash = ko.observable(false);
this.viewHash = ko.computed(function () {
return '' + self.viewScopeType() + ' - ' + _.map(self.viewProperties(), function (oItem) {
return oItem.value();
}).join('');
});
this.saveCommandDebounce = _.debounce(_.bind(this.saveCommand, this), 1000);
this.viewHash.subscribe(function () {
if (this.watchHash() && !this.viewReadOnly())
{
this.saveCommandDebounce();
}
}, this);
Knoin.constructorEnd(this); Knoin.constructorEnd(this);
} }
Utils.extendAsViewModel('PopupsContactsViewModel', PopupsContactsViewModel); Utils.extendAsViewModel('PopupsContactsViewModel', PopupsContactsViewModel);
PopupsContactsViewModel.prototype.setShareToNone = function ()
{
this.viewScopeType(Enums.ContactScopeType.Default);
};
PopupsContactsViewModel.prototype.setShareToAll = function ()
{
this.viewScopeType(Enums.ContactScopeType.ShareAll);
};
PopupsContactsViewModel.prototype.addNewProperty = function (sType) PopupsContactsViewModel.prototype.addNewProperty = function (sType)
{ {
@ -377,10 +418,11 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
aList = [] aList = []
; ;
this.watchHash(false);
this.emptySelection(false); this.emptySelection(false);
this.viewReadOnly(false); this.viewReadOnly(false);
this.viewScopeType(Enums.ContactScopeType.Default); this.viewScopeType(Enums.ContactScopeType.Default);
this.viewScopeValue('');
if (oContact) if (oContact)
{ {
@ -391,7 +433,9 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
_.each(oContact.properties, function (aProperty) { _.each(oContact.properties, function (aProperty) {
if (aProperty && aProperty[0]) if (aProperty && aProperty[0])
{ {
aList.push(new ContactPropertyModel(aProperty[0], aProperty[1])); aList.push(new ContactPropertyModel(aProperty[0], aProperty[1], false,
Enums.ContactPropertyType.FullName === aProperty[0] ? 'CONTACTS/PLACEHOLDER_ENTER_DISPLAY_NAME' : ''));
if (Enums.ContactPropertyType.FullName === aProperty[0]) if (Enums.ContactPropertyType.FullName === aProperty[0])
{ {
bHasName = true; bHasName = true;
@ -402,17 +446,18 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
this.viewReadOnly(!!oContact.readOnly); this.viewReadOnly(!!oContact.readOnly);
this.viewScopeType(oContact.scopeType); this.viewScopeType(oContact.scopeType);
this.viewScopeValue(oContact.scopeValue);
} }
if (!bHasName) if (!bHasName)
{ {
aList.push(new ContactPropertyModel(Enums.ContactPropertyType.FullName, '', true)); aList.push(new ContactPropertyModel(Enums.ContactPropertyType.FullName, '', !oContact, 'CONTACTS/PLACEHOLDER_ENTER_DISPLAY_NAME'));
} }
this.viewID(sId); this.viewID(sId);
this.viewProperties([]); this.viewProperties([]);
this.viewProperties(aList); this.viewProperties(aList);
this.watchHash(true);
}; };
/** /**
@ -446,7 +491,7 @@ PopupsContactsViewModel.prototype.reloadContactList = function (bDropPagePositio
{ {
aList = _.map(oData.Result.List, function (oItem) { aList = _.map(oData.Result.List, function (oItem) {
var oContact = new ContactModel(); var oContact = new ContactModel();
return oContact.parse(oItem) ? oContact : null; return oContact.parse(oItem, self.contactsSharingIsAllowed) ? oContact : null;
}); });
aList = _.compact(aList); aList = _.compact(aList);

View file

@ -2,7 +2,7 @@
"name": "RainLoop", "name": "RainLoop",
"title": "RainLoop Webmail", "title": "RainLoop Webmail",
"version": "1.5.1", "version": "1.5.1",
"release": "554", "release": "555",
"description": "Simple, modern & fast web-based email client", "description": "Simple, modern & fast web-based email client",
"homepage": "http://rainloop.net", "homepage": "http://rainloop.net",
"main": "Gruntfile.js", "main": "Gruntfile.js",

View file

@ -562,6 +562,9 @@ class Actions
{ {
$this->oPersonalAddressBookProvider = new \RainLoop\Providers\PersonalAddressBook( $this->oPersonalAddressBookProvider = new \RainLoop\Providers\PersonalAddressBook(
$this->Config()->Get('contacts', 'enable', false) || $bForceEnable ? $this->fabrica('personal-address-book', $oAccount) : null); $this->Config()->Get('contacts', 'enable', false) || $bForceEnable ? $this->fabrica('personal-address-book', $oAccount) : null);
$this->oPersonalAddressBookProvider->ConsiderShare(
!!$this->Config()->Get('contacts', 'allow_sharing', false));
} }
else if ($oAccount && $this->oPersonalAddressBookProvider->IsSupported()) else if ($oAccount && $this->oPersonalAddressBookProvider->IsSupported())
{ {
@ -932,6 +935,7 @@ class Actions
$aResult['AccountHash'] = $oAccount->Hash(); $aResult['AccountHash'] = $oAccount->Hash();
$aResult['ChangePasswordIsAllowed'] = $this->ChangePasswordProvider()->PasswordChangePossibility($oAccount); $aResult['ChangePasswordIsAllowed'] = $this->ChangePasswordProvider()->PasswordChangePossibility($oAccount);
$aResult['ContactsIsAllowed'] = $this->PersonalAddressBookProvider($oAccount)->IsActive(); $aResult['ContactsIsAllowed'] = $this->PersonalAddressBookProvider($oAccount)->IsActive();
$aResult['ContactsSharingIsAllowed'] = $this->PersonalAddressBookProvider($oAccount)->IsSharingAllowed();
$oSettings = $this->SettingsProvider()->Load($oAccount); $oSettings = $this->SettingsProvider()->Load($oAccount);
} }
@ -990,6 +994,7 @@ class Actions
$aResult['PostgreSqlIsSupported'] = \is_array($aDrivers) ? \in_array('pgsql', $aDrivers) : false; $aResult['PostgreSqlIsSupported'] = \is_array($aDrivers) ? \in_array('pgsql', $aDrivers) : false;
$aResult['ContactsEnable'] = (bool) $oConfig->Get('contacts', 'enable', false); $aResult['ContactsEnable'] = (bool) $oConfig->Get('contacts', 'enable', false);
$aResult['ContactsSharing'] = (bool) $oConfig->Get('contacts', 'allow_sharing', false);
$aResult['ContactsPdoType'] = $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite'))); $aResult['ContactsPdoType'] = $this->ValidateContactPdoType(\trim($this->Config()->Get('contacts', 'type', 'sqlite')));
$aResult['ContactsPdoDsn'] = (string) $oConfig->Get('contacts', 'pdo_dsn', ''); $aResult['ContactsPdoDsn'] = (string) $oConfig->Get('contacts', 'pdo_dsn', '');
$aResult['ContactsPdoType'] = (string) $oConfig->Get('contacts', 'type', ''); $aResult['ContactsPdoType'] = (string) $oConfig->Get('contacts', 'type', '');
@ -1033,6 +1038,7 @@ class Actions
// user // user
$aResult['EditorDefaultType'] = (string) $oConfig->Get('webmail', 'editor_default_type', ''); $aResult['EditorDefaultType'] = (string) $oConfig->Get('webmail', 'editor_default_type', '');
$aResult['ShowImages'] = (bool) $oConfig->Get('webmail', 'show_images', false); $aResult['ShowImages'] = (bool) $oConfig->Get('webmail', 'show_images', false);
$aResult['ContactsAutosave'] = true;
$aResult['MPP'] = (int) $oConfig->Get('webmail', 'messages_per_page', 25); $aResult['MPP'] = (int) $oConfig->Get('webmail', 'messages_per_page', 25);
$aResult['DesktopNotifications'] = false; $aResult['DesktopNotifications'] = false;
$aResult['UseThreads'] = false; $aResult['UseThreads'] = false;
@ -1066,6 +1072,7 @@ class Actions
$aResult['NullFolder'] = $oSettings->GetConf('NullFolder', ''); $aResult['NullFolder'] = $oSettings->GetConf('NullFolder', '');
$aResult['EditorDefaultType'] = $oSettings->GetConf('EditorDefaultType', $aResult['EditorDefaultType']); $aResult['EditorDefaultType'] = $oSettings->GetConf('EditorDefaultType', $aResult['EditorDefaultType']);
$aResult['ShowImages'] = (bool) $oSettings->GetConf('ShowImages', $aResult['ShowImages']); $aResult['ShowImages'] = (bool) $oSettings->GetConf('ShowImages', $aResult['ShowImages']);
$aResult['ContactsAutosave'] = (bool) $oSettings->GetConf('ContactsAutosave', $aResult['ContactsAutosave']);
$aResult['MPP'] = (int) $oSettings->GetConf('MPP', $aResult['MPP']); $aResult['MPP'] = (int) $oSettings->GetConf('MPP', $aResult['MPP']);
$aResult['DesktopNotifications'] = (bool) $oSettings->GetConf('DesktopNotifications', $aResult['DesktopNotifications']); $aResult['DesktopNotifications'] = (bool) $oSettings->GetConf('DesktopNotifications', $aResult['DesktopNotifications']);
$aResult['UseThreads'] = (bool) $oSettings->GetConf('UseThreads', $aResult['UseThreads']); $aResult['UseThreads'] = (bool) $oSettings->GetConf('UseThreads', $aResult['UseThreads']);
@ -1867,6 +1874,7 @@ class Actions
$this->setConfigFromParams($oConfig, 'LoginDefaultDomain', 'login', 'default_domain', 'string'); $this->setConfigFromParams($oConfig, 'LoginDefaultDomain', 'login', 'default_domain', 'string');
$this->setConfigFromParams($oConfig, 'ContactsEnable', 'contacts', 'enable', 'bool'); $this->setConfigFromParams($oConfig, 'ContactsEnable', 'contacts', 'enable', 'bool');
$this->setConfigFromParams($oConfig, 'ContactsSharing', 'contacts', 'allow_sharing', 'bool');
$this->setConfigFromParams($oConfig, 'ContactsPdoDsn', 'contacts', 'pdo_dsn', 'string'); $this->setConfigFromParams($oConfig, 'ContactsPdoDsn', 'contacts', 'pdo_dsn', 'string');
$this->setConfigFromParams($oConfig, 'ContactsPdoUser', 'contacts', 'pdo_user', 'string'); $this->setConfigFromParams($oConfig, 'ContactsPdoUser', 'contacts', 'pdo_user', 'string');
$this->setConfigFromParams($oConfig, 'ContactsPdoPassword', 'contacts', 'pdo_password', 'dummy'); $this->setConfigFromParams($oConfig, 'ContactsPdoPassword', 'contacts', 'pdo_password', 'dummy');
@ -3000,6 +3008,7 @@ class Actions
$this->setSettingsFromParams($oSettings, 'EditorDefaultType', 'string'); $this->setSettingsFromParams($oSettings, 'EditorDefaultType', 'string');
$this->setSettingsFromParams($oSettings, 'ShowImages', 'bool'); $this->setSettingsFromParams($oSettings, 'ShowImages', 'bool');
$this->setSettingsFromParams($oSettings, 'ContactsAutosave', 'bool');
$this->setSettingsFromParams($oSettings, 'InterfaceAnimation', 'string', function ($sValue) { $this->setSettingsFromParams($oSettings, 'InterfaceAnimation', 'string', function ($sValue) {
return (\in_array($sValue, return (\in_array($sValue,
array(\RainLoop\Enumerations\InterfaceAnimation::NONE, array(\RainLoop\Enumerations\InterfaceAnimation::NONE,
@ -4153,7 +4162,10 @@ class Actions
if (0 < \count($aArrayToFrec)) if (0 < \count($aArrayToFrec))
{ {
$this->PersonalAddressBookProvider($oAccount)->IncFrec($oAccount, \array_values($aArrayToFrec)); $oSettings = $this->SettingsProvider()->Load($oAccount);
$this->PersonalAddressBookProvider($oAccount)->IncFrec($oAccount, \array_values($aArrayToFrec),
!!$oSettings->GetConf('ContactsAutosave', false));
} }
} }
@ -4196,7 +4208,7 @@ class Actions
{ {
$iCount = 0; $iCount = 0;
$mResult = $this->PersonalAddressBookProvider($oAccount)->GetContacts($oAccount, $mResult = $this->PersonalAddressBookProvider($oAccount)->GetContacts($oAccount,
$iOffset, $iLimit, $sSearch, \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_, $iCount); $iOffset, $iLimit, $sSearch, $iCount);
} }
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(__FUNCTION__, array(
@ -4244,6 +4256,13 @@ class Actions
if ($oPab && $oPab->IsActive() && 0 < \strlen($sRequestUid)) if ($oPab && $oPab->IsActive() && 0 < \strlen($sRequestUid))
{ {
$sUid = \trim($this->GetActionParam('Uid', '')); $sUid = \trim($this->GetActionParam('Uid', ''));
$iScopeType = (int) $this->GetActionParam('ScopeType', null);
if (!in_array($iScopeType, array(
\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_,
\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL)))
{
$iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
}
$oContact = new \RainLoop\Providers\PersonalAddressBook\Classes\Contact(); $oContact = new \RainLoop\Providers\PersonalAddressBook\Classes\Contact();
if (0 < \strlen($sUid)) if (0 < \strlen($sUid))
@ -4251,6 +4270,8 @@ class Actions
$oContact->IdContact = $sUid; $oContact->IdContact = $sUid;
} }
$oContact->ScopeType = $iScopeType;
$aProperties = $this->GetActionParam('Properties', array()); $aProperties = $this->GetActionParam('Properties', array());
if (\is_array($aProperties)) if (\is_array($aProperties))
{ {
@ -4262,6 +4283,7 @@ class Actions
$oProp = new \RainLoop\Providers\PersonalAddressBook\Classes\Property(); $oProp = new \RainLoop\Providers\PersonalAddressBook\Classes\Property();
$oProp->Type = (int) $aItem[0]; $oProp->Type = (int) $aItem[0];
$oProp->Value = $aItem[1]; $oProp->Value = $aItem[1];
$oProp->ScopeType = $iScopeType;
$oContact->Properties[] = $oProp; $oContact->Properties[] = $oProp;
} }
@ -5911,16 +5933,6 @@ class Actions
'Email' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetEmail()) 'Email' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetEmail())
)); ));
} }
else if ('RainLoop\Providers\Contacts\Classes\Contact' === $sClassName)
{
$mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
'IdContact' => $mResponse->IdContact,
'ImageHash' => $mResponse->ImageHash,
'ListName' => \MailSo\Base\Utils::Utf8Clear($mResponse->ListName),
'Name' => \MailSo\Base\Utils::Utf8Clear($mResponse->Name),
'Emails' => $mResponse->Emails
));
}
else if ('RainLoop\Providers\PersonalAddressBook\Classes\Contact' === $sClassName) else if ('RainLoop\Providers\PersonalAddressBook\Classes\Contact' === $sClassName)
{ {
$mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array( $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
@ -5929,7 +5941,6 @@ class Actions
'Display' => \MailSo\Base\Utils::Utf8Clear($mResponse->Display), 'Display' => \MailSo\Base\Utils::Utf8Clear($mResponse->Display),
'ReadOnly' => $mResponse->ReadOnly, 'ReadOnly' => $mResponse->ReadOnly,
'ScopeType' => $mResponse->ScopeType, 'ScopeType' => $mResponse->ScopeType,
'ScopeValue' => $mResponse->ScopeValue,
'IdPropertyFromSearch' => $mResponse->IdPropertyFromSearch, 'IdPropertyFromSearch' => $mResponse->IdPropertyFromSearch,
'Properties' => $this->responseObject($mResponse->Properties, $sParent, $aParameters) 'Properties' => $this->responseObject($mResponse->Properties, $sParent, $aParameters)
)); ));
@ -5942,7 +5953,7 @@ class Actions
'Type' => $mResponse->Type, 'Type' => $mResponse->Type,
'TypeCustom' => $mResponse->TypeCustom, 'TypeCustom' => $mResponse->TypeCustom,
'Value' => \MailSo\Base\Utils::Utf8Clear($mResponse->Value), 'Value' => \MailSo\Base\Utils::Utf8Clear($mResponse->Value),
'ValueClear' => \MailSo\Base\Utils::Utf8Clear($mResponse->ValueClear) 'ValueCustom' => \MailSo\Base\Utils::Utf8Clear($mResponse->ValueCustom)
)); ));
} }
else if ('MailSo\Mail\Attachment' === $sClassName) else if ('MailSo\Mail\Attachment' === $sClassName)

View file

@ -83,6 +83,7 @@ class Application extends \RainLoop\Config\AbstractConfig
'contacts' => array( 'contacts' => array(
'enable' => array(false, 'Enable contacts'), 'enable' => array(false, 'Enable contacts'),
'allow_sharing' => array(true),
'suggestions_limit' => array(30), 'suggestions_limit' => array(30),
'type' => array('sqlite', ''), 'type' => array('sqlite', ''),
'pdo_dsn' => array('mysql:host=127.0.0.1;port=3306;dbname=rainloop', ''), 'pdo_dsn' => array('mysql:host=127.0.0.1;port=3306;dbname=rainloop', ''),

View file

@ -1,121 +0,0 @@
<?php
namespace RainLoop\Providers;
class Contacts extends \RainLoop\Providers\AbstractProvider
{
/**
* @var \RainLoop\Providers\Contacts\ContactsInterface
*/
private $oDriver;
/**
* @param \RainLoop\Providers\Contacts\ContactsInterface $oDriver
*
* @return void
*/
public function __construct($oDriver)
{
$this->oDriver = null;
if ($oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface)
{
$this->oDriver = $oDriver;
}
}
/**
* @return bool
*/
public function IsActive()
{
return $this->oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface &&
$this->oDriver->IsSupported();
}
/**
* @return bool
*/
public function IsSupported()
{
return $this->oDriver instanceof \RainLoop\Providers\Contacts\ContactsInterface &&
$this->oDriver->IsSupported();
}
/**
* @param \RainLoop\Account $oAccount
* @param int $iIdContact
*
* @return array
*/
public function GetContactById($oAccount, $iIdContact)
{
return $this->oDriver ? $this->oDriver->GetContactById($oAccount, $iIdContact) : null;
}
/**
* @param \RainLoop\Account $oAccount
* @param int $iOffset = 0
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '')
{
return $this->oDriver ? $this->oDriver->GetContacts($oAccount, $iOffset, $iLimit, $sSearch) : array();
}
/**
* @param \RainLoop\Account $oAccount
*
* @return array
*/
public function GetContactsImageHashes($oAccount)
{
return $this->oDriver ? $this->oDriver->GetContactsImageHashes($oAccount) : array();
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function CreateContact($oAccount, &$oContact)
{
return $this->oDriver ? $this->oDriver->CreateContact($oAccount, $oContact) : false;
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function UpdateContact($oAccount, &$oContact)
{
return $this->oDriver ? $this->oDriver->UpdateContact($oAccount, $oContact) : false;
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function DeleteContacts($oAccount, $aContactIds)
{
return $this->oDriver ? $this->oDriver->DeleteContacts($oAccount, $aContactIds) : false;
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function IncFrec($oAccount, $aContactIds)
{
return $this->oDriver ? $this->oDriver->IncFrec($oAccount, $aContactIds) : false;
}
}

View file

@ -1,111 +0,0 @@
<?php
namespace RainLoop\Providers\Contacts\Classes;
class Contact
{
/**
* @var int
*/
public $IdContact;
/**
* @var int
*/
public $IdUser;
/**
* @var int
*/
public $Type;
/**
* @var int
*/
public $Frec;
/**
* @var string
*/
public $ListName;
/**
* @var string
*/
public $Name;
/**
* @var array
*/
public $Emails;
/**
* @var string
*/
public $ImageHash;
/**
* @var array
*/
public $Data;
public function __construct()
{
$this->Clear();
}
public function Clear()
{
$this->IdContact = 0;
$this->IdUser = 0;
$this->Type = 0;
$this->Frec = 0;
$this->ListName = '';
$this->Name = '';
$this->ImageHash = '';
$this->Emails = array();
$this->Data = array();
}
/**
* @return string
*/
public function GenarateListName()
{
return 0 < \strlen($this->Name) ? $this->Name : (!empty($this->Emails[0]) ? $this->Emails[0] : '');
}
/**
* @return string
*/
public function EmailsAsString()
{
return \trim(\implode(' ', $this->Emails));
}
/**
* @return string
*/
public function DataAsString()
{
return @\serialize($this->Data);
}
/**
* @param string $sData
*/
public function ParseData($sData)
{
$sData = (string) $sData;
$sData = \trim($sData);
if (!empty($sData))
{
$aData = @\unserialize($sData);
if (\is_array($aData))
{
$this->Data = $aData;
}
}
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace RainLoop\Providers\Contacts\Classes;
class Db
{
/**
* @return int
*/
static public function Version()
{
return 1;
}
/**
* @return array
*/
static public function Strucure()
{
return array(
'rlContactsUsers' => array(
'IdUser' => 'INTEGER PRIMARY KEY',
'Email' => 'TEXT'
),
'rlContactsItems' => array(
'IdContact' => 'INTEGER PRIMARY KEY',
'IdUser' => 'INTEGER',
'Type' => 'INTEGER',
'Frec' => 'INTEGER',
'ImageHash' => 'TEXT',
'ListName' => 'TEXT',
'Name' => 'TEXT',
'Emails' => 'TEXT',
'Data' => 'TEXT'
)
);
}
}

View file

@ -1,68 +0,0 @@
<?php
namespace RainLoop\Providers\Contacts;
interface ContactsInterface
{
/**
* @param \RainLoop\Account $oAccount
* @param int $iIdContact
*
* @return $oContact|null
*/
public function GetContactById($oAccount, $iIdContact);
/**
* @param \RainLoop\Account $oAccount
* @param int $iOffset = 0
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '');
/**
* @param \RainLoop\Account $oAccount
*
* @return array
*/
public function GetContactsImageHashes($oAccount);
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function CreateContact($oAccount, &$oContact);
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function UpdateContact($oAccount, &$oContact);
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function DeleteContacts($oAccount, $aContactIds);
/**
* @return bool
*/
public function IsSupported();
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function IncFrec($oAccount, $aContactIds);
}

View file

@ -1,600 +0,0 @@
<?php
namespace RainLoop\Providers\Contacts;
class DefaultContacts implements \RainLoop\Providers\Contacts\ContactsInterface
{
/**
* @var \MailSo\Log\Logger
*/
private $oLogger;
/**
* @var bool
*/
private $bUseDbPerUser;
/**
* @param \MailSo\Log\Logger $oLogger = null
*/
public function __construct($oLogger = null)
{
$this->oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null;
$this->bUseDbPerUser = true;
}
/**
* @param \RainLoop\Account $oAccount
* @staticvar array $aPdoCache
* @return \PDO
*/
private function getPDO($oAccount)
{
static $aPdoCache = array();
$sEmail = $oAccount->ParentEmailHelper();
if (isset($aPdoCache[$sEmail]))
{
return $aPdoCache[$sEmail];
}
if (!\class_exists('PDO'))
{
throw new \Exception('class_exists=PDO');
}
$sVersionFile = '';
$sDsn = '';
if ($this->bUseDbPerUser)
{
$sSubPath = APP_PRIVATE_DATA.'storage/contacts/'.\rtrim(\substr($sEmail, 0, 2), '@').'/'.$sEmail.'/';
if (!\is_dir($sSubPath))
{
if (\mkdir($sSubPath, 0755, true) && \is_dir($sSubPath))
{
$sVersionFile = $sSubPath.'.version';
$sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite';
}
}
else
{
$sVersionFile = $sSubPath.'.version';
$sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite';
}
}
else
{
$sVersionFile = APP_PRIVATE_DATA.'.version';
$sDsn = 'sqlite:'.APP_PRIVATE_DATA.'contacts.sqlite';
}
$sDbLogin = '';
$sDbPassword = '';
$oPdo = false;
try
{
$oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword);
if ($oPdo)
{
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
if (!@\file_exists($sVersionFile) ||
(string) @file_get_contents($sVersionFile) !== (string) \RainLoop\Providers\Contacts\Classes\Db::Version())
{
$this->syncTables($oPdo, $sVersionFile);
}
$oPdo->sqliteCreateFunction('SIMPLESEARCH', function ($sEmailValue, $sNameValue, $sMask) {
return \preg_match('/'.\preg_quote($sMask, '/').'/ui',
$sEmailValue.' '.$sNameValue) ? 1 : 0;
});
}
}
catch (\Exception $oException)
{
throw $oException;
$oPdo = false;
}
if ($oPdo)
{
$aPdoCache[$oAccount->ParentEmailHelper()] = $oPdo;
}
return $oPdo;
}
protected function getWantedColumnsInfo($sTableName, $aCurrent)
{
$aColumns = array();
foreach ($aCurrent as $sName => $sType)
{
$sSql = $sName.' '.$sType;
switch ($sType)
{
case 'INTEGER':
$sSql .= ' DEFAILT \'0\'';
break;
case 'TEXT':
$sSql .= ' DEFAILT \'\'';
break;
}
$aColumns[$sName] = $sSql;
}
if (0 === \count($aColumns))
{
return '';
}
return 'CREATE TABLE '.$sTableName.' (' .\implode(', ', $aColumns).')';
}
/**
* @param \PDO $oAccount
* @param string $sTableName
*/
protected function getCurrentColumnsInfo($oPdo, $sTableName)
{
$oStmt = $this->prepareAndExecute($oPdo, 'SELECT `sql` FROM `sqlite_master` WHERE `tbl_name` = :TableName AND `type` = :Type', array(
':TableName' => array($sTableName, \PDO::PARAM_STR),
':Type' => array('table', \PDO::PARAM_STR)
));
if ($oStmt)
{
$mRow = $oStmt->fetch(\PDO::FETCH_ASSOC);
if ($mRow && isset($mRow['sql']))
{
return (string) $mRow['sql'];
}
}
return '';
}
/**
* @param \PDO $oPdo
* @param string $sVersionFile = ''
*/
private function syncTables($oPdo, $sVersionFile = '')
{
if ($this->oLogger)
{
$this->oLogger->Write('Start to sync', \MailSo\Log\Enumerations\Type::INFO);
}
$aStrucure = \RainLoop\Providers\Contacts\Classes\Db::Strucure();
foreach ($aStrucure as $sTableName => $aField)
{
$sCurrent = $this->getCurrentColumnsInfo($oPdo, $sTableName);
$sWanted = $this->getWantedColumnsInfo($sTableName, $aField);
if (empty($sCurrent))
{
$this->prepareAndExecute($oPdo, $sWanted);
}
else if ($sCurrent !== $sWanted)
{
$this->prepareAndExecute($oPdo, 'DROP TABLE IF EXISTS `'.$sTableName.'_old`');
$this->prepareAndExecute($oPdo, 'ALTER TABLE `'.$sTableName.'` RENAME TO `'.$sTableName.'_old`');
$this->prepareAndExecute($oPdo, $sWanted);
$aNewKeys = array();
$aOldKeys = array();
foreach ($aField as $sKey => $sType)
{
$aNewKeys[] = $sKey;
$aOldKeys[] = false !== \strpos($sCurrent, $sKey.' ') ? $sKey :
(0 === \strpos($sType, 'INT') ? '\'0\'' : '\'\'');
}
$sNewKeys = \implode(', ', $aNewKeys);
$sOldKeys = \implode(', ', $aOldKeys);
$this->prepareAndExecute($oPdo, 'INSERT INTO `'.$sTableName.'` ('.$sNewKeys.') SELECT '.$sOldKeys.' FROM `'.$sTableName.'_old`');
$this->prepareAndExecute($oPdo, 'DROP TABLE `'.$sTableName.'_old`');
}
}
@\file_put_contents($sVersionFile, \RainLoop\Providers\Contacts\Classes\Db::Version());
if ($this->oLogger)
{
$this->oLogger->Write('Stop to sync', \MailSo\Log\Enumerations\Type::INFO);
}
}
/**
* @param \RainLoop\Account|\PDO $oAccountOrPdo
* @param string $sSql
* @param array $aParams
*
* @return \PDOStatement|null
*/
private function prepareAndExecute($oAccountOrPdo, $sSql, $aParams = array())
{
if ($this->oLogger)
{
$this->oLogger->Write($sSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE');
}
$oPdo = $oAccountOrPdo instanceof \PDO ? $oAccountOrPdo : $this->getPDO($oAccountOrPdo);
$oStmt = $oPdo->prepare($sSql);
foreach ($aParams as $sName => $aValue)
{
$oStmt->bindValue($sName, $aValue[0], $aValue[1]);
}
// $sLogSql = $sSql;
// foreach($aParams as $sName => $aValue)
// {
// $sLogSql = \str_replace($sName, $aValue[1] === \PDO::PARAM_INT ? $aValue[0] : '\''.$aValue[0].'\'', $sLogSql);
// }
//
// if ($this->oLogger)
// {
// $this->oLogger->Write($sLogSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE');
// }
$mResult = $oStmt->execute() ? $oStmt : null;
// if ($this->oLogger)
// {
// $this->oLogger->Write('RESULT: '.($mResult ? 'true' : 'false'), \MailSo\Log\Enumerations\Type::INFO, 'SQLITE');
// }
return $mResult;
}
/**
* @param \RainLoop\Account|null $oAccount
* @param bool $bSkipInsert = false
*
* @return int
*/
private function getUserId($oAccount, $bSkipInsert = false)
{
if (!$this->bUseDbPerUser)
{
$oStmt = $this->prepareAndExecute($oAccount,
'SELECT IdUser FROM rlContactsUsers WHERE Email = :Email LIMIT 1',
array(
':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR)
));
$mRow = $oStmt->fetch(\PDO::FETCH_ASSOC);
if ($mRow && isset($mRow['IdUser']) && \is_numeric($mRow['IdUser']))
{
return (int) $mRow['IdUser'];
}
if (!$bSkipInsert)
{
$oStmt->closeCursor();
$oStmt = $this->prepareAndExecute($oAccount,
'INSERT INTO rlContactsUsers (Email) VALUES (:Email)',
array(
':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR)
));
return $this->getUserId($oAccount, true);
}
throw new \Exception('IdUser=0');
}
return 0;
}
/**
* @param string $sSearch
* @return string
*/
private function convertSearchValue($sSearch)
{
return '%'.$sSearch.'%';
}
private function populateContactFromDB($iUserID, $aItem)
{
$oContact = null;
if (isset($aItem['IdContact']))
{
$oContact = new \RainLoop\Providers\Contacts\Classes\Contact();
$oContact->IdContact = (int) $aItem['IdContact'];
$oContact->IdUser = $iUserID;
$oContact->Type = (int) $aItem['Type'];
$oContact->Frec = (int) $aItem['Frec'];
$oContact->ListName = (string) $aItem['ListName'];
$oContact->Name = (string) $aItem['Name'];
$oContact->Emails = \explode(' ', \trim((string) $aItem['Emails']));
$oContact->ImageHash = (string) $aItem['ImageHash'];
$oContact->ParseData($aItem['Data']);
}
return $oContact;
}
/**
* @param \RainLoop\Account $oAccount
* @param int $iIdContact
*
* @return $oContact|null
*/
public function GetContactById($oAccount, $iIdContact)
{
$oResultContact = null;
$iUserID = $this->getUserId($oAccount);
$oStmt = $this->prepareAndExecute($oAccount,
'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'.
' FROM rlContactsItems WHERE IdContact = :IdContact AND IdUser = :IdUser LIMIT 1',
array(
':IdContact' => array($iIdContact, \PDO::PARAM_INT),
':IdUser' => array($iUserID, \PDO::PARAM_INT)
));
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
if (\is_array($aFetch) && isset($aFetch[0]) && \is_array($aFetch[0]))
{
$oContact = $this->populateContactFromDB($iUserID, $aFetch[0]);
if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact)
{
$oResultContact = $oContact;
}
}
return $oResultContact;
}
/**
* @param \RainLoop\Account $oAccount
* @param int $iOffset = 0
* @param int $iLimit = 20
* @param string $sSearch = ''
*
* @return array
*/
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '')
{
$iOffset = 0 <= $iOffset ? $iOffset : 0;
$iLimit = 0 < $iLimit ? (int) $iLimit : 0;
$sSearch = \trim($sSearch);
$iUserID = $this->getUserId($oAccount);
$sSql = 'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'.
' FROM rlContactsItems WHERE IdUser = :IdUser'
;
$aParams = array(
':IdUser' => array($iUserID, \PDO::PARAM_INT),
':limit' => array($iLimit, \PDO::PARAM_INT),
':offset' => array($iOffset, \PDO::PARAM_INT)
);
if (0 < strlen($sSearch))
{
if (\MailSo\Base\Utils::IsAscii($sSearch))
{
$sSql .= ' AND Name LIKE :Search OR Emails LIKE :Search';
$aParams[':Search'] = array($this->convertSearchValue($sSearch), \PDO::PARAM_STR);
}
else
{
$sSql .= ' AND SIMPLESEARCH(Emails, Name, :Search)';
$aParams[':Search'] = array($sSearch, \PDO::PARAM_STR);
}
}
$sSql .= ' ORDER BY ListName ASC LIMIT :limit OFFSET :offset';
$oStmt = $this->prepareAndExecute($oAccount, $sSql, $aParams);
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
$aResult = array();
if (\is_array($aFetch) && 0 < \count($aFetch))
{
foreach ($aFetch as $aItem)
{
$oContact = $this->populateContactFromDB($iUserID, $aItem);
if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact)
{
$aResult[] = $oContact;
}
}
}
unset($aFetch);
return $aResult;
}
/**
* @param \RainLoop\Account $oAccount
*
* @return array
*/
public function GetContactsImageHashes($oAccount)
{
$iUserID = $this->getUserId($oAccount);
$oStmt = $this->prepareAndExecute($oAccount,
'SELECT Emails, ImageHash FROM rlContactsItems WHERE IdUser = :IdUser AND ImageHash <> :ImageHash',
array(
':IdUser' => array($iUserID, \PDO::PARAM_INT),
':ImageHash' => array('', \PDO::PARAM_STR)
));
$aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
$aResult = array();
if (\is_array($aFetch) && 0 < \count($aFetch))
{
foreach ($aFetch as $aItem)
{
if (!empty($aItem['Emails']) && !empty($aItem['ImageHash']))
{
$aEmails = \explode(' ', $aItem['Emails']);
foreach ($aEmails as $sEmail)
{
$sEmail = \trim($sEmail);
if (0 < strlen($sEmail))
{
$aResult[$sEmail] = $aItem['ImageHash'];
}
}
}
}
}
unset($aFetch);
return $aResult;
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function CreateContact($oAccount, &$oContact)
{
$iUserID = $this->getUserId($oAccount);
$oContact->IdUser = $iUserID;
$oStmt = $this->prepareAndExecute($oAccount,
'INSERT INTO rlContactsItems '.
'( IdUser, Type, Frec, ListName, Name, Emails, ImageHash, Data) VALUES '.
'(:IdUser, :Type, 0, :ListName, :Name, :Emails, :ImageHash, :Data)',
array(
':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT),
':Type' => array($oContact->Type, \PDO::PARAM_INT),
':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR),
':Name' => array($oContact->Name, \PDO::PARAM_STR),
':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR),
':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR),
':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR),
));
if ($oStmt)
{
$iContactID = $this->getPDO($oAccount)->lastInsertId('IdContact');
if (is_numeric($iContactID) && 0 < (int) $iContactID)
{
$oContact->IdContact = (int) $iContactID;
return true;
}
}
throw new \Exception('CreateContact');
}
/**
* @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\Contacts\Classes\Contact $oContact
*
* @return bool
*/
public function UpdateContact($oAccount, &$oContact)
{
$iUserID = $this->getUserId($oAccount);
$oContact->IdUser = $iUserID;
return !!$this->prepareAndExecute($oAccount,
'UPDATE rlContactsItems SET'.
' Type = :Type, ListName = :ListName, Name = :Name, Emails = :Emails,'.
' ImageHash = :ImageHash, Data = :Data'.
' WHERE IdContact = :IdContact AND IdUser = :IdUser',
array(
':IdContact' => array($oContact->IdContact, \PDO::PARAM_INT),
':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT),
':Type' => array($oContact->Type, \PDO::PARAM_INT),
':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR),
':Name' => array($oContact->Name, \PDO::PARAM_STR),
':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR),
':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR),
':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR),
));
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function DeleteContacts($oAccount, $aContactIds)
{
$iUserID = $this->getUserId($oAccount);
$aParams = array(
':IdUser' => array($iUserID, \PDO::PARAM_INT),
);
$aInQuery = array();
foreach ($aContactIds as $iIndex => $iId)
{
$aInQuery[] = ':IdContact_'.$iIndex;
$aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT);
}
if (0 === \count($aInQuery))
{
return false;
}
return !!$this->prepareAndExecute($oAccount,
'DELETE FROM rlContactsItems WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')',
$aParams);
}
/**
* @return bool
*/
public function IsSupported()
{
$aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array();
return \is_array($aDrivers) ? \in_array('sqlite', $aDrivers) : false;
}
/**
* @param \RainLoop\Account $oAccount
* @param array $aContactIds
*
* @return bool
*/
public function IncFrec($oAccount, $aContactIds)
{
if (\is_array($aContactIds) && 0 < \count($aContactIds))
{
$iUserID = $this->getUserId($oAccount);
$aParams = array(
':IdUser' => array($iUserID, \PDO::PARAM_INT),
);
$aInQuery = array();
foreach ($aContactIds as $iIndex => $iId)
{
$aInQuery[] = ':IdContact_'.$iIndex;
$aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT);
}
return !!$this->prepareAndExecute($oAccount,
'UPDATE rlContactsItems SET Frec = Frec + 1 WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')',
$aParams);
}
return false;
}
}

View file

@ -42,6 +42,15 @@ class PersonalAddressBook extends \RainLoop\Providers\AbstractProvider
$this->oDriver->IsSupported(); $this->oDriver->IsSupported();
} }
/**
* @return bool
*/
public function IsSharingAllowed()
{
return $this->oDriver instanceof \RainLoop\Providers\PersonalAddressBook\PersonalAddressBookInterface &&
$this->oDriver->IsSharingAllowed();
}
/** /**
* @return bool * @return bool
*/ */
@ -51,6 +60,19 @@ class PersonalAddressBook extends \RainLoop\Providers\AbstractProvider
$this->oDriver->IsSupported(); $this->oDriver->IsSupported();
} }
/**
* @param bool $bConsiderShare = true
*/
public function ConsiderShare($bConsiderShare = true)
{
if ($this->oDriver)
{
$this->oDriver->ConsiderShare($bConsiderShare);
}
return $this;
}
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\PersonalAddressBook\Classes\Contact $oContact * @param \RainLoop\Providers\PersonalAddressBook\Classes\Contact $oContact
@ -78,16 +100,14 @@ class PersonalAddressBook extends \RainLoop\Providers\AbstractProvider
* @param int $iOffset = 0 * @param int $iOffset = 0
* @param type $iLimit = 20 * @param type $iLimit = 20
* @param string $sSearch = '' * @param string $sSearch = ''
* @param int $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_
* @param int $iResultCount = 0 * @param int $iResultCount = 0
* *
* @return array * @return array
*/ */
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0)
$iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_, &$iResultCount = 0)
{ {
return $this->IsActive() ? $this->oDriver->GetContacts($oAccount, return $this->IsActive() ? $this->oDriver->GetContacts($oAccount,
$iOffset, $iLimit, $sSearch, $iScopeType, $iResultCount) : array(); $iOffset, $iLimit, $sSearch, $iResultCount) : array();
} }
/** /**

View file

@ -29,11 +29,6 @@ class Contact
*/ */
public $ScopeType; public $ScopeType;
/**
* @var string
*/
public $ScopeValue;
/** /**
* @var int * @var int
*/ */
@ -67,7 +62,6 @@ class Contact
$this->DisplayName = ''; $this->DisplayName = '';
$this->DisplayEmail = ''; $this->DisplayEmail = '';
$this->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_; $this->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
$this->ScopeValue = '';
$this->Changed = \time(); $this->Changed = \time();
$this->IdPropertyFromSearch = 0; $this->IdPropertyFromSearch = 0;
$this->Properties = array(); $this->Properties = array();
@ -84,7 +78,6 @@ class Contact
if ($oProperty) if ($oProperty)
{ {
$oProperty->ScopeType = $this->ScopeType; $oProperty->ScopeType = $this->ScopeType;
$oProperty->ScopeValue = $this->ScopeValue;
$oProperty->UpdateDependentValues(); $oProperty->UpdateDependentValues();
if ('' === $sDisplayName && \RainLoop\Providers\PersonalAddressBook\Enumerations\PropertyType::FULLNAME === $oProperty->Type && if ('' === $sDisplayName && \RainLoop\Providers\PersonalAddressBook\Enumerations\PropertyType::FULLNAME === $oProperty->Type &&

View file

@ -21,11 +21,6 @@ class Property
*/ */
public $ScopeType; public $ScopeType;
/**
* @var string
*/
public $ScopeValue;
/** /**
* @var string * @var string
*/ */
@ -39,7 +34,7 @@ class Property
/** /**
* @var string * @var string
*/ */
public $ValueClear; public $ValueCustom;
/** /**
* @var int * @var int
@ -57,11 +52,10 @@ class Property
$this->Type = PropertyType::UNKNOWN; $this->Type = PropertyType::UNKNOWN;
$this->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_; $this->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
$this->ScopeValue = '';
$this->TypeCustom = ''; $this->TypeCustom = '';
$this->Value = ''; $this->Value = '';
$this->ValueClear = ''; $this->ValueCustom = '';
$this->Frec = 0; $this->Frec = 0;
} }
@ -92,7 +86,7 @@ class Property
{ {
// trimer // trimer
$this->Value = \trim($this->Value); $this->Value = \trim($this->Value);
$this->ValueClear = \trim($this->ValueClear); $this->ValueCustom = \trim($this->ValueCustom);
$this->TypeCustom = \trim($this->TypeCustom); $this->TypeCustom = \trim($this->TypeCustom);
if (0 < \strlen($this->Value)) if (0 < \strlen($this->Value))
@ -109,7 +103,7 @@ class Property
$sPhone = $this->Value; $sPhone = $this->Value;
$sPhone = \preg_replace('/^[+]+/', '', $sPhone); $sPhone = \preg_replace('/^[+]+/', '', $sPhone);
$sPhone = \preg_replace('/[^\d]/', '', $sPhone); $sPhone = \preg_replace('/[^\d]/', '', $sPhone);
$this->ValueClear = $sPhone; $this->ValueCustom = $sPhone;
} }
} }
} }

View file

@ -5,8 +5,5 @@ namespace RainLoop\Providers\PersonalAddressBook\Enumerations;
class ScopeType class ScopeType
{ {
const DEFAULT_ = 0; const DEFAULT_ = 0;
const AUTO = 1;
const SHARE_ALL = 2; const SHARE_ALL = 2;
const SHARE_DOMAIN = 3;
const SHARE_EMAIL = 4;
} }

View file

@ -28,6 +28,11 @@ class PdoPersonalAddressBook
*/ */
private $sPassword; private $sPassword;
/**
* @var bool
*/
private $bConsiderShare;
public function __construct($sDsn, $sUser = '', $sPassword = '', $sDsnType = 'mysql') public function __construct($sDsn, $sUser = '', $sPassword = '', $sDsnType = 'mysql')
{ {
$this->sDsn = $sDsn; $this->sDsn = $sDsn;
@ -35,9 +40,23 @@ class PdoPersonalAddressBook
$this->sPassword = $sPassword; $this->sPassword = $sPassword;
$this->sDsnType = $sDsnType; $this->sDsnType = $sDsnType;
$this->bConsiderShare = true;
$this->bExplain = false; $this->bExplain = false;
} }
/**
* @param bool $bConsiderShare
*
* @return \RainLoop\Providers\PersonalAddressBook\PdoPersonalAddressBook
*/
public function ConsiderShare($bConsiderShare = true)
{
$this->bConsiderShare = !!$bConsiderShare;
return $this;
}
/** /**
* @return bool * @return bool
*/ */
@ -47,6 +66,22 @@ class PdoPersonalAddressBook
return \is_array($aDrivers) ? \in_array($this->sDsnType, $aDrivers) : false; return \is_array($aDrivers) ? \in_array($this->sDsnType, $aDrivers) : false;
} }
/**
* @return bool
*/
public function IsConsiderShare()
{
return $this->bConsiderShare;
}
/**
* @return bool
*/
public function IsSharingAllowed()
{
return $this->IsConsiderShare() && $this->IsSupported();
}
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount
* @param \RainLoop\Providers\PersonalAddressBook\Classes\Contact $oContact * @param \RainLoop\Providers\PersonalAddressBook\Classes\Contact $oContact
@ -62,42 +97,14 @@ class PdoPersonalAddressBook
$bUpdate = 0 < $iIdContact; $bUpdate = 0 < $iIdContact;
if (!$this->bConsiderShare)
{
$oContact->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
}
$oContact->UpdateDependentValues(); $oContact->UpdateDependentValues();
$oContact->Changed = \time(); $oContact->Changed = \time();
if (\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::AUTO !== $oContact->ScopeType)
{
$aEmail = $oContact->GetEmails();
if (0 < \count($aEmail))
{
$aEmail = \array_map(function ($sValue) {
return \strtolower(\trim($sValue));
}, $aEmail);
$aEmail = \array_filter($aEmail, function ($sValue) {
return !empty($sValue);
});
if (0 < \count($aEmail))
{
$self = $this;
$aEmail = \array_map(function ($sValue) use ($self) {
return $self->quoteValue($sValue);
}, $aEmail);
// clear autocreated contacts
$this->prepareAndExecute(
'DELETE FROM rainloop_pab_contacts WHERE id_user = :id_user AND scope_type = :scope_type AND display_email IN ('.\implode(',', $aEmail).')',
array(
':scope_type' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::AUTO, \PDO::PARAM_INT),
':id_user' => array($iUserID, \PDO::PARAM_INT)
)
);
}
}
}
try try
{ {
if ($this->isTransactionSupported()) if ($this->isTransactionSupported())
@ -111,7 +118,7 @@ class PdoPersonalAddressBook
$aFreq = $this->getContactFreq($iUserID, $iIdContact); $aFreq = $this->getContactFreq($iUserID, $iIdContact);
$sSql = 'UPDATE rainloop_pab_contacts SET display = :display, display_name = :display_name, display_email = :display_email, '. $sSql = 'UPDATE rainloop_pab_contacts SET display = :display, display_name = :display_name, display_email = :display_email, '.
'scope_type = :scope_type, scope_value = :scope_value, changed = :changed WHERE id_user = :id_user AND id_contact = :id_contact'; 'scope_type = :scope_type, changed = :changed WHERE id_user = :id_user AND id_contact = :id_contact';
$this->prepareAndExecute($sSql, $this->prepareAndExecute($sSql,
array( array(
@ -121,7 +128,6 @@ class PdoPersonalAddressBook
':display_name' => array($oContact->DisplayName, \PDO::PARAM_STR), ':display_name' => array($oContact->DisplayName, \PDO::PARAM_STR),
':display_email' => array($oContact->DisplayEmail, \PDO::PARAM_STR), ':display_email' => array($oContact->DisplayEmail, \PDO::PARAM_STR),
':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT), ':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT),
':scope_value' => array($oContact->ScopeValue, \PDO::PARAM_STR),
':changed' => array($oContact->Changed, \PDO::PARAM_INT), ':changed' => array($oContact->Changed, \PDO::PARAM_INT),
) )
); );
@ -138,8 +144,8 @@ class PdoPersonalAddressBook
else else
{ {
$sSql = 'INSERT INTO rainloop_pab_contacts '. $sSql = 'INSERT INTO rainloop_pab_contacts '.
'( id_user, display, display_name, display_email, scope_type, scope_value, changed) VALUES '. '( id_user, display, display_name, display_email, scope_type, changed) VALUES '.
'(:id_user, :display, :display_name, :display_email, :scope_type, :scope_value, :changed)'; '(:id_user, :display, :display_name, :display_email, :scope_type, :changed)';
$this->prepareAndExecute($sSql, $this->prepareAndExecute($sSql,
array( array(
@ -148,7 +154,6 @@ class PdoPersonalAddressBook
':display_name' => array($oContact->DisplayName, \PDO::PARAM_STR), ':display_name' => array($oContact->DisplayName, \PDO::PARAM_STR),
':display_email' => array($oContact->DisplayEmail, \PDO::PARAM_STR), ':display_email' => array($oContact->DisplayEmail, \PDO::PARAM_STR),
':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT), ':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT),
':scope_value' => array($oContact->ScopeValue, \PDO::PARAM_STR),
':changed' => array($oContact->Changed, \PDO::PARAM_INT) ':changed' => array($oContact->Changed, \PDO::PARAM_INT)
) )
); );
@ -176,18 +181,17 @@ class PdoPersonalAddressBook
':id_contact' => array($iIdContact, \PDO::PARAM_INT), ':id_contact' => array($iIdContact, \PDO::PARAM_INT),
':id_user' => array($iUserID, \PDO::PARAM_INT), ':id_user' => array($iUserID, \PDO::PARAM_INT),
':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT), ':scope_type' => array($oContact->ScopeType, \PDO::PARAM_INT),
':scope_value' => array($oContact->ScopeValue, \PDO::PARAM_STR),
':prop_type' => array($oProp->Type, \PDO::PARAM_INT), ':prop_type' => array($oProp->Type, \PDO::PARAM_INT),
':prop_type_custom' => array($oProp->TypeCustom, \PDO::PARAM_STR), ':prop_type_custom' => array($oProp->TypeCustom, \PDO::PARAM_STR),
':prop_value' => array($oProp->Value, \PDO::PARAM_STR), ':prop_value' => array($oProp->Value, \PDO::PARAM_STR),
':prop_value_custom' => array($oProp->ValueClear, \PDO::PARAM_STR), ':prop_value_custom' => array($oProp->ValueCustom, \PDO::PARAM_STR),
':prop_frec' => array($iFreq, \PDO::PARAM_INT), ':prop_frec' => array($iFreq, \PDO::PARAM_INT),
); );
} }
$sSql = 'INSERT INTO rainloop_pab_properties '. $sSql = 'INSERT INTO rainloop_pab_properties '.
'( id_contact, id_user, prop_type, prop_type_custom, prop_value, prop_value_custom, scope_type, scope_value, prop_frec) VALUES '. '( id_contact, id_user, prop_type, prop_type_custom, prop_value, prop_value_custom, scope_type, prop_frec) VALUES '.
'(:id_contact, :id_user, :prop_type, :prop_type_custom, :prop_value, :prop_value_custom, :scope_type, :scope_value, :prop_frec)'; '(:id_contact, :id_user, :prop_type, :prop_type_custom, :prop_value, :prop_value_custom, :scope_type, :prop_frec)';
$this->prepareAndExecute($sSql, $aParams, true); $this->prepareAndExecute($sSql, $aParams, true);
} }
@ -275,13 +279,11 @@ class PdoPersonalAddressBook
* @param int $iOffset = 0 * @param int $iOffset = 0
* @param int $iLimit = 20 * @param int $iLimit = 20
* @param string $sSearch = '' * @param string $sSearch = ''
* @param bool $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_
* @param int $iResultCount = 0 * @param int $iResultCount = 0
* *
* @return array * @return array
*/ */
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0)
$iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_, &$iResultCount = 0)
{ {
$this->Sync(); $this->Sync();
@ -289,10 +291,7 @@ class PdoPersonalAddressBook
$iLimit = 0 < $iLimit ? (int) $iLimit : 20; $iLimit = 0 < $iLimit ? (int) $iLimit : 20;
$sSearch = \trim($sSearch); $sSearch = \trim($sSearch);
$sEmail = $oAccount->ParentEmailHelper(); $iUserID = $this->getUserId($oAccount->ParentEmailHelper());
$sDomain = \MailSo\Base\Utils::GetDomainFromEmail($sEmail);
$iUserID = $this->getUserId($sEmail);
$iCount = 0; $iCount = 0;
$aSearchIds = array(); $aSearchIds = array();
@ -302,22 +301,27 @@ class PdoPersonalAddressBook
{ {
$sSql = 'SELECT id_user, id_prop, id_contact FROM rainloop_pab_properties '. $sSql = 'SELECT id_user, id_prop, id_contact FROM rainloop_pab_properties '.
'WHERE ('. 'WHERE ('.
'(id_user = :id_user)'. 'id_user = :id_user'.
' OR (scope_type = :scope_type_share_all)'. ($this->bConsiderShare ? ' OR scope_type = :scope_type_share_all' : '').
' OR (scope_type = :scope_type_share_domain AND scope_value = :scope_value_domain)'. ') AND (prop_value LIKE :search ESCAPE \'=\' OR ('.
' OR (scope_type = :scope_type_share_email AND scope_value = :scope_value_email)'. 'prop_type IN ('.\implode(',', array(
') AND prop_value LIKE :search ESCAPE \'=\' GROUP BY id_contact, id_prop'; PropertyType::PHONE_PERSONAL, PropertyType::PHONE_BUSSINES, PropertyType::PHONE_OTHER,
PropertyType::MOBILE_PERSONAL, PropertyType::MOBILE_BUSSINES, PropertyType::MOBILE_OTHER,
PropertyType::FAX_PERSONAL, PropertyType::FAX_BUSSINES, PropertyType::FAX_OTHER
)).') AND prop_value_custom LIKE :search_custom_phone'.
')) GROUP BY id_contact, id_prop';
$aParams = array( $aParams = array(
':id_user' => array($iUserID, \PDO::PARAM_INT), ':id_user' => array($iUserID, \PDO::PARAM_INT),
':scope_type_share_all' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT), ':search' => array($this->specialConvertSearchValue($sSearch, '='), \PDO::PARAM_STR),
':scope_type_share_domain' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_DOMAIN, \PDO::PARAM_INT), ':search_custom_phone' => array($this->specialConvertSearchValueCustomPhone($sSearch), \PDO::PARAM_STR)
':scope_type_share_email' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_EMAIL, \PDO::PARAM_INT),
':scope_value_domain' => array($sDomain, \PDO::PARAM_STR),
':scope_value_email' => array($sEmail, \PDO::PARAM_STR),
':search' => array($this->specialConvertSearchValue($sSearch, '='), \PDO::PARAM_STR)
); );
if ($this->bConsiderShare)
{
$aParams[':scope_type_share_all'] = array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT);
}
$oStmt = $this->prepareAndExecute($sSql, $aParams); $oStmt = $this->prepareAndExecute($sSql, $aParams);
if ($oStmt) if ($oStmt)
{ {
@ -341,23 +345,19 @@ class PdoPersonalAddressBook
else else
{ {
$sSql = 'SELECT COUNT(DISTINCT id_contact) as contact_count FROM rainloop_pab_properties '. $sSql = 'SELECT COUNT(DISTINCT id_contact) as contact_count FROM rainloop_pab_properties '.
'WHERE ('. 'WHERE id_user = :id_user'.
'(id_user = :id_user)'. ($this->bConsiderShare ? ' OR scope_type = :scope_type_share_all' : '')
' OR (scope_type = :scope_type_share_all)'.
' OR (scope_type = :scope_type_share_domain AND scope_value = :scope_value_domain)'.
' OR (scope_type = :scope_type_share_email AND scope_value = :scope_value_email)'.
')'
; ;
$aParams = array( $aParams = array(
':id_user' => array($iUserID, \PDO::PARAM_INT), ':id_user' => array($iUserID, \PDO::PARAM_INT)
':scope_type_share_all' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT),
':scope_type_share_domain' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_DOMAIN, \PDO::PARAM_INT),
':scope_type_share_email' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_EMAIL, \PDO::PARAM_INT),
':scope_value_domain' => array($sDomain, \PDO::PARAM_STR),
':scope_value_email' => array($sEmail, \PDO::PARAM_STR)
); );
if ($this->bConsiderShare)
{
$aParams[':scope_type_share_all'] = array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT);
}
$oStmt = $this->prepareAndExecute($sSql, $aParams); $oStmt = $this->prepareAndExecute($sSql, $aParams);
if ($oStmt) if ($oStmt)
{ {
@ -374,23 +374,19 @@ class PdoPersonalAddressBook
if (0 < $iCount) if (0 < $iCount)
{ {
$sSql = 'SELECT * FROM rainloop_pab_contacts '. $sSql = 'SELECT * FROM rainloop_pab_contacts '.
'WHERE ('. 'WHERE id_user = :id_user'.
'(id_user = :id_user)'. ($this->bConsiderShare ? ' OR scope_type = :scope_type_share_all' : '')
' OR (scope_type = :scope_type_share_all)'.
' OR (scope_type = :scope_type_share_domain AND scope_value = :scope_value_domain)'.
' OR (scope_type = :scope_type_share_email AND scope_value = :scope_value_email)'.
')'
; ;
$aParams = array( $aParams = array(
':id_user' => array($iUserID, \PDO::PARAM_INT), ':id_user' => array($iUserID, \PDO::PARAM_INT)
':scope_type_share_all' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT),
':scope_type_share_domain' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_DOMAIN, \PDO::PARAM_INT),
':scope_type_share_email' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_EMAIL, \PDO::PARAM_INT),
':scope_value_domain' => array($sDomain, \PDO::PARAM_STR),
':scope_value_email' => array($sEmail, \PDO::PARAM_STR)
); );
if ($this->bConsiderShare)
{
$aParams[':scope_type_share_all'] = array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT);
}
if (0 < \count($aSearchIds)) if (0 < \count($aSearchIds))
{ {
$sSql .= ' AND id_contact IN ('.implode(',', $aSearchIds).')'; $sSql .= ' AND id_contact IN ('.implode(',', $aSearchIds).')';
@ -423,7 +419,6 @@ class PdoPersonalAddressBook
$oContact->DisplayEmail = isset($aItem['display_email']) ? (string) $aItem['display_email'] : ''; $oContact->DisplayEmail = isset($aItem['display_email']) ? (string) $aItem['display_email'] : '';
$oContact->ScopeType = isset($aItem['scope_type']) ? (int) $aItem['scope_type'] : $oContact->ScopeType = isset($aItem['scope_type']) ? (int) $aItem['scope_type'] :
\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_; \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
$oContact->ScopeValue = isset($aItem['scope_value']) ? (string) $aItem['scope_value'] : '';
$oContact->Changed = isset($aItem['changed']) ? (int) $aItem['changed'] : 0; $oContact->Changed = isset($aItem['changed']) ? (int) $aItem['changed'] : 0;
$oContact->ReadOnly = $iUserID !== (isset($aItem['id_user']) ? (int) $aItem['id_user'] : 0); $oContact->ReadOnly = $iUserID !== (isset($aItem['id_user']) ? (int) $aItem['id_user'] : 0);
@ -460,11 +455,10 @@ class PdoPersonalAddressBook
$oProperty->IdProperty = (int) $aItem['id_prop']; $oProperty->IdProperty = (int) $aItem['id_prop'];
$oProperty->ScopeType = isset($aItem['scope_type']) ? (int) $aItem['scope_type'] : $oProperty->ScopeType = isset($aItem['scope_type']) ? (int) $aItem['scope_type'] :
\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_; \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
$oProperty->ScopeValue = isset($aItem['scope_value']) ? (string) $aItem['scope_value'] : '';
$oProperty->Type = (int) $aItem['prop_type']; $oProperty->Type = (int) $aItem['prop_type'];
$oProperty->TypeCustom = isset($aItem['prop_type_custom']) ? (string) $aItem['prop_type_custom'] : ''; $oProperty->TypeCustom = isset($aItem['prop_type_custom']) ? (string) $aItem['prop_type_custom'] : '';
$oProperty->Value = (string) $aItem['prop_value']; $oProperty->Value = (string) $aItem['prop_value'];
$oProperty->ValueClear = isset($aItem['prop_value_clear']) ? (string) $aItem['prop_value_clear'] : ''; $oProperty->ValueCustom = isset($aItem['prop_value_custom']) ? (string) $aItem['prop_value_custom'] : '';
$oProperty->Frec = isset($aItem['prop_frec']) ? (int) $aItem['prop_frec'] : 0; $oProperty->Frec = isset($aItem['prop_frec']) ? (int) $aItem['prop_frec'] : 0;
$aContacts[$iId]->Properties[] = $oProperty; $aContacts[$iId]->Properties[] = $oProperty;
@ -508,10 +502,7 @@ class PdoPersonalAddressBook
$this->Sync(); $this->Sync();
$sEmail = $oAccount->ParentEmailHelper(); $iUserID = $this->getUserId($oAccount->ParentEmailHelper());
$sDomain = \MailSo\Base\Utils::GetDomainFromEmail($sEmail);
$iUserID = $this->getUserId($sEmail);
$sTypes = implode(',', array( $sTypes = implode(',', array(
PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER, PropertyType::FULLNAME PropertyType::EMAIl_PERSONAL, PropertyType::EMAIl_BUSSINES, PropertyType::EMAIl_OTHER, PropertyType::FULLNAME
@ -519,23 +510,21 @@ class PdoPersonalAddressBook
$sSql = 'SELECT id_contact, id_prop, prop_type, prop_value FROM rainloop_pab_properties '. $sSql = 'SELECT id_contact, id_prop, prop_type, prop_value FROM rainloop_pab_properties '.
'WHERE ('. 'WHERE ('.
'(id_user = :id_user)'. 'id_user = :id_user'.
' OR (scope_type = :scope_type_share_all)'. ($this->bConsiderShare ? ' OR scope_type = :scope_type_share_all' : '').
' OR (scope_type = :scope_type_share_domain AND scope_value = :scope_value_domain)'.
' OR (scope_type = :scope_type_share_email AND scope_value = :scope_value_email)'.
') AND prop_type IN ('.$sTypes.') AND prop_value LIKE :search ESCAPE \'=\''; ') AND prop_type IN ('.$sTypes.') AND prop_value LIKE :search ESCAPE \'=\'';
$aParams = array( $aParams = array(
':id_user' => array($iUserID, \PDO::PARAM_INT), ':id_user' => array($iUserID, \PDO::PARAM_INT),
':limit' => array($iLimit, \PDO::PARAM_INT), ':limit' => array($iLimit, \PDO::PARAM_INT),
':scope_type_share_all' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT),
':scope_type_share_domain' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_DOMAIN, \PDO::PARAM_INT),
':scope_type_share_email' => array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_EMAIL, \PDO::PARAM_INT),
':scope_value_domain' => array($sDomain, \PDO::PARAM_STR),
':scope_value_email' => array($sEmail, \PDO::PARAM_STR),
':search' => array($this->specialConvertSearchValue($sSearch, '='), \PDO::PARAM_STR) ':search' => array($this->specialConvertSearchValue($sSearch, '='), \PDO::PARAM_STR)
); );
if ($this->bConsiderShare)
{
$aParams[':scope_type_share_all'] = array(\RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::SHARE_ALL, \PDO::PARAM_INT);
}
$sSql .= ' ORDER BY prop_frec DESC'; $sSql .= ' ORDER BY prop_frec DESC';
$sSql .= ' LIMIT :limit'; $sSql .= ' LIMIT :limit';
@ -765,7 +754,7 @@ class PdoPersonalAddressBook
$oContact = new \RainLoop\Providers\PersonalAddressBook\Classes\Contact(); $oContact = new \RainLoop\Providers\PersonalAddressBook\Classes\Contact();
foreach ($aEmailsToCreate as $oEmail) foreach ($aEmailsToCreate as $oEmail)
{ {
$oContact->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::AUTO; $oContact->ScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_;
if ('' !== \trim($oEmail->GetEmail())) if ('' !== \trim($oEmail->GetEmail()))
{ {
@ -1042,27 +1031,15 @@ SQLITEINITIAL;
{ {
case 'mysql': case 'mysql':
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array( return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
1 => $this->getInitialTablesArray($this->sDsnType), 1 => $this->getInitialTablesArray($this->sDsnType)
2 => array(
'ALTER TABLE rainloop_pab_contacts ADD scope_value varchar(128) NOT NULL DEFAULT \'\' AFTER scope_type',
'ALTER TABLE rainloop_pab_properties ADD scope_value varchar(128) NOT NULL DEFAULT \'\' AFTER scope_type'
)
)); ));
case 'pgsql': case 'pgsql':
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array( return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
1 => $this->getInitialTablesArray($this->sDsnType), 1 => $this->getInitialTablesArray($this->sDsnType)
2 => array(
'ALTER TABLE rainloop_pab_contacts ADD scope_value varchar(128) NOT NULL DEFAULT \'\'',
'ALTER TABLE rainloop_pab_properties ADD scope_value varchar(128) NOT NULL DEFAULT \'\''
)
)); ));
case 'sqlite': case 'sqlite':
return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array( return $this->dataBaseUpgrade($this->sDsnType.'-pab-version', array(
1 => $this->getInitialTablesArray($this->sDsnType), 1 => $this->getInitialTablesArray($this->sDsnType)
2 => array(
'ALTER TABLE rainloop_pab_contacts ADD scope_value text NOT NULL default \'\'',
'ALTER TABLE rainloop_pab_properties ADD scope_value text NOT NULL default \'\''
)
)); ));
} }
@ -1109,6 +1086,7 @@ SQLITEINITIAL;
/** /**
* @param string $sSearch * @param string $sSearch
* @param string $sEscapeSign = '='
* *
* @return string * @return string
*/ */
@ -1118,6 +1096,16 @@ SQLITEINITIAL;
array($sEscapeSign.$sEscapeSign, $sEscapeSign.'_', $sEscapeSign.'%'), $sSearch).'%'; array($sEscapeSign.$sEscapeSign, $sEscapeSign.'_', $sEscapeSign.'%'), $sSearch).'%';
} }
/**
* @param string $sSearch
*
* @return string
*/
private function specialConvertSearchValueCustomPhone($sSearch)
{
return '%'.\preg_replace('/[^\d]/', '', $sSearch).'%';
}
/** /**
* @return array * @return array
*/ */

View file

@ -38,13 +38,11 @@ interface PersonalAddressBookInterface
* @param int $iOffset = 0 * @param int $iOffset = 0
* @param int $iLimit = 20 * @param int $iLimit = 20
* @param string $sSearch = '' * @param string $sSearch = ''
* @param bool $iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_
* @param int $iResultCount = 0 * @param int $iResultCount = 0
* *
* @return array * @return array
*/ */
public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0);
$iScopeType = \RainLoop\Providers\PersonalAddressBook\Enumerations\ScopeType::DEFAULT_, &$iResultCount = 0);
/** /**
* @param \RainLoop\Account $oAccount * @param \RainLoop\Account $oAccount

View file

@ -75,6 +75,10 @@
} }
} }
.g-ui-menu .e-item.selected > .e-link {
background-color: @dropdown-menu-selected-background-color !important;
}
.g-ui-menu .e-item > .e-link:hover { .g-ui-menu .e-item > .e-link:hover {
color: @dropdown-menu-hover-color !important; color: @dropdown-menu-hover-color !important;
background-color: @dropdown-menu-hover-background-color !important; background-color: @dropdown-menu-hover-background-color !important;

View file

@ -24,6 +24,7 @@
@dropdown-menu-hover-background-color: #444; @dropdown-menu-hover-background-color: #444;
@dropdown-menu-hover-color: #eee; @dropdown-menu-hover-color: #eee;
@dropdown-menu-disable-color: #999; @dropdown-menu-disable-color: #999;
@dropdown-menu-selected-background-color: #eee;
// FOLDERS // FOLDERS
@folders-color: #333; @folders-color: #333;

View file

@ -19,6 +19,10 @@
<i data-bind="css: enableContacts() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i> <i data-bind="css: enableContacts() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
Enable contacts Enable contacts
</label> </label>
<label data-bind="click: function () { contactsSharing(!contactsSharing()); }">
<i data-bind="css: contactsSharing() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
Allow contacts sharing
</label>
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">

View file

@ -61,7 +61,7 @@
<div class="control-group" data-bind="visible: subscriptionEnabled() && !licensingProcess()"> <div class="control-group" data-bind="visible: subscriptionEnabled() && !licensingProcess()">
<div class="controls"> <div class="controls">
<a class="btn" data-bind="click: showActivationForm"> <a class="btn" data-bind="click: showActivationForm">
<i class="icon-heart-empty"></i> <i class="icon-happy-smiley"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
Activate Subscription Key Activate Subscription Key
</a> </a>

View file

@ -94,14 +94,15 @@
</div> </div>
<div data-bind="visible: !emptySelection()"> <div data-bind="visible: !emptySelection()">
<div class="form-horizontal top-part"> <div class="form-horizontal top-part">
<div class="control-group" data-bind="visible: !viewReadOnly() || 0 < viewPropertiesNames().length"> <div class="control-group" data-bind="visible: !viewReadOnly() || 0 < viewPropertiesEmailsNonEmpty().length">
<label class="control-label remove-padding-top fix-width"> <label class="control-label remove-padding-top fix-width">
<i class="icon-user iconsize24" data-placement="left" data-bind="tooltip: 'CONTACTS/LABEL_DISPLAY_NAME'"></i> <i class="icon-user iconsize24" data-placement="left" data-bind="tooltip: 'CONTACTS/LABEL_DISPLAY_NAME'"></i>
</label> </label>
<div class="controls fix-width" data-bind="foreach: viewPropertiesNames"> <div class="controls fix-width" data-bind="foreach: viewPropertiesNames">
<div class="property-line"> <div class="property-line">
<span class="contactValueStatic" data-bind="text: value" /> <span class="contactValueStatic" data-bind="text: value" />
<input type="text" class="contactValueInput" data-bind="value: value, hasFocus: focused, valueUpdate: 'keyup'" /> <input type="text" class="contactValueInput" placeholder="" data-bind="value: value, hasFocus: focused, valueUpdate: 'keyup', attr: {'placeholder': placeholderValue}" />
</div> </div>
</div> </div>
</div> </div>
@ -152,35 +153,32 @@
</div> </div>
</div> </div>
<div class="e-read-only-sign" style="display: none"> <div class="e-save-trigger">
<div data-bind="saveTrigger: viewSaveTrigger"></div>
</div>
<div class="e-read-only-sign">
<i class="icon-lock iconsize24" data-placement="left" data-bind="tooltip: 'CONTACTS/LABEL_READ_ONLY'"></i> <i class="icon-lock iconsize24" data-placement="left" data-bind="tooltip: 'CONTACTS/LABEL_READ_ONLY'"></i>
</div> </div>
<div class="e-share-sign" style="display: none"> <div class="e-share-sign" data-bind="visible: contactsSharingIsAllowed">
<div class="btn-group pull-right"> <div class="btn-group pull-right">
<a class="btn dropdown-toggle" data-placement="left" data-toggle="dropdown" data-bind="tooltip: 'CONTACTS/LABEL_SHARE'"> <a class="btn dropdown-toggle" data-placement="left" data-toggle="dropdown" data-bind="tooltip: 'CONTACTS/LABEL_SHARE'">
<i class="icon-share"></i> <i data-bind="css: shareIcon"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
<span class="caret"></span> <span class="caret"></span>
</a> </a>
<ul class="dropdown-menu g-ui-menu"> <ul class="dropdown-menu g-ui-menu">
<li class="e-item"> <li class="e-item" data-bind="css: {'selected': shareToNone}">
<a class="e-link" data-bind="css: {'selected': this.shareToNone}"> <a class="e-link" data-bind="click: setShareToNone">
<i class="icon-none"></i> <i class="icon-none"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_SHARE_NONE"></span> <span class="i18n" data-i18n-text="CONTACTS/BUTTON_SHARE_NONE"></span>
</a> </a>
</li> </li>
<li class="e-item"> <li class="e-item" data-bind="css: {'selected': shareToAll}">
<a class="e-link" data-bind="css: {'selected': this.shareToDomain}"> <a class="e-link" data-bind="click: setShareToAll">
<i class="icon-none"></i> <i class="icon-earth"></i>
&nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_SHARE_DOMAIN"></span>
</a>
</li>
<li class="e-item">
<a class="e-link" data-bind="css: {'selected': this.shareToAll}">
<i class="icon-none"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_SHARE_ALL"></span> <span class="i18n" data-i18n-text="CONTACTS/BUTTON_SHARE_ALL"></span>
</a> </a>
@ -189,12 +187,12 @@
</div> </div>
</div> </div>
<button class="btn button-save-contact" data-bind="command: saveCommand"> <!-- <button class="btn button-save-contact" data-bind="command: saveCommand">
<i data-bind="css: {'icon-ok': !viewSaving(), 'icon-spinner animated': viewSaving()}"></i> <i data-bind="css: {'icon-ok': !viewSaving(), 'icon-spinner animated': viewSaving()}"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_CREATE_CONTACT" data-bind="visible: '' === viewID()"></span> <span class="i18n" data-i18n-text="CONTACTS/BUTTON_CREATE_CONTACT" data-bind="visible: '' === viewID()"></span>
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_UPDATE_CONTACT" data-bind="visible: '' !== viewID()"></span> <span class="i18n" data-i18n-text="CONTACTS/BUTTON_UPDATE_CONTACT" data-bind="visible: '' !== viewID()"></span>
</button> </button>-->
</div> </div>
</div> </div>
</div> </div>

View file

@ -63,6 +63,15 @@
</label> </label>
</div> </div>
</div> </div>
<div class="control-group">
<div class="controls">
<label data-bind="click: function () { contactsAutosave(!contactsAutosave()); }">
<i data-bind="css: contactsAutosave() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
&nbsp;&nbsp;
<span class="i18n" data-i18n-text="SETTINGS_GENERAL/LABEL_CONTACTS_AUTOSAVE"></span>
</label>
</div>
</div>
</div> </div>
<div class="form-horizontal"> <div class="form-horizontal">
<div class="legend"> <div class="legend">

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "Von" TITLE_FROM = "Von"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "Nachrichten pro Seite"
LABEL_CHROME_NOTIFICATION = "Benachrichtigungen" LABEL_CHROME_NOTIFICATION = "Benachrichtigungen"
LABEL_CHROME_NOTIFICATION_DESC = "Popups einblenden, wenn neue Nachrichten vorhanden sind" LABEL_CHROME_NOTIFICATION_DESC = "Popups einblenden, wenn neue Nachrichten vorhanden sind"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Vom Browser blockiert.)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Vom Browser blockiert.)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Vorlagen" LEGEND_THEMES = "Vorlagen"

View file

@ -144,11 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only" LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share" LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None" BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All" BUTTON_SHARE_ALL = "All"
BUTTON_SHARE_DOMAIN = "Domain"
[COMPOSE] [COMPOSE]
TITLE_FROM = "From" TITLE_FROM = "From"
@ -303,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "messages on page"
LABEL_CHROME_NOTIFICATION = "Notifications" LABEL_CHROME_NOTIFICATION = "Notifications"
LABEL_CHROME_NOTIFICATION_DESC = "Show new messages notification popups" LABEL_CHROME_NOTIFICATION_DESC = "Show new messages notification popups"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blocked by the browser)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blocked by the browser)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Themes" LEGEND_THEMES = "Themes"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "De" TITLE_FROM = "De"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "mensajes en página"
LABEL_CHROME_NOTIFICATION = "Notificaciones" LABEL_CHROME_NOTIFICATION = "Notificaciones"
LABEL_CHROME_NOTIFICATION_DESC = "Mostrar notificación de nuevos mensajes en Popup" LABEL_CHROME_NOTIFICATION_DESC = "Mostrar notificación de nuevos mensajes en Popup"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado por el explorador)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado por el explorador)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Temas" LEGEND_THEMES = "Temas"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Téléphone" LABEL_PHONE = "Téléphone"
LINK_ADD_EMAIL = "Ajouter une adresse email" LINK_ADD_EMAIL = "Ajouter une adresse email"
LINK_ADD_PHONE = "Ajouter un numéro de téléphone" LINK_ADD_PHONE = "Ajouter un numéro de téléphone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "De" TITLE_FROM = "De"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "messages par page"
LABEL_CHROME_NOTIFICATION = "Notifications" LABEL_CHROME_NOTIFICATION = "Notifications"
LABEL_CHROME_NOTIFICATION_DESC = "Afficher un pop-up de notification pour les nouveaux messages" LABEL_CHROME_NOTIFICATION_DESC = "Afficher un pop-up de notification pour les nouveaux messages"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqué par le navigateur)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqué par le navigateur)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Thèmes" LEGEND_THEMES = "Thèmes"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "Frá" TITLE_FROM = "Frá"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "bréf á síðu"
LABEL_CHROME_NOTIFICATION = "Tilkynningar" LABEL_CHROME_NOTIFICATION = "Tilkynningar"
LABEL_CHROME_NOTIFICATION_DESC = "Sýna tilkynningarglugga fyrir ný bréf" LABEL_CHROME_NOTIFICATION_DESC = "Sýna tilkynningarglugga fyrir ný bréf"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Lokað af vafra)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Lokað af vafra)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Þemur" LEGEND_THEMES = "Þemur"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "보낸 이" TITLE_FROM = "보낸 이"
@ -295,6 +300,7 @@ LABEL_MESSAGE_PER_PAGE = "페이지 당 메시지 수"
LABEL_CHROME_NOTIFICATION = "알림" LABEL_CHROME_NOTIFICATION = "알림"
LABEL_CHROME_NOTIFICATION_DESC = "새 메시지 알림 팝업 사용" LABEL_CHROME_NOTIFICATION_DESC = "새 메시지 알림 팝업 사용"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(브라우저에 의해 차단됨)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(브라우저에 의해 차단됨)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "테마" LEGEND_THEMES = "테마"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "No" TITLE_FROM = "No"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "ziņojumi lapā"
LABEL_CHROME_NOTIFICATION = "Paziņojumi" LABEL_CHROME_NOTIFICATION = "Paziņojumi"
LABEL_CHROME_NOTIFICATION_DESC = "Rādīt jaunus paziņojumus kā izlecošus logus" LABEL_CHROME_NOTIFICATION_DESC = "Rādīt jaunus paziņojumus kā izlecošus logus"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Parlūkprogramma bloķēja)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Parlūkprogramma bloķēja)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Tēmas" LEGEND_THEMES = "Tēmas"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "Van" TITLE_FROM = "Van"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "berichten op pagina"
LABEL_CHROME_NOTIFICATION = "Notificaties" LABEL_CHROME_NOTIFICATION = "Notificaties"
LABEL_CHROME_NOTIFICATION_DESC = "Toon nieuwe berichten popup" LABEL_CHROME_NOTIFICATION_DESC = "Toon nieuwe berichten popup"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Geblokkeerd door de browser)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Geblokkeerd door de browser)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Themes" LEGEND_THEMES = "Themes"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "E-post"
LABEL_PHONE = "Telefon" LABEL_PHONE = "Telefon"
LINK_ADD_EMAIL = "Legg til en e-postadresse" LINK_ADD_EMAIL = "Legg til en e-postadresse"
LINK_ADD_PHONE = "Legg til en telefon" LINK_ADD_PHONE = "Legg til en telefon"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "Fra" TITLE_FROM = "Fra"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "meldinger på side"
LABEL_CHROME_NOTIFICATION = "Varsler" LABEL_CHROME_NOTIFICATION = "Varsler"
LABEL_CHROME_NOTIFICATION_DESC = "Vis nye meldinger varslings popups" LABEL_CHROME_NOTIFICATION_DESC = "Vis nye meldinger varslings popups"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "( Blokkert av nettleseren )" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "( Blokkert av nettleseren )"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Tema" LEGEND_THEMES = "Tema"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "Od" TITLE_FROM = "Od"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "wiadomości na stronie"
LABEL_CHROME_NOTIFICATION = "Powiadomienia" LABEL_CHROME_NOTIFICATION = "Powiadomienia"
LABEL_CHROME_NOTIFICATION_DESC = "Wyświetlaj powiadomienia o nowych wiadomościach" LABEL_CHROME_NOTIFICATION_DESC = "Wyświetlaj powiadomienia o nowych wiadomościach"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Zablokowane przez przeglądarkę)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Zablokowane przez przeglądarkę)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Wygląd" LEGEND_THEMES = "Wygląd"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "De" TITLE_FROM = "De"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "Página de mensagens"
LABEL_CHROME_NOTIFICATION = "Notificações" LABEL_CHROME_NOTIFICATION = "Notificações"
LABEL_CHROME_NOTIFICATION_DESC = "Mostrar as novas mensagens de notificação" LABEL_CHROME_NOTIFICATION_DESC = "Mostrar as novas mensagens de notificação"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado pelo navegador)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado pelo navegador)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Temas" LEGEND_THEMES = "Temas"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "De" TITLE_FROM = "De"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "Página de mensagens"
LABEL_CHROME_NOTIFICATION = "Notificações" LABEL_CHROME_NOTIFICATION = "Notificações"
LABEL_CHROME_NOTIFICATION_DESC = "Mostrar as novas mensagens de notificação" LABEL_CHROME_NOTIFICATION_DESC = "Mostrar as novas mensagens de notificação"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado pelo navegador)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado pelo navegador)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Temas" LEGEND_THEMES = "Temas"

View file

@ -139,11 +139,16 @@ EMPTY_LIST = "Нет контактов"
EMPTY_SEARCH = "Контакты не найдены" EMPTY_SEARCH = "Контакты не найдены"
CLEAR_SEARCH = "Очистить поиск" CLEAR_SEARCH = "Очистить поиск"
CONTACT_VIEW_DESC = "Выберите контакт для просмотра." CONTACT_VIEW_DESC = "Выберите контакт для просмотра."
LABEL_DISPLAY_NAME = "Полное Имя" LABEL_DISPLAY_NAME = "Полное имя"
LABEL_EMAIL = "Электронная почта" LABEL_EMAIL = "Электронная почта"
LABEL_PHONE = "Телефон" LABEL_PHONE = "Телефон"
LINK_ADD_EMAIL = "Добавьте адрес электронной почты" LINK_ADD_EMAIL = "Добавьте адрес электронной почты"
LINK_ADD_PHONE = "Добавьте телефон" LINK_ADD_PHONE = "Добавьте телефон"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Введите полное имя"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Поделиться"
BUTTON_SHARE_NONE = "Отменить"
BUTTON_SHARE_ALL = "Всем"
[COMPOSE] [COMPOSE]
TITLE_FROM = "От" TITLE_FROM = "От"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "сообщений на одной странице"
LABEL_CHROME_NOTIFICATION = "Уведомления" LABEL_CHROME_NOTIFICATION = "Уведомления"
LABEL_CHROME_NOTIFICATION_DESC = "Показывать уведомления о новых сообщениях в всплывающих подсказках" LABEL_CHROME_NOTIFICATION_DESC = "Показывать уведомления о новых сообщениях в всплывающих подсказках"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Блокировано браузером)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Блокировано браузером)"
LABEL_CONTACTS_AUTOSAVE = "Автоматически добавлять получателей писем в адресную книгу"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "Темы Оформления" LEGEND_THEMES = "Темы Оформления"

View file

@ -144,6 +144,11 @@ LABEL_EMAIL = "Email"
LABEL_PHONE = "Phone" LABEL_PHONE = "Phone"
LINK_ADD_EMAIL = "Add an email address" LINK_ADD_EMAIL = "Add an email address"
LINK_ADD_PHONE = "Add a phone" LINK_ADD_PHONE = "Add a phone"
PLACEHOLDER_ENTER_DISPLAY_NAME = "Enter display name"
LABEL_READ_ONLY = "Read only"
LABEL_SHARE = "Share"
BUTTON_SHARE_NONE = "None"
BUTTON_SHARE_ALL = "All"
[COMPOSE] [COMPOSE]
TITLE_FROM = "发送自" TITLE_FROM = "发送自"
@ -298,6 +303,7 @@ LABEL_MESSAGE_PER_PAGE = "封邮件每页"
LABEL_CHROME_NOTIFICATION = "通知" LABEL_CHROME_NOTIFICATION = "通知"
LABEL_CHROME_NOTIFICATION_DESC = "显示新邮件弹窗" LABEL_CHROME_NOTIFICATION_DESC = "显示新邮件弹窗"
LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(被浏览器阻止)" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(被浏览器阻止)"
LABEL_CONTACTS_AUTOSAVE = "Automatically add recipients to your address book"
[SETTINGS_THEMES] [SETTINGS_THEMES]
LEGEND_THEMES = "主题" LEGEND_THEMES = "主题"

View file

@ -1143,7 +1143,7 @@ table {
border-spacing: 0; border-spacing: 0;
} }
/*@charset "UTF-8";*/ @charset "UTF-8";
@font-face { @font-face {
font-family: "rainloop"; font-family: "rainloop";
@ -1393,12 +1393,6 @@ table {
.icon-bug:before { .icon-bug:before {
content: "\e045"; content: "\e045";
} }
.icon-heart:before {
content: "\e046";
}
.icon-heart-empty:before {
content: "\e047";
}
.icon-popup:before { .icon-popup:before {
content: "\e048"; content: "\e048";
} }
@ -1420,57 +1414,66 @@ table {
.icon-google-drive:before { .icon-google-drive:before {
content: "\e04e"; content: "\e04e";
} }
.icon-spinner:before { .icon-github:before {
content: "\e04f"; content: "\e04f";
} }
.icon-github:before { .icon-telephone:before {
content: "\e050"; content: "\e050";
} }
.icon-telephone:before { .icon-mobile:before {
content: "\e051"; content: "\e051";
} }
.icon-mobile:before { .icon-pencil:before {
content: "\e052"; content: "\e052";
} }
.icon-mail:before { .icon-trash:before {
content: "\e053"; content: "\e053";
} }
.icon-pencil:before { .icon-left-middle:before {
content: "\e054"; content: "\e054";
} }
.icon-trash:before { .icon-right-middle:before {
content: "\e055"; content: "\e055";
} }
.icon-left-middle:before { .icon-repeat:before {
content: "\e056"; content: "\e056";
} }
.icon-right-middle:before { .icon-key:before {
content: "\e057"; content: "\e057";
} }
.icon-repeat:before { .icon-lock:before {
content: "\e058"; content: "\e058";
} }
.icon-key:before { .icon-home:before {
content: "\e059"; content: "\e059";
} }
.icon-lock:before { .icon-address-book:before {
content: "\e05a"; content: "\e05a";
} }
.icon-home:before { .icon-share:before {
content: "\e05b"; content: "\e05b";
} }
.icon-address-book:before { .icon-suitcase:before {
content: "\e05c"; content: "\e05c";
} }
.icon-share:before { .icon-new-sign:before {
content: "\e05d"; content: "\e05d";
} }
.icon-suitcase:before { .icon-spinner:before {
content: "\e05e"; content: "\e05e";
} }
.icon-mailbox:before { .icon-users:before {
content: "\e05f"; content: "\e05f";
} }
.icon-earth:before {
content: "\e060";
}
.icon-happy-smiley:before {
content: "\e061";
}
.icon-mail:before {
content: "\e062";
}
/** initial setup **/ /** initial setup **/
.nano { .nano {
@ -5710,6 +5713,9 @@ html.no-rgba .modal {
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
} }
.g-ui-menu .e-item.selected > .e-link {
background-color: #eee;
}
.g-ui-menu .e-item > .e-link:hover { .g-ui-menu .e-item > .e-link:hover {
background-color: #555; background-color: #555;
background-image: none; background-image: none;
@ -7094,10 +7100,10 @@ html.rl-message-fullscreen .messageView .b-content .buttonFull {
display: none; display: none;
} }
.b-contacts-content .control-group .control-label.fix-width { .b-contacts-content .control-group .control-label.fix-width {
width: 110px; width: 90px;
} }
.b-contacts-content .control-group .controls.fix-width { .b-contacts-content .control-group .controls.fix-width {
margin-left: 135px; margin-left: 110px;
} }
.b-contacts-content.modal { .b-contacts-content.modal {
position: absolute; position: absolute;
@ -7368,6 +7374,11 @@ html.rl-message-fullscreen .messageView .b-content .buttonFull {
color: #ee5f5b; color: #ee5f5b;
border-color: #ee5f5b; border-color: #ee5f5b;
} }
.b-contacts-content.modal .b-view-content .e-save-trigger {
position: absolute;
top: 25px;
left: 10px;
}
.b-contacts-content.modal .b-view-content .e-read-only-sign { .b-contacts-content.modal .b-view-content .e-read-only-sign {
display: none; display: none;
position: absolute; position: absolute;
@ -7376,13 +7387,13 @@ html.rl-message-fullscreen .messageView .b-content .buttonFull {
} }
.b-contacts-content.modal .b-view-content .e-share-sign { .b-contacts-content.modal .b-view-content .e-share-sign {
position: absolute; position: absolute;
top: 60px; top: 20px;
right: 20px; right: 20px;
cursor: pointer; cursor: pointer;
} }
.b-contacts-content.modal .b-view-content .button-save-contact { .b-contacts-content.modal .b-view-content .button-save-contact {
position: absolute; position: absolute;
top: 20px; top: 100px;
right: 20px; right: 20px;
} }
.b-contacts-content.modal .b-view-content.read-only .e-read-only-sign { .b-contacts-content.modal .b-view-content.read-only .e-read-only-sign {

File diff suppressed because one or more lines are too long

View file

@ -77,8 +77,6 @@
<glyph unicode="&#57411;" d="m480 288c-18 0-32-14-32-32l0-192l-384 0l0 192c0 18-14 32-32 32c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32z m-192 0l0 196c0 15-14 28-32 28c-18 0-32-13-32-28l0-196l-96 0l128-128l128 128z"/> <glyph unicode="&#57411;" d="m480 288c-18 0-32-14-32-32l0-192l-384 0l0 192c0 18-14 32-32 32c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32z m-192 0l0 196c0 15-14 28-32 28c-18 0-32-13-32-28l0-196l-96 0l128-128l128 128z"/>
<glyph unicode="&#57412;" d="m480 288c-18 0-32-14-32-32l0-192l-384 0l0 192c0 18-14 32-32 32c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32z m-256-96c0-18 14-32 32-32c18 0 32 14 32 32l0 192l96 0l-128 128l-128-128l96 0z"/> <glyph unicode="&#57412;" d="m480 288c-18 0-32-14-32-32l0-192l-384 0l0 192c0 18-14 32-32 32c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32z m-256-96c0-18 14-32 32-32c18 0 32 14 32 32l0 192l96 0l-128 128l-128-128l96 0z"/>
<glyph unicode="&#57413;" d="m485 238c0-5-2-10-6-13c-3-4-8-6-13-6l-64 0c0-32-6-60-19-82l60-60c3-4 5-8 5-13c0-5-2-9-5-13c-4-3-8-5-13-5c-5 0-10 2-13 5l-57 56c-1-1-2-2-4-3c-2-2-6-5-12-8c-6-4-12-8-19-11c-6-3-14-6-23-8c-9-3-19-4-28-4l0 256l-36 0l0-256c-10 0-20 1-29 4c-10 3-18 6-25 9c-7 4-13 8-19 12c-6 3-10 6-12 9l-5 4l-52-59c-4-4-8-6-14-6c-4 0-8 1-12 4c-4 4-6 8-6 13c0 5 1 9 5 13l57 65c-11 22-16 48-16 78l-64 0c-5 0-10 2-13 6c-4 3-6 8-6 13c0 5 2 9 6 13c3 3 8 5 13 5l64 0l0 84l-50 49c-3 4-5 8-5 13c0 5 2 10 5 13c4 4 8 6 13 6c5 0 9-2 13-6l49-49l242 0l49 49c4 4 8 6 13 6c5 0 9-2 13-6c3-3 5-8 5-13c0-5-2-9-5-13l-50-49l0-84l64 0c5 0 10-2 13-5c4-4 6-8 6-13z m-138 164l-182 0c0 26 8 47 26 65c18 18 40 27 65 27c25 0 47-9 65-27c18-18 26-39 26-65z"/> <glyph unicode="&#57413;" d="m485 238c0-5-2-10-6-13c-3-4-8-6-13-6l-64 0c0-32-6-60-19-82l60-60c3-4 5-8 5-13c0-5-2-9-5-13c-4-3-8-5-13-5c-5 0-10 2-13 5l-57 56c-1-1-2-2-4-3c-2-2-6-5-12-8c-6-4-12-8-19-11c-6-3-14-6-23-8c-9-3-19-4-28-4l0 256l-36 0l0-256c-10 0-20 1-29 4c-10 3-18 6-25 9c-7 4-13 8-19 12c-6 3-10 6-12 9l-5 4l-52-59c-4-4-8-6-14-6c-4 0-8 1-12 4c-4 4-6 8-6 13c0 5 1 9 5 13l57 65c-11 22-16 48-16 78l-64 0c-5 0-10 2-13 6c-4 3-6 8-6 13c0 5 2 9 6 13c3 3 8 5 13 5l64 0l0 84l-50 49c-3 4-5 8-5 13c0 5 2 10 5 13c4 4 8 6 13 6c5 0 9-2 13-6l49-49l242 0l49 49c4 4 8 6 13 6c5 0 9-2 13-6c3-3 5-8 5-13c0-5-2-9-5-13l-50-49l0-84l64 0c5 0 10-2 13-5c4-4 6-8 6-13z m-138 164l-182 0c0 26 8 47 26 65c18 18 40 27 65 27c25 0 47-9 65-27c18-18 26-39 26-65z"/>
<glyph unicode="&#57414;" d="m440 407c24-22 36-49 36-80c0-32-12-59-36-81c0 0-184-169-184-169c0 0-184 169-184 169c-24 22-36 49-36 81c0 31 12 58 36 80c21 19 47 29 77 29c30 0 56-10 78-29c0 0 29-27 29-27c0 0 30 27 30 27c21 19 46 29 76 29c31 0 56-10 78-29"/>
<glyph unicode="&#57415;" d="m440 406c24-22 36-49 36-80c0-32-12-58-36-80c0 0-184-169-184-169c0 0-184 169-184 169c-24 22-36 48-36 80c0 31 12 58 36 80c22 19 47 29 78 29c30 0 55-10 76-29c0 0 30-27 30-27c0 0 29 27 29 27c22 19 47 29 77 29c31 0 56-10 78-29m-27-134c14 14 21 32 21 54c0 22-6 39-19 51c-13 13-31 19-53 19c-17 0-35-8-53-24c0 0-53-47-53-47c0 0-54 47-54 47c-17 16-34 24-52 24c-22 0-40-6-54-19c-13-12-19-30-19-51c0-23 7-41 22-54c0 0 157-146 157-146c0 0 157 146 157 146"/>
<glyph unicode="&#57416;" d="m410 461c14 0 26-5 36-15c10-10 15-22 15-36c0 0 0-205 0-205c0-14-5-26-15-36c-10-10-22-15-36-15c0 0-205 0-205 0c-14 0-26 5-36 15c-10 10-15 22-15 36c0 0 0 206 0 206c0 13 5 25 14 35c10 10 22 15 37 15c0 0 205 0 205 0m0-256c0 0 0 205 0 205c0 0-205 0-205 0c0 0 0-205 0-205c0 0 205 0 205 0m-308 51c0 0 0-154 0-154c0 0 154 0 154 0c0 0 0-51 0-51c0 0-154 0-154 0c-13 0-25 5-35 16c-11 10-16 22-16 35c0 0 0 154 0 154c0 0 51 0 51 0"/> <glyph unicode="&#57416;" d="m410 461c14 0 26-5 36-15c10-10 15-22 15-36c0 0 0-205 0-205c0-14-5-26-15-36c-10-10-22-15-36-15c0 0-205 0-205 0c-14 0-26 5-36 15c-10 10-15 22-15 36c0 0 0 206 0 206c0 13 5 25 14 35c10 10 22 15 37 15c0 0 205 0 205 0m0-256c0 0 0 205 0 205c0 0-205 0-205 0c0 0 0-205 0-205c0 0 205 0 205 0m-308 51c0 0 0-154 0-154c0 0 154 0 154 0c0 0 0-51 0-51c0 0-154 0-154 0c-13 0-25 5-35 16c-11 10-16 22-16 35c0 0 0 154 0 154c0 0 51 0 51 0"/>
<glyph unicode="&#57417;" d="m0 512l0-512l512 0l0 512z m480-480l-448 0l0 448l448 0z m-96 368l-160-160l-96 96l-64-64l160-160l224 224z"/> <glyph unicode="&#57417;" d="m0 512l0-512l512 0l0 512z m480-480l-448 0l0 448l448 0z m-96 368l-160-160l-96 96l-64-64l160-160l224 224z"/>
<glyph unicode="&#57418;" d="m0 512l0-512l512 0l0 512z m480-480l-448 0l0 448l448 0z"/> <glyph unicode="&#57418;" d="m0 512l0-512l512 0l0 512z m480-480l-448 0l0 448l448 0z"/>
@ -86,21 +84,24 @@
<glyph unicode="&#57420;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256z m0-448c-106 0-192 86-192 192c0 106 86 192 192 192c106 0 192-86 192-192c0-106-86-192-192-192z m-96 192c0 53 43 96 96 96c53 0 96-43 96-96c0-53-43-96-96-96c-53 0-96 43-96 96z"/> <glyph unicode="&#57420;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256z m0-448c-106 0-192 86-192 192c0 106 86 192 192 192c106 0 192-86 192-192c0-106-86-192-192-192z m-96 192c0 53 43 96 96 96c53 0 96-43 96-96c0-53-43-96-96-96c-53 0-96 43-96 96z"/>
<glyph unicode="&#57421;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256z m0-448c-106 0-192 86-192 192c0 106 86 192 192 192c106 0 192-86 192-192c0-106-86-192-192-192z"/> <glyph unicode="&#57421;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256z m0-448c-106 0-192 86-192 192c0 106 86 192 192 192c106 0 192-86 192-192c0-106-86-192-192-192z"/>
<glyph unicode="&#57422;" d="m230 182l-86-148l283 0l85 148z m258 42l-147 254l-170 0l146-254z m-342 212l-146-254l85-148l147 254z"/> <glyph unicode="&#57422;" d="m230 182l-86-148l283 0l85 148z m258 42l-147 254l-170 0l146-254z m-342 212l-146-254l85-148l147 254z"/>
<glyph unicode="&#57423;" d="m256 512c-139 0-253-111-256-250c3 121 95 218 208 218c115 0 208-100 208-224c0-27 21-48 48-48c27 0 48 21 48 48c0 141-115 256-256 256z m0-512c139 0 253 111 256 250c-3-121-95-218-208-218c-115 0-208 100-208 224c0 27-21 48-48 48c-27 0-48-21-48-48c0-141 115-256 256-256z"/> <glyph unicode="&#57423;" d="m446 256c0 51-22 100-56 134c-34 34-83 56-134 56c-51 0-100-22-134-56c-34-34-56-83-56-134c0-83 55-156 133-181l0 50c-11-1-17-2-20-2c-22 0-37 10-46 30c-3 7-6 13-10 19c-1 1-3 2-7 5c-3 3-6 5-8 7c-3 2-4 4-4 5c0 2 3 4 9 4c11 0 20-7 26-15c6-8 12-17 22-23c4-3 10-4 16-4c8 0 16 1 24 4c3 11 10 20 19 26c-66 7-97 30-97 92c0 23 7 43 22 58c-3 9-4 17-4 25c0 12 2 22 8 32c22 0 37-7 60-23c15 3 31 5 50 5c15 0 30-1 45-5c22 16 37 23 59 23c6-10 8-20 8-32c0-8-1-16-4-24c15-17 22-36 22-59c0-62-31-86-97-92c14-9 21-22 21-39l0-67c78 25 133 98 133 181z m7 114c20-35 31-73 31-114c0-83-44-156-114-197c-35-20-73-31-114-31c-83 0-156 44-197 114c-20 35-31 73-31 114c0 83 44 156 114 197c35 20 73 31 114 31c83 0 156-44 197-114z"/>
<glyph unicode="&#57424;" d="m446 256c0 51-22 100-56 134c-34 34-83 56-134 56c-51 0-100-22-134-56c-34-34-56-83-56-134c0-83 55-156 133-181l0 50c-11-1-17-2-20-2c-22 0-37 10-46 30c-3 7-6 13-10 19c-1 1-3 2-7 5c-3 3-6 5-8 7c-3 2-4 4-4 5c0 2 3 4 9 4c11 0 20-7 26-15c6-8 12-17 22-23c4-3 10-4 16-4c8 0 16 1 24 4c3 11 10 20 19 26c-66 7-97 30-97 92c0 23 7 43 22 58c-3 9-4 17-4 25c0 12 2 22 8 32c22 0 37-7 60-23c15 3 31 5 50 5c15 0 30-1 45-5c22 16 37 23 59 23c6-10 8-20 8-32c0-8-1-16-4-24c15-17 22-36 22-59c0-62-31-86-97-92c14-9 21-22 21-39l0-67c78 25 133 98 133 181z m7 114c20-35 31-73 31-114c0-83-44-156-114-197c-35-20-73-31-114-31c-83 0-156 44-197 114c-20 35-31 73-31 114c0 83 44 156 114 197c35 20 73 31 114 31c83 0 156-44 197-114z"/> <glyph unicode="&#57424;" d="m435 152c-1 6-4 10-9 13l-74 43l0 0c-3 2-7 3-10 3c-6 0-12-3-16-7l-22-21c-1-1-4-2-5-3c0 0-25 2-71 48c-46 46-48 71-48 71c0 1 2 4 3 5l18 19c7 6 8 17 5 26l-41 76c-3 6-9 10-15 10c-5 0-9-2-13-5l-50-50c-5-5-9-14-10-20c0-4-9-81 97-186c89-90 159-97 179-97c4 0 6 0 7 0c6 1 15 5 20 10l50 50c4 5 6 10 5 15z"/>
<glyph unicode="&#57425;" d="m435 152c-1 6-4 10-9 13l-74 43l0 0c-3 2-7 3-10 3c-6 0-12-3-16-7l-22-21c-1-1-4-2-5-3c0 0-25 2-71 48c-46 46-48 71-48 71c0 1 2 4 3 5l18 19c7 6 8 17 5 26l-41 76c-3 6-9 10-15 10c-5 0-9-2-13-5l-50-50c-5-5-9-14-10-20c0-4-9-81 97-186c89-90 159-97 179-97c4 0 6 0 7 0c6 1 15 5 20 10l50 50c4 5 6 10 5 15z"/> <glyph unicode="&#57425;" d="m279 110c0 6-2 11-7 16c-4 4-10 7-16 7c-6 0-12-3-16-7c-5-5-7-10-7-16c0-7 2-12 7-16c4-5 10-7 16-7c6 0 12 2 16 7c5 4 7 9 7 16z m59 45l0 202c0 2-1 4-2 6c-2 2-4 3-7 3l-146 0c-3 0-5-1-7-3c-1-2-2-4-2-6l0-202c0-2 1-4 2-6c2-2 4-3 7-3l146 0c3 0 5 1 7 3c1 2 2 4 2 6z m-55 243c0 3-1 4-4 4l-46 0c-3 0-4-1-4-4c0-3 1-5 4-5l46 0c3 0 4 2 4 5z m83 4l0-292c0-10-4-19-11-26c-7-7-16-11-26-11l-146 0c-10 0-19 4-26 11c-7 7-11 16-11 26l0 292c0 10 4 19 11 26c7 7 16 11 26 11l146 0c10 0 19-4 26-11c7-7 11-16 11-26z"/>
<glyph unicode="&#57426;" d="m279 110c0 6-2 11-7 16c-4 4-10 7-16 7c-6 0-12-3-16-7c-5-5-7-10-7-16c0-7 2-12 7-16c4-5 10-7 16-7c6 0 12 2 16 7c5 4 7 9 7 16z m59 45l0 202c0 2-1 4-2 6c-2 2-4 3-7 3l-146 0c-3 0-5-1-7-3c-1-2-2-4-2-6l0-202c0-2 1-4 2-6c2-2 4-3 7-3l146 0c3 0 5 1 7 3c1 2 2 4 2 6z m-55 243c0 3-1 4-4 4l-46 0c-3 0-4-1-4-4c0-3 1-5 4-5l46 0c3 0 4 2 4 5z m83 4l0-292c0-10-4-19-11-26c-7-7-16-11-26-11l-146 0c-10 0-19 4-26 11c-7 7-11 16-11 26l0 292c0 10 4 19 11 26c7 7 16 11 26 11l146 0c10 0 19-4 26-11c7-7 11-16 11-26z"/> <glyph unicode="&#57426;" d="m11 78l-11-78l79 11l78 11l-67 68l-68 67z m168 12l-22 22l202 202l-45 45l-202-202l-23 23l202 202l-22 22l-224-224l134-135l224 225l-22 22z m294 290l-90 90c-12 12-32 13-44 1l-2-3l0 0l-43-43l134-134l43 43l0 0l3 2c12 12 12 32-1 44"/>
<glyph unicode="&#57427;" d="m269 232l189 193c-3 1-7 2-10 2l-384 0c-3 0-6-1-10-2l190-193c6-6 18-6 25 0z m25-26c-10-10-24-16-38-16c-14 0-28 5-38 16l-189 192c0-3 0-5 0-8l0-268c0-20 16-37 35-37l384 0c19 0 35 17 35 37l0 268c0 3 0 5 0 8z"/> <glyph unicode="&#57427;" d="m480 403c-2 25-23 45-48 45l-48 0l0 16c0 26-22 48-48 48l-160 0c-27 0-48-22-48-48l0-16l-48 0c-26 0-46-20-48-45l0 0l0-35c0-18 14-32 32-32l0-272c0-35 29-64 64-64l256 0c35 0 64 29 64 64l0 272c18 0 32 14 32 32l0 35z m-320 61c0 9 7 16 16 16l160 0c9 0 16-7 16-16l0-16l-192 0z m256-400c0-18-14-32-32-32l-256 0c-18 0-32 14-32 32l0 272l320 0z m32 320l0-16l-384 0l0 32c0 9 7 16 16 16l352 0c9 0 16-7 16-16z m-304-320l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z m96-224l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z m96-224l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z"/>
<glyph unicode="&#57428;" d="m11 78l-11-78l79 11l78 11l-67 68l-68 67z m168 12l-22 22l202 202l-45 45l-202-202l-23 23l202 202l-22 22l-224-224l134-135l224 225l-22 22z m294 290l-90 90c-12 12-32 13-44 1l-2-3l0 0l-43-43l134-134l43 43l0 0l3 2c12 12 12 32-1 44"/> <glyph unicode="&#57428;" d="m293 397c4 6 11 9 20 9c8 0 15-3 21-9c13-12 13-26 0-41c0 0-96-100-96-100c0 0 96-99 96-99c13-15 13-29 0-41c-6-6-13-8-21-8c-8 0-15 2-20 8c0 0-116 121-116 121c-6 5-8 11-8 19c0 8 2 15 8 20c70 74 109 114 116 121"/>
<glyph unicode="&#57429;" d="m480 403c-2 25-23 45-48 45l-48 0l0 16c0 26-22 48-48 48l-160 0c-27 0-48-22-48-48l0-16l-48 0c-26 0-46-20-48-45l0 0l0-35c0-18 14-32 32-32l0-272c0-35 29-64 64-64l256 0c35 0 64 29 64 64l0 272c18 0 32 14 32 32l0 35z m-320 61c0 9 7 16 16 16l160 0c9 0 16-7 16-16l0-16l-192 0z m256-400c0-18-14-32-32-32l-256 0c-18 0-32 14-32 32l0 272l320 0z m32 320l0-16l-384 0l0 32c0 9 7 16 16 16l352 0c9 0 16-7 16-16z m-304-320l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z m96-224l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z m96-224l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z"/> <glyph unicode="&#57429;" d="m219 397c0 0 116-121 116-121c5-5 8-12 8-20c0-8-3-14-8-19c0 0-116-121-116-121c-5-6-12-8-20-8c-9 0-15 2-21 8c-12 12-12 26 0 41c0 0 95 99 95 99c0 0-95 100-95 100c-12 15-12 29 0 41c6 6 13 9 21 9c9 0 15-3 20-9"/>
<glyph unicode="&#57430;" d="m293 397c4 6 11 9 20 9c8 0 15-3 21-9c13-12 13-26 0-41c0 0-96-100-96-100c0 0 96-99 96-99c13-15 13-29 0-41c-6-6-13-8-21-8c-8 0-15 2-20 8c0 0-116 121-116 121c-6 5-8 11-8 19c0 8 2 15 8 20c70 74 109 114 116 121"/> <glyph unicode="&#57430;" d="m256 480c-60 0-117-24-158-66l-66 66l0-192l192 0l-81 81c30 30 70 47 113 47c88 0 160-72 160-160c0-88-72-160-160-160c-57 0-110 31-139 80l-55-32c40-69 114-112 194-112c124 0 224 101 224 224c0 123-100 224-224 224"/>
<glyph unicode="&#57431;" d="m219 397c0 0 116-121 116-121c5-5 8-12 8-20c0-8-3-14-8-19c0 0-116-121-116-121c-5-6-12-8-20-8c-9 0-15 2-21 8c-12 12-12 26 0 41c0 0 95 99 95 99c0 0-95 100-95 100c-12 15-12 29 0 41c6 6 13 9 21 9c9 0 15-3 20-9"/> <glyph unicode="&#57431;" d="m352 448c53 0 96-43 96-96c0-53-43-96-96-96c-5 0-10 1-17 2l-33 6l-24-24l-3-3l-19-19l0-26l-64 0l0-64l-64 0l0-64l-64 0l0 38l200 200l-6 33c-1 7-2 12-2 17c0 53 43 96 96 96m0 64c-88 0-160-72-160-160c0-10 1-20 3-29l-195-195l0-128l192 0l0 64l64 0l0 64l64 0l0 64l3 3c9-2 19-3 29-3c88 0 160 72 160 160c0 88-72 160-160 160z m32-160c0-18-14-32-32-32c-18 0-32 14-32 32c0 18 14 32 32 32c18 0 32-14 32-32z"/>
<glyph unicode="&#57432;" d="m256 480c-60 0-117-24-158-66l-66 66l0-192l192 0l-81 81c30 30 70 47 113 47c88 0 160-72 160-160c0-88-72-160-160-160c-57 0-110 31-139 80l-55-32c40-69 114-112 194-112c124 0 224 101 224 224c0 123-100 224-224 224"/> <glyph unicode="&#57432;" d="m420 286l-45 0l0 43c0 0 0 0 0 0c0 67-54 122-121 122c-67 0-122-55-122-122l0-43l-40 0c-8 0-14-6-14-14l0-197c0-8 6-14 14-14l328 0c8 0 14 6 14 14l0 197c0 8-6 14-14 14z m-216 43c0 28 22 50 50 50c27 0 49-22 50-49c0 0 0 0 0 0l0 0c0-1 0-1 0-1l0-43l-100 0z"/>
<glyph unicode="&#57433;" d="m352 448c53 0 96-43 96-96c0-53-43-96-96-96c-5 0-10 1-17 2l-33 6l-24-24l-3-3l-19-19l0-26l-64 0l0-64l-64 0l0-64l-64 0l0 38l200 200l-6 33c-1 7-2 12-2 17c0 53 43 96 96 96m0 64c-88 0-160-72-160-160c0-10 1-20 3-29l-195-195l0-128l192 0l0 64l64 0l0 64l64 0l0 64l3 3c9-2 19-3 29-3c88 0 160 72 160 160c0 88-72 160-160 160z m32-160c0-18-14-32-32-32c-18 0-32 14-32 32c0 18 14 32 32 32c18 0 32-14 32-32z"/> <glyph unicode="&#57433;" d="m480 249c6-6 8-10 6-14c-2-4-6-6-14-6c0 0-43 0-43 0c0 0 0-158 0-158c0-5 0-9 0-11c-1-2-2-5-4-7c-3-2-7-3-12-3c0 0-105 0-105 0c0 0 0 159 0 159c0 0-104 0-104 0c0 0 0-159 0-159c0 0-99 0-99 0c-10 0-16 2-18 5c-3 4-4 9-4 16c0 0 0 158 0 158c0 0-43 0-43 0c-7 0-12 2-14 6c-1 4 0 8 6 14c0 0 205 206 205 206c5 5 12 8 19 8c8 0 14-3 20-8c0 0 204-206 204-206"/>
<glyph unicode="&#57434;" d="m420 286l-45 0l0 43c0 0 0 0 0 0c0 67-54 122-121 122c-67 0-122-55-122-122l0-43l-40 0c-8 0-14-6-14-14l0-197c0-8 6-14 14-14l328 0c8 0 14 6 14 14l0 197c0 8-6 14-14 14z m-216 43c0 28 22 50 50 50c27 0 49-22 50-49c0 0 0 0 0 0l0 0c0-1 0-1 0-1l0-43l-100 0z"/> <glyph unicode="&#57434;" d="m37 475l0-438l438 0l0 77l-47 0l0 43l47 0l0 78l-47 0l0 42l47 0l0 78l-47 0l0 43l47 0l0 77l-438 0z m195-76c35 0 64-29 64-64c0-24-15-46-36-56l82-49l1 0l0-69l-221 0l0 69l1 0l81 49c-21 10-35 32-35 56c0 35 28 64 63 64z"/>
<glyph unicode="&#57435;" d="m480 249c6-6 8-10 6-14c-2-4-6-6-14-6c0 0-43 0-43 0c0 0 0-158 0-158c0-5 0-9 0-11c-1-2-2-5-4-7c-3-2-7-3-12-3c0 0-105 0-105 0c0 0 0 159 0 159c0 0-104 0-104 0c0 0 0-159 0-159c0 0-99 0-99 0c-10 0-16 2-18 5c-3 4-4 9-4 16c0 0 0 158 0 158c0 0-43 0-43 0c-7 0-12 2-14 6c-1 4 0 8 6 14c0 0 205 206 205 206c5 5 12 8 19 8c8 0 14-3 20-8c0 0 204-206 204-206"/> <glyph unicode="&#57435;" d="m384 179c21 0 39-7 54-22c15-14 23-33 23-55c0-21-8-39-23-54c-15-15-33-22-54-22c-21 0-39 7-54 22c-15 15-23 33-23 54c0 2 0 5 1 8c0 2 0 4 0 6c0 0-133 80-133 80c-14-11-30-17-47-17c-21 0-39 8-54 23c-15 15-23 33-23 54c0 21 8 39 23 54c15 15 33 23 54 23c18 0 34-5 47-16c0 0 133 80 133 80c0 2 0 4 0 6c-1 3-1 5-1 7c0 21 8 39 23 54c15 15 33 22 54 22c21 0 39-7 54-22c15-14 23-33 23-54c0-22-8-40-23-55c-15-15-33-22-54-22c-18 0-33 5-46 16c0 0-134-80-134-80c0-2 1-7 1-13c0-5-1-10-1-12c0 0 134-80 134-80c12 10 28 15 46 15"/>
<glyph unicode="&#57436;" d="m37 475l0-438l438 0l0 77l-47 0l0 43l47 0l0 78l-47 0l0 42l47 0l0 78l-47 0l0 43l47 0l0 77l-438 0z m195-76c35 0 64-29 64-64c0-24-15-46-36-56l82-49l1 0l0-69l-221 0l0 69l1 0l81 49c-21 10-35 32-35 56c0 35 28 64 63 64z"/> <glyph unicode="&#57436;" d="m461 410c14 0 26-6 36-16c10-10 15-22 15-36c0 0 0-281 0-281c0-15-5-27-15-37c-10-9-22-14-36-14c0 0-26 0-26 0c0 0 0 384 0 384c0 0 26 0 26 0m-461-52c0 14 5 26 15 36c11 10 23 16 36 16c0 0 26 0 26 0c0 0 0-384 0-384c0 0-26 0-26 0c-13 0-25 5-36 14c-10 10-15 22-15 37c0 0 0 281 0 281m343 105c0 0 0-53 0-53c0 0 56 0 56 0c0 0 0-384 0-384c0 0-286 0-286 0c0 0 0 384 0 384c0 0 56 0 56 0c0 0 0 53 0 53c33 16 62 23 87 23c25 0 54-7 87-23m-31-53c0 0 0 33 0 33c-17 9-36 13-56 13c-18 0-37-4-56-13c0 0 0-33 0-33c0 0 112 0 112 0"/>
<glyph unicode="&#57437;" d="m384 179c21 0 39-7 54-22c15-14 23-33 23-55c0-21-8-39-23-54c-15-15-33-22-54-22c-21 0-39 7-54 22c-15 15-23 33-23 54c0 2 0 5 1 8c0 2 0 4 0 6c0 0-133 80-133 80c-14-11-30-17-47-17c-21 0-39 8-54 23c-15 15-23 33-23 54c0 21 8 39 23 54c15 15 33 23 54 23c18 0 34-5 47-16c0 0 133 80 133 80c0 2 0 4 0 6c-1 3-1 5-1 7c0 21 8 39 23 54c15 15 33 22 54 22c21 0 39-7 54-22c15-14 23-33 23-54c0-22-8-40-23-55c-15-15-33-22-54-22c-18 0-33 5-46 16c0 0-134-80-134-80c0-2 1-7 1-13c0-5-1-10-1-12c0 0 134-80 134-80c12 10 28 15 46 15"/> <glyph unicode="&#57437;" d="m480 384l-448 0c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32m-288-224l-32 0l-64 107l0-107l-32 0l0 160l32 0l64-107l0 107l32 0z m96 128l-32 0l0-32l32 0l0-32l-32 0l0-32l32 0l0-32l-64 0l0 160l64 0z m160-128l-32 0l-32 64l-32-64l-32 0l0 160l32 0l0-96l32 64l32-64l0 96l32 0z"/>
<glyph unicode="&#57438;" d="m461 410c14 0 26-6 36-16c10-10 15-22 15-36c0 0 0-281 0-281c0-15-5-27-15-37c-10-9-22-14-36-14c0 0-26 0-26 0c0 0 0 384 0 384c0 0 26 0 26 0m-461-52c0 14 5 26 15 36c11 10 23 16 36 16c0 0 26 0 26 0c0 0 0-384 0-384c0 0-26 0-26 0c-13 0-25 5-36 14c-10 10-15 22-15 37c0 0 0 281 0 281m343 105c0 0 0-53 0-53c0 0 56 0 56 0c0 0 0-384 0-384c0 0-286 0-286 0c0 0 0 384 0 384c0 0 56 0 56 0c0 0 0 53 0 53c33 16 62 23 87 23c25 0 54-7 87-23m-31-53c0 0 0 33 0 33c-17 9-36 13-56 13c-18 0-37-4-56-13c0 0 0-33 0-33c0 0 112 0 112 0"/> <glyph unicode="&#57438;" d="m256 512c-139 0-253-111-256-250c3 121 95 218 208 218c115 0 208-100 208-224c0-27 21-48 48-48c27 0 48 21 48 48c0 141-115 256-256 256z m0-512c139 0 253 111 256 250c-3-121-95-218-208-218c-115 0-208 100-208 224c0 27-21 48-48 48c-27 0-48-21-48-48c0-141 115-256 256-256z"/>
<glyph unicode="&#57439;" d="m448 384l-256 0l0 32l48 0c27 0 48 21 48 48c0 26-21 48-48 48l-80 0c-18 0-32-14-32-32l0-96l-96 0c-18 0-32-14-32-32l0-192c0-18 14-32 32-32l160 0l0-128l128 0l0 128l128 0c18 0 32 14 32 32l0 192c0 18-14 32-32 32m-192-352l-32 0l0 96l32 0z m192 128l-416 0l0 192l96 0l0-96c0-18 14-32 32-32c18 0 32 14 32 32l0 96l256 0z"/> <glyph unicode="&#57439;" d="m492 217l-83 40c20 12 33 36 33 63c0 40-28 72-62 72c-12 0-23-4-32-11c6-14 9-29 9-46c0-24-7-48-20-67c4-5 9-9 15-12l0 0l53-25c15-8 25-24 25-41l0-70l57 0c7 0 14 7 14 16l0 66c0 7-4 13-9 15z m-330 40c4 3 8 6 12 10c-13 19-21 43-21 68c0 17 4 33 10 47c-10 6-20 10-31 10c-34 0-62-32-62-72c0-28 14-52 34-64l-84-39c-5-2-9-8-9-15l0-66c0-9 7-16 14-16l55 0l0 70c0 17 10 34 26 41z m232-49l-72 34l-31 15c14 8 25 21 32 37c5 12 9 26 9 41c0 9-2 17-4 24c-9 38-38 65-73 65c-34 0-63-26-73-63c-2-8-3-17-3-26c0-16 3-31 10-44c7-14 18-27 31-35l-29-13l-75-35c-6-3-10-10-10-18l0-82c0-11 7-20 17-20l264 0c10 0 18 9 18 20l0 82c0 8-5 15-11 18z"/>
<glyph unicode="&#57440;" d="m256 476c-121 0-220-99-220-220c0-121 99-220 220-220c121 0 220 99 220 220c0 121-99 220-220 220z m-54-60c8-4 17-8 28-12c11-4 22-6 32-6c8 0 16 2 23 7c7 4 13 7 21 6c9-1 18-4 27-4c11-6 23-14 33-23c-5 0-10-1-16-2c-6-1-12-2-17-3c-6-2-11-4-16-6c-4-3-8-6-10-9c-3-6-6-11-7-15c-3-8-2-20-9-26c-1-1-2-2-3-3c-1-2-1-3-1-5c0-2 1-5 3-9c1-2 1-4 2-8c6 0 12 1 17 5l31-3c7 9 17 9 24 0c3-2 6-6 8-11l-13-9c-3 1-6 3-11 6c-2 1-4 3-6 4c-12 6-36-1-50-2c-2-3-3-7-7-8c-1-2 0-4-1-6c-6-10-8-19-6-30c3-16 11-24 25-24l5 0c6 0 11 0 13 0c3-1 4-2 4-2c-1-4-2-6-1-9c1-7 6-12 6-19c-1-10-4-18-1-27c4-10 9-20 12-29c2-3 4-5 6-5c6-1 13 2 21 11c6 6 10 14 11 22c1 7 6 13 8 21l0 6c1 3 2 6 4 9c1 4 1 9 2 14c4 5 9 9 13 15c2 4 2 7 1 10c0 1-1 1-2 2l-7 3c0 4 7 3 11 2l16 11c0-21-4-42-12-61c-7-20-19-37-33-53c-20-21-44-37-71-46c-28-9-56-11-85-6c5 9 8 19 14 28c0 5 0 9 2 12c5 13 15 17 26 28c11 11 11 25 12 42c0 10-17 17-25 23c-18 12-30 30-55 25c-10-1-12-3-19 3l-2 1l0 1l1 2c3 3-1 7-5 5c-1 0-1 0-2 0c-1 4-4 8-5 13c5-4 8-6 12-8c3-2 5-3 7-3c3-1 4-2 6-1c3 0 5 4 6 10c0 6 0 13-1 21c1 1 2 3 2 4c3 17 12 13 25 18c2 1 2 3 1 4c0 1 0 1 0 1c0 0 0 0 0 0c7 4 11 11 15 18c-3 6-9 11-16 14c-3 5-17 2-20 9c-3 0-4 1-6 1c-12 8-17 23-31 28c-5 1-10 1-16 0c16 13 33 22 52 28z m-113-130c3-5 7-9 11-12c20-20 40-24 66-33c2-1 3-3 6-5c2-2 5-5 8-7c0-1 0-3-1-6c0-3 0-7 0-14c1-17 15-30 19-47c-4-21-4-42-6-63c-21 9-39 21-55 37c-16 16-28 35-37 56c-6 15-10 31-12 47c-1 16-1 31 1 47z"/>
<glyph unicode="&#57441;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256m0-480c-123 0-224 100-224 224c0 123 101 224 224 224c123 0 224-101 224-224c0-124-101-224-224-224m-64 256c18 0 32 21 32 48c0 26-14 48-32 48c-18 0-32-22-32-48c0-27 14-48 32-48m128 0c18 0 32 21 32 48c0 26-14 48-32 48c-18 0-32-22-32-48c0-27 14-48 32-48m-200-115c28-46 78-77 136-77c58 0 108 31 136 77c9 16 16 33 19 51l-310 0c3-18 10-35 19-51"/>
<glyph unicode="&#57442;" d="m485 415l-5 1l-448 0l-3-1l227-202z m25-20l-161-143l159-139c2 5 4 9 4 15l0 256c0 4-1 7-2 11m-508 1c-1-3-2-8-2-12l0-256c0-5 1-9 3-13l161 138z m254-225l-68 60l-158-135l2 0l447 0l-155 135z"/>
</font></defs></svg> </font></defs></svg>

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before After
Before After

View file

@ -495,12 +495,7 @@ Enums.InterfaceAnimation = {
Enums.ContactScopeType = { Enums.ContactScopeType = {
'Default': 0, 'Default': 0,
'ShareAll': 2
'Auto': 1,
'ShareAll': 2,
'ShareDomain': 3,
'ShareEmail': 4
}; };
/** /**
@ -1316,6 +1311,7 @@ Utils.initDataConstructorBySettings = function (oData)
oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html); oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html);
oData.showImages = ko.observable(false); oData.showImages = ko.observable(false);
oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full); oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full);
oData.contactsAutosave = ko.observable(false);
Globals.sAnimationType = Enums.InterfaceAnimation.Full; Globals.sAnimationType = Enums.InterfaceAnimation.Full;
@ -5319,6 +5315,7 @@ function AdminContacts()
this.defautOptionsAfterRender = Utils.defautOptionsAfterRender; this.defautOptionsAfterRender = Utils.defautOptionsAfterRender;
this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable')); this.enableContacts = ko.observable(!!RL.settingsGet('ContactsEnable'));
this.contactsSharing = ko.observable(!!RL.settingsGet('ContactsSharing'));
var var
aTypes = ['sqlite', 'mysql', 'pgsql'], aTypes = ['sqlite', 'mysql', 'pgsql'],
@ -5487,6 +5484,12 @@ AdminContacts.prototype.onBuild = function ()
}); });
}); });
self.contactsSharing.subscribe(function (bValue) {
RL.remote().saveAdminConfig(null, {
'ContactsSharing': bValue ? '1' : '0'
});
});
self.contactsType.subscribe(function (sValue) { self.contactsType.subscribe(function (sValue) {
RL.remote().saveAdminConfig(f5, { RL.remote().saveAdminConfig(f5, {
'ContactsPdoType': sValue 'ContactsPdoType': sValue
@ -6094,6 +6097,7 @@ AbstractData.prototype.populateDataOnStart = function()
this.editorDefaultType(RL.settingsGet('EditorDefaultType')); this.editorDefaultType(RL.settingsGet('EditorDefaultType'));
this.showImages(!!RL.settingsGet('ShowImages')); this.showImages(!!RL.settingsGet('ShowImages'));
this.contactsAutosave(!!RL.settingsGet('ContactsAutosave'));
this.interfaceAnimation(RL.settingsGet('InterfaceAnimation')); this.interfaceAnimation(RL.settingsGet('InterfaceAnimation'));
this.mainMessagesPerPage(RL.settingsGet('MPP')); this.mainMessagesPerPage(RL.settingsGet('MPP'));

File diff suppressed because one or more lines are too long

View file

@ -495,12 +495,7 @@ Enums.InterfaceAnimation = {
Enums.ContactScopeType = { Enums.ContactScopeType = {
'Default': 0, 'Default': 0,
'ShareAll': 2
'Auto': 1,
'ShareAll': 2,
'ShareDomain': 3,
'ShareEmail': 4
}; };
/** /**
@ -1316,6 +1311,7 @@ Utils.initDataConstructorBySettings = function (oData)
oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html); oData.editorDefaultType = ko.observable(Enums.EditorDefaultType.Html);
oData.showImages = ko.observable(false); oData.showImages = ko.observable(false);
oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full); oData.interfaceAnimation = ko.observable(Enums.InterfaceAnimation.Full);
oData.contactsAutosave = ko.observable(false);
Globals.sAnimationType = Enums.InterfaceAnimation.Full; Globals.sAnimationType = Enums.InterfaceAnimation.Full;
@ -5792,7 +5788,6 @@ function ContactModel()
this.properties = []; this.properties = [];
this.readOnly = false; this.readOnly = false;
this.scopeType = Enums.ContactScopeType.Default; this.scopeType = Enums.ContactScopeType.Default;
this.scopeValue = '';
this.checked = ko.observable(false); this.checked = ko.observable(false);
this.selected = ko.observable(false); this.selected = ko.observable(false);
@ -5843,7 +5838,6 @@ ContactModel.prototype.parse = function (oItem)
this.display = Utils.pString(oItem['Display']); this.display = Utils.pString(oItem['Display']);
this.readOnly = !!oItem['ReadOnly']; this.readOnly = !!oItem['ReadOnly'];
this.scopeType = Utils.pInt(oItem['ScopeType']); this.scopeType = Utils.pInt(oItem['ScopeType']);
this.scopeValue = Utils.pString(oItem['ScopeValue']);
if (Utils.isNonEmptyArray(oItem['Properties'])) if (Utils.isNonEmptyArray(oItem['Properties']))
{ {
@ -5855,10 +5849,7 @@ ContactModel.prototype.parse = function (oItem)
}, this); }, this);
} }
this.shared(-1 < Utils.inArray(this.scopeType, [ this.shared(Enums.ContactScopeType.ShareAll === this.scopeType);
Enums.ContactScopeType.ShareAll, Enums.ContactScopeType.ShareDomain, Enums.ContactScopeType.ShareEmail
]));
bResult = true; bResult = true;
} }
@ -5911,14 +5902,22 @@ ContactModel.prototype.lineAsCcc = function ()
* @param {number=} iType = Enums.ContactPropertyType.Unknown * @param {number=} iType = Enums.ContactPropertyType.Unknown
* @param {string=} sValue = '' * @param {string=} sValue = ''
* @param {boolean=} bFocused = false * @param {boolean=} bFocused = false
* @param {string=} sPlaceholder = ''
* *
* @constructor * @constructor
*/ */
function ContactPropertyModel(iType, sValue, bFocused) function ContactPropertyModel(iType, sValue, bFocused, sPlaceholder)
{ {
this.type = ko.observable(Utils.isUnd(iType) ? Enums.ContactPropertyType.Unknown : iType); this.type = ko.observable(Utils.isUnd(iType) ? Enums.ContactPropertyType.Unknown : iType);
this.focused = ko.observable(Utils.isUnd(bFocused) ? false : !!bFocused); this.focused = ko.observable(Utils.isUnd(bFocused) ? false : !!bFocused);
this.value = ko.observable(Utils.pString(sValue)); this.value = ko.observable(Utils.pString(sValue));
this.placeholder = ko.observable(sPlaceholder || '');
this.placeholderValue = ko.computed(function () {
var sPlaceholder = this.placeholder();
return sPlaceholder ? Utils.i18n(sPlaceholder) : '';
}, this);
} }
/** /**
@ -9308,8 +9307,8 @@ function PopupsContactsViewModel()
KnoinAbstractViewModel.call(this, 'Popups', 'PopupsContacts'); KnoinAbstractViewModel.call(this, 'Popups', 'PopupsContacts');
var var
oT = Enums.ContactPropertyType,
self = this, self = this,
oT = Enums.ContactPropertyType,
aNameTypes = [oT.FullName, oT.FirstName, oT.SurName, oT.MiddleName], aNameTypes = [oT.FullName, oT.FirstName, oT.SurName, oT.MiddleName],
aEmailTypes = [oT.EmailPersonal, oT.EmailBussines, oT.EmailOther], aEmailTypes = [oT.EmailPersonal, oT.EmailBussines, oT.EmailOther],
aPhonesTypes = [ aPhonesTypes = [
@ -9333,6 +9332,8 @@ function PopupsContactsViewModel()
this.contacts.loading = ko.observable(false).extend({'throttle': 200}); this.contacts.loading = ko.observable(false).extend({'throttle': 200});
this.currentContact = ko.observable(null); this.currentContact = ko.observable(null);
this.contactsSharingIsAllowed = !!RL.settingsGet('ContactsSharingIsAllowed');
this.contactsPage = ko.observable(1); this.contactsPage = ko.observable(1);
this.contactsPageCount = ko.computed(function () { this.contactsPageCount = ko.computed(function () {
var iPage = Math.ceil(this.contactsCount() / Consts.Defaults.ContactsPerPage); var iPage = Math.ceil(this.contactsCount() / Consts.Defaults.ContactsPerPage);
@ -9347,9 +9348,10 @@ function PopupsContactsViewModel()
this.viewID = ko.observable(''); this.viewID = ko.observable('');
this.viewReadOnly = ko.observable(false); this.viewReadOnly = ko.observable(false);
this.viewScopeType = ko.observable(Enums.ContactScopeType.Default); this.viewScopeType = ko.observable(Enums.ContactScopeType.Default);
this.viewScopeValue = ko.observable('');
this.viewProperties = ko.observableArray([]); this.viewProperties = ko.observableArray([]);
this.viewSaveTrigger = ko.observable(Enums.SaveSettingsStep.Idle);
this.viewPropertiesNames = this.viewProperties.filter(function(oProperty) { this.viewPropertiesNames = this.viewProperties.filter(function(oProperty) {
return -1 < Utils.inArray(oProperty.type(), aNameTypes); return -1 < Utils.inArray(oProperty.type(), aNameTypes);
}); });
@ -9358,24 +9360,18 @@ function PopupsContactsViewModel()
return -1 < Utils.inArray(oProperty.type(), aEmailTypes); return -1 < Utils.inArray(oProperty.type(), aEmailTypes);
}); });
this.shareIcon = ko.computed(function() {
return Enums.ContactScopeType.ShareAll === this.viewScopeType() ? 'icon-earth' : 'icon-share';
}, this);
this.shareToNone = ko.computed(function() { this.shareToNone = ko.computed(function() {
return -1 === Utils.inArray(this.viewScopeType(), [ return Enums.ContactScopeType.ShareAll !== this.viewScopeType();
Enums.ContactScopeType.ShareAll, Enums.ContactScopeType.ShareDomain, Enums.ContactScopeType.ShareEmail
]);
}, this); }, this);
this.shareToAll = ko.computed(function() { this.shareToAll = ko.computed(function() {
return Enums.ContactScopeType.ShareAll === this.viewScopeType(); return Enums.ContactScopeType.ShareAll === this.viewScopeType();
}, this); }, this);
this.shareToDomain = ko.computed(function() {
return Enums.ContactScopeType.ShareDomain === this.viewScopeType();
}, this);
this.shareToEmail = ko.computed(function() {
return Enums.ContactScopeType.ShareEmail === this.viewScopeType();
}, this);
this.viewHasNonEmptyRequaredProperties = ko.computed(function() { this.viewHasNonEmptyRequaredProperties = ko.computed(function() {
var var
@ -9397,6 +9393,10 @@ function PopupsContactsViewModel()
return -1 < Utils.inArray(oProperty.type(), aOtherTypes); return -1 < Utils.inArray(oProperty.type(), aOtherTypes);
}); });
this.viewPropertiesEmailsNonEmpty = this.viewPropertiesNames.filter(function(oProperty) {
return '' !== Utils.trim(oProperty.value());
});
this.viewPropertiesEmailsEmptyAndOnFocused = this.viewPropertiesEmails.filter(function(oProperty) { this.viewPropertiesEmailsEmptyAndOnFocused = this.viewPropertiesEmails.filter(function(oProperty) {
var bF = oProperty.focused(); var bF = oProperty.focused();
return '' === Utils.trim(oProperty.value()) && !bF; return '' === Utils.trim(oProperty.value()) && !bF;
@ -9522,6 +9522,7 @@ function PopupsContactsViewModel()
this.saveCommand = Utils.createCommand(this, function () { this.saveCommand = Utils.createCommand(this, function () {
this.viewSaving(true); this.viewSaving(true);
this.viewSaveTrigger(Enums.SaveSettingsStep.Animate);
var var
sRequestUid = Utils.fakeMd5(), sRequestUid = Utils.fakeMd5(),
@ -9537,7 +9538,9 @@ function PopupsContactsViewModel()
RL.remote().contactSave(function (sResult, oData) { RL.remote().contactSave(function (sResult, oData) {
var bRes = false;
self.viewSaving(false); self.viewSaving(false);
if (Enums.StorageResultType.Success === sResult && oData && oData.Result && if (Enums.StorageResultType.Success === sResult && oData && oData.Result &&
oData.Result.RequestUid === sRequestUid && 0 < Utils.pInt(oData.Result.ResultID)) oData.Result.RequestUid === sRequestUid && 0 < Utils.pInt(oData.Result.ResultID))
{ {
@ -9547,13 +9550,25 @@ function PopupsContactsViewModel()
} }
self.reloadContactList(); self.reloadContactList();
bRes = true;
} }
// else // else
// { // {
// // TODO // // TODO
// } // }
}, sRequestUid, this.viewID(), aProperties); _.delay(function () {
self.viewSaveTrigger(bRes ? Enums.SaveSettingsStep.TrueResult : Enums.SaveSettingsStep.FalseResult);
}, 300);
if (bRes)
{
_.delay(function () {
self.viewSaveTrigger(Enums.SaveSettingsStep.Idle);
}, 1000);
}
}, sRequestUid, this.viewID(), this.viewScopeType(), aProperties);
}, function () { }, function () {
var var
@ -9565,11 +9580,36 @@ function PopupsContactsViewModel()
this.bDropPageAfterDelete = false; this.bDropPageAfterDelete = false;
this.watchHash = ko.observable(false);
this.viewHash = ko.computed(function () {
return '' + self.viewScopeType() + ' - ' + _.map(self.viewProperties(), function (oItem) {
return oItem.value();
}).join('');
});
this.saveCommandDebounce = _.debounce(_.bind(this.saveCommand, this), 1000);
this.viewHash.subscribe(function () {
if (this.watchHash() && !this.viewReadOnly())
{
this.saveCommandDebounce();
}
}, this);
Knoin.constructorEnd(this); Knoin.constructorEnd(this);
} }
Utils.extendAsViewModel('PopupsContactsViewModel', PopupsContactsViewModel); Utils.extendAsViewModel('PopupsContactsViewModel', PopupsContactsViewModel);
PopupsContactsViewModel.prototype.setShareToNone = function ()
{
this.viewScopeType(Enums.ContactScopeType.Default);
};
PopupsContactsViewModel.prototype.setShareToAll = function ()
{
this.viewScopeType(Enums.ContactScopeType.ShareAll);
};
PopupsContactsViewModel.prototype.addNewProperty = function (sType) PopupsContactsViewModel.prototype.addNewProperty = function (sType)
{ {
@ -9676,10 +9716,11 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
aList = [] aList = []
; ;
this.watchHash(false);
this.emptySelection(false); this.emptySelection(false);
this.viewReadOnly(false); this.viewReadOnly(false);
this.viewScopeType(Enums.ContactScopeType.Default); this.viewScopeType(Enums.ContactScopeType.Default);
this.viewScopeValue('');
if (oContact) if (oContact)
{ {
@ -9690,7 +9731,9 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
_.each(oContact.properties, function (aProperty) { _.each(oContact.properties, function (aProperty) {
if (aProperty && aProperty[0]) if (aProperty && aProperty[0])
{ {
aList.push(new ContactPropertyModel(aProperty[0], aProperty[1])); aList.push(new ContactPropertyModel(aProperty[0], aProperty[1], false,
Enums.ContactPropertyType.FullName === aProperty[0] ? 'CONTACTS/PLACEHOLDER_ENTER_DISPLAY_NAME' : ''));
if (Enums.ContactPropertyType.FullName === aProperty[0]) if (Enums.ContactPropertyType.FullName === aProperty[0])
{ {
bHasName = true; bHasName = true;
@ -9701,17 +9744,18 @@ PopupsContactsViewModel.prototype.populateViewContact = function (oContact)
this.viewReadOnly(!!oContact.readOnly); this.viewReadOnly(!!oContact.readOnly);
this.viewScopeType(oContact.scopeType); this.viewScopeType(oContact.scopeType);
this.viewScopeValue(oContact.scopeValue);
} }
if (!bHasName) if (!bHasName)
{ {
aList.push(new ContactPropertyModel(Enums.ContactPropertyType.FullName, '', true)); aList.push(new ContactPropertyModel(Enums.ContactPropertyType.FullName, '', !oContact, 'CONTACTS/PLACEHOLDER_ENTER_DISPLAY_NAME'));
} }
this.viewID(sId); this.viewID(sId);
this.viewProperties([]); this.viewProperties([]);
this.viewProperties(aList); this.viewProperties(aList);
this.watchHash(true);
}; };
/** /**
@ -9745,7 +9789,7 @@ PopupsContactsViewModel.prototype.reloadContactList = function (bDropPagePositio
{ {
aList = _.map(oData.Result.List, function (oItem) { aList = _.map(oData.Result.List, function (oItem) {
var oContact = new ContactModel(); var oContact = new ContactModel();
return oContact.parse(oItem) ? oContact : null; return oContact.parse(oItem, self.contactsSharingIsAllowed) ? oContact : null;
}); });
aList = _.compact(aList); aList = _.compact(aList);
@ -12185,6 +12229,7 @@ function SettingsGeneral()
this.mainMessagesPerPageArray = Consts.Defaults.MessagesPerPageArray; this.mainMessagesPerPageArray = Consts.Defaults.MessagesPerPageArray;
this.editorDefaultType = oData.editorDefaultType; this.editorDefaultType = oData.editorDefaultType;
this.showImages = oData.showImages; this.showImages = oData.showImages;
this.contactsAutosave = oData.contactsAutosave;
this.interfaceAnimation = oData.interfaceAnimation; this.interfaceAnimation = oData.interfaceAnimation;
this.useDesktopNotifications = oData.useDesktopNotifications; this.useDesktopNotifications = oData.useDesktopNotifications;
this.threading = oData.threading; this.threading = oData.threading;
@ -12268,6 +12313,12 @@ SettingsGeneral.prototype.onBuild = function ()
}); });
}); });
oData.contactsAutosave.subscribe(function (bValue) {
RL.remote().saveSettings(Utils.emptyFunction, {
'ContactsAutosave': bValue ? '1' : '0'
});
});
oData.interfaceAnimation.subscribe(function (sValue) { oData.interfaceAnimation.subscribe(function (sValue) {
RL.remote().saveSettings(Utils.emptyFunction, { RL.remote().saveSettings(Utils.emptyFunction, {
'InterfaceAnimation': sValue 'InterfaceAnimation': sValue
@ -13148,6 +13199,7 @@ AbstractData.prototype.populateDataOnStart = function()
this.editorDefaultType(RL.settingsGet('EditorDefaultType')); this.editorDefaultType(RL.settingsGet('EditorDefaultType'));
this.showImages(!!RL.settingsGet('ShowImages')); this.showImages(!!RL.settingsGet('ShowImages'));
this.contactsAutosave(!!RL.settingsGet('ContactsAutosave'));
this.interfaceAnimation(RL.settingsGet('InterfaceAnimation')); this.interfaceAnimation(RL.settingsGet('InterfaceAnimation'));
this.mainMessagesPerPage(RL.settingsGet('MPP')); this.mainMessagesPerPage(RL.settingsGet('MPP'));
@ -14968,11 +15020,12 @@ WebMailAjaxRemoteStorage.prototype.contacts = function (fCallback, iOffset, iLim
/** /**
* @param {?Function} fCallback * @param {?Function} fCallback
*/ */
WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, aProperties) WebMailAjaxRemoteStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, nScopeType, aProperties)
{ {
this.defaultRequest(fCallback, 'ContactSave', { this.defaultRequest(fCallback, 'ContactSave', {
'RequestUid': sRequestUid, 'RequestUid': sRequestUid,
'Uid': Utils.trim(sUid), 'Uid': Utils.trim(sUid),
'ScopeType': nScopeType,
'Properties': aProperties 'Properties': aProperties
}); });
}; };

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -77,8 +77,6 @@
<glyph unicode="&#57411;" d="m480 288c-18 0-32-14-32-32l0-192l-384 0l0 192c0 18-14 32-32 32c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32z m-192 0l0 196c0 15-14 28-32 28c-18 0-32-13-32-28l0-196l-96 0l128-128l128 128z"/> <glyph unicode="&#57411;" d="m480 288c-18 0-32-14-32-32l0-192l-384 0l0 192c0 18-14 32-32 32c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32z m-192 0l0 196c0 15-14 28-32 28c-18 0-32-13-32-28l0-196l-96 0l128-128l128 128z"/>
<glyph unicode="&#57412;" d="m480 288c-18 0-32-14-32-32l0-192l-384 0l0 192c0 18-14 32-32 32c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32z m-256-96c0-18 14-32 32-32c18 0 32 14 32 32l0 192l96 0l-128 128l-128-128l96 0z"/> <glyph unicode="&#57412;" d="m480 288c-18 0-32-14-32-32l0-192l-384 0l0 192c0 18-14 32-32 32c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32z m-256-96c0-18 14-32 32-32c18 0 32 14 32 32l0 192l96 0l-128 128l-128-128l96 0z"/>
<glyph unicode="&#57413;" d="m485 238c0-5-2-10-6-13c-3-4-8-6-13-6l-64 0c0-32-6-60-19-82l60-60c3-4 5-8 5-13c0-5-2-9-5-13c-4-3-8-5-13-5c-5 0-10 2-13 5l-57 56c-1-1-2-2-4-3c-2-2-6-5-12-8c-6-4-12-8-19-11c-6-3-14-6-23-8c-9-3-19-4-28-4l0 256l-36 0l0-256c-10 0-20 1-29 4c-10 3-18 6-25 9c-7 4-13 8-19 12c-6 3-10 6-12 9l-5 4l-52-59c-4-4-8-6-14-6c-4 0-8 1-12 4c-4 4-6 8-6 13c0 5 1 9 5 13l57 65c-11 22-16 48-16 78l-64 0c-5 0-10 2-13 6c-4 3-6 8-6 13c0 5 2 9 6 13c3 3 8 5 13 5l64 0l0 84l-50 49c-3 4-5 8-5 13c0 5 2 10 5 13c4 4 8 6 13 6c5 0 9-2 13-6l49-49l242 0l49 49c4 4 8 6 13 6c5 0 9-2 13-6c3-3 5-8 5-13c0-5-2-9-5-13l-50-49l0-84l64 0c5 0 10-2 13-5c4-4 6-8 6-13z m-138 164l-182 0c0 26 8 47 26 65c18 18 40 27 65 27c25 0 47-9 65-27c18-18 26-39 26-65z"/> <glyph unicode="&#57413;" d="m485 238c0-5-2-10-6-13c-3-4-8-6-13-6l-64 0c0-32-6-60-19-82l60-60c3-4 5-8 5-13c0-5-2-9-5-13c-4-3-8-5-13-5c-5 0-10 2-13 5l-57 56c-1-1-2-2-4-3c-2-2-6-5-12-8c-6-4-12-8-19-11c-6-3-14-6-23-8c-9-3-19-4-28-4l0 256l-36 0l0-256c-10 0-20 1-29 4c-10 3-18 6-25 9c-7 4-13 8-19 12c-6 3-10 6-12 9l-5 4l-52-59c-4-4-8-6-14-6c-4 0-8 1-12 4c-4 4-6 8-6 13c0 5 1 9 5 13l57 65c-11 22-16 48-16 78l-64 0c-5 0-10 2-13 6c-4 3-6 8-6 13c0 5 2 9 6 13c3 3 8 5 13 5l64 0l0 84l-50 49c-3 4-5 8-5 13c0 5 2 10 5 13c4 4 8 6 13 6c5 0 9-2 13-6l49-49l242 0l49 49c4 4 8 6 13 6c5 0 9-2 13-6c3-3 5-8 5-13c0-5-2-9-5-13l-50-49l0-84l64 0c5 0 10-2 13-5c4-4 6-8 6-13z m-138 164l-182 0c0 26 8 47 26 65c18 18 40 27 65 27c25 0 47-9 65-27c18-18 26-39 26-65z"/>
<glyph unicode="&#57414;" d="m440 407c24-22 36-49 36-80c0-32-12-59-36-81c0 0-184-169-184-169c0 0-184 169-184 169c-24 22-36 49-36 81c0 31 12 58 36 80c21 19 47 29 77 29c30 0 56-10 78-29c0 0 29-27 29-27c0 0 30 27 30 27c21 19 46 29 76 29c31 0 56-10 78-29"/>
<glyph unicode="&#57415;" d="m440 406c24-22 36-49 36-80c0-32-12-58-36-80c0 0-184-169-184-169c0 0-184 169-184 169c-24 22-36 48-36 80c0 31 12 58 36 80c22 19 47 29 78 29c30 0 55-10 76-29c0 0 30-27 30-27c0 0 29 27 29 27c22 19 47 29 77 29c31 0 56-10 78-29m-27-134c14 14 21 32 21 54c0 22-6 39-19 51c-13 13-31 19-53 19c-17 0-35-8-53-24c0 0-53-47-53-47c0 0-54 47-54 47c-17 16-34 24-52 24c-22 0-40-6-54-19c-13-12-19-30-19-51c0-23 7-41 22-54c0 0 157-146 157-146c0 0 157 146 157 146"/>
<glyph unicode="&#57416;" d="m410 461c14 0 26-5 36-15c10-10 15-22 15-36c0 0 0-205 0-205c0-14-5-26-15-36c-10-10-22-15-36-15c0 0-205 0-205 0c-14 0-26 5-36 15c-10 10-15 22-15 36c0 0 0 206 0 206c0 13 5 25 14 35c10 10 22 15 37 15c0 0 205 0 205 0m0-256c0 0 0 205 0 205c0 0-205 0-205 0c0 0 0-205 0-205c0 0 205 0 205 0m-308 51c0 0 0-154 0-154c0 0 154 0 154 0c0 0 0-51 0-51c0 0-154 0-154 0c-13 0-25 5-35 16c-11 10-16 22-16 35c0 0 0 154 0 154c0 0 51 0 51 0"/> <glyph unicode="&#57416;" d="m410 461c14 0 26-5 36-15c10-10 15-22 15-36c0 0 0-205 0-205c0-14-5-26-15-36c-10-10-22-15-36-15c0 0-205 0-205 0c-14 0-26 5-36 15c-10 10-15 22-15 36c0 0 0 206 0 206c0 13 5 25 14 35c10 10 22 15 37 15c0 0 205 0 205 0m0-256c0 0 0 205 0 205c0 0-205 0-205 0c0 0 0-205 0-205c0 0 205 0 205 0m-308 51c0 0 0-154 0-154c0 0 154 0 154 0c0 0 0-51 0-51c0 0-154 0-154 0c-13 0-25 5-35 16c-11 10-16 22-16 35c0 0 0 154 0 154c0 0 51 0 51 0"/>
<glyph unicode="&#57417;" d="m0 512l0-512l512 0l0 512z m480-480l-448 0l0 448l448 0z m-96 368l-160-160l-96 96l-64-64l160-160l224 224z"/> <glyph unicode="&#57417;" d="m0 512l0-512l512 0l0 512z m480-480l-448 0l0 448l448 0z m-96 368l-160-160l-96 96l-64-64l160-160l224 224z"/>
<glyph unicode="&#57418;" d="m0 512l0-512l512 0l0 512z m480-480l-448 0l0 448l448 0z"/> <glyph unicode="&#57418;" d="m0 512l0-512l512 0l0 512z m480-480l-448 0l0 448l448 0z"/>
@ -86,21 +84,24 @@
<glyph unicode="&#57420;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256z m0-448c-106 0-192 86-192 192c0 106 86 192 192 192c106 0 192-86 192-192c0-106-86-192-192-192z m-96 192c0 53 43 96 96 96c53 0 96-43 96-96c0-53-43-96-96-96c-53 0-96 43-96 96z"/> <glyph unicode="&#57420;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256z m0-448c-106 0-192 86-192 192c0 106 86 192 192 192c106 0 192-86 192-192c0-106-86-192-192-192z m-96 192c0 53 43 96 96 96c53 0 96-43 96-96c0-53-43-96-96-96c-53 0-96 43-96 96z"/>
<glyph unicode="&#57421;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256z m0-448c-106 0-192 86-192 192c0 106 86 192 192 192c106 0 192-86 192-192c0-106-86-192-192-192z"/> <glyph unicode="&#57421;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256z m0-448c-106 0-192 86-192 192c0 106 86 192 192 192c106 0 192-86 192-192c0-106-86-192-192-192z"/>
<glyph unicode="&#57422;" d="m230 182l-86-148l283 0l85 148z m258 42l-147 254l-170 0l146-254z m-342 212l-146-254l85-148l147 254z"/> <glyph unicode="&#57422;" d="m230 182l-86-148l283 0l85 148z m258 42l-147 254l-170 0l146-254z m-342 212l-146-254l85-148l147 254z"/>
<glyph unicode="&#57423;" d="m256 512c-139 0-253-111-256-250c3 121 95 218 208 218c115 0 208-100 208-224c0-27 21-48 48-48c27 0 48 21 48 48c0 141-115 256-256 256z m0-512c139 0 253 111 256 250c-3-121-95-218-208-218c-115 0-208 100-208 224c0 27-21 48-48 48c-27 0-48-21-48-48c0-141 115-256 256-256z"/> <glyph unicode="&#57423;" d="m446 256c0 51-22 100-56 134c-34 34-83 56-134 56c-51 0-100-22-134-56c-34-34-56-83-56-134c0-83 55-156 133-181l0 50c-11-1-17-2-20-2c-22 0-37 10-46 30c-3 7-6 13-10 19c-1 1-3 2-7 5c-3 3-6 5-8 7c-3 2-4 4-4 5c0 2 3 4 9 4c11 0 20-7 26-15c6-8 12-17 22-23c4-3 10-4 16-4c8 0 16 1 24 4c3 11 10 20 19 26c-66 7-97 30-97 92c0 23 7 43 22 58c-3 9-4 17-4 25c0 12 2 22 8 32c22 0 37-7 60-23c15 3 31 5 50 5c15 0 30-1 45-5c22 16 37 23 59 23c6-10 8-20 8-32c0-8-1-16-4-24c15-17 22-36 22-59c0-62-31-86-97-92c14-9 21-22 21-39l0-67c78 25 133 98 133 181z m7 114c20-35 31-73 31-114c0-83-44-156-114-197c-35-20-73-31-114-31c-83 0-156 44-197 114c-20 35-31 73-31 114c0 83 44 156 114 197c35 20 73 31 114 31c83 0 156-44 197-114z"/>
<glyph unicode="&#57424;" d="m446 256c0 51-22 100-56 134c-34 34-83 56-134 56c-51 0-100-22-134-56c-34-34-56-83-56-134c0-83 55-156 133-181l0 50c-11-1-17-2-20-2c-22 0-37 10-46 30c-3 7-6 13-10 19c-1 1-3 2-7 5c-3 3-6 5-8 7c-3 2-4 4-4 5c0 2 3 4 9 4c11 0 20-7 26-15c6-8 12-17 22-23c4-3 10-4 16-4c8 0 16 1 24 4c3 11 10 20 19 26c-66 7-97 30-97 92c0 23 7 43 22 58c-3 9-4 17-4 25c0 12 2 22 8 32c22 0 37-7 60-23c15 3 31 5 50 5c15 0 30-1 45-5c22 16 37 23 59 23c6-10 8-20 8-32c0-8-1-16-4-24c15-17 22-36 22-59c0-62-31-86-97-92c14-9 21-22 21-39l0-67c78 25 133 98 133 181z m7 114c20-35 31-73 31-114c0-83-44-156-114-197c-35-20-73-31-114-31c-83 0-156 44-197 114c-20 35-31 73-31 114c0 83 44 156 114 197c35 20 73 31 114 31c83 0 156-44 197-114z"/> <glyph unicode="&#57424;" d="m435 152c-1 6-4 10-9 13l-74 43l0 0c-3 2-7 3-10 3c-6 0-12-3-16-7l-22-21c-1-1-4-2-5-3c0 0-25 2-71 48c-46 46-48 71-48 71c0 1 2 4 3 5l18 19c7 6 8 17 5 26l-41 76c-3 6-9 10-15 10c-5 0-9-2-13-5l-50-50c-5-5-9-14-10-20c0-4-9-81 97-186c89-90 159-97 179-97c4 0 6 0 7 0c6 1 15 5 20 10l50 50c4 5 6 10 5 15z"/>
<glyph unicode="&#57425;" d="m435 152c-1 6-4 10-9 13l-74 43l0 0c-3 2-7 3-10 3c-6 0-12-3-16-7l-22-21c-1-1-4-2-5-3c0 0-25 2-71 48c-46 46-48 71-48 71c0 1 2 4 3 5l18 19c7 6 8 17 5 26l-41 76c-3 6-9 10-15 10c-5 0-9-2-13-5l-50-50c-5-5-9-14-10-20c0-4-9-81 97-186c89-90 159-97 179-97c4 0 6 0 7 0c6 1 15 5 20 10l50 50c4 5 6 10 5 15z"/> <glyph unicode="&#57425;" d="m279 110c0 6-2 11-7 16c-4 4-10 7-16 7c-6 0-12-3-16-7c-5-5-7-10-7-16c0-7 2-12 7-16c4-5 10-7 16-7c6 0 12 2 16 7c5 4 7 9 7 16z m59 45l0 202c0 2-1 4-2 6c-2 2-4 3-7 3l-146 0c-3 0-5-1-7-3c-1-2-2-4-2-6l0-202c0-2 1-4 2-6c2-2 4-3 7-3l146 0c3 0 5 1 7 3c1 2 2 4 2 6z m-55 243c0 3-1 4-4 4l-46 0c-3 0-4-1-4-4c0-3 1-5 4-5l46 0c3 0 4 2 4 5z m83 4l0-292c0-10-4-19-11-26c-7-7-16-11-26-11l-146 0c-10 0-19 4-26 11c-7 7-11 16-11 26l0 292c0 10 4 19 11 26c7 7 16 11 26 11l146 0c10 0 19-4 26-11c7-7 11-16 11-26z"/>
<glyph unicode="&#57426;" d="m279 110c0 6-2 11-7 16c-4 4-10 7-16 7c-6 0-12-3-16-7c-5-5-7-10-7-16c0-7 2-12 7-16c4-5 10-7 16-7c6 0 12 2 16 7c5 4 7 9 7 16z m59 45l0 202c0 2-1 4-2 6c-2 2-4 3-7 3l-146 0c-3 0-5-1-7-3c-1-2-2-4-2-6l0-202c0-2 1-4 2-6c2-2 4-3 7-3l146 0c3 0 5 1 7 3c1 2 2 4 2 6z m-55 243c0 3-1 4-4 4l-46 0c-3 0-4-1-4-4c0-3 1-5 4-5l46 0c3 0 4 2 4 5z m83 4l0-292c0-10-4-19-11-26c-7-7-16-11-26-11l-146 0c-10 0-19 4-26 11c-7 7-11 16-11 26l0 292c0 10 4 19 11 26c7 7 16 11 26 11l146 0c10 0 19-4 26-11c7-7 11-16 11-26z"/> <glyph unicode="&#57426;" d="m11 78l-11-78l79 11l78 11l-67 68l-68 67z m168 12l-22 22l202 202l-45 45l-202-202l-23 23l202 202l-22 22l-224-224l134-135l224 225l-22 22z m294 290l-90 90c-12 12-32 13-44 1l-2-3l0 0l-43-43l134-134l43 43l0 0l3 2c12 12 12 32-1 44"/>
<glyph unicode="&#57427;" d="m269 232l189 193c-3 1-7 2-10 2l-384 0c-3 0-6-1-10-2l190-193c6-6 18-6 25 0z m25-26c-10-10-24-16-38-16c-14 0-28 5-38 16l-189 192c0-3 0-5 0-8l0-268c0-20 16-37 35-37l384 0c19 0 35 17 35 37l0 268c0 3 0 5 0 8z"/> <glyph unicode="&#57427;" d="m480 403c-2 25-23 45-48 45l-48 0l0 16c0 26-22 48-48 48l-160 0c-27 0-48-22-48-48l0-16l-48 0c-26 0-46-20-48-45l0 0l0-35c0-18 14-32 32-32l0-272c0-35 29-64 64-64l256 0c35 0 64 29 64 64l0 272c18 0 32 14 32 32l0 35z m-320 61c0 9 7 16 16 16l160 0c9 0 16-7 16-16l0-16l-192 0z m256-400c0-18-14-32-32-32l-256 0c-18 0-32 14-32 32l0 272l320 0z m32 320l0-16l-384 0l0 32c0 9 7 16 16 16l352 0c9 0 16-7 16-16z m-304-320l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z m96-224l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z m96-224l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z"/>
<glyph unicode="&#57428;" d="m11 78l-11-78l79 11l78 11l-67 68l-68 67z m168 12l-22 22l202 202l-45 45l-202-202l-23 23l202 202l-22 22l-224-224l134-135l224 225l-22 22z m294 290l-90 90c-12 12-32 13-44 1l-2-3l0 0l-43-43l134-134l43 43l0 0l3 2c12 12 12 32-1 44"/> <glyph unicode="&#57428;" d="m293 397c4 6 11 9 20 9c8 0 15-3 21-9c13-12 13-26 0-41c0 0-96-100-96-100c0 0 96-99 96-99c13-15 13-29 0-41c-6-6-13-8-21-8c-8 0-15 2-20 8c0 0-116 121-116 121c-6 5-8 11-8 19c0 8 2 15 8 20c70 74 109 114 116 121"/>
<glyph unicode="&#57429;" d="m480 403c-2 25-23 45-48 45l-48 0l0 16c0 26-22 48-48 48l-160 0c-27 0-48-22-48-48l0-16l-48 0c-26 0-46-20-48-45l0 0l0-35c0-18 14-32 32-32l0-272c0-35 29-64 64-64l256 0c35 0 64 29 64 64l0 272c18 0 32 14 32 32l0 35z m-320 61c0 9 7 16 16 16l160 0c9 0 16-7 16-16l0-16l-192 0z m256-400c0-18-14-32-32-32l-256 0c-18 0-32 14-32 32l0 272l320 0z m32 320l0-16l-384 0l0 32c0 9 7 16 16 16l352 0c9 0 16-7 16-16z m-304-320l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z m96-224l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z m96-224l32 0c9 0 16 7 16 16l0 208c0 9-7 16-16 16l-32 0c-9 0-16-7-16-16l0-208c0-9 7-16 16-16z m0 224l32 0l0-208l-32 0z"/> <glyph unicode="&#57429;" d="m219 397c0 0 116-121 116-121c5-5 8-12 8-20c0-8-3-14-8-19c0 0-116-121-116-121c-5-6-12-8-20-8c-9 0-15 2-21 8c-12 12-12 26 0 41c0 0 95 99 95 99c0 0-95 100-95 100c-12 15-12 29 0 41c6 6 13 9 21 9c9 0 15-3 20-9"/>
<glyph unicode="&#57430;" d="m293 397c4 6 11 9 20 9c8 0 15-3 21-9c13-12 13-26 0-41c0 0-96-100-96-100c0 0 96-99 96-99c13-15 13-29 0-41c-6-6-13-8-21-8c-8 0-15 2-20 8c0 0-116 121-116 121c-6 5-8 11-8 19c0 8 2 15 8 20c70 74 109 114 116 121"/> <glyph unicode="&#57430;" d="m256 480c-60 0-117-24-158-66l-66 66l0-192l192 0l-81 81c30 30 70 47 113 47c88 0 160-72 160-160c0-88-72-160-160-160c-57 0-110 31-139 80l-55-32c40-69 114-112 194-112c124 0 224 101 224 224c0 123-100 224-224 224"/>
<glyph unicode="&#57431;" d="m219 397c0 0 116-121 116-121c5-5 8-12 8-20c0-8-3-14-8-19c0 0-116-121-116-121c-5-6-12-8-20-8c-9 0-15 2-21 8c-12 12-12 26 0 41c0 0 95 99 95 99c0 0-95 100-95 100c-12 15-12 29 0 41c6 6 13 9 21 9c9 0 15-3 20-9"/> <glyph unicode="&#57431;" d="m352 448c53 0 96-43 96-96c0-53-43-96-96-96c-5 0-10 1-17 2l-33 6l-24-24l-3-3l-19-19l0-26l-64 0l0-64l-64 0l0-64l-64 0l0 38l200 200l-6 33c-1 7-2 12-2 17c0 53 43 96 96 96m0 64c-88 0-160-72-160-160c0-10 1-20 3-29l-195-195l0-128l192 0l0 64l64 0l0 64l64 0l0 64l3 3c9-2 19-3 29-3c88 0 160 72 160 160c0 88-72 160-160 160z m32-160c0-18-14-32-32-32c-18 0-32 14-32 32c0 18 14 32 32 32c18 0 32-14 32-32z"/>
<glyph unicode="&#57432;" d="m256 480c-60 0-117-24-158-66l-66 66l0-192l192 0l-81 81c30 30 70 47 113 47c88 0 160-72 160-160c0-88-72-160-160-160c-57 0-110 31-139 80l-55-32c40-69 114-112 194-112c124 0 224 101 224 224c0 123-100 224-224 224"/> <glyph unicode="&#57432;" d="m420 286l-45 0l0 43c0 0 0 0 0 0c0 67-54 122-121 122c-67 0-122-55-122-122l0-43l-40 0c-8 0-14-6-14-14l0-197c0-8 6-14 14-14l328 0c8 0 14 6 14 14l0 197c0 8-6 14-14 14z m-216 43c0 28 22 50 50 50c27 0 49-22 50-49c0 0 0 0 0 0l0 0c0-1 0-1 0-1l0-43l-100 0z"/>
<glyph unicode="&#57433;" d="m352 448c53 0 96-43 96-96c0-53-43-96-96-96c-5 0-10 1-17 2l-33 6l-24-24l-3-3l-19-19l0-26l-64 0l0-64l-64 0l0-64l-64 0l0 38l200 200l-6 33c-1 7-2 12-2 17c0 53 43 96 96 96m0 64c-88 0-160-72-160-160c0-10 1-20 3-29l-195-195l0-128l192 0l0 64l64 0l0 64l64 0l0 64l3 3c9-2 19-3 29-3c88 0 160 72 160 160c0 88-72 160-160 160z m32-160c0-18-14-32-32-32c-18 0-32 14-32 32c0 18 14 32 32 32c18 0 32-14 32-32z"/> <glyph unicode="&#57433;" d="m480 249c6-6 8-10 6-14c-2-4-6-6-14-6c0 0-43 0-43 0c0 0 0-158 0-158c0-5 0-9 0-11c-1-2-2-5-4-7c-3-2-7-3-12-3c0 0-105 0-105 0c0 0 0 159 0 159c0 0-104 0-104 0c0 0 0-159 0-159c0 0-99 0-99 0c-10 0-16 2-18 5c-3 4-4 9-4 16c0 0 0 158 0 158c0 0-43 0-43 0c-7 0-12 2-14 6c-1 4 0 8 6 14c0 0 205 206 205 206c5 5 12 8 19 8c8 0 14-3 20-8c0 0 204-206 204-206"/>
<glyph unicode="&#57434;" d="m420 286l-45 0l0 43c0 0 0 0 0 0c0 67-54 122-121 122c-67 0-122-55-122-122l0-43l-40 0c-8 0-14-6-14-14l0-197c0-8 6-14 14-14l328 0c8 0 14 6 14 14l0 197c0 8-6 14-14 14z m-216 43c0 28 22 50 50 50c27 0 49-22 50-49c0 0 0 0 0 0l0 0c0-1 0-1 0-1l0-43l-100 0z"/> <glyph unicode="&#57434;" d="m37 475l0-438l438 0l0 77l-47 0l0 43l47 0l0 78l-47 0l0 42l47 0l0 78l-47 0l0 43l47 0l0 77l-438 0z m195-76c35 0 64-29 64-64c0-24-15-46-36-56l82-49l1 0l0-69l-221 0l0 69l1 0l81 49c-21 10-35 32-35 56c0 35 28 64 63 64z"/>
<glyph unicode="&#57435;" d="m480 249c6-6 8-10 6-14c-2-4-6-6-14-6c0 0-43 0-43 0c0 0 0-158 0-158c0-5 0-9 0-11c-1-2-2-5-4-7c-3-2-7-3-12-3c0 0-105 0-105 0c0 0 0 159 0 159c0 0-104 0-104 0c0 0 0-159 0-159c0 0-99 0-99 0c-10 0-16 2-18 5c-3 4-4 9-4 16c0 0 0 158 0 158c0 0-43 0-43 0c-7 0-12 2-14 6c-1 4 0 8 6 14c0 0 205 206 205 206c5 5 12 8 19 8c8 0 14-3 20-8c0 0 204-206 204-206"/> <glyph unicode="&#57435;" d="m384 179c21 0 39-7 54-22c15-14 23-33 23-55c0-21-8-39-23-54c-15-15-33-22-54-22c-21 0-39 7-54 22c-15 15-23 33-23 54c0 2 0 5 1 8c0 2 0 4 0 6c0 0-133 80-133 80c-14-11-30-17-47-17c-21 0-39 8-54 23c-15 15-23 33-23 54c0 21 8 39 23 54c15 15 33 23 54 23c18 0 34-5 47-16c0 0 133 80 133 80c0 2 0 4 0 6c-1 3-1 5-1 7c0 21 8 39 23 54c15 15 33 22 54 22c21 0 39-7 54-22c15-14 23-33 23-54c0-22-8-40-23-55c-15-15-33-22-54-22c-18 0-33 5-46 16c0 0-134-80-134-80c0-2 1-7 1-13c0-5-1-10-1-12c0 0 134-80 134-80c12 10 28 15 46 15"/>
<glyph unicode="&#57436;" d="m37 475l0-438l438 0l0 77l-47 0l0 43l47 0l0 78l-47 0l0 42l47 0l0 78l-47 0l0 43l47 0l0 77l-438 0z m195-76c35 0 64-29 64-64c0-24-15-46-36-56l82-49l1 0l0-69l-221 0l0 69l1 0l81 49c-21 10-35 32-35 56c0 35 28 64 63 64z"/> <glyph unicode="&#57436;" d="m461 410c14 0 26-6 36-16c10-10 15-22 15-36c0 0 0-281 0-281c0-15-5-27-15-37c-10-9-22-14-36-14c0 0-26 0-26 0c0 0 0 384 0 384c0 0 26 0 26 0m-461-52c0 14 5 26 15 36c11 10 23 16 36 16c0 0 26 0 26 0c0 0 0-384 0-384c0 0-26 0-26 0c-13 0-25 5-36 14c-10 10-15 22-15 37c0 0 0 281 0 281m343 105c0 0 0-53 0-53c0 0 56 0 56 0c0 0 0-384 0-384c0 0-286 0-286 0c0 0 0 384 0 384c0 0 56 0 56 0c0 0 0 53 0 53c33 16 62 23 87 23c25 0 54-7 87-23m-31-53c0 0 0 33 0 33c-17 9-36 13-56 13c-18 0-37-4-56-13c0 0 0-33 0-33c0 0 112 0 112 0"/>
<glyph unicode="&#57437;" d="m384 179c21 0 39-7 54-22c15-14 23-33 23-55c0-21-8-39-23-54c-15-15-33-22-54-22c-21 0-39 7-54 22c-15 15-23 33-23 54c0 2 0 5 1 8c0 2 0 4 0 6c0 0-133 80-133 80c-14-11-30-17-47-17c-21 0-39 8-54 23c-15 15-23 33-23 54c0 21 8 39 23 54c15 15 33 23 54 23c18 0 34-5 47-16c0 0 133 80 133 80c0 2 0 4 0 6c-1 3-1 5-1 7c0 21 8 39 23 54c15 15 33 22 54 22c21 0 39-7 54-22c15-14 23-33 23-54c0-22-8-40-23-55c-15-15-33-22-54-22c-18 0-33 5-46 16c0 0-134-80-134-80c0-2 1-7 1-13c0-5-1-10-1-12c0 0 134-80 134-80c12 10 28 15 46 15"/> <glyph unicode="&#57437;" d="m480 384l-448 0c-18 0-32-14-32-32l0-224c0-18 14-32 32-32l448 0c18 0 32 14 32 32l0 224c0 18-14 32-32 32m-288-224l-32 0l-64 107l0-107l-32 0l0 160l32 0l64-107l0 107l32 0z m96 128l-32 0l0-32l32 0l0-32l-32 0l0-32l32 0l0-32l-64 0l0 160l64 0z m160-128l-32 0l-32 64l-32-64l-32 0l0 160l32 0l0-96l32 64l32-64l0 96l32 0z"/>
<glyph unicode="&#57438;" d="m461 410c14 0 26-6 36-16c10-10 15-22 15-36c0 0 0-281 0-281c0-15-5-27-15-37c-10-9-22-14-36-14c0 0-26 0-26 0c0 0 0 384 0 384c0 0 26 0 26 0m-461-52c0 14 5 26 15 36c11 10 23 16 36 16c0 0 26 0 26 0c0 0 0-384 0-384c0 0-26 0-26 0c-13 0-25 5-36 14c-10 10-15 22-15 37c0 0 0 281 0 281m343 105c0 0 0-53 0-53c0 0 56 0 56 0c0 0 0-384 0-384c0 0-286 0-286 0c0 0 0 384 0 384c0 0 56 0 56 0c0 0 0 53 0 53c33 16 62 23 87 23c25 0 54-7 87-23m-31-53c0 0 0 33 0 33c-17 9-36 13-56 13c-18 0-37-4-56-13c0 0 0-33 0-33c0 0 112 0 112 0"/> <glyph unicode="&#57438;" d="m256 512c-139 0-253-111-256-250c3 121 95 218 208 218c115 0 208-100 208-224c0-27 21-48 48-48c27 0 48 21 48 48c0 141-115 256-256 256z m0-512c139 0 253 111 256 250c-3-121-95-218-208-218c-115 0-208 100-208 224c0 27-21 48-48 48c-27 0-48-21-48-48c0-141 115-256 256-256z"/>
<glyph unicode="&#57439;" d="m448 384l-256 0l0 32l48 0c27 0 48 21 48 48c0 26-21 48-48 48l-80 0c-18 0-32-14-32-32l0-96l-96 0c-18 0-32-14-32-32l0-192c0-18 14-32 32-32l160 0l0-128l128 0l0 128l128 0c18 0 32 14 32 32l0 192c0 18-14 32-32 32m-192-352l-32 0l0 96l32 0z m192 128l-416 0l0 192l96 0l0-96c0-18 14-32 32-32c18 0 32 14 32 32l0 96l256 0z"/> <glyph unicode="&#57439;" d="m492 217l-83 40c20 12 33 36 33 63c0 40-28 72-62 72c-12 0-23-4-32-11c6-14 9-29 9-46c0-24-7-48-20-67c4-5 9-9 15-12l0 0l53-25c15-8 25-24 25-41l0-70l57 0c7 0 14 7 14 16l0 66c0 7-4 13-9 15z m-330 40c4 3 8 6 12 10c-13 19-21 43-21 68c0 17 4 33 10 47c-10 6-20 10-31 10c-34 0-62-32-62-72c0-28 14-52 34-64l-84-39c-5-2-9-8-9-15l0-66c0-9 7-16 14-16l55 0l0 70c0 17 10 34 26 41z m232-49l-72 34l-31 15c14 8 25 21 32 37c5 12 9 26 9 41c0 9-2 17-4 24c-9 38-38 65-73 65c-34 0-63-26-73-63c-2-8-3-17-3-26c0-16 3-31 10-44c7-14 18-27 31-35l-29-13l-75-35c-6-3-10-10-10-18l0-82c0-11 7-20 17-20l264 0c10 0 18 9 18 20l0 82c0 8-5 15-11 18z"/>
<glyph unicode="&#57440;" d="m256 476c-121 0-220-99-220-220c0-121 99-220 220-220c121 0 220 99 220 220c0 121-99 220-220 220z m-54-60c8-4 17-8 28-12c11-4 22-6 32-6c8 0 16 2 23 7c7 4 13 7 21 6c9-1 18-4 27-4c11-6 23-14 33-23c-5 0-10-1-16-2c-6-1-12-2-17-3c-6-2-11-4-16-6c-4-3-8-6-10-9c-3-6-6-11-7-15c-3-8-2-20-9-26c-1-1-2-2-3-3c-1-2-1-3-1-5c0-2 1-5 3-9c1-2 1-4 2-8c6 0 12 1 17 5l31-3c7 9 17 9 24 0c3-2 6-6 8-11l-13-9c-3 1-6 3-11 6c-2 1-4 3-6 4c-12 6-36-1-50-2c-2-3-3-7-7-8c-1-2 0-4-1-6c-6-10-8-19-6-30c3-16 11-24 25-24l5 0c6 0 11 0 13 0c3-1 4-2 4-2c-1-4-2-6-1-9c1-7 6-12 6-19c-1-10-4-18-1-27c4-10 9-20 12-29c2-3 4-5 6-5c6-1 13 2 21 11c6 6 10 14 11 22c1 7 6 13 8 21l0 6c1 3 2 6 4 9c1 4 1 9 2 14c4 5 9 9 13 15c2 4 2 7 1 10c0 1-1 1-2 2l-7 3c0 4 7 3 11 2l16 11c0-21-4-42-12-61c-7-20-19-37-33-53c-20-21-44-37-71-46c-28-9-56-11-85-6c5 9 8 19 14 28c0 5 0 9 2 12c5 13 15 17 26 28c11 11 11 25 12 42c0 10-17 17-25 23c-18 12-30 30-55 25c-10-1-12-3-19 3l-2 1l0 1l1 2c3 3-1 7-5 5c-1 0-1 0-2 0c-1 4-4 8-5 13c5-4 8-6 12-8c3-2 5-3 7-3c3-1 4-2 6-1c3 0 5 4 6 10c0 6 0 13-1 21c1 1 2 3 2 4c3 17 12 13 25 18c2 1 2 3 1 4c0 1 0 1 0 1c0 0 0 0 0 0c7 4 11 11 15 18c-3 6-9 11-16 14c-3 5-17 2-20 9c-3 0-4 1-6 1c-12 8-17 23-31 28c-5 1-10 1-16 0c16 13 33 22 52 28z m-113-130c3-5 7-9 11-12c20-20 40-24 66-33c2-1 3-3 6-5c2-2 5-5 8-7c0-1 0-3-1-6c0-3 0-7 0-14c1-17 15-30 19-47c-4-21-4-42-6-63c-21 9-39 21-55 37c-16 16-28 35-37 56c-6 15-10 31-12 47c-1 16-1 31 1 47z"/>
<glyph unicode="&#57441;" d="m256 512c-141 0-256-115-256-256c0-141 115-256 256-256c141 0 256 115 256 256c0 141-115 256-256 256m0-480c-123 0-224 100-224 224c0 123 101 224 224 224c123 0 224-101 224-224c0-124-101-224-224-224m-64 256c18 0 32 21 32 48c0 26-14 48-32 48c-18 0-32-22-32-48c0-27 14-48 32-48m128 0c18 0 32 21 32 48c0 26-14 48-32 48c-18 0-32-22-32-48c0-27 14-48 32-48m-200-115c28-46 78-77 136-77c58 0 108 31 136 77c9 16 16 33 19 51l-310 0c3-18 10-35 19-51"/>
<glyph unicode="&#57442;" d="m485 415l-5 1l-448 0l-3-1l227-202z m25-20l-161-143l159-139c2 5 4 9 4 15l0 256c0 4-1 7-2 11m-508 1c-1-3-2-8-2-12l0-256c0-5 1-9 3-13l161 138z m254-225l-68 60l-158-135l2 0l447 0l-155 135z"/>
</font></defs></svg> </font></defs></svg>

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before After
Before After

Binary file not shown.

Binary file not shown.

View file

@ -325,14 +325,6 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
<div data-icon="&#xe045;" class="icon"></div> <div data-icon="&#xe045;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe045;"> <input type="text" readonly="readonly" value="&amp;#xe045;">
</li> </li>
<li>
<div data-icon="&#xe046;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe046;">
</li>
<li>
<div data-icon="&#xe047;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe047;">
</li>
<li> <li>
<div data-icon="&#xe048;" class="icon"></div> <div data-icon="&#xe048;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe048;"> <input type="text" readonly="readonly" value="&amp;#xe048;">
@ -429,6 +421,18 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
<div data-icon="&#xe05f;" class="icon"></div> <div data-icon="&#xe05f;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe05f;"> <input type="text" readonly="readonly" value="&amp;#xe05f;">
</li> </li>
<li>
<div data-icon="&#xe060;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe060;">
</li>
<li>
<div data-icon="&#xe061;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe061;">
</li>
<li>
<div data-icon="&#xe062;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe062;">
</li>
</ul> </ul>
<h2>CSS mapping</h2> <h2>CSS mapping</h2>
<ul class="glyphs css-mapping"> <ul class="glyphs css-mapping">
@ -712,14 +716,6 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
<div class="icon icon-bug"></div> <div class="icon icon-bug"></div>
<input type="text" readonly="readonly" value="bug"> <input type="text" readonly="readonly" value="bug">
</li> </li>
<li>
<div class="icon icon-heart"></div>
<input type="text" readonly="readonly" value="heart">
</li>
<li>
<div class="icon icon-heart-empty"></div>
<input type="text" readonly="readonly" value="heart-empty">
</li>
<li> <li>
<div class="icon icon-popup"></div> <div class="icon icon-popup"></div>
<input type="text" readonly="readonly" value="popup"> <input type="text" readonly="readonly" value="popup">
@ -748,10 +744,6 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
<div class="icon icon-google-drive"></div> <div class="icon icon-google-drive"></div>
<input type="text" readonly="readonly" value="google-drive"> <input type="text" readonly="readonly" value="google-drive">
</li> </li>
<li>
<div class="icon icon-spinner"></div>
<input type="text" readonly="readonly" value="spinner">
</li>
<li> <li>
<div class="icon icon-github"></div> <div class="icon icon-github"></div>
<input type="text" readonly="readonly" value="github"> <input type="text" readonly="readonly" value="github">
@ -764,10 +756,6 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
<div class="icon icon-mobile"></div> <div class="icon icon-mobile"></div>
<input type="text" readonly="readonly" value="mobile"> <input type="text" readonly="readonly" value="mobile">
</li> </li>
<li>
<div class="icon icon-mail"></div>
<input type="text" readonly="readonly" value="mail">
</li>
<li> <li>
<div class="icon icon-pencil"></div> <div class="icon icon-pencil"></div>
<input type="text" readonly="readonly" value="pencil"> <input type="text" readonly="readonly" value="pencil">
@ -813,8 +801,28 @@ h2{font-size:18px;padding:0 0 21px 5px;margin:45px 0 0 0;text-transform:uppercas
<input type="text" readonly="readonly" value="suitcase"> <input type="text" readonly="readonly" value="suitcase">
</li> </li>
<li> <li>
<div class="icon icon-mailbox"></div> <div class="icon icon-new-sign"></div>
<input type="text" readonly="readonly" value="mailbox"> <input type="text" readonly="readonly" value="new-sign">
</li>
<li>
<div class="icon icon-spinner"></div>
<input type="text" readonly="readonly" value="spinner">
</li>
<li>
<div class="icon icon-users"></div>
<input type="text" readonly="readonly" value="users">
</li>
<li>
<div class="icon icon-earth"></div>
<input type="text" readonly="readonly" value="earth">
</li>
<li>
<div class="icon icon-happy-smiley"></div>
<input type="text" readonly="readonly" value="happy-smiley">
</li>
<li>
<div class="icon icon-mail"></div>
<input type="text" readonly="readonly" value="mail">
</li> </li>
</ul> </ul>
</div><script type="text/javascript"> </div><script type="text/javascript">

View file

@ -1,4 +1,4 @@
/*@charset "UTF-8";*/ @charset "UTF-8";
@font-face { @font-face {
font-family: "rainloop"; font-family: "rainloop";
@ -248,12 +248,6 @@
.icon-bug:before { .icon-bug:before {
content: "\e045"; content: "\e045";
} }
.icon-heart:before {
content: "\e046";
}
.icon-heart-empty:before {
content: "\e047";
}
.icon-popup:before { .icon-popup:before {
content: "\e048"; content: "\e048";
} }
@ -275,54 +269,63 @@
.icon-google-drive:before { .icon-google-drive:before {
content: "\e04e"; content: "\e04e";
} }
.icon-spinner:before { .icon-github:before {
content: "\e04f"; content: "\e04f";
} }
.icon-github:before { .icon-telephone:before {
content: "\e050"; content: "\e050";
} }
.icon-telephone:before { .icon-mobile:before {
content: "\e051"; content: "\e051";
} }
.icon-mobile:before { .icon-pencil:before {
content: "\e052"; content: "\e052";
} }
.icon-mail:before { .icon-trash:before {
content: "\e053"; content: "\e053";
} }
.icon-pencil:before { .icon-left-middle:before {
content: "\e054"; content: "\e054";
} }
.icon-trash:before { .icon-right-middle:before {
content: "\e055"; content: "\e055";
} }
.icon-left-middle:before { .icon-repeat:before {
content: "\e056"; content: "\e056";
} }
.icon-right-middle:before { .icon-key:before {
content: "\e057"; content: "\e057";
} }
.icon-repeat:before { .icon-lock:before {
content: "\e058"; content: "\e058";
} }
.icon-key:before { .icon-home:before {
content: "\e059"; content: "\e059";
} }
.icon-lock:before { .icon-address-book:before {
content: "\e05a"; content: "\e05a";
} }
.icon-home:before { .icon-share:before {
content: "\e05b"; content: "\e05b";
} }
.icon-address-book:before { .icon-suitcase:before {
content: "\e05c"; content: "\e05c";
} }
.icon-share:before { .icon-new-sign:before {
content: "\e05d"; content: "\e05d";
} }
.icon-suitcase:before { .icon-spinner:before {
content: "\e05e"; content: "\e05e";
} }
.icon-mailbox:before { .icon-users:before {
content: "\e05f"; content: "\e05f";
} }
.icon-earth:before {
content: "\e060";
}
.icon-happy-smiley:before {
content: "\e061";
}
.icon-mail:before {
content: "\e062";
}