2015-05-20 07:06:59 +08:00
|
|
|
_ = require 'underscore'
|
2015-03-10 09:25:53 +08:00
|
|
|
React = require 'react'
|
2015-04-25 02:33:10 +08:00
|
|
|
classNames = require 'classnames'
|
2015-09-22 07:21:57 +08:00
|
|
|
{ListTabular,
|
|
|
|
MultiselectList,
|
|
|
|
RetinaImg,
|
|
|
|
MailLabel,
|
|
|
|
InjectedComponentSet} = require 'nylas-component-kit'
|
2015-03-10 09:25:53 +08:00
|
|
|
{timestamp, subject} = require './formatting-utils'
|
2015-03-26 02:17:57 +08:00
|
|
|
{Actions,
|
2015-03-26 03:41:48 +08:00
|
|
|
Utils,
|
2015-07-24 02:10:51 +08:00
|
|
|
CanvasUtils,
|
2015-04-07 02:46:20 +08:00
|
|
|
Thread,
|
2015-03-26 02:17:57 +08:00
|
|
|
WorkspaceStore,
|
feat(accounts): Kill namespaces, long live accounts
Summary:
This diff replaces the Namespace object with the Account object, and changes all references to namespace_id => account_id, etc. The endpoints are now `/threads` instead of `/n/<id>/threads`.
This diff also adds preliminary support for multiple accounts. When you log in, we now log you in to all the attached accounts on edgehill server. From the preferences panel, you can auth with / unlink additional accounts. Shockingly, this all seems to pretty much work.
When replying to a thread, you cannot switch from addresses. However, when creating a new message in a popout composer, you can change the from address and the SaveDraftTask will delete/re-root the draft on the new account.
Search bar doesn't need to do full refresh on clear if it never committed
Allow drafts to be switched to a different account when not in reply to an existing thread
Fix edge case where ChangeMailTask throws exception if no models are modified during performLocal
Show many dots for many accounts in long polling status bar
add/remove accounts from prefs
Spec fixes!
Test Plan: Run tests, none broken!
Reviewers: evan, dillon
Reviewed By: evan, dillon
Differential Revision: https://phab.nylas.com/D1928
2015-08-22 06:29:58 +08:00
|
|
|
AccountStore,
|
2015-07-22 02:50:08 +08:00
|
|
|
CategoryStore,
|
2015-09-05 03:23:15 +08:00
|
|
|
FocusedMailViewStore} = require 'nylas-exports'
|
2015-03-26 03:41:48 +08:00
|
|
|
|
|
|
|
ThreadListParticipants = require './thread-list-participants'
|
2015-06-12 09:38:57 +08:00
|
|
|
ThreadListQuickActions = require './thread-list-quick-actions'
|
2015-04-09 10:25:00 +08:00
|
|
|
ThreadListStore = require './thread-list-store'
|
2015-06-09 08:02:50 +08:00
|
|
|
ThreadListIcon = require './thread-list-icon'
|
2015-03-10 09:25:53 +08:00
|
|
|
|
2015-06-18 04:14:45 +08:00
|
|
|
EmptyState = require './empty-state'
|
2015-09-09 01:53:07 +08:00
|
|
|
{MailImportantIcon} = require 'nylas-component-kit'
|
2015-06-18 04:14:45 +08:00
|
|
|
|
2015-06-06 02:50:55 +08:00
|
|
|
class ThreadListScrollTooltip extends React.Component
|
|
|
|
@displayName: 'ThreadListScrollTooltip'
|
|
|
|
@propTypes:
|
|
|
|
viewportCenter: React.PropTypes.number.isRequired
|
|
|
|
totalHeight: React.PropTypes.number.isRequired
|
|
|
|
|
|
|
|
componentWillMount: =>
|
|
|
|
@setupForProps(@props)
|
|
|
|
|
|
|
|
componentWillReceiveProps: (newProps) =>
|
|
|
|
@setupForProps(newProps)
|
|
|
|
|
|
|
|
shouldComponentUpdate: (newProps, newState) =>
|
|
|
|
@state?.idx isnt newState.idx
|
|
|
|
|
|
|
|
setupForProps: (props) ->
|
|
|
|
idx = Math.floor(ThreadListStore.view().count() / @props.totalHeight * @props.viewportCenter)
|
|
|
|
@setState
|
|
|
|
idx: idx
|
|
|
|
item: ThreadListStore.view().get(idx)
|
|
|
|
|
|
|
|
render: ->
|
perf(thread-list): Tailored SQLite indexes, ListTabular / ScrollRegion optimizations galore
Summary:
Allow Database models to create indexes, but don't autocreate bad ones
fix minor bug in error-reporter
Fix index on message list to make thread list lookups use proper index
Developer bar ignores state changes unless it's open
DatabaseView now asks for metadata for a set of items rather than calling a function for every item. Promise.props was cute but we really needed to make a single database query for all message metadata.
New "in" matcher so you can say `thread_id IN (1,2,3)`
Add .scroll-region-content-inner which is larger than the viewport by 1 page size, and uses transform(0,0,0) trick
ScrollRegion exposes `onScrollEnd` so listTabular, et al don't need to re-implement it with more timers. Also removing requestAnimationFrame which was causing us to request scrollTop when it was not ready, and caching the values of...
...clientHeight/scrollHeight while scrolling is in-flight
Updating rendered content 10 rows at a time (RangeChunkSize) was a bad idea. Instead, add every row in a render: pass as it comes in (less work all the time vs more work intermittently). Also remove bad requestAnimationFrame, and prevent calls to...
...updateRangeState from triggering additional calls to updateRangeState by removing `componentDidUpdate => updateRangeState `
Turning off hover (pointer-events:none) is now standard in ScrollRegion
Loading text in the scroll tooltip, instead of random date shown
Handle query parse errors by catching error and throwing a better more explanatory error
Replace "quick action" retina images with background images to make React render easier
Replace hasTagId with a faster implementation which doesn't call functions and doesn't build a temporary array
Print query durations when printing to console instead of only in metadata
Remove headers from support from ListTabular, we'll never use it
Making columns part of state was a good idea but changing the array causes the entire ListTabular to re-render. To avoid this, be smarter about updating columns. This logic could potentially go in `componentDidReceiveProps` too.
Fix specs and add 6 more for new database store functionality
Test Plan: Run 6 new specs. More in the works?
Reviewers: evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D1651
2015-06-18 11:12:48 +08:00
|
|
|
if @state.item
|
2015-07-29 05:03:55 +08:00
|
|
|
content = timestamp(@state.item.lastMessageReceivedTimestamp)
|
perf(thread-list): Tailored SQLite indexes, ListTabular / ScrollRegion optimizations galore
Summary:
Allow Database models to create indexes, but don't autocreate bad ones
fix minor bug in error-reporter
Fix index on message list to make thread list lookups use proper index
Developer bar ignores state changes unless it's open
DatabaseView now asks for metadata for a set of items rather than calling a function for every item. Promise.props was cute but we really needed to make a single database query for all message metadata.
New "in" matcher so you can say `thread_id IN (1,2,3)`
Add .scroll-region-content-inner which is larger than the viewport by 1 page size, and uses transform(0,0,0) trick
ScrollRegion exposes `onScrollEnd` so listTabular, et al don't need to re-implement it with more timers. Also removing requestAnimationFrame which was causing us to request scrollTop when it was not ready, and caching the values of...
...clientHeight/scrollHeight while scrolling is in-flight
Updating rendered content 10 rows at a time (RangeChunkSize) was a bad idea. Instead, add every row in a render: pass as it comes in (less work all the time vs more work intermittently). Also remove bad requestAnimationFrame, and prevent calls to...
...updateRangeState from triggering additional calls to updateRangeState by removing `componentDidUpdate => updateRangeState `
Turning off hover (pointer-events:none) is now standard in ScrollRegion
Loading text in the scroll tooltip, instead of random date shown
Handle query parse errors by catching error and throwing a better more explanatory error
Replace "quick action" retina images with background images to make React render easier
Replace hasTagId with a faster implementation which doesn't call functions and doesn't build a temporary array
Print query durations when printing to console instead of only in metadata
Remove headers from support from ListTabular, we'll never use it
Making columns part of state was a good idea but changing the array causes the entire ListTabular to re-render. To avoid this, be smarter about updating columns. This logic could potentially go in `componentDidReceiveProps` too.
Fix specs and add 6 more for new database store functionality
Test Plan: Run 6 new specs. More in the works?
Reviewers: evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D1651
2015-06-18 11:12:48 +08:00
|
|
|
else
|
|
|
|
content = "Loading..."
|
2015-06-06 02:50:55 +08:00
|
|
|
<div className="scroll-tooltip">
|
perf(thread-list): Tailored SQLite indexes, ListTabular / ScrollRegion optimizations galore
Summary:
Allow Database models to create indexes, but don't autocreate bad ones
fix minor bug in error-reporter
Fix index on message list to make thread list lookups use proper index
Developer bar ignores state changes unless it's open
DatabaseView now asks for metadata for a set of items rather than calling a function for every item. Promise.props was cute but we really needed to make a single database query for all message metadata.
New "in" matcher so you can say `thread_id IN (1,2,3)`
Add .scroll-region-content-inner which is larger than the viewport by 1 page size, and uses transform(0,0,0) trick
ScrollRegion exposes `onScrollEnd` so listTabular, et al don't need to re-implement it with more timers. Also removing requestAnimationFrame which was causing us to request scrollTop when it was not ready, and caching the values of...
...clientHeight/scrollHeight while scrolling is in-flight
Updating rendered content 10 rows at a time (RangeChunkSize) was a bad idea. Instead, add every row in a render: pass as it comes in (less work all the time vs more work intermittently). Also remove bad requestAnimationFrame, and prevent calls to...
...updateRangeState from triggering additional calls to updateRangeState by removing `componentDidUpdate => updateRangeState `
Turning off hover (pointer-events:none) is now standard in ScrollRegion
Loading text in the scroll tooltip, instead of random date shown
Handle query parse errors by catching error and throwing a better more explanatory error
Replace "quick action" retina images with background images to make React render easier
Replace hasTagId with a faster implementation which doesn't call functions and doesn't build a temporary array
Print query durations when printing to console instead of only in metadata
Remove headers from support from ListTabular, we'll never use it
Making columns part of state was a good idea but changing the array causes the entire ListTabular to re-render. To avoid this, be smarter about updating columns. This logic could potentially go in `componentDidReceiveProps` too.
Fix specs and add 6 more for new database store functionality
Test Plan: Run 6 new specs. More in the works?
Reviewers: evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D1651
2015-06-18 11:12:48 +08:00
|
|
|
{content}
|
2015-06-06 02:50:55 +08:00
|
|
|
</div>
|
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
class ThreadList extends React.Component
|
|
|
|
@displayName: 'ThreadList'
|
2015-05-09 10:55:32 +08:00
|
|
|
|
feat(unsafe-components): Wrap injected components, catch exceptions, clean up ComponentRegistry
Summary:
This diff gives the ComponentRegistry a cleaner, smaller API. Instead of querying by name, location or role,
it's now just location and role, and you can register components for one or more location and one or more
roles without assigning the entries in the registry separate names.
When you register with the ComponentRegistry, the syntax is also cleaner and uses the component's displayName
instead of requiring you to provide a name. You also provide the actual component when unregistering, ensuring
that you can't unregister someone else's component.
InjectedComponent and InjectedComponentSet now wrap their children in UnsafeComponent, which prevents
render/component lifecycle problems from propogating.
Existing components have been updated:
1. maxWidth / minWidth are now containerStyles.maxWidth/minWidth
2. displayName is now required to use the CR.
3. containerRequired = false can be provided to exempt a component from being wrapped in an UnsafeComponent.
This is useful because it's slightly faster and keeps DOM flat.
This diff also makes the "Show Component Regions" more awesome. It displays column regions, since they now
use the InjectedComponentSet, and also shows for InjectedComponent as well as InjectedComponentSet.
Change ComponentRegistry syntax, lots more work on safely wrapping items. See description.
Fix for inline flexbox scenarios (message actions)
Allow ~/.inbox/packages to be symlinked to a github repo
Test Plan: Run tests!
Reviewers: evan
Reviewed By: evan
Differential Revision: https://review.inboxapp.com/D1457
2015-05-01 07:10:15 +08:00
|
|
|
@containerRequired: false
|
2015-09-05 03:27:05 +08:00
|
|
|
@containerStyles:
|
|
|
|
minWidth: 300
|
|
|
|
maxWidth: 999999
|
2015-03-10 09:25:53 +08:00
|
|
|
|
2015-06-12 09:00:40 +08:00
|
|
|
constructor: (@props) ->
|
|
|
|
@state =
|
|
|
|
style: 'unknown'
|
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
componentWillMount: =>
|
2015-03-26 03:41:48 +08:00
|
|
|
c1 = new ListTabular.Column
|
2015-03-10 09:25:53 +08:00
|
|
|
name: "★"
|
2015-05-01 04:08:29 +08:00
|
|
|
resolver: (thread) =>
|
2015-09-22 09:17:05 +08:00
|
|
|
[
|
2015-09-09 01:53:07 +08:00
|
|
|
<ThreadListIcon thread={thread} />
|
|
|
|
<MailImportantIcon thread={thread} />
|
2015-09-22 07:21:57 +08:00
|
|
|
<InjectedComponentSet
|
|
|
|
inline={true}
|
|
|
|
containersRequired={false}
|
|
|
|
matching={role: "ThreadListIcon"}
|
2015-09-22 09:17:05 +08:00
|
|
|
className="thread-injected-icons"
|
2015-09-22 07:21:57 +08:00
|
|
|
exposedProps={thread: thread}/>
|
2015-09-22 09:17:05 +08:00
|
|
|
]
|
2015-03-10 09:25:53 +08:00
|
|
|
|
2015-03-26 03:41:48 +08:00
|
|
|
c2 = new ListTabular.Column
|
2015-07-22 02:50:08 +08:00
|
|
|
name: "Participants"
|
2015-03-26 09:22:52 +08:00
|
|
|
width: 200
|
2015-05-01 04:08:29 +08:00
|
|
|
resolver: (thread) =>
|
feat(*): draft icon, misc fixes, and WorkspaceStore / custom toolbar in secondary windows
Summary:
Features:
- ThreadListParticipants ignores drafts when computing participants, renders "Draft" label, pending design
- Put the WorkspaceStore in every window—means they all get toolbars and custom gumdrop icons on Mac OS X
Bug Fixes:
- Never display notifications for email the user just sent
- Fix obscure issue with DatabaseView trying to update metadata on items it froze. This resolves issue with names remaining bold after marking as read, drafts not appearing in message list immediately.
- When you pop out a draft, save it first and *wait* for the commit() promise to succeed.
- If you scroll very fast, you node.contentWindow can be null in eventedIframe
Other:
Make it OK to re-register the same component
Make it possible to unregister a hot window
Break the Sheet Toolbar out into it's own file to make things manageable
Replace `package.windowPropsReceived` with a store-style model where anyone can listen for changes to `windowProps`
When I put the WorkspaceStore in every window, I ran into a problem because the package was no longer rendering an instance of the Composer, it was declaring a root sheet with a composer in it. This meant that it was actually a React component that needed to listen to window props, not the package itself.
`atom` is already an event emitter, so I added a `onWindowPropsReceived` hook so that components can listen to window props as if they were listening to a store. I think this might be more flexible than only broadcasting the props change event to packages.
Test Plan: Run tests
Reviewers: evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D1592
2015-06-04 07:02:19 +08:00
|
|
|
hasDraft = _.find (thread.metadata ? []), (m) -> m.draft
|
|
|
|
if hasDraft
|
|
|
|
<div style={display: 'flex'}>
|
|
|
|
<ThreadListParticipants thread={thread} />
|
2015-06-06 02:40:44 +08:00
|
|
|
<RetinaImg name="icon-draft-pencil.png"
|
|
|
|
className="draft-icon"
|
|
|
|
mode={RetinaImg.Mode.ContentPreserve} />
|
feat(*): draft icon, misc fixes, and WorkspaceStore / custom toolbar in secondary windows
Summary:
Features:
- ThreadListParticipants ignores drafts when computing participants, renders "Draft" label, pending design
- Put the WorkspaceStore in every window—means they all get toolbars and custom gumdrop icons on Mac OS X
Bug Fixes:
- Never display notifications for email the user just sent
- Fix obscure issue with DatabaseView trying to update metadata on items it froze. This resolves issue with names remaining bold after marking as read, drafts not appearing in message list immediately.
- When you pop out a draft, save it first and *wait* for the commit() promise to succeed.
- If you scroll very fast, you node.contentWindow can be null in eventedIframe
Other:
Make it OK to re-register the same component
Make it possible to unregister a hot window
Break the Sheet Toolbar out into it's own file to make things manageable
Replace `package.windowPropsReceived` with a store-style model where anyone can listen for changes to `windowProps`
When I put the WorkspaceStore in every window, I ran into a problem because the package was no longer rendering an instance of the Composer, it was declaring a root sheet with a composer in it. This meant that it was actually a React component that needed to listen to window props, not the package itself.
`atom` is already an event emitter, so I added a `onWindowPropsReceived` hook so that components can listen to window props as if they were listening to a store. I think this might be more flexible than only broadcasting the props change event to packages.
Test Plan: Run tests
Reviewers: evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D1592
2015-06-04 07:02:19 +08:00
|
|
|
</div>
|
|
|
|
else
|
|
|
|
<ThreadListParticipants thread={thread} />
|
2015-03-10 09:25:53 +08:00
|
|
|
|
2015-07-24 05:30:32 +08:00
|
|
|
c3LabelComponentCache = {}
|
|
|
|
|
2015-03-10 09:25:53 +08:00
|
|
|
c3 = new ListTabular.Column
|
2015-03-26 03:41:48 +08:00
|
|
|
name: "Message"
|
2015-03-10 09:25:53 +08:00
|
|
|
flex: 4
|
2015-05-01 04:08:29 +08:00
|
|
|
resolver: (thread) =>
|
2015-07-18 07:34:48 +08:00
|
|
|
attachment = []
|
2015-07-22 02:50:08 +08:00
|
|
|
labels = []
|
2015-09-24 06:48:03 +08:00
|
|
|
if thread.hasAttachments
|
2015-07-18 07:34:48 +08:00
|
|
|
attachment = <div className="thread-icon thread-icon-attachment"></div>
|
2015-07-22 02:50:08 +08:00
|
|
|
|
2015-09-05 03:23:15 +08:00
|
|
|
currentCategoryId = FocusedMailViewStore.mailView()?.categoryId()
|
2015-07-22 02:50:08 +08:00
|
|
|
allCategoryId = CategoryStore.getStandardCategory('all')?.id
|
2015-09-09 01:53:07 +08:00
|
|
|
|
|
|
|
ignoredIds = [currentCategoryId]
|
|
|
|
ignoredIds.push(cat.id) for cat in CategoryStore.getHiddenCategories()
|
2015-07-24 05:30:32 +08:00
|
|
|
|
2015-09-02 05:47:22 +08:00
|
|
|
for label in (thread.sortedLabels())
|
2015-07-22 02:50:08 +08:00
|
|
|
continue if label.id in ignoredIds
|
2015-09-09 01:53:07 +08:00
|
|
|
c3LabelComponentCache[label.id] ?= <MailLabel label={label} key={label.id} />
|
2015-07-24 05:30:32 +08:00
|
|
|
labels.push c3LabelComponentCache[label.id]
|
2015-07-22 02:50:08 +08:00
|
|
|
|
2015-03-26 03:41:48 +08:00
|
|
|
<span className="details">
|
2015-07-22 02:50:08 +08:00
|
|
|
{labels}
|
2015-03-26 03:41:48 +08:00
|
|
|
<span className="subject">{subject(thread.subject)}</span>
|
|
|
|
<span className="snippet">{thread.snippet}</span>
|
2015-07-18 07:34:48 +08:00
|
|
|
{attachment}
|
2015-03-26 03:41:48 +08:00
|
|
|
</span>
|
2015-03-10 09:25:53 +08:00
|
|
|
|
|
|
|
c4 = new ListTabular.Column
|
|
|
|
name: "Date"
|
2015-05-01 04:08:29 +08:00
|
|
|
resolver: (thread) =>
|
2015-07-29 05:03:55 +08:00
|
|
|
<span className="timestamp">{timestamp(thread.lastMessageReceivedTimestamp)}</span>
|
2015-03-10 09:25:53 +08:00
|
|
|
|
2015-06-12 09:38:57 +08:00
|
|
|
c5 = new ListTabular.Column
|
|
|
|
name: "HoverActions"
|
|
|
|
resolver: (thread) =>
|
2015-09-05 03:23:15 +08:00
|
|
|
currentCategoryId = FocusedMailViewStore.mailView()?.categoryId()
|
2015-08-14 05:56:22 +08:00
|
|
|
<ThreadListQuickActions thread={thread} categoryId={currentCategoryId}/>
|
2015-06-12 09:38:57 +08:00
|
|
|
|
|
|
|
@wideColumns = [c1, c2, c3, c4, c5]
|
2015-06-12 09:00:40 +08:00
|
|
|
|
|
|
|
cNarrow = new ListTabular.Column
|
|
|
|
name: "Item"
|
2015-06-18 13:38:55 +08:00
|
|
|
flex: 1
|
2015-06-12 09:00:40 +08:00
|
|
|
resolver: (thread) =>
|
|
|
|
pencil = []
|
2015-07-18 07:34:48 +08:00
|
|
|
attachment = []
|
2015-06-12 09:00:40 +08:00
|
|
|
hasDraft = _.find (thread.metadata ? []), (m) -> m.draft
|
2015-09-24 06:48:03 +08:00
|
|
|
if thread.hasAttachments
|
|
|
|
attachment = <div className="thread-icon thread-icon-attachment"></div>
|
2015-06-12 09:00:40 +08:00
|
|
|
if hasDraft
|
|
|
|
pencil = <RetinaImg name="icon-draft-pencil.png" className="draft-icon" mode={RetinaImg.Mode.ContentPreserve} />
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<div style={display: 'flex'}>
|
|
|
|
<ThreadListIcon thread={thread} />
|
|
|
|
<ThreadListParticipants thread={thread} />
|
|
|
|
{pencil}
|
2015-07-18 07:34:48 +08:00
|
|
|
<span style={flex:1}></span>
|
|
|
|
{attachment}
|
2015-07-29 05:03:55 +08:00
|
|
|
<span className="timestamp">{timestamp(thread.lastMessageReceivedTimestamp)}</span>
|
2015-06-12 09:00:40 +08:00
|
|
|
</div>
|
2015-09-09 01:53:07 +08:00
|
|
|
<MailImportantIcon thread={thread} />
|
2015-06-12 09:00:40 +08:00
|
|
|
<div className="subject">{subject(thread.subject)}</div>
|
|
|
|
<div className="snippet">{thread.snippet}</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
@narrowColumns = [cNarrow]
|
|
|
|
|
2015-04-09 10:25:00 +08:00
|
|
|
@commands =
|
refactor(*): Thread list fixes, flexible workspace store, multiple root sheets
Summary:
Remember to remove all the event listeners added to email frame
New files tab, queryable filename, not attribute
Rename ThreadSelectionBar to RootSelectionBar to go with RootCenterComponent, make it appear for draft selection and file selection as well
Initial file list and file list store, File Location
Remove unnecessary shouldComponentUpdate
Always track whether new requests have happened since ours to prevent out of order triggers
Always scroll to the current [focused/keyboard-cursor] in lists
So goodbye to the trash tag
Only scroll to current item if focus or keyboard has moved
Show message snippet in notification if no subject line
Make the RootSelectionBar pull items from Component Registry
New Archive button (prettier than the other one)
Refactor event additions to iframe so iframe can be used for file display also
Thread List is no longer the uber root package - drafts and files moved to separate packages
WorkspaceStore now allows packages to register sheets, "view" concept replaced with "root sheet" concept, "mode" may not be observed by all sheets, and is now called "preferred mode"
Don't animate transitions between two root sheets
Mode switch is only visible on root sheets that support multiple modes
Account sidebar now shows "Views" that have registered themselves: drafts and files for now
Model Selection Bar is now a component, just like ModelList. Meant to be in the toolbar above a Model List
Misc supporting changes
New files package which registers it's views and components
Rename files package to `file-list`
Move checkmark column down into model list
Don't throw exception if shift-down arrow and nothing selected
Takes a long time on login to fetch first page of threads, make pages smaller
Displaynames, spec fixes
Test Plan: Run tests
Reviewers: evan
Reviewed By: evan
Differential Revision: https://review.inboxapp.com/D1412
2015-04-11 05:33:05 +08:00
|
|
|
'core:remove-item': @_onArchive
|
2015-06-27 05:06:31 +08:00
|
|
|
'core:star-item': @_onStarItem
|
2015-04-09 10:25:00 +08:00
|
|
|
'core:remove-and-previous': -> Actions.archiveAndPrevious()
|
|
|
|
'core:remove-and-next': -> Actions.archiveAndNext()
|
2015-06-18 04:14:45 +08:00
|
|
|
|
2015-04-23 07:41:29 +08:00
|
|
|
@itemPropsProvider = (item) ->
|
2015-04-25 02:33:10 +08:00
|
|
|
className: classNames
|
2015-07-16 23:54:20 +08:00
|
|
|
'unread': item.unread
|
2015-07-24 02:10:51 +08:00
|
|
|
'data-thread-id': item.id
|
2015-04-09 10:25:00 +08:00
|
|
|
|
2015-06-12 09:00:40 +08:00
|
|
|
componentDidMount: =>
|
|
|
|
window.addEventListener('resize', @_onResize, true)
|
|
|
|
@_onResize()
|
|
|
|
|
|
|
|
componentWillUnmount: =>
|
2015-08-04 02:08:15 +08:00
|
|
|
window.removeEventListener('resize', @_onResize, true)
|
2015-06-12 09:00:40 +08:00
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
render: =>
|
2015-06-12 09:00:40 +08:00
|
|
|
if @state.style is 'wide'
|
2015-08-04 10:09:08 +08:00
|
|
|
<MultiselectList
|
|
|
|
dataStore={ThreadListStore}
|
|
|
|
columns={@wideColumns}
|
|
|
|
commands={@commands}
|
|
|
|
itemPropsProvider={@itemPropsProvider}
|
|
|
|
itemHeight={39}
|
|
|
|
className="thread-list"
|
|
|
|
scrollTooltipComponent={ThreadListScrollTooltip}
|
|
|
|
emptyComponent={EmptyState}
|
|
|
|
onDragStart={@_onDragStart}
|
|
|
|
onDragEnd={@_onDragEnd}
|
|
|
|
draggable="true"
|
|
|
|
collection="thread" />
|
2015-06-12 09:00:40 +08:00
|
|
|
else if @state.style is 'narrow'
|
2015-08-04 10:09:08 +08:00
|
|
|
<MultiselectList
|
|
|
|
dataStore={ThreadListStore}
|
|
|
|
columns={@narrowColumns}
|
|
|
|
commands={@commands}
|
|
|
|
itemPropsProvider={@itemPropsProvider}
|
|
|
|
itemHeight={90}
|
|
|
|
className="thread-list thread-list-narrow"
|
|
|
|
scrollTooltipComponent={ThreadListScrollTooltip}
|
|
|
|
emptyComponent={EmptyState}
|
|
|
|
collection="thread" />
|
2015-06-12 09:00:40 +08:00
|
|
|
else
|
|
|
|
<div></div>
|
|
|
|
|
2015-07-24 02:10:51 +08:00
|
|
|
_threadIdAtPoint: (x, y) ->
|
|
|
|
item = document.elementFromPoint(event.clientX, event.clientY).closest('.list-item')
|
|
|
|
return null unless item
|
|
|
|
return item.dataset.threadId
|
|
|
|
|
|
|
|
_onDragStart: (event) =>
|
|
|
|
itemThreadId = @_threadIdAtPoint(event.clientX, event.clientY)
|
|
|
|
unless itemThreadId
|
|
|
|
event.preventDefault()
|
|
|
|
return
|
|
|
|
|
|
|
|
if itemThreadId in ThreadListStore.view().selection.ids()
|
|
|
|
dragThreadIds = ThreadListStore.view().selection.ids()
|
|
|
|
else
|
|
|
|
dragThreadIds = [itemThreadId]
|
|
|
|
|
|
|
|
event.dataTransfer.effectAllowed = "move"
|
|
|
|
event.dataTransfer.dragEffect = "move"
|
|
|
|
|
|
|
|
canvas = CanvasUtils.canvasWithThreadDragImage(dragThreadIds.length)
|
|
|
|
event.dataTransfer.setDragImage(canvas, 10, 10)
|
|
|
|
event.dataTransfer.setData('nylas-thread-ids', JSON.stringify(dragThreadIds))
|
|
|
|
return
|
|
|
|
|
|
|
|
_onDragEnd: (event) =>
|
|
|
|
|
2015-06-12 09:00:40 +08:00
|
|
|
_onResize: (event) =>
|
|
|
|
current = @state.style
|
|
|
|
desired = if React.findDOMNode(@).offsetWidth < 540 then 'narrow' else 'wide'
|
|
|
|
if current isnt desired
|
|
|
|
@setState(style: desired)
|
2015-03-10 09:25:53 +08:00
|
|
|
|
2015-04-09 10:25:00 +08:00
|
|
|
# Additional Commands
|
2015-03-21 01:23:50 +08:00
|
|
|
|
2015-06-27 05:47:14 +08:00
|
|
|
_onStarItem: =>
|
2015-08-19 01:31:18 +08:00
|
|
|
return unless ThreadListStore.view()
|
|
|
|
|
2015-06-27 05:47:14 +08:00
|
|
|
if WorkspaceStore.layoutMode() is "list" and WorkspaceStore.topSheet() is WorkspaceStore.Sheet.Thread
|
|
|
|
Actions.toggleStarFocused()
|
|
|
|
else if ThreadListStore.view().selection.count() > 0
|
|
|
|
Actions.toggleStarSelection()
|
|
|
|
else
|
|
|
|
Actions.toggleStarFocused()
|
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
_onArchive: =>
|
2015-08-19 01:31:18 +08:00
|
|
|
return unless ThreadListStore.view()
|
|
|
|
|
2015-06-27 05:47:14 +08:00
|
|
|
if WorkspaceStore.layoutMode() is "list" and WorkspaceStore.topSheet() is WorkspaceStore.Sheet.Thread
|
refactor(*): Thread list fixes, flexible workspace store, multiple root sheets
Summary:
Remember to remove all the event listeners added to email frame
New files tab, queryable filename, not attribute
Rename ThreadSelectionBar to RootSelectionBar to go with RootCenterComponent, make it appear for draft selection and file selection as well
Initial file list and file list store, File Location
Remove unnecessary shouldComponentUpdate
Always track whether new requests have happened since ours to prevent out of order triggers
Always scroll to the current [focused/keyboard-cursor] in lists
So goodbye to the trash tag
Only scroll to current item if focus or keyboard has moved
Show message snippet in notification if no subject line
Make the RootSelectionBar pull items from Component Registry
New Archive button (prettier than the other one)
Refactor event additions to iframe so iframe can be used for file display also
Thread List is no longer the uber root package - drafts and files moved to separate packages
WorkspaceStore now allows packages to register sheets, "view" concept replaced with "root sheet" concept, "mode" may not be observed by all sheets, and is now called "preferred mode"
Don't animate transitions between two root sheets
Mode switch is only visible on root sheets that support multiple modes
Account sidebar now shows "Views" that have registered themselves: drafts and files for now
Model Selection Bar is now a component, just like ModelList. Meant to be in the toolbar above a Model List
Misc supporting changes
New files package which registers it's views and components
Rename files package to `file-list`
Move checkmark column down into model list
Don't throw exception if shift-down arrow and nothing selected
Takes a long time on login to fetch first page of threads, make pages smaller
Displaynames, spec fixes
Test Plan: Run tests
Reviewers: evan
Reviewed By: evan
Differential Revision: https://review.inboxapp.com/D1412
2015-04-11 05:33:05 +08:00
|
|
|
Actions.archive()
|
2015-06-27 05:47:14 +08:00
|
|
|
else if ThreadListStore.view().selection.count() > 0
|
refactor(*): Thread list fixes, flexible workspace store, multiple root sheets
Summary:
Remember to remove all the event listeners added to email frame
New files tab, queryable filename, not attribute
Rename ThreadSelectionBar to RootSelectionBar to go with RootCenterComponent, make it appear for draft selection and file selection as well
Initial file list and file list store, File Location
Remove unnecessary shouldComponentUpdate
Always track whether new requests have happened since ours to prevent out of order triggers
Always scroll to the current [focused/keyboard-cursor] in lists
So goodbye to the trash tag
Only scroll to current item if focus or keyboard has moved
Show message snippet in notification if no subject line
Make the RootSelectionBar pull items from Component Registry
New Archive button (prettier than the other one)
Refactor event additions to iframe so iframe can be used for file display also
Thread List is no longer the uber root package - drafts and files moved to separate packages
WorkspaceStore now allows packages to register sheets, "view" concept replaced with "root sheet" concept, "mode" may not be observed by all sheets, and is now called "preferred mode"
Don't animate transitions between two root sheets
Mode switch is only visible on root sheets that support multiple modes
Account sidebar now shows "Views" that have registered themselves: drafts and files for now
Model Selection Bar is now a component, just like ModelList. Meant to be in the toolbar above a Model List
Misc supporting changes
New files package which registers it's views and components
Rename files package to `file-list`
Move checkmark column down into model list
Don't throw exception if shift-down arrow and nothing selected
Takes a long time on login to fetch first page of threads, make pages smaller
Displaynames, spec fixes
Test Plan: Run tests
Reviewers: evan
Reviewed By: evan
Differential Revision: https://review.inboxapp.com/D1412
2015-04-11 05:33:05 +08:00
|
|
|
Actions.archiveSelection()
|
2015-04-01 08:19:17 +08:00
|
|
|
else
|
2015-06-27 05:47:14 +08:00
|
|
|
Actions.archive()
|
2015-05-01 04:08:29 +08:00
|
|
|
|
|
|
|
|
|
|
|
module.exports = ThreadList
|