mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-10-07 11:48:29 +08:00
feat(account-sidebar): Ability to add custom items to the sidebar
This commit is contained in:
parent
3d84c41625
commit
a316518326
7 changed files with 217 additions and 155 deletions
|
@ -44,11 +44,8 @@ class AccountSidebarStore extends NylasStore
|
||||||
account = AccountStore.current()
|
account = AccountStore.current()
|
||||||
return unless account
|
return unless account
|
||||||
|
|
||||||
viewFilterForCategory = (cat) ->
|
|
||||||
return MailViewFilter.forCategory(cat)
|
|
||||||
|
|
||||||
userCategories = CategoryStore.getUserCategories()
|
userCategories = CategoryStore.getUserCategories()
|
||||||
userCategoryViews = _.map(userCategories, viewFilterForCategory)
|
userCategoryItems = _.map(userCategories, @_sidebarItemForCategory)
|
||||||
|
|
||||||
# Our drafts are displayed via the `DraftListSidebarItem` which
|
# Our drafts are displayed via the `DraftListSidebarItem` which
|
||||||
# is loading into the `Drafts` Sheet.
|
# is loading into the `Drafts` Sheet.
|
||||||
|
@ -56,30 +53,33 @@ class AccountSidebarStore extends NylasStore
|
||||||
standardCategories = _.reject standardCategories, (category) =>
|
standardCategories = _.reject standardCategories, (category) =>
|
||||||
category.name is "drafts"
|
category.name is "drafts"
|
||||||
|
|
||||||
standardViews = _.map(standardCategories, viewFilterForCategory)
|
standardCategoryItems = _.map(standardCategories, @_sidebarItemForCategory)
|
||||||
|
starredItem = @_sidebarItemForMailView('starred', MailViewFilter.forStarred())
|
||||||
starredView = MailViewFilter.forStarred()
|
|
||||||
standardViews.splice(1, 0, starredView)
|
|
||||||
|
|
||||||
# Find root views and add them to the bottom of the list (Drafts, etc.)
|
# Find root views and add them to the bottom of the list (Drafts, etc.)
|
||||||
_.each WorkspaceStore.Sheet, (sheet) ->
|
standardItems = standardCategoryItems
|
||||||
if sheet.root and sheet.name
|
standardItems.splice(1, 0, starredItem)
|
||||||
standardViews.push(sheet)
|
standardItems.push(WorkspaceStore.sidebarItems()...)
|
||||||
|
|
||||||
@_sections = []
|
@_sections = []
|
||||||
@_sections.push
|
@_sections.push
|
||||||
label: 'Mailboxes'
|
label: 'Mailboxes'
|
||||||
items: standardViews
|
items: standardItems
|
||||||
type: 'mailboxes'
|
type: 'mailboxes'
|
||||||
|
|
||||||
@_sections.push
|
@_sections.push
|
||||||
label: CategoryStore.categoryLabel()
|
label: CategoryStore.categoryLabel()
|
||||||
items: userCategoryViews
|
items: userCategoryItems
|
||||||
type: 'category'
|
type: 'category'
|
||||||
|
|
||||||
@trigger()
|
@trigger()
|
||||||
|
|
||||||
_isStandardCategory: (category) =>
|
_sidebarItemForMailView: (id, filter) =>
|
||||||
category.name and category.name in CategoryStore.standardCategories
|
new WorkspaceStore.SidebarItem({id: id, name: filter.name, mailViewFilter: filter})
|
||||||
|
|
||||||
|
_sidebarItemForCategory: (category) =>
|
||||||
|
filter = MailViewFilter.forCategory(category)
|
||||||
|
@_sidebarItemForMailView(category.id, filter)
|
||||||
|
|
||||||
|
|
||||||
module.exports = new AccountSidebarStore()
|
module.exports = new AccountSidebarStore()
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
React = require 'react'
|
React = require 'react'
|
||||||
{Actions, MailViewFilter, AccountStore} = require("nylas-exports")
|
{Actions, MailViewFilter, WorkspaceStore} = require("nylas-exports")
|
||||||
{ScrollRegion} = require("nylas-component-kit")
|
{ScrollRegion} = require("nylas-component-kit")
|
||||||
SidebarDividerItem = require("./account-sidebar-divider-item")
|
SidebarDividerItem = require("./account-sidebar-divider-item")
|
||||||
SidebarSheetItem = require("./account-sidebar-sheet-item")
|
SidebarSheetItem = require("./account-sidebar-sheet-item")
|
||||||
|
AccountSwitcher = require ("./account-switcher")
|
||||||
AccountSidebarStore = require ("./account-sidebar-store")
|
AccountSidebarStore = require ("./account-sidebar-store")
|
||||||
AccountSidebarMailViewItem = require("./account-sidebar-mail-view-item")
|
AccountSidebarMailViewItem = require("./account-sidebar-mail-view-item")
|
||||||
crypto = require 'crypto'
|
|
||||||
{RetinaImg} = require 'nylas-component-kit'
|
{RetinaImg} = require 'nylas-component-kit'
|
||||||
classNames = require 'classnames'
|
|
||||||
|
|
||||||
class AccountSidebar extends React.Component
|
class AccountSidebar extends React.Component
|
||||||
@displayName: 'AccountSidebar'
|
@displayName: 'AccountSidebar'
|
||||||
|
@ -19,169 +18,64 @@ class AccountSidebar extends React.Component
|
||||||
|
|
||||||
constructor: (@props) ->
|
constructor: (@props) ->
|
||||||
@state = @_getStateFromStores()
|
@state = @_getStateFromStores()
|
||||||
@state.showing = false
|
|
||||||
|
|
||||||
componentDidMount: =>
|
componentDidMount: =>
|
||||||
@unsubscribers = []
|
@unsubscribers = []
|
||||||
@unsubscribers.push AccountSidebarStore.listen @_onStoreChange
|
@unsubscribers.push AccountSidebarStore.listen @_onStoreChange
|
||||||
@unsubscribers.push AccountStore.listen @_onStoreChange
|
|
||||||
|
|
||||||
# It's important that every React class explicitly stops listening to
|
|
||||||
# atom events before it unmounts. Thank you event-kit
|
|
||||||
# This can be fixed via a Reflux mixin
|
|
||||||
componentWillUnmount: =>
|
componentWillUnmount: =>
|
||||||
unsubscribe() for unsubscribe in @unsubscribers
|
unsubscribe() for unsubscribe in @unsubscribers
|
||||||
|
|
||||||
render: =>
|
render: =>
|
||||||
<ScrollRegion style={flex:1} id="account-sidebar">
|
<ScrollRegion style={flex:1} id="account-sidebar">
|
||||||
{@_accountSwitcher()}
|
<AccountSwitcher />
|
||||||
<div className="account-sidebar-sections">
|
<div className="account-sidebar-sections">
|
||||||
{@_sections()}
|
{@_sections()}
|
||||||
</div>
|
</div>
|
||||||
</ScrollRegion>
|
</ScrollRegion>
|
||||||
|
|
||||||
_accountSwitcher: =>
|
|
||||||
return undefined if @state.accounts.length < 1
|
|
||||||
|
|
||||||
<div id="account-switcher" tabIndex={-1} onBlur={@_onBlur} ref="button">
|
|
||||||
{@_renderAccount @state.account, true}
|
|
||||||
{@_renderDropdown()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
_renderAccount: (account, isPrimaryItem) =>
|
|
||||||
classes = classNames
|
|
||||||
"account": true
|
|
||||||
"item": true
|
|
||||||
"dropdown-item-padding": not isPrimaryItem
|
|
||||||
"active": account is @state.account
|
|
||||||
"bg-color-hover": not isPrimaryItem
|
|
||||||
"primary-item": isPrimaryItem
|
|
||||||
"account-option": not isPrimaryItem
|
|
||||||
|
|
||||||
email = account.emailAddress.trim().toLowerCase()
|
|
||||||
|
|
||||||
if isPrimaryItem
|
|
||||||
dropdownClasses = classNames
|
|
||||||
"account-switcher-dropdown": true,
|
|
||||||
"account-switcher-dropdown-hidden": @state.showing
|
|
||||||
|
|
||||||
dropdownArrow = <div style={float: 'right', marginTop: -2}>
|
|
||||||
<RetinaImg className={dropdownClasses} name="account-switcher-dropdown.png"
|
|
||||||
mode={RetinaImg.Mode.ContentPreserve} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
onClick = @_toggleDropdown
|
|
||||||
|
|
||||||
else
|
|
||||||
onClick = =>
|
|
||||||
@_onSwitchAccount account
|
|
||||||
|
|
||||||
<div className={classes}
|
|
||||||
onClick={onClick}
|
|
||||||
key={email}>
|
|
||||||
<div style={float: 'left'}>
|
|
||||||
<div className="gravatar" style={backgroundImage: @_gravatarUrl(email)}></div>
|
|
||||||
<RetinaImg name={"ic-settings-account-#{account.provider}@2x.png"}
|
|
||||||
style={width: 28, height: 28, marginTop: -10}
|
|
||||||
fallback="ic-settings-account-imap.png"
|
|
||||||
mode={RetinaImg.Mode.ContentPreserve} />
|
|
||||||
</div>
|
|
||||||
{dropdownArrow}
|
|
||||||
<div className="name" style={lineHeight: "110%"}>
|
|
||||||
{email}
|
|
||||||
</div>
|
|
||||||
<div style={clear: "both"}>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
_renderNewAccountOption: =>
|
|
||||||
<div className="account item dropdown-item-padding bg-color-hover new-account-option"
|
|
||||||
onClick={@_onAddAccount}
|
|
||||||
tabIndex={999}>
|
|
||||||
<div style={float: 'left'}>
|
|
||||||
<RetinaImg name="icon-accounts-addnew.png"
|
|
||||||
fallback="ic-settings-account-imap.png"
|
|
||||||
mode={RetinaImg.Mode.ContentPreserve}
|
|
||||||
style={width: 28, height: 28, marginTop: -10} />
|
|
||||||
</div>
|
|
||||||
<div className="name" style={lineHeight: "110%", textTransform: 'none'}>
|
|
||||||
Add account…
|
|
||||||
</div>
|
|
||||||
<div style={clear: "both"}>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
_renderDropdown: =>
|
|
||||||
display = if @state.showing then "block" else "none"
|
|
||||||
# display = "block"
|
|
||||||
|
|
||||||
accounts = @state.accounts.map (a) =>
|
|
||||||
@_renderAccount(a)
|
|
||||||
|
|
||||||
<div style={display: display}
|
|
||||||
ref="account-switcher-dropdown"
|
|
||||||
className="dropdown dropdown-positioning dropdown-colors">
|
|
||||||
{accounts}
|
|
||||||
{@_renderNewAccountOption()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
_toggleDropdown: =>
|
|
||||||
@setState showing: !@state.showing
|
|
||||||
|
|
||||||
_gravatarUrl: (email) =>
|
|
||||||
hash = crypto.createHash('md5').update(email, 'utf8').digest('hex')
|
|
||||||
|
|
||||||
"url(http://www.gravatar.com/avatar/#{hash}?d=blank&s=56)"
|
|
||||||
|
|
||||||
_sections: =>
|
_sections: =>
|
||||||
return @state.sections.map (section) =>
|
@state.sections.map (section) =>
|
||||||
<section key={section.label}>
|
<section key={section.label}>
|
||||||
<div className="heading">{section.label}</div>
|
<div className="heading">{section.label}</div>
|
||||||
{@_itemComponents(section)}
|
{@_itemComponents(section)}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
_itemComponents: (section) =>
|
_itemComponents: (section) =>
|
||||||
section.items?.map (item) =>
|
section.items.map (item) =>
|
||||||
return unless item
|
unless item instanceof WorkspaceStore.SidebarItem
|
||||||
if item instanceof MailViewFilter
|
throw new Error("AccountSidebar:_itemComponents: sections contained an \
|
||||||
<AccountSidebarMailViewItem
|
item which was not a SidebarItem")
|
||||||
key={item.id ? item.type}
|
|
||||||
mailView={item}
|
|
||||||
select={ item.isEqual(@state.selected) }/>
|
|
||||||
else
|
|
||||||
if item.sidebarComponent
|
|
||||||
itemClass = item.sidebarComponent
|
|
||||||
else
|
|
||||||
itemClass = SidebarSheetItem
|
|
||||||
|
|
||||||
<itemClass
|
if item.component
|
||||||
key={item.id ? item.type}
|
Component = item.component
|
||||||
|
<Component
|
||||||
|
key={item.id}
|
||||||
item={item}
|
item={item}
|
||||||
sectionType={section.type}
|
select={item.id is @state.selected?.id } />
|
||||||
select={item.id is @state.selected?.id }/>
|
|
||||||
|
else if item.mailViewFilter
|
||||||
|
<AccountSidebarMailViewItem
|
||||||
|
key={item.id}
|
||||||
|
mailView={item.mailViewFilter}
|
||||||
|
select={item.mailViewFilter.isEqual(@state.selected)} />
|
||||||
|
|
||||||
|
else if item.sheet
|
||||||
|
<SidebarSheetItem
|
||||||
|
key={item.id}
|
||||||
|
item={item.sheet}
|
||||||
|
select={item.sheet.id is @state.selected?.id} />
|
||||||
|
|
||||||
|
else
|
||||||
|
throw new Error("AccountSidebar:_itemComponents: each item must have a \
|
||||||
|
custom component, or a sheet or mailViewFilter")
|
||||||
|
|
||||||
_onStoreChange: =>
|
_onStoreChange: =>
|
||||||
@setState @_getStateFromStores()
|
@setState @_getStateFromStores()
|
||||||
|
|
||||||
_onBlur: (e) =>
|
|
||||||
target = e.nativeEvent.relatedTarget
|
|
||||||
if target? and React.findDOMNode(@refs.button).contains(target)
|
|
||||||
return
|
|
||||||
@setState(showing: false)
|
|
||||||
|
|
||||||
_onSwitchAccount: (account) =>
|
|
||||||
Actions.selectAccountId(account.id)
|
|
||||||
@setState(showing: false)
|
|
||||||
|
|
||||||
_onAddAccount: =>
|
|
||||||
require('remote').getGlobal('application').windowManager.newOnboardingWindow()
|
|
||||||
@setState showing: false
|
|
||||||
|
|
||||||
_getStateFromStores: =>
|
_getStateFromStores: =>
|
||||||
sections: AccountSidebarStore.sections()
|
sections: AccountSidebarStore.sections()
|
||||||
selected: AccountSidebarStore.selected()
|
selected: AccountSidebarStore.selected()
|
||||||
accounts: AccountStore.items()
|
|
||||||
account: AccountStore.current()
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = AccountSidebar
|
module.exports = AccountSidebar
|
||||||
|
|
136
internal_packages/account-sidebar/lib/account-switcher.cjsx
Normal file
136
internal_packages/account-sidebar/lib/account-switcher.cjsx
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
React = require 'react'
|
||||||
|
{Actions, AccountStore} = require("nylas-exports")
|
||||||
|
{ScrollRegion} = require("nylas-component-kit")
|
||||||
|
crypto = require 'crypto'
|
||||||
|
{RetinaImg} = require 'nylas-component-kit'
|
||||||
|
classNames = require 'classnames'
|
||||||
|
|
||||||
|
class AccountSwitcher extends React.Component
|
||||||
|
@displayName: 'AccountSwitcher'
|
||||||
|
|
||||||
|
constructor: (@props) ->
|
||||||
|
@state = @_getStateFromStores()
|
||||||
|
@state.showing = false
|
||||||
|
|
||||||
|
componentDidMount: =>
|
||||||
|
@unsubscribers = []
|
||||||
|
@unsubscribers.push AccountStore.listen @_onStoreChange
|
||||||
|
|
||||||
|
componentWillUnmount: =>
|
||||||
|
unsubscribe() for unsubscribe in @unsubscribers
|
||||||
|
|
||||||
|
render: =>
|
||||||
|
return undefined if @state.accounts.length < 1
|
||||||
|
|
||||||
|
<div id="account-switcher" tabIndex={-1} onBlur={@_onBlur} ref="button">
|
||||||
|
{@_renderAccount(@state.account, true)}
|
||||||
|
{@_renderDropdown()}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
_renderAccount: (account, isPrimaryItem) =>
|
||||||
|
classes = classNames
|
||||||
|
"account": true
|
||||||
|
"item": true
|
||||||
|
"dropdown-item-padding": not isPrimaryItem
|
||||||
|
"active": account is @state.account
|
||||||
|
"bg-color-hover": not isPrimaryItem
|
||||||
|
"primary-item": isPrimaryItem
|
||||||
|
"account-option": not isPrimaryItem
|
||||||
|
|
||||||
|
email = account.emailAddress.trim().toLowerCase()
|
||||||
|
|
||||||
|
if isPrimaryItem
|
||||||
|
dropdownClasses = classNames
|
||||||
|
"account-switcher-dropdown": true,
|
||||||
|
"account-switcher-dropdown-hidden": @state.showing
|
||||||
|
|
||||||
|
dropdownArrow = <div style={float: 'right', marginTop: -2}>
|
||||||
|
<RetinaImg className={dropdownClasses} name="account-switcher-dropdown.png"
|
||||||
|
mode={RetinaImg.Mode.ContentPreserve} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
onClick = @_toggleDropdown
|
||||||
|
|
||||||
|
else
|
||||||
|
onClick = =>
|
||||||
|
@_onSwitchAccount account
|
||||||
|
|
||||||
|
<div className={classes}
|
||||||
|
onClick={onClick}
|
||||||
|
key={email}>
|
||||||
|
<div style={float: 'left'}>
|
||||||
|
<div className="gravatar" style={backgroundImage: @_gravatarUrl(email)}></div>
|
||||||
|
<RetinaImg name={"ic-settings-account-#{account.provider}@2x.png"}
|
||||||
|
style={width: 28, height: 28, marginTop: -10}
|
||||||
|
fallback="ic-settings-account-imap.png"
|
||||||
|
mode={RetinaImg.Mode.ContentPreserve} />
|
||||||
|
</div>
|
||||||
|
{dropdownArrow}
|
||||||
|
<div className="name" style={lineHeight: "110%"}>
|
||||||
|
{email}
|
||||||
|
</div>
|
||||||
|
<div style={clear: "both"}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
_renderNewAccountOption: =>
|
||||||
|
<div className="account item dropdown-item-padding bg-color-hover new-account-option"
|
||||||
|
onClick={@_onAddAccount}
|
||||||
|
tabIndex={999}>
|
||||||
|
<div style={float: 'left'}>
|
||||||
|
<RetinaImg name="icon-accounts-addnew.png"
|
||||||
|
fallback="ic-settings-account-imap.png"
|
||||||
|
mode={RetinaImg.Mode.ContentPreserve}
|
||||||
|
style={width: 28, height: 28, marginTop: -10} />
|
||||||
|
</div>
|
||||||
|
<div className="name" style={lineHeight: "110%", textTransform: 'none'}>
|
||||||
|
Add account…
|
||||||
|
</div>
|
||||||
|
<div style={clear: "both"}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
_renderDropdown: =>
|
||||||
|
display = if @state.showing then "block" else "none"
|
||||||
|
# display = "block"
|
||||||
|
|
||||||
|
accounts = @state.accounts.map (a) =>
|
||||||
|
@_renderAccount(a)
|
||||||
|
|
||||||
|
<div style={display: display}
|
||||||
|
ref="account-switcher-dropdown"
|
||||||
|
className="dropdown dropdown-positioning dropdown-colors">
|
||||||
|
{accounts}
|
||||||
|
{@_renderNewAccountOption()}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
_toggleDropdown: =>
|
||||||
|
@setState showing: !@state.showing
|
||||||
|
|
||||||
|
_gravatarUrl: (email) =>
|
||||||
|
hash = crypto.createHash('md5').update(email, 'utf8').digest('hex')
|
||||||
|
"url(http://www.gravatar.com/avatar/#{hash}?d=blank&s=56)"
|
||||||
|
|
||||||
|
_onStoreChange: =>
|
||||||
|
@setState @_getStateFromStores()
|
||||||
|
|
||||||
|
_onBlur: (e) =>
|
||||||
|
target = e.nativeEvent.relatedTarget
|
||||||
|
if target? and React.findDOMNode(@refs.button).contains(target)
|
||||||
|
return
|
||||||
|
@setState(showing: false)
|
||||||
|
|
||||||
|
_onSwitchAccount: (account) =>
|
||||||
|
Actions.selectAccountId(account.id)
|
||||||
|
@setState(showing: false)
|
||||||
|
|
||||||
|
_onAddAccount: =>
|
||||||
|
require('remote').getGlobal('application').windowManager.newOnboardingWindow()
|
||||||
|
@setState showing: false
|
||||||
|
|
||||||
|
_getStateFromStores: =>
|
||||||
|
accounts: AccountStore.items()
|
||||||
|
account: AccountStore.current()
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = AccountSwitcher
|
|
@ -7,7 +7,7 @@ SettingsTabsView = require "./settings-tabs-view"
|
||||||
module.exports =
|
module.exports =
|
||||||
|
|
||||||
activate: (@state={}) ->
|
activate: (@state={}) ->
|
||||||
WorkspaceStore.defineSheet 'Settings', {root: true, supportedModes: ['list'], name: 'Plugins'},
|
WorkspaceStore.defineSheet 'Settings', {root: true, supportedModes: ['list']},
|
||||||
list: ['RootSidebar', 'SettingsSidebar', 'Settings']
|
list: ['RootSidebar', 'SettingsSidebar', 'Settings']
|
||||||
|
|
||||||
ComponentRegistry.register SettingsTabsView,
|
ComponentRegistry.register SettingsTabsView,
|
||||||
|
|
|
@ -34,11 +34,11 @@ class DraftListSidebarItem extends React.Component
|
||||||
<div className={classSet} onClick={@_onClick}>
|
<div className={classSet} onClick={@_onClick}>
|
||||||
{unread}
|
{unread}
|
||||||
<div className="icon"><RetinaImg name={'drafts.png'} mode={RetinaImg.Mode.ContentIsMask} /></div>
|
<div className="icon"><RetinaImg name={'drafts.png'} mode={RetinaImg.Mode.ContentIsMask} /></div>
|
||||||
<div className="name"> {@props.item.name}</div>
|
<div className="name"> Drafts</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
_onClick: (event) =>
|
_onClick: (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
Actions.selectRootSheet(@props.item)
|
Actions.selectRootSheet(WorkspaceStore.Sheet.Drafts)
|
||||||
|
|
||||||
module.exports = DraftListSidebarItem
|
module.exports = DraftListSidebarItem
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
_ = require 'underscore'
|
_ = require 'underscore'
|
||||||
React = require "react"
|
React = require "react"
|
||||||
{ComponentRegistry, WorkspaceStore} = require "nylas-exports"
|
{MailViewFilter, ComponentRegistry, WorkspaceStore} = require "nylas-exports"
|
||||||
|
|
||||||
{DownButton, UpButton, ThreadBulkArchiveButton, ThreadBulkStarButton, ThreadBulkToggleUnreadButton} = require "./thread-buttons"
|
{DownButton, UpButton, ThreadBulkArchiveButton, ThreadBulkStarButton, ThreadBulkToggleUnreadButton} = require "./thread-buttons"
|
||||||
{DraftDeleteButton} = require "./draft-buttons"
|
{DraftDeleteButton} = require "./draft-buttons"
|
||||||
|
@ -13,9 +13,17 @@ DraftList = require './draft-list'
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
activate: (@state={}) ->
|
activate: (@state={}) ->
|
||||||
WorkspaceStore.defineSheet 'Drafts', {root: true, name: 'Drafts', sidebarComponent: DraftListSidebarItem},
|
WorkspaceStore.defineSheet 'Drafts', {root: true},
|
||||||
list: ['RootSidebar', 'DraftList']
|
list: ['RootSidebar', 'DraftList']
|
||||||
|
|
||||||
|
@sidebarItem = new WorkspaceStore.SidebarItem
|
||||||
|
component: DraftListSidebarItem
|
||||||
|
sheet: WorkspaceStore.Sheet.Drafts
|
||||||
|
id: 'Drafts'
|
||||||
|
name: 'Drafts'
|
||||||
|
|
||||||
|
WorkspaceStore.addSidebarItem(@sidebarItem)
|
||||||
|
|
||||||
ComponentRegistry.register ThreadList,
|
ComponentRegistry.register ThreadList,
|
||||||
location: WorkspaceStore.Location.ThreadList
|
location: WorkspaceStore.Location.ThreadList
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,13 @@ NylasStore = require 'nylas-store'
|
||||||
|
|
||||||
Sheet = {}
|
Sheet = {}
|
||||||
Location = {}
|
Location = {}
|
||||||
|
SidebarItems = {}
|
||||||
|
|
||||||
|
class WorkspaceSidebarItem
|
||||||
|
constructor: ({@id, @component, @name, @sheet, @mailViewFilter}) ->
|
||||||
|
if not @sheet and not @mailViewFilter and not @component
|
||||||
|
throw new Error("WorkspaceSidebarItem: You must provide either a sheet \
|
||||||
|
component, or a mailViewFilter for the sidebar item named #{@name}")
|
||||||
|
|
||||||
###
|
###
|
||||||
Public: The WorkspaceStore manages Sheets and layout modes in the application.
|
Public: The WorkspaceStore manages Sheets and layout modes in the application.
|
||||||
|
@ -40,6 +47,9 @@ class WorkspaceStore extends NylasStore
|
||||||
@Location = Location = {}
|
@Location = Location = {}
|
||||||
@Sheet = Sheet = {}
|
@Sheet = Sheet = {}
|
||||||
|
|
||||||
|
@SidebarItem = WorkspaceSidebarItem
|
||||||
|
@SidebarItems = SidebarItems = {}
|
||||||
|
|
||||||
@_hiddenLocations = {}
|
@_hiddenLocations = {}
|
||||||
@_sheetStack = []
|
@_sheetStack = []
|
||||||
|
|
||||||
|
@ -137,6 +147,20 @@ class WorkspaceStore extends NylasStore
|
||||||
return false unless loc
|
return false unless loc
|
||||||
@_hiddenLocations[loc.id]?
|
@_hiddenLocations[loc.id]?
|
||||||
|
|
||||||
|
|
||||||
|
sidebarItems: =>
|
||||||
|
_.values(@SidebarItems)
|
||||||
|
|
||||||
|
addSidebarItem: (item) =>
|
||||||
|
unless item instanceof WorkspaceSidebarItem
|
||||||
|
throw new Error("WorkspaceStore::addSidebarItem requires a `WorkspaceSidebarItem`")
|
||||||
|
@SidebarItems[item.id] = item
|
||||||
|
@triggerDebounced()
|
||||||
|
|
||||||
|
removeSidebarItem: (item) =>
|
||||||
|
delete @SidebarItems[item.id]
|
||||||
|
@triggerDebounced()
|
||||||
|
|
||||||
###
|
###
|
||||||
Managing Sheets
|
Managing Sheets
|
||||||
###
|
###
|
||||||
|
|
Loading…
Add table
Reference in a new issue