Mailspring/internal_packages/message-list/lib/sidebar-participant-picker.jsx

74 lines
1.8 KiB
React
Raw Normal View History

feat(sidebar): Add thread list of currently selected participants Summary: WIP. I added a collection index to make displaying the threads of a currently selected participant on the sidebar easy and fast. The problem is that the `participants` of a thread, while a collection of `Contact` objects, have no "ids" for those contact objects. One idea was to create the join table but access contacts by email instead of id. This required a minor change to the way the data is entered in the join table. This means the sidebar can now simply do: `DatabaseStore.findAll(Thread).where(Thread.attributes.participants.contains('foo@bar.com'))` While I didn't for this initial test, we could also/instead create the `Message-Contact` join table. The trick about a Message-Contact table is that I believe we'd have to create additional columns further specifying which field we're interested in. The following two queries: `DatabaseStore.findAll(Message).where(Message.attributes.to.contains('foo@bar.com'))` `DatabaseStore.findAll(Message).where(Message.attributes.from.contains('foo@bar.com'))` would require additional columns in the `Message-Contact` join table because currently the only columns are `id` and `value`. In the case of the sidebar use case, I think the Thread participants is what you want to see anyway. Unfortunately an email-centric scheme can't distinguish between `noreply@phab.com <Evan>` and `noreply@phab.com <Juan>`. I actually think this may be a good thing since I think most people think in terms of email address as the unique key anyway and for the use case of showing related emails in the sidebar I'd rather overshow than undershow. This solution seems to be working pretty well in initial testing, but I want to see if you guys can think of anything this may subtly screw up down the line, or if you can think of a simpler way to do this. Test Plan: todo Reviewers: juan, bengotow Reviewed By: bengotow Differential Revision: https://phab.nylas.com/D2687
2016-03-10 03:33:31 +08:00
/** @babel */
import _ from 'underscore'
import React from 'react';
import {Actions, FocusedContactsStore} from 'nylas-exports'
const SPLIT_KEY = "---splitvalue---"
export default class SidebarParticipantPicker extends React.Component {
static displayName = 'SidebarParticipantPicker';
constructor(props) {
super(props);
this.props = props;
this._onSelectContact = this._onSelectContact.bind(this);
this.state = this._getStateFromStores();
}
componentDidMount() {
this._usub = FocusedContactsStore.listen(() => {
return this.setState(this._getStateFromStores());
});
}
componentWillUnmount() {
this._usub();
}
static containerStyles = {
order: 0,
flexShrink: 0,
};
_getStateFromStores() {
return {
sortedContacts: FocusedContactsStore.sortedContacts(),
focusedContact: FocusedContactsStore.focusedContact(),
};
}
_renderSortedContacts() {
return this.state.sortedContacts.map((contact) => {
const selected = contact.email === (this.state.focusedContact || {}).email
const key = contact.email + SPLIT_KEY + contact.name;
return (
<option selected={selected} value={key} key={key}>
{contact.displayName({includeAccountLabel: true, forceAccountLabel: true})}
</option>
)
});
}
_onSelectContact = (event) => {
const [email, name] = event.target.value.split(SPLIT_KEY);
const contact = _.filter(this.state.sortedContacts, (c) => {
return c.name === name && c.email === email;
})[0];
return Actions.focusContact(contact);
}
render() {
return (
<div className="sidebar-participant-picker">
fix(focus): Remove focusedField in favor of imperative focus, break apart ComposerView Summary: - Removes controlled focus in the composer! - No React components ever perfom focus in lifecycle methods. Never again. - A new `Utils.schedule({action, after, timeout})` helper makes it easy to say "setState or load draft, etc. and then focus" - The DraftStore issues a focusDraft action after creating a draft, which causes the MessageList to focus and scroll to the desired composer, which itself decides which field to focus. - The MessageList never focuses anything automatically. - Refactors ComposerView apart — ComposerHeader handles all top fields, DraftSessionContainer handles draft session initialization and exposes props to ComposerView - ComposerHeader now uses a KeyCommandRegion (with focusIn and focusOut) to do the expanding and collapsing of the participants fields. May rename that container very soon. - Removes all CommandRegistry handling of tab and shift-tab. Unless you preventDefault, the browser does it's thing. - Removes all tabIndexes greater than 1. This is an anti-pattern—assigning everything a tabIndex of 0 tells the browser to move between them based on their order in the DOM, and is almost always what you want. - Adds "TabGroupRegion" which allows you to create a tab/shift-tabbing group, (so tabbing does not leave the active composer). Can't believe this isn't a browser feature. Todos: - Occasionally, clicking out of the composer contenteditable requires two clicks. This is because atomicEdit is restoring selection within the contenteditable and breaking blur. - Because the ComposerView does not render until it has a draft, we're back to it being white in popout composers for a brief moment. We will fix this another way - all the "return unless draft" statements were untenable. - Clicking a row in the thread list no longer shifts focus to the message list and focuses the last draft. This will be restored soon. Test Plan: Broken Reviewers: juan, evan Reviewed By: juan, evan Differential Revision: https://phab.nylas.com/D2814
2016-04-05 06:22:01 +08:00
<select tabIndex={-1} onChange={this._onSelectContact}>
feat(sidebar): Add thread list of currently selected participants Summary: WIP. I added a collection index to make displaying the threads of a currently selected participant on the sidebar easy and fast. The problem is that the `participants` of a thread, while a collection of `Contact` objects, have no "ids" for those contact objects. One idea was to create the join table but access contacts by email instead of id. This required a minor change to the way the data is entered in the join table. This means the sidebar can now simply do: `DatabaseStore.findAll(Thread).where(Thread.attributes.participants.contains('foo@bar.com'))` While I didn't for this initial test, we could also/instead create the `Message-Contact` join table. The trick about a Message-Contact table is that I believe we'd have to create additional columns further specifying which field we're interested in. The following two queries: `DatabaseStore.findAll(Message).where(Message.attributes.to.contains('foo@bar.com'))` `DatabaseStore.findAll(Message).where(Message.attributes.from.contains('foo@bar.com'))` would require additional columns in the `Message-Contact` join table because currently the only columns are `id` and `value`. In the case of the sidebar use case, I think the Thread participants is what you want to see anyway. Unfortunately an email-centric scheme can't distinguish between `noreply@phab.com <Evan>` and `noreply@phab.com <Juan>`. I actually think this may be a good thing since I think most people think in terms of email address as the unique key anyway and for the use case of showing related emails in the sidebar I'd rather overshow than undershow. This solution seems to be working pretty well in initial testing, but I want to see if you guys can think of anything this may subtly screw up down the line, or if you can think of a simpler way to do this. Test Plan: todo Reviewers: juan, bengotow Reviewed By: bengotow Differential Revision: https://phab.nylas.com/D2687
2016-03-10 03:33:31 +08:00
{this._renderSortedContacts()}
</select>
</div>
)
}
}