mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-12-25 16:42:13 +08:00
Idea for contacts screen route
This commit is contained in:
parent
a25d35d6df
commit
fc141fe29b
10 changed files with 197 additions and 9 deletions
|
@ -48,6 +48,7 @@ import { IdentityModel } from 'Model/Identity';
|
||||||
|
|
||||||
import { LoginUserScreen } from 'Screen/User/Login';
|
import { LoginUserScreen } from 'Screen/User/Login';
|
||||||
import { MailBoxUserScreen } from 'Screen/User/MailBox';
|
import { MailBoxUserScreen } from 'Screen/User/MailBox';
|
||||||
|
import { ContactsUserScreen } from 'Screen/User/Contacts';
|
||||||
import { SettingsUserScreen } from 'Screen/User/Settings';
|
import { SettingsUserScreen } from 'Screen/User/Settings';
|
||||||
|
|
||||||
import { startScreens, showScreenPopup, arePopupsVisible } from 'Knoin/Knoin';
|
import { startScreens, showScreenPopup, arePopupsVisible } from 'Knoin/Knoin';
|
||||||
|
@ -211,6 +212,7 @@ export class AppUser extends AbstractApp {
|
||||||
if (value) {
|
if (value) {
|
||||||
startScreens([
|
startScreens([
|
||||||
MailBoxUserScreen,
|
MailBoxUserScreen,
|
||||||
|
ContactsUserScreen,
|
||||||
SettingsUserScreen
|
SettingsUserScreen
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ ScopeMessageList = 'MessageList',
|
||||||
ScopeFolderList = 'FolderList',
|
ScopeFolderList = 'FolderList',
|
||||||
ScopeMessageView = 'MessageView',
|
ScopeMessageView = 'MessageView',
|
||||||
ScopeSettings = 'Settings',
|
ScopeSettings = 'Settings',
|
||||||
|
ScopeContacts = 'Contacts',
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
|
|
33
dev/Screen/User/Contacts.js
Normal file
33
dev/Screen/User/Contacts.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { ScopeContacts } from 'Common/Enums';
|
||||||
|
import { i18n } from 'Common/Translator';
|
||||||
|
|
||||||
|
import { AppUserStore } from 'Stores/User/App';
|
||||||
|
|
||||||
|
import { SystemDropDownUserView } from 'View/User/SystemDropDown';
|
||||||
|
import { AddressBooks } from 'View/User/Contacts/AddressBooks';
|
||||||
|
import { ContactsList } from 'View/User/Contacts/ContactsList';
|
||||||
|
import { ContactView } from 'View/User/Contacts/ContactView';
|
||||||
|
|
||||||
|
import { AbstractScreen } from 'Knoin/AbstractScreen';
|
||||||
|
|
||||||
|
export class ContactsUserScreen extends AbstractScreen {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super('contacts', [
|
||||||
|
SystemDropDownUserView,
|
||||||
|
AddressBooks,
|
||||||
|
ContactsList,
|
||||||
|
ContactView
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow() {
|
||||||
|
this.setTitle();
|
||||||
|
AppUserStore.focusedState('none');
|
||||||
|
AppUserStore.focusedState(ScopeContacts);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTitle() {
|
||||||
|
rl.setTitle(i18n('GLOBAL/CONTACTS'));
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ export class MailBoxUserScreen extends AbstractScreen {
|
||||||
/**
|
/**
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
updateWindowTitle() {
|
setTitle() {
|
||||||
const count = Settings.app('listPermanentFiltered') ? 0 : FolderUserStore.foldersInboxUnreadCount(),
|
const count = Settings.app('listPermanentFiltered') ? 0 : FolderUserStore.foldersInboxUnreadCount(),
|
||||||
email = AccountUserStore.email();
|
email = AccountUserStore.email();
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ export class MailBoxUserScreen extends AbstractScreen {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
onShow() {
|
onShow() {
|
||||||
this.updateWindowTitle();
|
this.setTitle();
|
||||||
AppUserStore.focusedState('none');
|
AppUserStore.focusedState('none');
|
||||||
AppUserStore.focusedState(ScopeMessageList);
|
AppUserStore.focusedState(ScopeMessageList);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ export class MailBoxUserScreen extends AbstractScreen {
|
||||||
email === item?.email && item?.count(e.detail)
|
email === item?.email && item?.count(e.detail)
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
this.updateWindowTitle();
|
this.setTitle();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,11 +66,11 @@ export class SettingsUserScreen extends AbstractSettingsScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
this.setSettingsTitle();
|
this.setTitle();
|
||||||
keyScope(ScopeSettings);
|
keyScope(ScopeSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSettingsTitle() {
|
setTitle() {
|
||||||
const sEmail = AccountUserStore.email();
|
const sEmail = AccountUserStore.email();
|
||||||
rl.setTitle((sEmail ? sEmail + ' - ' : '') + this.sSettingsTitle);
|
rl.setTitle((sEmail ? sEmail + ' - ' : '') + this.sSettingsTitle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ AppUserStore.focusedState.subscribe(value => {
|
||||||
arePopupsVisible() || keyScope(value);
|
arePopupsVisible() || keyScope(value);
|
||||||
ThemeStore.isMobile() && leftPanelDisabled('FolderList' !== value);
|
ThemeStore.isMobile() && leftPanelDisabled('FolderList' !== value);
|
||||||
}
|
}
|
||||||
elementById('V-Mail'+name).classList.toggle('focused', name === value);
|
let el = elementById('V-Mail'+name);
|
||||||
|
el && el.classList.toggle('focused', name === value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,9 +21,10 @@ import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||||
|
|
||||||
import { AskPopupView } from 'View/Popup/Ask';
|
import { AskPopupView } from 'View/Popup/Ask';
|
||||||
|
|
||||||
|
import { ScopeContacts } from 'Common/Enums';
|
||||||
|
|
||||||
const
|
const
|
||||||
CONTACTS_PER_PAGE = 50,
|
CONTACTS_PER_PAGE = 50;
|
||||||
ScopeContacts = 'Contacts';
|
|
||||||
|
|
||||||
let
|
let
|
||||||
bOpenCompose = false,
|
bOpenCompose = false,
|
||||||
|
@ -342,7 +343,7 @@ export class ContactsPopupView extends AbstractViewPopup {
|
||||||
this.search('');
|
this.search('');
|
||||||
this.contactsCount(0);
|
this.contactsCount(0);
|
||||||
|
|
||||||
ContactUserStore([]);
|
// ContactUserStore([]);
|
||||||
|
|
||||||
bOpenCompose && showMessageComposer();
|
bOpenCompose && showMessageComposer();
|
||||||
}
|
}
|
||||||
|
|
7
dev/View/User/Contacts/AddressBooks.js
Normal file
7
dev/View/User/Contacts/AddressBooks.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import { AbstractViewLeft } from 'Knoin/AbstractViews';
|
||||||
|
|
||||||
|
export class AddressBooks extends AbstractViewLeft {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
47
dev/View/User/Contacts/ContactView.js
Normal file
47
dev/View/User/Contacts/ContactView.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
||||||
|
import { addObservablesTo } from 'External/ko';
|
||||||
|
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||||
|
import Remote from 'Remote/User/Fetch';
|
||||||
|
import { getNotification } from 'Common/Translator';
|
||||||
|
|
||||||
|
export class ContactView extends AbstractViewRight {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
addObservablesTo(this, {
|
||||||
|
contact: null
|
||||||
|
});
|
||||||
|
|
||||||
|
this.saveCommand = this.saveCommand.bind(this);
|
||||||
|
|
||||||
|
decorateKoCommands(this, {
|
||||||
|
saveCommand: self => !self.isBusy()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
saveCommand() {
|
||||||
|
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) => {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.isSaving(false);
|
||||||
|
}, data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
96
dev/View/User/Contacts/ContactsList.js
Normal file
96
dev/View/User/Contacts/ContactsList.js
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
||||||
|
|
||||||
|
import { addObservablesTo, addComputablesTo } from 'External/ko';
|
||||||
|
import { computedPaginatorHelper } from 'Common/UtilsUser';
|
||||||
|
|
||||||
|
import { Selector } from 'Common/Selector';
|
||||||
|
|
||||||
|
import { SettingsUserStore } from 'Stores/User/Settings';
|
||||||
|
import { ContactUserStore } from 'Stores/User/Contact';
|
||||||
|
|
||||||
|
import { decorateKoCommands } from 'Knoin/Knoin';
|
||||||
|
|
||||||
|
const
|
||||||
|
CONTACTS_PER_PAGE = 50;
|
||||||
|
|
||||||
|
export class ContactsList extends AbstractViewRight {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
addObservablesTo(this, {
|
||||||
|
search: '',
|
||||||
|
contactsCount: 0,
|
||||||
|
|
||||||
|
selectorContact: null,
|
||||||
|
|
||||||
|
importButton: null,
|
||||||
|
|
||||||
|
contactsPage: 1,
|
||||||
|
|
||||||
|
isSaving: false,
|
||||||
|
|
||||||
|
contact: null
|
||||||
|
});
|
||||||
|
|
||||||
|
addComputablesTo(this, {
|
||||||
|
checkAll: {
|
||||||
|
read: () => ContactUserStore.hasChecked(),
|
||||||
|
write: (value) => {
|
||||||
|
value = !!value;
|
||||||
|
ContactUserStore.forEach(contact => contact.checked(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.contacts = ContactUserStore;
|
||||||
|
|
||||||
|
this.useCheckboxesInList = SettingsUserStore.useCheckboxesInList;
|
||||||
|
|
||||||
|
this.selector = new Selector(
|
||||||
|
ContactUserStore,
|
||||||
|
this.selectorContact,
|
||||||
|
null,
|
||||||
|
'.e-contact-item',
|
||||||
|
'.e-contact-item .checkboxItem'
|
||||||
|
);
|
||||||
|
|
||||||
|
this.selector.on('ItemSelect', contact => this.populateViewContact(contact));
|
||||||
|
|
||||||
|
this.selector.on('ItemGetUid', contact => contact ? contact.id() : '');
|
||||||
|
|
||||||
|
addComputablesTo(this, {
|
||||||
|
contactsPaginator: computedPaginatorHelper(
|
||||||
|
this.contactsPage,
|
||||||
|
() => Math.max(1, Math.ceil(this.contactsCount() / CONTACTS_PER_PAGE))
|
||||||
|
),
|
||||||
|
|
||||||
|
contactsCheckedOrSelected: () => {
|
||||||
|
const checked = ContactUserStore.filter(item => item.checked()),
|
||||||
|
selected = this.selectorContact();
|
||||||
|
return checked.length ? checked : (selected ? [selected] : []);
|
||||||
|
},
|
||||||
|
|
||||||
|
contactsSyncEnabled: () => ContactUserStore.allowSync() && ContactUserStore.syncMode(),
|
||||||
|
|
||||||
|
isIncompleteChecked: () => {
|
||||||
|
const c = ContactUserStore.listChecked().length;
|
||||||
|
return c && ContactUserStore().length > c;
|
||||||
|
},
|
||||||
|
|
||||||
|
isBusy: () => ContactUserStore.syncing() | ContactUserStore.importing() | ContactUserStore.loading()
|
||||||
|
| this.isSaving()
|
||||||
|
});
|
||||||
|
|
||||||
|
this.search.subscribe(() => this.reloadContactList());
|
||||||
|
|
||||||
|
decorateKoCommands(this, {
|
||||||
|
deleteCommand: self => !self.isBusy() && 0 < self.contactsCheckedOrSelected().length,
|
||||||
|
newMessageCommand: self => !self.isBusy() && 0 < self.contactsCheckedOrSelected().length,
|
||||||
|
syncCommand: self => !self.isBusy()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSearch() {
|
||||||
|
this.search('');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue