diff --git a/internal_packages/attachments/package.json b/internal_packages/attachments/package.json index 42c35c833..5dfb572ba 100644 --- a/internal_packages/attachments/package.json +++ b/internal_packages/attachments/package.json @@ -13,6 +13,7 @@ "windowTypes": { "default": true, "composer": true, - "composer-preload": true + "composer-preload": true, + "thread-popout": true } } diff --git a/internal_packages/composer-emoji/package.json b/internal_packages/composer-emoji/package.json index a17c322c9..4cdf994d9 100644 --- a/internal_packages/composer-emoji/package.json +++ b/internal_packages/composer-emoji/package.json @@ -21,7 +21,8 @@ }, "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true }, "license": "GPL-3.0" } diff --git a/internal_packages/composer-markdown/package.json b/internal_packages/composer-markdown/package.json index d2471cd55..14a597e0f 100644 --- a/internal_packages/composer-markdown/package.json +++ b/internal_packages/composer-markdown/package.json @@ -16,7 +16,8 @@ }, "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true }, "dependencies": { "marked": "^0.3", diff --git a/internal_packages/composer-signature/package.json b/internal_packages/composer-signature/package.json index be75f2ba1..045b0da8c 100755 --- a/internal_packages/composer-signature/package.json +++ b/internal_packages/composer-signature/package.json @@ -10,7 +10,8 @@ }, "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true }, "dependencies": { } diff --git a/internal_packages/composer-spellcheck/package.json b/internal_packages/composer-spellcheck/package.json index 834087dc4..546255970 100755 --- a/internal_packages/composer-spellcheck/package.json +++ b/internal_packages/composer-spellcheck/package.json @@ -10,7 +10,8 @@ }, "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true }, "dependencies": { } diff --git a/internal_packages/composer-templates/package.json b/internal_packages/composer-templates/package.json index 99bfb2a07..6e2067772 100755 --- a/internal_packages/composer-templates/package.json +++ b/internal_packages/composer-templates/package.json @@ -16,6 +16,7 @@ }, "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true } } diff --git a/internal_packages/composer-translate/package.json b/internal_packages/composer-translate/package.json index 716397418..b04221ed8 100755 --- a/internal_packages/composer-translate/package.json +++ b/internal_packages/composer-translate/package.json @@ -19,6 +19,7 @@ }, "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true } } diff --git a/internal_packages/composer/lib/main.es6 b/internal_packages/composer/lib/main.es6 index 72b2f8f0d..57ba29ccd 100644 --- a/internal_packages/composer/lib/main.es6 +++ b/internal_packages/composer/lib/main.es6 @@ -115,6 +115,10 @@ export function activate() { ComponentRegistry.register(ComposeButton, { location: WorkspaceStore.Location.RootSidebar.Toolbar, }); + } else if (NylasEnv.isThreadWindow()) { + ComponentRegistry.register(ComposerViewForDraftClientId, { + role: 'Composer', + }); } else { NylasEnv.getCurrentWindow().setMinimumSize(480, 250); ComponentRegistry.register(ComposerWithWindowProps, { diff --git a/internal_packages/composer/package.json b/internal_packages/composer/package.json index 9dfb64905..a0f2b67fe 100644 --- a/internal_packages/composer/package.json +++ b/internal_packages/composer/package.json @@ -15,6 +15,7 @@ "windowTypes": { "default": true, "composer": true, - "composer-preload": true + "composer-preload": true, + "thread-popout": true } } diff --git a/internal_packages/keybase/package.json b/internal_packages/keybase/package.json index 001b26605..fef5a5255 100755 --- a/internal_packages/keybase/package.json +++ b/internal_packages/keybase/package.json @@ -17,6 +17,7 @@ "license": "GPL-3.0", "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true } } diff --git a/internal_packages/message-list/lib/main.cjsx b/internal_packages/message-list/lib/main.cjsx index 66ec072c3..47a7aaf19 100644 --- a/internal_packages/message-list/lib/main.cjsx +++ b/internal_packages/message-list/lib/main.cjsx @@ -1,6 +1,9 @@ {ComponentRegistry, ExtensionRegistry, - WorkspaceStore} = require 'nylas-exports' + WorkspaceStore, + DatabaseStore, + Actions, + Thread} = require 'nylas-exports' MessageList = require("./message-list") MessageListHiddenMessagesToggle = require('./message-list-hidden-messages-toggle').default @@ -10,18 +13,27 @@ SidebarParticipantPicker = require('./sidebar-participant-picker').default module.exports = activate: -> - # Register Message List Actions we provide globally - ComponentRegistry.register MessageList, - location: WorkspaceStore.Location.MessageList + if NylasEnv.isMainWindow() + # Register Message List Actions we provide globally + ComponentRegistry.register MessageList, + location: WorkspaceStore.Location.MessageList - ComponentRegistry.register SidebarParticipantPicker, - location: WorkspaceStore.Location.MessageListSidebar + ComponentRegistry.register SidebarParticipantPicker, + location: WorkspaceStore.Location.MessageListSidebar - ComponentRegistry.register SidebarPluginContainer, - location: WorkspaceStore.Location.MessageListSidebar + ComponentRegistry.register SidebarPluginContainer, + location: WorkspaceStore.Location.MessageListSidebar - ComponentRegistry.register MessageListHiddenMessagesToggle, - role: 'MessageListHeaders' + ComponentRegistry.register MessageListHiddenMessagesToggle, + role: 'MessageListHeaders' + else + # This is for the thread-popout window. + ComponentRegistry.register(MessageList, {location: WorkspaceStore.Location.Center}) + threadId = NylasEnv.getWindowProps().threadId; + # We need to locate the thread and focus it so that the MessageList displays it + DatabaseStore.find(Thread, threadId).then((thread) => + Actions.setFocus({collection: 'thread', item: thread}) + ) deactivate: -> ComponentRegistry.unregister MessageList diff --git a/internal_packages/message-list/lib/message-list.cjsx b/internal_packages/message-list/lib/message-list.cjsx index 405a72cff..41048e59c 100644 --- a/internal_packages/message-list/lib/message-list.cjsx +++ b/internal_packages/message-list/lib/message-list.cjsx @@ -204,6 +204,7 @@ class MessageList extends React.Component
+ {@_renderPopoutToggle()} _renderExpandToggle: => @@ -218,6 +219,17 @@ class MessageList extends React.Component + _renderPopoutToggle: => + if NylasEnv.isThreadWindow() +
+ +
+ else +
+ +
+ + _renderReplyArea: =>
@@ -250,6 +262,18 @@ class MessageList extends React.Component node = ReactDOM.findDOMNode(@) Actions.printThread(@state.currentThread, node.innerHTML) + _onPopThreadIn: => + return unless @state.currentThread + Actions.focusThreadMainWindow(@state.currentThread) + NylasEnv.close() + + _onPopoutThread: => + return unless @state.currentThread + Actions.popoutThread(@state.currentThread) + # This returns the single-pane view to the inbox, and does nothing for + # double-pane view because we're at the root sheet. + Actions.popSheet() + _onClickReplyArea: => return unless @state.currentThread Actions.composeReply({ diff --git a/internal_packages/message-list/package.json b/internal_packages/message-list/package.json index 5c4a8d614..0524f4893 100755 --- a/internal_packages/message-list/package.json +++ b/internal_packages/message-list/package.json @@ -7,5 +7,9 @@ "private": true, "engines": { "nylas": "*" + }, + "windowTypes": { + "default": true, + "thread-popout": true } } diff --git a/internal_packages/phishing-detection/package.json b/internal_packages/phishing-detection/package.json index d5e00886c..baeb9e80e 100644 --- a/internal_packages/phishing-detection/package.json +++ b/internal_packages/phishing-detection/package.json @@ -14,7 +14,8 @@ }, "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true }, "dependencies": { "tld": "^0.0.2" diff --git a/internal_packages/send-and-archive/package.json b/internal_packages/send-and-archive/package.json index 29370271d..be14076d3 100755 --- a/internal_packages/send-and-archive/package.json +++ b/internal_packages/send-and-archive/package.json @@ -10,7 +10,8 @@ }, "windowTypes": { "default": true, - "composer": true + "composer": true, + "thread-popout": true }, "dependencies": { } diff --git a/internal_packages/thread-list/lib/thread-list.cjsx b/internal_packages/thread-list/lib/thread-list.cjsx index f8fea53f8..058b6f59f 100644 --- a/internal_packages/thread-list/lib/thread-list.cjsx +++ b/internal_packages/thread-list/lib/thread-list.cjsx @@ -101,6 +101,7 @@ class ThreadList extends React.Component scrollTooltipComponent={ThreadListScrollTooltip} emptyComponent={EmptyListState} keymapHandlers={@_keymapHandlers()} + onDoubleClick={(thread) -> Actions.popoutThread(thread)} onDragStart={@_onDragStart} onDragEnd={@_onDragEnd} draggable="true" /> diff --git a/src/flux/actions.coffee b/src/flux/actions.coffee index 1dc960bfb..a332b3b98 100644 --- a/src/flux/actions.coffee +++ b/src/flux/actions.coffee @@ -305,6 +305,30 @@ class Actions ### @printThread: ActionScopeWindow + ### + Public: Display the thread in a new popout window + + *Scope: Window* + + ``` + thread = + Actions.popoutThread(thread) + ``` + ### + @popoutThread: ActionScopeWindow + + ### + Public: Display the thread in the main window + + *Scope: Global* + + ``` + thread = + Actions.focusThreadMainWindow(thread) + ``` + ### + @focusThreadMainWindow: ActionScopeGlobal + ### Public: Create a new reply to the provided threadId and messageId and populate it with the body provided. diff --git a/src/flux/stores/message-store.coffee b/src/flux/stores/message-store.coffee index f4c2c3afd..fc54b1a61 100644 --- a/src/flux/stores/message-store.coffee +++ b/src/flux/stores/message-store.coffee @@ -107,6 +107,8 @@ class MessageStore extends NylasStore @listenTo Actions.toggleAllMessagesExpanded, @_onToggleAllMessagesExpanded @listenTo Actions.toggleHiddenMessages, @_onToggleHiddenMessages @listenTo FocusedPerspectiveStore, @_onPerspectiveChanged + @listenTo Actions.popoutThread, @_onPopoutThread + @listenTo Actions.focusThreadMainWindow, @_onFocusThreadMainWindow _onPerspectiveChanged: => @trigger() @@ -313,6 +315,20 @@ class MessageStore extends NylasStore items + _onPopoutThread: (thread) -> + NylasEnv.newWindow + title: false, # MessageList already displays the thread subject + hidden: false, + windowKey: "thread-#{thread.id}", + windowType: 'thread-popout', + windowProps: threadId: thread.id, + + _onFocusThreadMainWindow: (thread) -> + if NylasEnv.isMainWindow() + Actions.setFocus({collection: 'thread', item: thread}) + NylasEnv.focus() + + store = new MessageStore() store.registerExtension = deprecate( 'MessageStore.registerExtension', diff --git a/src/nylas-env.coffee b/src/nylas-env.coffee index 51494d2b1..20d00284f 100644 --- a/src/nylas-env.coffee +++ b/src/nylas-env.coffee @@ -360,6 +360,9 @@ class NylasEnvConstructor isComposerWindow: -> @getWindowType() in ["composer", "composer-preload"] + isThreadWindow: -> + @getWindowType() is 'thread-popout' + getWindowType: -> @getLoadSettings().windowType diff --git a/src/pro b/src/pro index ddb1789ab..26431475c 160000 --- a/src/pro +++ b/src/pro @@ -1 +1 @@ -Subproject commit ddb1789abc9aa34ac9a3fb893e7ee71e7893af67 +Subproject commit 26431475c6590262a190e572d0717fd730827cff diff --git a/static/images/message-list/thread-popin@2x.png b/static/images/message-list/thread-popin@2x.png new file mode 100644 index 000000000..8b16614be Binary files /dev/null and b/static/images/message-list/thread-popin@2x.png differ diff --git a/static/images/message-list/thread-popout@2x.png b/static/images/message-list/thread-popout@2x.png new file mode 100644 index 000000000..c851ed73a Binary files /dev/null and b/static/images/message-list/thread-popout@2x.png differ