mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-28 11:39:21 +03:00
Improved Contacts to check if changes should be saved
This commit is contained in:
parent
c9ad0ef170
commit
2627a16c36
43 changed files with 102 additions and 63 deletions
|
|
@ -2,12 +2,6 @@
|
|||
* Inspired by https://github.com/mcpar-land/vcfer
|
||||
*/
|
||||
|
||||
const
|
||||
camelCase = str =>
|
||||
str.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) =>
|
||||
index === 0 ? word.toLowerCase() : word.toUpperCase()
|
||||
).replace(/\s+/g, '');
|
||||
|
||||
export class VCardProperty {
|
||||
|
||||
/**
|
||||
|
|
@ -68,7 +62,7 @@ export class VCardProperty {
|
|||
parseFromJCardProperty(jCardProp)
|
||||
{
|
||||
jCardProp = JSON.parse(JSON.stringify(jCardProp));
|
||||
this.field = camelCase(jCardProp[0]);
|
||||
this.field = jCardProp[0].toLowerCase();
|
||||
this.params = jCardProp[1];
|
||||
this.type = jCardProp[2];
|
||||
this.value = jCardProp[3];
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ export class ContactModel extends AbstractModel {
|
|||
constructor() {
|
||||
super();
|
||||
|
||||
this.jCard = new JCard();
|
||||
this.jCard = ['vcard',[]];
|
||||
|
||||
this.addObservables({
|
||||
focused: false,
|
||||
|
|
@ -122,14 +122,13 @@ export class ContactModel extends AbstractModel {
|
|||
this.addComputables({
|
||||
hasValidName: () => !!(this.givenName() || this.surName()),
|
||||
|
||||
fullName: () => (this.givenName() + ' ' + this.surName()).trim(),
|
||||
fullName: () => [this.namePrefix(), this.givenName(), this.middleName(), this.surName()].join(' ').trim(),
|
||||
|
||||
display: () => {
|
||||
let a = this.jCard.getOne('fn')?.value,
|
||||
b = this.fullName(),
|
||||
c = this.jCard.getOne('email')?.value,
|
||||
d = this.nickname();
|
||||
return a || b || c || d;
|
||||
let a = this.fullName(),
|
||||
b = this.email()?.[0]?.value,
|
||||
c = this.nickname();
|
||||
return a || b || c;
|
||||
}
|
||||
/*
|
||||
fullName: {
|
||||
|
|
@ -200,12 +199,12 @@ export class ContactModel extends AbstractModel {
|
|||
});
|
||||
});
|
||||
|
||||
props = jCard.getOne('x-Crypto');
|
||||
props = jCard.getOne('x-crypto');
|
||||
contact.signpref(props?.params.signpref || 'Ask');
|
||||
contact.encryptpref(props?.params.encryptpref || 'Ask');
|
||||
// contact.encryptpref(props?.params.allowed || 'PGP/INLINE,PGP/MIME,S/MIME,S/MIMEOpaque');
|
||||
|
||||
contact.jCard = jCard;
|
||||
contact.jCard = json.jCard;
|
||||
}
|
||||
return contact;
|
||||
}
|
||||
|
|
@ -246,9 +245,14 @@ export class ContactModel extends AbstractModel {
|
|||
this.nickname() || this.nickname('');
|
||||
}
|
||||
|
||||
hasChanges()
|
||||
{
|
||||
return this.toJSON().jCard != JSON.stringify(this.jCard);
|
||||
}
|
||||
|
||||
toJSON()
|
||||
{
|
||||
let jCard = this.jCard;
|
||||
let jCard = new JCard(this.jCard);
|
||||
jCard.set('n', [
|
||||
this.surName(),
|
||||
this.givenName(),
|
||||
|
|
@ -273,7 +277,7 @@ export class ContactModel extends AbstractModel {
|
|||
values.forEach(value => value && jCard.add(field, value));
|
||||
});
|
||||
|
||||
jCard.set('x-Crypto', '', {
|
||||
jCard.set('x-crypto', '', {
|
||||
allowed: 'PGP/INLINE,PGP/MIME,S/MIME,S/MIMEOpaque',
|
||||
signpref: this.signpref(),
|
||||
encryptpref: this.encryptpref()
|
||||
|
|
|
|||
|
|
@ -142,13 +142,6 @@
|
|||
text-align: right;
|
||||
border-top: 1px solid rgba(128,128,128,0.4);
|
||||
|
||||
.button-save-contact {
|
||||
&.dirty:enabled {
|
||||
color: #51a351;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu.right-edge {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import Remote from 'Remote/User/Fetch';
|
|||
import { EmailModel } from 'Model/Email';
|
||||
import { ContactModel } from 'Model/Contact';
|
||||
|
||||
import { decorateKoCommands, showScreenPopup } from 'Knoin/Knoin';
|
||||
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
import { AskPopupView } from 'View/Popup/Ask';
|
||||
|
|
@ -43,8 +43,6 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
|
||||
isSaving: false,
|
||||
|
||||
hasChanges: false,
|
||||
|
||||
contact: null
|
||||
});
|
||||
|
||||
|
|
@ -61,9 +59,7 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
'.e-contact-item.focused'
|
||||
);
|
||||
|
||||
this.selector.on('ItemSelect', contact => {
|
||||
this.populateViewContact(contact);
|
||||
});
|
||||
this.selector.on('ItemSelect', contact => this.populateViewContact(contact));
|
||||
|
||||
this.selector.on('ItemGetUid', contact => contact ? contact.generateUid() : '');
|
||||
|
||||
|
|
@ -95,13 +91,10 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
|
||||
this.saveCommand = this.saveCommand.bind(this);
|
||||
|
||||
// this.hasChanges(!!contact()?.toJSON().jCard);
|
||||
|
||||
decorateKoCommands(this, {
|
||||
// close: self => !self.hasChanges(),
|
||||
deleteCommand: self => 0 < self.contactsCheckedOrSelected().length,
|
||||
newMessageCommand: self => 0 < self.contactsCheckedOrSelected().length,
|
||||
saveCommand: self => !self.isSaving() && !self.hasChanges(),
|
||||
saveCommand: self => !self.isSaving(),
|
||||
syncCommand: self => !self.contacts.syncing() && !self.contacts.importing()
|
||||
});
|
||||
}
|
||||
|
|
@ -171,22 +164,29 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
}
|
||||
|
||||
saveCommand() {
|
||||
this.isSaving(true);
|
||||
const contact = this.contact();
|
||||
Remote.request('ContactSave',
|
||||
(iError, oData) => {
|
||||
this.isSaving(false);
|
||||
if (!iError && oData.Result.ResultID) {
|
||||
contact.id(oData.Result.ResultID);
|
||||
this.reloadContactList(); // TODO: remove when e-contact-foreach is dynamic
|
||||
this.hasChanges(false);
|
||||
}
|
||||
}, {
|
||||
Contact: contact
|
||||
// Uid: contact.id(),
|
||||
// jCard: contact.jCard
|
||||
}
|
||||
);
|
||||
this.saveContact(this.contact());
|
||||
}
|
||||
|
||||
saveContact(contact) {
|
||||
const data = contact.toJSON();
|
||||
if (data.jCard != JSON.stringify(contact.jCard)) {
|
||||
this.isSaving(true);
|
||||
Remote.request('ContactSave',
|
||||
(iError, oData) => {
|
||||
this.isSaving(false);
|
||||
if (iError) {
|
||||
alert(oData?.ErrorMessage || getNotification(iError));
|
||||
} else if (oData.Result.ResultID) {
|
||||
if (contact.id()) {
|
||||
contact.id(oData.Result.ResultID);
|
||||
contact.jCard = JSON.parse(data.jCard);
|
||||
} else {
|
||||
this.reloadContactList(); // TODO: remove when e-contact-foreach is dynamic
|
||||
}
|
||||
}
|
||||
}, data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
syncCommand() {
|
||||
|
|
@ -252,8 +252,14 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
* @param {?ContactModel} contact
|
||||
*/
|
||||
populateViewContact(contact) {
|
||||
const oldContact = this.contact();
|
||||
if (oldContact?.hasChanges()) {
|
||||
AskPopupView.showModal([
|
||||
i18n('GLOBAL/SAVE_CHANGES'),
|
||||
() => this.saveContact(oldContact)
|
||||
]);
|
||||
}
|
||||
this.contact(contact || new ContactModel);
|
||||
this.hasChanges(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -349,10 +355,16 @@ export class ContactsPopupView extends AbstractViewPopup {
|
|||
}
|
||||
}
|
||||
|
||||
tryToClose() {
|
||||
(false === this.onClose()) || this.close();
|
||||
}
|
||||
|
||||
onClose() {
|
||||
if (this.hasChanges() && AskPopupView.hidden()) {
|
||||
showScreenPopup(AskPopupView, [
|
||||
i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'),
|
||||
const contact = this.contact();
|
||||
if (AskPopupView.hidden() && contact?.hasChanges()) {
|
||||
AskPopupView.showModal([
|
||||
i18n('GLOBAL/SAVE_CHANGES'),
|
||||
() => this.close() | this.saveContact(contact),
|
||||
() => this.close()
|
||||
]);
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue