From 5acbdb09554c0f951c41e622e8f98857990ac5c5 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Thu, 23 Jul 2015 11:18:42 -0700 Subject: [PATCH] fix(workspace): Support for hidden locations / columns Summary: - New control will likely be shortlived - SDW mocking up replacement for when settings UI lands - New action for toggling location hidden - New rule for mail labels: can't remove "Sent" Test Plan: Run tests - none new atm Reviewers: evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D1782 --- .../message-list/lib/message-list.cjsx | 31 +++++++++++++++++- .../stylesheets/message-list.less | 21 ++++++++---- .../mode-switch/lib/mode-toggle.cjsx | 2 +- src/components/mail-label.cjsx | 7 ++-- src/flux/actions.coffee | 9 +++++ src/flux/stores/workspace-store.coffee | 29 ++++++++++++++-- src/sheet-toolbar.cjsx | 1 + src/sheet.cjsx | 1 + .../icon-thread-hidesidebar@2x.png | Bin 0 -> 15219 bytes .../icon-thread-showsidebar@2x.png | Bin 0 -> 15216 bytes static/workspace.less | 6 ++-- 11 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 static/images/message-list-toggle-sidebar/icon-thread-hidesidebar@2x.png create mode 100644 static/images/message-list-toggle-sidebar/icon-thread-showsidebar@2x.png diff --git a/internal_packages/message-list/lib/message-list.cjsx b/internal_packages/message-list/lib/message-list.cjsx index f39089a18..a982bbfe3 100755 --- a/internal_packages/message-list/lib/message-list.cjsx +++ b/internal_packages/message-list/lib/message-list.cjsx @@ -8,6 +8,7 @@ MessageItem = require "./message-item" DraftStore, MessageStore, DatabaseStore, + WorkspaceStore, ComponentRegistry, ChangeLabelsTask, UpdateThreadsTask} = require("nylas-exports") @@ -20,6 +21,34 @@ MessageItem = require "./message-item" MailLabel, InjectedComponent} = require('nylas-component-kit') +class HideSidebarButton extends React.Component + constructor: (@props) -> + @column = WorkspaceStore.Location.MessageListSidebar + @state = @getStateFromStores() + + componentDidMount: => + @unlisten = WorkspaceStore.listen => @setState(@getStateFromStores()) + + componentWillUnmount: => + @unlisten() + + render: => + if @state.hidden + contents = {label: 'Show Sidebar', name: 'icon-thread-showsidebar.png'} + else + contents = {label: 'Hide Sidebar', name: 'icon-thread-hidesidebar.png'} + +
+ + {contents.label} +
+ + _onClick: => + Actions.toggleWorkspaceLocationHidden(@column) + + getStateFromStores: => + {hidden: WorkspaceStore.isLocationHidden(@column)} + class MessageListScrollTooltip extends React.Component @displayName: 'MessageListScrollTooltip' @propTypes: @@ -226,7 +255,7 @@ class MessageList extends React.Component _renderSubject: ->
-
{@state.messages.length} {if @state.messages.length is 1 then "message" else "messages"}
+ {@state.currentThread?.subject} {@_renderLabels()}
diff --git a/internal_packages/message-list/stylesheets/message-list.less b/internal_packages/message-list/stylesheets/message-list.less index 34db31336..8cca9c14f 100644 --- a/internal_packages/message-list/stylesheets/message-list.less +++ b/internal_packages/message-list/stylesheets/message-list.less @@ -49,6 +49,19 @@ } } +.hide-sidebar-button { + font-size: @font-size-small; + color: @text-color-subtle; + margin-left: @spacing-standard; + cursor:default; + .img-wrap { + margin-right: @spacing-half; + position: relative; + top: -1px; + } + img { background: @text-color-subtle; } +} + #message-list { display: flex; flex-direction: column; @@ -64,7 +77,7 @@ width: calc(~"100% - 12px"); max-width: @message-max-width; margin: 11px auto 10px auto; - padding: 0 20px; + padding-left: 20px; -webkit-user-select: text; line-height: @font-size-large * 1.8; } @@ -73,12 +86,6 @@ color: @text-color; margin-right: @spacing-standard; } - .message-count { - float: right; - font-size: @font-size-small; - color: @text-color-very-subtle; - } - .message-list-headers { margin: 0 auto; width: 100%; diff --git a/internal_packages/mode-switch/lib/mode-toggle.cjsx b/internal_packages/mode-switch/lib/mode-toggle.cjsx index d926b2817..11eceff63 100644 --- a/internal_packages/mode-switch/lib/mode-toggle.cjsx +++ b/internal_packages/mode-switch/lib/mode-toggle.cjsx @@ -21,7 +21,7 @@ class ModeToggle extends React.Component return
unless @state.visible
{content} x = {content}{x}
- _renderX: -> + _removable: -> + isLockedLabel = @props.label.name in CategoryStore.LockedCategoryNames + return @props.onRemove and not isLockedLabel module.exports = MailLabel diff --git a/src/flux/actions.coffee b/src/flux/actions.coffee index d1d90a91c..c2f8c348d 100644 --- a/src/flux/actions.coffee +++ b/src/flux/actions.coffee @@ -175,6 +175,15 @@ class Actions ### @selectLayoutMode: ActionScopeWindow + ### + Public: Toggle whether a particular column is visible. Call this action + with one of the Sheet location constants: + + ``` + Actions.toggleWorkspaceLocationHidden(WorkspaceStore.Location.MessageListSidebar) + ``` + ### + @toggleWorkspaceLocationHidden: ActionScopeWindow ### Public: Focus the keyboard on an item in a collection. This action moves the diff --git a/src/flux/stores/workspace-store.coffee b/src/flux/stores/workspace-store.coffee index a1c8ba2dc..dfcab1a9d 100644 --- a/src/flux/stores/workspace-store.coffee +++ b/src/flux/stores/workspace-store.coffee @@ -30,6 +30,8 @@ class WorkspaceStore @listenTo Actions.selectLayoutMode, @_onSelectLayoutMode @listenTo Actions.setFocus, @_onSetFocus + @listenTo Actions.toggleWorkspaceLocationHidden, @_onToggleLocationHidden + @listenTo Actions.popSheet, @popSheet @listenTo Actions.searchQueryCommitted, @popToRootSheet @@ -41,6 +43,7 @@ class WorkspaceStore @Sheet = Sheet = {} @_preferredLayoutMode = 'list' + @_hiddenLocations = {} @_sheetStack = [] if atom.isMainWindow() @@ -71,6 +74,16 @@ class WorkspaceStore @_preferredLayoutMode = mode @trigger(@) + _onToggleLocationHidden: (location) => + if not location.id + throw new Error("Actions.toggleWorkspaceLocationHidden - pass a WorkspaceStore.Location") + + if @_hiddenLocations[location.id] + delete @_hiddenLocations[location.id] + else + @_hiddenLocations[location.id] = location + @trigger(@) + _onSetFocus: ({collection, item}) => if collection is 'thread' if @layoutMode() is 'list' @@ -101,22 +114,32 @@ class WorkspaceStore else root.supportedModes[0] - # Returns The top {Sheet} in the current stack. Use this method to determine + # Public: Returns The top {Sheet} in the current stack. Use this method to determine # the sheet the user is looking at. # topSheet: => @_sheetStack[@_sheetStack.length - 1] - # Returns The {Sheet} at the root of the current stack. + # Public: Returns The {Sheet} at the root of the current stack. # rootSheet: => @_sheetStack[0] - # Returns an {Array} The stack of sheets + # Public: Returns an {Array} The stack of sheets # sheetStack: => @_sheetStack + # Public: Returns an {Array} of locations that have been hidden. + # + hiddenLocations: => + _.values(@_hiddenLocations) + + # Public: Returns a {Boolean} indicating whether the location provided is hidden. + # You should provide one of the WorkspaceStore.Location constant values. + isLocationHidden: (loc) => + @_hiddenLocations[loc.id] + ### Managing Sheets ### diff --git a/src/sheet-toolbar.cjsx b/src/sheet-toolbar.cjsx index 35aa70575..67c9a8dfd 100644 --- a/src/sheet-toolbar.cjsx +++ b/src/sheet-toolbar.cjsx @@ -182,6 +182,7 @@ class Toolbar extends React.Component # Add items registered to Regions in the current sheet if @props.data?.columns[state.mode]? for loc in @props.data.columns[state.mode] + continue if WorkspaceStore.isLocationHidden(loc) entries = ComponentRegistry.findComponentsMatching({location: loc.Toolbar, mode: state.mode}) state.columns.push(entries) diff --git a/src/sheet.cjsx b/src/sheet.cjsx index 3d5228618..5e2f4e1f0 100644 --- a/src/sheet.cjsx +++ b/src/sheet.cjsx @@ -90,6 +90,7 @@ class Sheet extends React.Component if @props.data?.columns[state.mode]? for location, idx in @props.data.columns[state.mode] + continue if WorkspaceStore.isLocationHidden(location) entries = ComponentRegistry.findComponentsMatching({location: location, mode: state.mode}) maxWidth = _.reduce entries, ((m,component) -> Math.min(component.containerStyles?.maxWidth ? 10000, m)), 10000 minWidth = _.reduce entries, ((m,component) -> Math.max(component.containerStyles?.minWidth ? 0, m)), 0 diff --git a/static/images/message-list-toggle-sidebar/icon-thread-hidesidebar@2x.png b/static/images/message-list-toggle-sidebar/icon-thread-hidesidebar@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fa6fc9eb33258e7ac939b83ecd9c611b87ad7835 GIT binary patch literal 15219 zcmeI3U2GIp6vxLX6-q!8G!Ox^SrjBPJDX1gJ?G5)?mcJcWp=eDH_WTQqn@Iuc`eQHHh5kNKMQBq!S5@x<2pRe$u)1WC~EEk z=W_$~!i$S2D*TJy(PeifHp;4*4Jew~4FZL14$h{i$eKby>jr7vi25(Td&2M2 zwWz-{m|zpRM$n@-59dMqaI!-k?p4E@e@(1DQjlSQEU*<{A)7HQxe)ccab@`18D{)G zcZ%H`^*1;PeO-xGU!$1^zF;6kt87T}N#Ot&lq6AF<>Of{$glzhXhr=!ww;q1W^iyYFen7fe463H;V{GU4A0YW25k))wo;%CYgsW! zIZhl{YF^LTx@q{FxJtL#Z%6%pCsE}n-B&hONn}_hc90@dP;v|xV3}G@np*M6_2)D0 zrD-YyG9U{K+k$>vO}|`^X`5D$IZeunJZ)mQCW%BPcg^d~W^1Ol?4|*TpoFxhr`0i( z156vR%>KLzng-ylEUR_*ww|gk&ZJ0=GVQg4fj_eviNr{lnw}c+#E@v7>)=FL5M^HU#_-HUW55d16kC~56z^P598Hx|WHUXxo4%T^2(w8Ud@AfW4-tbvrKiJVHS zp|Yb)OPCZmRuGy};1L)}omz3}3yhaEO;eA(5pe zRsuA~Nvr8_D#+3*uV~#|N>svJ$XzX%$P;WzqWkkY?0ibbGsn3X4JMO#MbJcEp#?sq z(xTX{(yM{Q)0)~XNJ=;*z@wa^Mwlt7nsp2A*CEe7hP&DAZSA0M@@QGe=x&e7DR~Px z6&UrGOR&<^Dm}~baVuF?RHwVeRHs0I7GWlhRxhjKS#r~-F6Yb;6ytl`r_V9i0}Nbw z6+^kRrVnD7DSJ@KgN8KRAv3G}V%*7&Xo3ji{2yfW|6nOBW#Hc}#LVjIpDjeq9`%1N zM0F>tJ&KVAT8t@g;_|@E)~>jsldG#-u~Vxt;`~L)u#(}fQrrsSBFvPrYUbknE~g?h z{qB5;XW_wc&UeYxE2FMk@UC7Nb**}CHgr42m$D(l9xvyAwAkX?;Ugc2!S*Z!BMdr> zdbH{Vkm-u+uoqiSPvOHQA5^I6xW(fLTcw-Kb@T`&$Kq0X9?skdHwWQsnwMG+zXMSrnH;x>wspNFrIntLBUwI0s>t0mshQ8;t*bo9QHYZuj>OE=kHHO?M8bl}dhb>R5+ zD~E6Wz0Uu@v1i8zLT9e-DAbt;LJu|A^wForJ6Da#BX>Qsux|OB{WtI3Z?4~T+u@xn zHf|C>dxe`g`r-1};<1UNZ~S!j)3aMQ)8O2OKX;G5cX8#8r2P5FCqI7Kduj2t-4j1g zgl^yd=E&1E+PaOLoAFv-6mfUo9d}J(~WS{)*i;qUeW+jj8=?lC$`qG6H z->&UE|LFYl!k$+TjqdvXICUlWw6b);%ALE9j4s=H`Yo;P!i_KYJ(%umJ}4#jz5n*C z6Jvq)NB&42`ue#QYhKHqzq;q%?2?b=k<|EQO8E6i*M|9PzkwL2mZoI<^>y1G`x~ZO Bp0)r0 literal 0 HcmV?d00001 diff --git a/static/images/message-list-toggle-sidebar/icon-thread-showsidebar@2x.png b/static/images/message-list-toggle-sidebar/icon-thread-showsidebar@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8c8330c63c8c7e6537960fc501ade669f0a06158 GIT binary patch literal 15216 zcmeI3Ym5_B6vsza5LYlH7$M+>QZQg-I*)cb+o3J{=q|frVcA{7Vl*(FxoyX7XG&+5 zc2|rDAAImiOg1P2AsU4!Ab!vwO8fv4VoXeY$C&UihJZ%YL>E4Q-syApZue%R7{A;m z?eyILJ?G5)?mcJb%RJw;a{2W7IrS7pP4Dc8bi-o<{LY#>1^$jqjcD+2XQpGVNl|yr zw7<7ed-l$zsKD=9Z=cl{eOOYAv`1Er81UrN891Awg3Iz5S?LFsD+Usp9&%s(;3Kz7 zQ$y}GLX?eWT0v6l7|Md4p_RSLP`?sT-OIxD!Mp?mq=6;7^68XrO8Jnx5Lbf#?P134 zDonBZL+)lfp{p<2qysPwa zhwI_LU{;Mw-I4ZEI%tL5Nz2Me43o>{JUOq&$R-#r5C||V&+t4AXVB)LZpnFCHy0Fx zl;cEzsbsZ`r5U=*jw{EE0W0Ko+leZl(siXXl|;H(Vh1TQc{#&y9+s))q$(Ak%s@6( zI5kyaKnkRRZkf=JtLc|X8kS)ujd4;|nPdkk`g>vz4M-VJj3@CQr6vYCI5;EfBVMB+dG1&fm)kk}n_$Jk5#{ z%Q}J-XCg78hN{H}9Wg|j=XyDx8D(HX-r6O92YNR=&lLQ$M^9dT4eiW}LqY=yP7 zoB&KlPXw9jpkrobUrDV-%E-dg0%32EsWt5ID(p3>Q#UPHS3qYZ3v1qfw{(n9vbJ8L;aGhAy@i)lgvg>S@Ikkr&h$ zON*=sXpR#b=|EgyX@!^77#H`+0nT4e-P#iRZs)v6g9$(N!6j5aK8>Z_A%Veh2GW!HjExE3n{J8qcU>V z1a<|6+~pFiG_^|4vV97bEXj)9-NK4pAV3W=qeiQzRq-sjX=9gjVhD=y9q!}j$R&Y} zE3aax!mROwm`2>n$yv~xfIDPjwO@=o+7V3roUH!9#sM(|b z&xNS&WF;x<3803V@+K}1Ol<9nD>}Nm$`w1d8iV#NN`jRPca>bIATG#^8LMV4&hN7; zGBr?`FY+w>Fr58ca&^k6>sq|4Q$}5@o{#9773NFXkYR_HeIG5h_#XJk2f}_q@Crc& z9Y#I6v^+@lMKsupO}nS?u;UecP@$&dT8AUNsZ<>uLdmhXRE~$ULKPNA;iDgX>SQX9 zons2L(#dY+pXwFe%BV;zk^}*QHwi90A4Da%5FmJy;KK7kRDufuf;R~+JRd|QxDX(C zliz*Z+dY z%M>-hQq-086eYa`Um-PKT=#K1oO`V^(%hT>?)2A7AF5k@&zaxOJ$LP_`}X;Z4{bX( zW8U1%ynA2O=l3lf-m!0Z_=V$Ba|irKn`Z22J2v~3o@p(go?Vy-H-0~BB3XCUyXD5tUFY9_%Q~8TLpuNDwe9U|%&(rgd)uL=)%#AKc<<(= zD{nKO{cvEWaB%XCJ5Frwe@tzjwP9Op5H#(cl;7-~wx{LNqV2iN*2niA*nQzLpjI86 ze7NqZ?b)TD@14{Td35B|H$NU;@Wm9