mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Improved Contacts window
This commit is contained in:
parent
56d64b325c
commit
0c90875b61
1 changed files with 65 additions and 126 deletions
|
|
@ -24,13 +24,14 @@ const
|
||||||
CONTACTS_PER_PAGE = 50,
|
CONTACTS_PER_PAGE = 50,
|
||||||
ScopeContacts = 'Contacts';
|
ScopeContacts = 'Contacts';
|
||||||
|
|
||||||
|
let
|
||||||
|
bOpenCompose = false,
|
||||||
|
sComposeRecipientsField = '';
|
||||||
|
|
||||||
export class ContactsPopupView extends AbstractViewPopup {
|
export class ContactsPopupView extends AbstractViewPopup {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('Contacts');
|
super('Contacts');
|
||||||
|
|
||||||
this.bBackToCompose = false;
|
|
||||||
this.sLastComposeFocusedField = '';
|
|
||||||
|
|
||||||
this.addObservables({
|
this.addObservables({
|
||||||
search: '',
|
search: '',
|
||||||
contactsCount: 0,
|
contactsCount: 0,
|
||||||
|
|
@ -63,28 +64,22 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
|
|
||||||
this.selector.on('ItemGetUid', contact => contact ? contact.generateUid() : '');
|
this.selector.on('ItemGetUid', contact => contact ? contact.generateUid() : '');
|
||||||
|
|
||||||
this.bDropPageAfterDelete = false;
|
|
||||||
|
|
||||||
const
|
|
||||||
pagecount = () => Math.max(1, Math.ceil(this.contactsCount() / CONTACTS_PER_PAGE));
|
|
||||||
|
|
||||||
this.addComputables({
|
this.addComputables({
|
||||||
contactsPageCount: pagecount,
|
contactsPaginator: computedPaginatorHelper(
|
||||||
|
this.contactsPage,
|
||||||
contactsPaginator: computedPaginatorHelper(this.contactsPage, pagecount),
|
() => Math.max(1, Math.ceil(this.contactsCount() / CONTACTS_PER_PAGE))
|
||||||
|
),
|
||||||
|
|
||||||
contactsCheckedOrSelected: () => {
|
contactsCheckedOrSelected: () => {
|
||||||
const checked = ContactUserStore.filter(item => item.checked?.()),
|
const checked = ContactUserStore.filter(item => item.checked?.()),
|
||||||
selected = this.selectorContact();
|
selected = this.selectorContact();
|
||||||
|
return checked.length ? checked : (selected ? [selected] : []);
|
||||||
return selected
|
|
||||||
? [...checked, selected].unique()
|
|
||||||
: checked;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
contactsCheckedOrSelectedUids: () => this.contactsCheckedOrSelected().map(contact => contact.id()),
|
contactsSyncEnabled: () => ContactUserStore.allowSync() && ContactUserStore.syncMode(),
|
||||||
|
|
||||||
contactsSyncEnabled: () => ContactUserStore.allowSync() && ContactUserStore.syncMode()
|
isBusy: () => ContactUserStore.syncing() | ContactUserStore.importing() | ContactUserStore.loading()
|
||||||
|
| this.isSaving()
|
||||||
});
|
});
|
||||||
|
|
||||||
this.search.subscribe(() => this.reloadContactList());
|
this.search.subscribe(() => this.reloadContactList());
|
||||||
|
|
@ -92,71 +87,67 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
this.saveCommand = this.saveCommand.bind(this);
|
this.saveCommand = this.saveCommand.bind(this);
|
||||||
|
|
||||||
decorateKoCommands(this, {
|
decorateKoCommands(this, {
|
||||||
deleteCommand: self => 0 < self.contactsCheckedOrSelected().length,
|
deleteCommand: self => !self.isBusy() && 0 < self.contactsCheckedOrSelected().length,
|
||||||
newMessageCommand: self => 0 < self.contactsCheckedOrSelected().length,
|
newMessageCommand: self => !self.isBusy() && 0 < self.contactsCheckedOrSelected().length,
|
||||||
saveCommand: self => !self.isSaving(),
|
saveCommand: self => !self.isBusy(),
|
||||||
syncCommand: self => !self.contacts.syncing() && !self.contacts.importing()
|
syncCommand: self => !self.isBusy()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
newContact() {
|
newContact() {
|
||||||
this.populateViewContact();
|
this.populateViewContact(new ContactModel);
|
||||||
this.selectorContact(null);
|
this.selectorContact(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteCommand() {
|
deleteCommand() {
|
||||||
this.deleteSelectedContacts();
|
const contacts = this.contactsCheckedOrSelected();
|
||||||
|
if (contacts.length) {
|
||||||
|
let selectorContact = this.selectorContact(),
|
||||||
|
Uids = [],
|
||||||
|
count = 0;
|
||||||
|
contacts.forEach(contact => {
|
||||||
|
Uids.push(contact.id());
|
||||||
|
if (selectorContact && selectorContact.id() === contact.id()) {
|
||||||
|
this.selectorContact(selectorContact = null);
|
||||||
|
}
|
||||||
|
contact.deleted(true);
|
||||||
|
++count;
|
||||||
|
});
|
||||||
|
Remote.request('ContactsDelete',
|
||||||
|
(iError, oData) => {
|
||||||
|
if (iError) {
|
||||||
|
alert(oData?.ErrorMessage || getNotification(iError));
|
||||||
|
} else {
|
||||||
|
const page = this.contactsPage();
|
||||||
|
if (page > Math.max(1, Math.ceil((this.contactsCount() - count) / CONTACTS_PER_PAGE))) {
|
||||||
|
this.contactsPage(page - 1);
|
||||||
|
}
|
||||||
|
// contacts.forEach(contact => ContactUserStore.remove(contact));
|
||||||
|
}
|
||||||
|
this.reloadContactList();
|
||||||
|
}, {
|
||||||
|
Uids: Uids.join(',')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newMessageCommand() {
|
newMessageCommand() {
|
||||||
let aE = [],
|
let aE = [],
|
||||||
toEmails = null,
|
recipients = {to:null,cc:null,bcc:null};
|
||||||
ccEmails = null,
|
|
||||||
bccEmails = null;
|
|
||||||
|
|
||||||
const aC = this.contactsCheckedOrSelected();
|
this.contactsCheckedOrSelected().forEach(oContact => {
|
||||||
if (arrayLength(aC)) {
|
const data = oContact?.getNameAndEmailHelper(),
|
||||||
aE = aC.map(oItem => {
|
email = data ? new EmailModel(data[0], data[1]) : null;
|
||||||
if (oItem) {
|
email?.validate() && aE.push(email);
|
||||||
const data = oItem.getNameAndEmailHelper(),
|
});
|
||||||
email = data ? new EmailModel(data[0], data[1]) : null;
|
|
||||||
|
|
||||||
if (email?.validate()) {
|
|
||||||
return email;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
aE = aE.filter(value => !!value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arrayLength(aE)) {
|
if (arrayLength(aE)) {
|
||||||
this.bBackToCompose = false;
|
bOpenCompose = false;
|
||||||
|
|
||||||
this.close();
|
this.close();
|
||||||
|
recipients[sComposeRecipientsField] = aE;
|
||||||
switch (this.sLastComposeFocusedField) {
|
showMessageComposer([ComposeType.Empty, null, recipients.to, recipients.cc, recipients.bcc])
|
||||||
case 'cc':
|
|
||||||
ccEmails = aE;
|
|
||||||
break;
|
|
||||||
case 'bcc':
|
|
||||||
bccEmails = aE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
toEmails = aE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sLastComposeFocusedField = '';
|
|
||||||
|
|
||||||
setTimeout(() =>
|
|
||||||
showMessageComposer([ComposeType.Empty, null, toEmails, ccEmails, bccEmails])
|
|
||||||
, 200);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSearch() {
|
clearSearch() {
|
||||||
|
|
@ -173,7 +164,6 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
this.isSaving(true);
|
this.isSaving(true);
|
||||||
Remote.request('ContactSave',
|
Remote.request('ContactSave',
|
||||||
(iError, oData) => {
|
(iError, oData) => {
|
||||||
this.isSaving(false);
|
|
||||||
if (iError) {
|
if (iError) {
|
||||||
alert(oData?.ErrorMessage || getNotification(iError));
|
alert(oData?.ErrorMessage || getNotification(iError));
|
||||||
} else if (oData.Result.ResultID) {
|
} else if (oData.Result.ResultID) {
|
||||||
|
|
@ -184,6 +174,7 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
this.reloadContactList(); // TODO: remove when e-contact-foreach is dynamic
|
this.reloadContactList(); // TODO: remove when e-contact-foreach is dynamic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.isSaving(false);
|
||||||
}, data
|
}, data
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -204,50 +195,6 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
download(serverRequestRaw('ContactsCsv'), 'contacts.csv');
|
download(serverRequestRaw('ContactsCsv'), 'contacts.csv');
|
||||||
}
|
}
|
||||||
|
|
||||||
removeCheckedOrSelectedContactsFromList() {
|
|
||||||
const contacts = this.contactsCheckedOrSelected();
|
|
||||||
|
|
||||||
let selectorContact = this.selectorContact(),
|
|
||||||
count = ContactUserStore.length;
|
|
||||||
|
|
||||||
if (contacts.length) {
|
|
||||||
contacts.forEach(contact => {
|
|
||||||
if (selectorContact && selectorContact.id() === contact.id()) {
|
|
||||||
selectorContact = null;
|
|
||||||
this.selectorContact(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
contact.deleted(true);
|
|
||||||
--count;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (0 >= count) {
|
|
||||||
this.bDropPageAfterDelete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
contacts.forEach(contact => ContactUserStore.remove(contact));
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteSelectedContacts() {
|
|
||||||
if (this.contactsCheckedOrSelected().length) {
|
|
||||||
Remote.request('ContactsDelete',
|
|
||||||
(iError, oData) => {
|
|
||||||
if (500 < (!iError && oData?.Time) ? pInt(oData.Time) : 0) {
|
|
||||||
this.reloadContactList(this.bDropPageAfterDelete);
|
|
||||||
} else {
|
|
||||||
setTimeout(() => this.reloadContactList(this.bDropPageAfterDelete), 500);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
Uids: this.contactsCheckedOrSelectedUids().join(',')
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.removeCheckedOrSelectedContactsFromList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {?ContactModel} contact
|
* @param {?ContactModel} contact
|
||||||
*/
|
*/
|
||||||
|
|
@ -259,7 +206,7 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
() => this.saveContact(oldContact)
|
() => this.saveContact(oldContact)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
this.contact(contact || new ContactModel);
|
this.contact(contact);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -268,8 +215,6 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
reloadContactList(dropPagePosition = false) {
|
reloadContactList(dropPagePosition = false) {
|
||||||
let offset = (this.contactsPage() - 1) * CONTACTS_PER_PAGE;
|
let offset = (this.contactsPage() - 1) * CONTACTS_PER_PAGE;
|
||||||
|
|
||||||
this.bDropPageAfterDelete = false;
|
|
||||||
|
|
||||||
if (dropPagePosition) {
|
if (dropPagePosition) {
|
||||||
this.contactsPage(1);
|
this.contactsPage(1);
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
@ -289,12 +234,10 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
item = ContactModel.reviveFromJson(item);
|
item = ContactModel.reviveFromJson(item);
|
||||||
item && list.push(item);
|
item && list.push(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
count = pInt(data.Result.Count);
|
count = pInt(data.Result.Count);
|
||||||
count = 0 < count ? count : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.contactsCount(count);
|
this.contactsCount(0 < count ? count : 0);
|
||||||
|
|
||||||
ContactUserStore(list);
|
ContactUserStore(list);
|
||||||
|
|
||||||
|
|
@ -325,8 +268,8 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
|
|
||||||
dom.addEventListener('click', event => {
|
dom.addEventListener('click', event => {
|
||||||
let el = event.target.closestWithin('.e-paginator a', dom);
|
let el = event.target.closestWithin('.e-paginator a', dom);
|
||||||
if (el && ko.dataFor(el)) {
|
if (el && (el = pInt(ko.dataFor(el)?.value))) {
|
||||||
self.contactsPage(pInt(ko.dataFor(el).value));
|
self.contactsPage(el);
|
||||||
self.reloadContactList();
|
self.reloadContactList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -371,9 +314,9 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onShow(bBackToCompose, sLastComposeFocusedField) {
|
onShow(bBackToCompose, sRecipientsField) {
|
||||||
this.bBackToCompose = !!bBackToCompose;
|
bOpenCompose = !!bBackToCompose;
|
||||||
this.sLastComposeFocusedField = sLastComposeFocusedField;
|
sComposeRecipientsField = ['to','cc','bcc'].includes(sRecipientsField) ? sRecipientsField : 'to';
|
||||||
this.reloadContactList(true);
|
this.reloadContactList(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -385,10 +328,6 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
|
|
||||||
ContactUserStore([]);
|
ContactUserStore([]);
|
||||||
|
|
||||||
this.sLastComposeFocusedField = '';
|
bOpenCompose && showMessageComposer();
|
||||||
if (this.bBackToCompose) {
|
|
||||||
this.bBackToCompose = false;
|
|
||||||
showMessageComposer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue