mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-11 01:54:40 +08:00
refactor(layout): More configuration into WorkspaceStore, less in packages
This commit is contained in:
parent
eb6cc11a83
commit
21e8455ef6
18 changed files with 174 additions and 171 deletions
|
@ -1,6 +1,6 @@
|
|||
React = require "react"
|
||||
AccountSidebar = require "./account-sidebar"
|
||||
{ComponentRegistry} = require "inbox-exports"
|
||||
{ComponentRegistry, WorkspaceStore} = require "inbox-exports"
|
||||
|
||||
module.exports =
|
||||
item: null # The DOM item the main React component renders into
|
||||
|
@ -9,4 +9,4 @@ module.exports =
|
|||
ComponentRegistry.register
|
||||
view: AccountSidebar
|
||||
name: 'AccountSidebar'
|
||||
role: 'Root:Left'
|
||||
location: WorkspaceStore.Location.RootSidebar
|
|
@ -2,7 +2,11 @@ _ = require 'underscore-plus'
|
|||
React = require 'react'
|
||||
ipc = require 'ipc'
|
||||
|
||||
{NamespaceStore, DatabaseStore, Message, ComponentRegistry} = require('inbox-exports')
|
||||
{NamespaceStore,
|
||||
DatabaseStore,
|
||||
Message,
|
||||
ComponentRegistry,
|
||||
WorkspaceStore} = require('inbox-exports')
|
||||
NewComposeButton = require('./new-compose-button')
|
||||
ComposerView = require('./composer-view')
|
||||
|
||||
|
@ -80,7 +84,7 @@ module.exports =
|
|||
ComponentRegistry.register
|
||||
view: NewComposeButton
|
||||
name: 'NewComposeButton'
|
||||
role: 'Root:Left:Toolbar'
|
||||
location: WorkspaceStore.Location.RootSidebar.Toolbar
|
||||
|
||||
_showInitialErrorDialog: (msg) ->
|
||||
remote = require('remote')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
React = require 'react'
|
||||
{ComponentRegistry} = require 'inbox-exports'
|
||||
{ComponentRegistry, WorkspaceStore} = require 'inbox-exports'
|
||||
|
||||
module.exports =
|
||||
item: null
|
||||
|
@ -7,8 +7,8 @@ module.exports =
|
|||
activate: (@state={}) ->
|
||||
ComponentRegistry.register
|
||||
name: 'activity-bar'
|
||||
role: 'Global:Footer'
|
||||
view: require './activity-bar'
|
||||
location: WorkspaceStore.Sheet.Global.Footer
|
||||
|
||||
deactivate: ->
|
||||
ComponentRegistry.unregister 'activity-bar'
|
||||
|
|
|
@ -2,7 +2,7 @@ React = require "react"
|
|||
MessageList = require "./message-list"
|
||||
MessageToolbarItems = require "./message-toolbar-items"
|
||||
MessageSubjectItem = require "./message-subject-item"
|
||||
{ComponentRegistry} = require 'inbox-exports'
|
||||
{ComponentRegistry, WorkspaceStore} = require 'inbox-exports'
|
||||
{RetinaImg} = require 'ui-components'
|
||||
|
||||
DownButton = React.createClass
|
||||
|
@ -29,52 +29,39 @@ module.exports =
|
|||
|
||||
activate: (@state={}) ->
|
||||
# Register Message List Actions we provide globally
|
||||
ComponentRegistry.register
|
||||
name: 'MessageListSplit'
|
||||
role: 'Root:Right'
|
||||
mode: 'split'
|
||||
view: MessageList
|
||||
|
||||
ComponentRegistry.register
|
||||
name: 'MessageToolbarItemsSplit'
|
||||
role: 'Root:Right:Toolbar'
|
||||
mode: 'split'
|
||||
view: MessageToolbarItems
|
||||
|
||||
ComponentRegistry.register
|
||||
name: 'MessageList'
|
||||
role: 'Thread:Center'
|
||||
mode: 'list'
|
||||
view: MessageList
|
||||
location: WorkspaceStore.Location.MessageList
|
||||
|
||||
ComponentRegistry.register
|
||||
name: 'MessageToolbarItems'
|
||||
role: 'Thread:Center:Toolbar'
|
||||
mode: 'list'
|
||||
view: MessageToolbarItems
|
||||
location: WorkspaceStore.Location.MessageList.Toolbar
|
||||
|
||||
ComponentRegistry.register
|
||||
name: 'MessageSubjectItem'
|
||||
role: 'Thread:Center:Toolbar'
|
||||
mode: 'list'
|
||||
view: MessageSubjectItem
|
||||
location: WorkspaceStore.Location.MessageList.Toolbar
|
||||
|
||||
ComponentRegistry.register
|
||||
name: 'DownButton'
|
||||
role: 'Thread:Right:Toolbar'
|
||||
mode: 'list'
|
||||
view: DownButton
|
||||
location: WorkspaceStore.Sheet.Thread.Toolbar.Right
|
||||
|
||||
ComponentRegistry.register
|
||||
name: 'UpButton'
|
||||
role: 'Thread:Right:Toolbar'
|
||||
mode: 'list'
|
||||
view: UpButton
|
||||
location: WorkspaceStore.Sheet.Thread.Toolbar.Right
|
||||
|
||||
|
||||
deactivate: ->
|
||||
ComponentRegistry.unregister 'MessageToolbarItems'
|
||||
ComponentRegistry.unregister 'MessageListSplit'
|
||||
ComponentRegistry.unregister 'MessageSubjectItem'
|
||||
ComponentRegistry.unregister 'MessageList'
|
||||
ComponentRegistry.unregister 'DownButton'
|
||||
ComponentRegistry.unregister 'UpButton'
|
||||
|
||||
serialize: -> @state
|
||||
|
|
|
@ -65,7 +65,6 @@ MessageList = React.createClass
|
|||
{@_messageListHeaders()}
|
||||
{@_messageComponents()}
|
||||
</div>
|
||||
{@_messageListSidebar()}
|
||||
<Spinner visible={!@state.ready} />
|
||||
</div>
|
||||
|
||||
|
@ -101,22 +100,6 @@ MessageList = React.createClass
|
|||
{<MLBar thread={@state.currentThread} /> for MLBar in MLBars}
|
||||
</div>
|
||||
|
||||
_messageListSidebar: ->
|
||||
sidebarItems = ComponentRegistry.findAllViewsByRole('MessageListSidebar')
|
||||
if sidebarItems.length > 0
|
||||
maxWidth = _.reduce sidebarItems, ((m,view) -> Math.min(view.maxWidth ? 640, m)), 640
|
||||
minWidth = _.reduce sidebarItems, ((m,view) -> Math.max(view.minWidth ? 240, m)), 240
|
||||
|
||||
<ResizableRegion handle={ResizableRegion.Handle.Left}
|
||||
minWidth={minWidth}
|
||||
maxWidth={maxWidth}>
|
||||
<div className="message-list-sidebar">
|
||||
{<view thread={@state.currentThread} /> for view in sidebarItems}
|
||||
</div>
|
||||
</ResizableRegion>
|
||||
else
|
||||
return <div></div>
|
||||
|
||||
_messageListHeaders: ->
|
||||
Participants = @state.Participants
|
||||
MessageListHeaders = ComponentRegistry.findAllViewsByRole('MessageListHeader')
|
||||
|
|
|
@ -70,9 +70,7 @@ module.exports = React.createClass
|
|||
"hidden": !@state.threadIsSelected
|
||||
|
||||
<div className={classes}>
|
||||
<div className="message-toolbar-items-inner">
|
||||
<ArchiveButton />
|
||||
</div>
|
||||
<ArchiveButton />
|
||||
</div>
|
||||
|
||||
componentDidMount: ->
|
||||
|
|
|
@ -8,21 +8,10 @@
|
|||
// toolbar. We want the toolbar items to sit right above the centered
|
||||
// content, so we need another 800px-wide container in the toolbar...
|
||||
.message-toolbar-items {
|
||||
order: -10000;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
|
||||
.message-toolbar-items-inner {
|
||||
margin: auto;
|
||||
max-width: @message-max-width - @spacing-three-quarters*2;
|
||||
text-align: right;
|
||||
pointer-events: none;
|
||||
& > * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
order: 200;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.message-toolbar-items.hidden {
|
||||
|
@ -66,13 +55,6 @@
|
|||
padding: 0;
|
||||
order: 2;
|
||||
|
||||
.message-list-sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: @background-off-primary;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.message-list-headers {
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
|
@ -191,6 +173,10 @@
|
|||
}
|
||||
|
||||
|
||||
.column-MessageListSidebar {
|
||||
background-color: @background-off-primary;
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
// message-participants.cjsx //
|
||||
///////////////////////////////
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ComponentRegistry} = require 'inbox-exports'
|
||||
{ComponentRegistry, WorkspaceStore} = require 'inbox-exports'
|
||||
ModeToggle = require './mode-toggle'
|
||||
|
||||
module.exports =
|
||||
|
@ -6,4 +6,4 @@ module.exports =
|
|||
ComponentRegistry.register
|
||||
name: 'ModeToggle'
|
||||
view: ModeToggle
|
||||
role: 'Root:Center:Toolbar'
|
||||
location: WorkspaceStore.Sheet.Root.Toolbar.Right
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
React = require "react"
|
||||
Notifications = require "./notifications"
|
||||
NotificationsStickyBar = require "./notifications-sticky-bar"
|
||||
{ComponentRegistry} = require("inbox-exports")
|
||||
{ComponentRegistry, WorkspaceStore} = require("inbox-exports")
|
||||
|
||||
module.exports =
|
||||
item: null # The DOM item the main React component renders into
|
||||
|
@ -10,12 +10,12 @@ module.exports =
|
|||
ComponentRegistry.register
|
||||
view: Notifications
|
||||
name: 'Notifications'
|
||||
role: 'Root:Left'
|
||||
location: WorkspaceStore.Location.RootSidebar
|
||||
|
||||
ComponentRegistry.register
|
||||
view: NotificationsStickyBar
|
||||
name: 'NotificationsStickyBar'
|
||||
role: 'Root:Top'
|
||||
location: WorkspaceStore.Sheet.Root.Header
|
||||
|
||||
deactivate: ->
|
||||
ComponentRegistry.unregister('NotificationsStickyBar')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
path = require 'path'
|
||||
require 'coffee-react/register'
|
||||
React = require 'react'
|
||||
{ComponentRegistry} = require 'inbox-exports'
|
||||
{ComponentRegistry, WorkspaceStore} = require 'inbox-exports'
|
||||
SearchBar = require './search-bar'
|
||||
SearchSettingsBar = require './search-settings-bar'
|
||||
|
||||
|
@ -13,7 +13,7 @@ module.exports =
|
|||
ComponentRegistry.register
|
||||
view: SearchBar
|
||||
name: 'SearchBar'
|
||||
role: 'Root:Center:Toolbar'
|
||||
location: WorkspaceStore.Location.RootCenter.Toolbar
|
||||
|
||||
deactivate: ->
|
||||
ComponentRegistry.unregister 'SearchBar'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
_ = require 'underscore-plus'
|
||||
React = require "react"
|
||||
SidebarFullContact = require "./sidebar-fullcontact.cjsx"
|
||||
{ComponentRegistry} = require("inbox-exports")
|
||||
{ComponentRegistry, WorkspaceStore} = require "inbox-exports"
|
||||
|
||||
module.exports =
|
||||
item: null
|
||||
|
@ -10,7 +10,7 @@ module.exports =
|
|||
ComponentRegistry.register
|
||||
name: 'SidebarFullContact'
|
||||
view: SidebarFullContact
|
||||
role: 'MessageListSidebar'
|
||||
location: WorkspaceStore.Location.MessageListSidebar
|
||||
|
||||
deactivate: ->
|
||||
ComponentRegistry.unregister('SidebarFullContact')
|
||||
|
|
|
@ -61,3 +61,6 @@ SidebarFullContact = React.createClass
|
|||
fullContactCache: FullContactStore.fullContactCache()
|
||||
sortedContacts: FullContactStore.sortedContacts()
|
||||
focusedContact: FullContactStore.focusedContact()
|
||||
|
||||
SidebarFullContact.maxWidth = 300
|
||||
SidebarFullContact.minWidth = 200
|
||||
|
|
|
@ -33,4 +33,4 @@ module.exports =
|
|||
ComponentRegistry.register
|
||||
view: RootCenterComponent
|
||||
name: 'RootCenterComponent'
|
||||
role: 'Root:Center'
|
||||
location: WorkspaceStore.Location.RootCenter
|
||||
|
|
|
@ -36,7 +36,7 @@ class Component
|
|||
# Don't shit the bed if the user forgets `new`
|
||||
return new Component(attributes) unless @ instanceof Component
|
||||
|
||||
['name', 'model', 'view', 'role', 'mode'].map (key) =>
|
||||
['name', 'model', 'view', 'role', 'mode', 'location'].map (key) =>
|
||||
@[key] = attributes[key] if attributes[key]
|
||||
|
||||
unless @name?
|
||||
|
@ -84,6 +84,13 @@ ComponentRegistry = Reflux.createStore
|
|||
findAllViewsByRole: (role) ->
|
||||
_.map @findAllByRole(role), (component) -> component.view
|
||||
|
||||
findAllByLocationAndMode: (location, mode) ->
|
||||
_.filter (_.values registry), (component) ->
|
||||
return false unless component.location
|
||||
return false if component.location.id isnt location.id
|
||||
return false if component.mode and component.mode isnt mode
|
||||
true
|
||||
|
||||
triggerDebounced: _.debounce(( -> @trigger(@)), 1)
|
||||
|
||||
_clear: ->
|
||||
|
|
|
@ -2,6 +2,30 @@ Reflux = require 'reflux'
|
|||
NamespaceStore = require './namespace-store'
|
||||
Actions = require '../actions'
|
||||
|
||||
Location = {}
|
||||
for key in ['RootSidebar', 'RootCenter', 'MessageList', 'MessageListSidebar']
|
||||
Location[key] = {id: "#{key}", Toolbar: {id: "#{key}:Toolbar"}}
|
||||
|
||||
defineSheet = (type, columns) ->
|
||||
Toolbar:
|
||||
Left: {id: "Sheet:#{type}:Toolbar:Left"}
|
||||
Right: {id: "Sheet:#{type}:Toolbar:Right"}
|
||||
Header: {id: "Sheet:#{type}:Header"}
|
||||
Footer: {id: "Sheet:#{type}:Footer"}
|
||||
type: type
|
||||
columns: columns
|
||||
|
||||
Sheet =
|
||||
Global: defineSheet 'Global'
|
||||
|
||||
Root: defineSheet 'Root',
|
||||
list: [Location.RootSidebar, Location.RootCenter]
|
||||
split: [Location.RootSidebar, Location.RootCenter, Location.MessageList, Location.MessageListSidebar]
|
||||
|
||||
Thread: defineSheet 'Thread',
|
||||
list: [Location.MessageList, Location.MessageListSidebar]
|
||||
|
||||
|
||||
WorkspaceStore = Reflux.createStore
|
||||
init: ->
|
||||
@_resetInstanceVars()
|
||||
|
@ -16,7 +40,7 @@ WorkspaceStore = Reflux.createStore
|
|||
'application:pop-sheet': => @popSheet()
|
||||
|
||||
_resetInstanceVars: ->
|
||||
@_sheetStack = ["Root"]
|
||||
@_sheetStack = [Sheet.Root]
|
||||
@_view = 'threads'
|
||||
@_layoutMode = 'list'
|
||||
|
||||
|
@ -51,8 +75,8 @@ WorkspaceStore = Reflux.createStore
|
|||
@trigger()
|
||||
|
||||
pushThreadSheet: (threadId) ->
|
||||
if @selectedLayoutMode() is 'list' and threadId and @sheet() isnt "Thread"
|
||||
@pushSheet("Thread")
|
||||
if @selectedLayoutMode() is 'list' and threadId and @sheet().type isnt Sheet.Thread.type
|
||||
@pushSheet(Sheet.Thread)
|
||||
|
||||
popSheet: ->
|
||||
if @_sheetStack.length > 1
|
||||
|
@ -61,8 +85,11 @@ WorkspaceStore = Reflux.createStore
|
|||
|
||||
popToRootSheet: ->
|
||||
if @_sheetStack.length > 1
|
||||
@_sheetStack = ["Root"]
|
||||
@_sheetStack = [Sheet.Root]
|
||||
@trigger()
|
||||
|
||||
|
||||
WorkspaceStore.Location = Location
|
||||
WorkspaceStore.Sheet = Sheet
|
||||
|
||||
module.exports = WorkspaceStore
|
||||
|
|
|
@ -38,13 +38,13 @@ ToolbarWindowControls = React.createClass
|
|||
ComponentRegistry.register
|
||||
view: ToolbarWindowControls
|
||||
name: 'ToolbarWindowControls'
|
||||
role: 'Global:Left:Toolbar'
|
||||
location: WorkspaceStore.Sheet.Global.Toolbar.Left
|
||||
|
||||
Toolbar = React.createClass
|
||||
className: 'Toolbar'
|
||||
|
||||
propTypes:
|
||||
type: React.PropTypes.string
|
||||
data: React.PropTypes.object
|
||||
depth: React.PropTypes.number
|
||||
|
||||
getInitialState: ->
|
||||
|
@ -84,10 +84,10 @@ Toolbar = React.createClass
|
|||
height:'100%'
|
||||
zIndex: 1
|
||||
|
||||
toolbars = @state.itemsForColumns.map ({column, items}) =>
|
||||
toolbars = @state.columns.map (items, idx) =>
|
||||
<div style={position: 'absolute', top:0, display:'none'}
|
||||
data-column={column}
|
||||
key={column}>
|
||||
data-column={idx}
|
||||
key={idx}>
|
||||
{@_flexboxForItems(items)}
|
||||
</div>
|
||||
|
||||
|
@ -96,7 +96,7 @@ Toolbar = React.createClass
|
|||
</div>
|
||||
|
||||
_flexboxForItems: (items) ->
|
||||
components = items.map ({view, name}) =>
|
||||
elements = items.map ({view, name}) =>
|
||||
<view key={name} {...@props} />
|
||||
|
||||
<TimeoutTransitionGroup
|
||||
|
@ -106,7 +106,7 @@ Toolbar = React.createClass
|
|||
leaveTimeout={200}
|
||||
enterTimeout={200}
|
||||
transitionName="sheet-toolbar">
|
||||
{components}
|
||||
{elements}
|
||||
<ToolbarSpacer key="spacer-50" order={-50}/>
|
||||
<ToolbarSpacer key="spacer+50" order={50}/>
|
||||
</TimeoutTransitionGroup>
|
||||
|
@ -134,42 +134,37 @@ Toolbar = React.createClass
|
|||
|
||||
_onWindowResize: ->
|
||||
@recomputeLayout()
|
||||
|
||||
|
||||
_getStateFromStores: (props) ->
|
||||
props ?= @props
|
||||
state =
|
||||
mode: WorkspaceStore.selectedLayoutMode()
|
||||
itemsForColumns: []
|
||||
columns: []
|
||||
|
||||
items = {}
|
||||
for column in ["Left", "Center", "Right"]
|
||||
items[column] = []
|
||||
for role in ["Global:#{column}:Toolbar", "#{props.type}:#{column}:Toolbar"]
|
||||
for entry in ComponentRegistry.findAllByRole(role)
|
||||
continue if entry.mode? and entry.mode != state.mode
|
||||
items[column].push(entry)
|
||||
|
||||
if @props.depth > 0
|
||||
items['Left'].push(view: ToolbarBack, name: 'ToolbarBack')
|
||||
# Add items registered to Regions in the current sheet
|
||||
for loc in @props.data.columns[state.mode]
|
||||
entries = ComponentRegistry.findAllByLocationAndMode(loc.Toolbar, state.mode)
|
||||
state.columns.push(entries)
|
||||
|
||||
# If the left or right column does not contain any components, it won't
|
||||
# be in the sheet. Go ahead and shift those toolbar items into the center
|
||||
# region.
|
||||
for column in ["Left", "Right"]
|
||||
if ComponentRegistry.findAllByRole("#{props.type}:#{column}").length is 0
|
||||
items['Center'].push(items[column]...)
|
||||
delete items[column]
|
||||
# Add left items registered to the Sheet instead of to a Region
|
||||
for loc in [WorkspaceStore.Sheet.Global, @props.data]
|
||||
entries = ComponentRegistry.findAllByLocationAndMode(loc.Toolbar.Left, state.mode)
|
||||
state.columns[0].push(entries...)
|
||||
state.columns[0].push(view: ToolbarBack, name: 'ToolbarBack') if @props.depth > 0
|
||||
|
||||
# Add right items registered to the Sheet instead of to a Region
|
||||
for loc in [WorkspaceStore.Sheet.Global, @props.data]
|
||||
entries = ComponentRegistry.findAllByLocationAndMode(loc.Toolbar.Right, state.mode)
|
||||
state.columns[state.columns.length - 1].push(entries...)
|
||||
|
||||
for key, val of items
|
||||
state.itemsForColumns.push({column: key, items: val}) if val.length > 0
|
||||
state
|
||||
|
||||
|
||||
FlexboxForRoles = React.createClass
|
||||
className: 'FlexboxForRoles'
|
||||
FlexboxForLocations = React.createClass
|
||||
className: 'FlexboxForLocations'
|
||||
|
||||
propTypes:
|
||||
roles: React.PropTypes.arrayOf(React.PropTypes.string)
|
||||
locations: React.PropTypes.arrayOf(React.PropTypes.object)
|
||||
|
||||
getInitialState: ->
|
||||
@_getComponentRegistryState()
|
||||
|
@ -190,17 +185,18 @@ FlexboxForRoles = React.createClass
|
|||
!_.isEqual(nextItemNames, itemNames)
|
||||
|
||||
render: ->
|
||||
components = @state.items.map ({view, name}) =>
|
||||
elements = @state.items.map ({view, name}) =>
|
||||
<view key={name} />
|
||||
|
||||
<Flexbox direction="row">
|
||||
{components}
|
||||
{elements}
|
||||
</Flexbox>
|
||||
|
||||
_getComponentRegistryState: ->
|
||||
items = []
|
||||
for role in @props.roles
|
||||
items = items.concat(ComponentRegistry.findAllByRole(role))
|
||||
mode = WorkspaceStore.selectedLayoutMode()
|
||||
for location in @props.locations
|
||||
items = items.concat(ComponentRegistry.findAllByLocationAndMode(location, mode))
|
||||
{items}
|
||||
|
||||
module.exports =
|
||||
|
@ -220,7 +216,7 @@ SheetContainer = React.createClass
|
|||
@unsubscribe() if @unsubscribe
|
||||
|
||||
render: ->
|
||||
topSheetType = @state.stack[@state.stack.length - 1]
|
||||
topSheet = @state.stack[@state.stack.length - 1]
|
||||
|
||||
<Flexbox direction="column">
|
||||
<TimeoutTransitionGroup name="Toolbar"
|
||||
|
@ -229,12 +225,12 @@ SheetContainer = React.createClass
|
|||
enterTimeout={200}
|
||||
className="sheet-toolbar"
|
||||
transitionName="sheet-toolbar">
|
||||
{@_toolbarComponents()}
|
||||
{@_toolbarElements()}
|
||||
</TimeoutTransitionGroup>
|
||||
|
||||
<div name="Top" style={order:1}>
|
||||
<FlexboxForRoles roles={["Global:Top", "#{topSheetType}:Top"]}
|
||||
type={topSheetType}/>
|
||||
<div name="Header" style={order:1}>
|
||||
<FlexboxForLocations locations={[topSheet.Header, WorkspaceStore.Sheet.Global.Header]}
|
||||
type={topSheet.type}/>
|
||||
</div>
|
||||
|
||||
<TimeoutTransitionGroup name="Center"
|
||||
|
@ -242,25 +238,25 @@ SheetContainer = React.createClass
|
|||
leaveTimeout={150}
|
||||
enterTimeout={150}
|
||||
transitionName="sheet-stack">
|
||||
{@_sheetComponents()}
|
||||
{@_sheetElements()}
|
||||
</TimeoutTransitionGroup>
|
||||
|
||||
<div name="Footer" style={order:3}>
|
||||
<FlexboxForRoles roles={["Global:Footer", "#{topSheetType}:Footer"]}
|
||||
type={topSheetType}/>
|
||||
<FlexboxForLocations locations={[topSheet.Footer, WorkspaceStore.Sheet.Global.Footer]}
|
||||
type={topSheet.type}/>
|
||||
</div>
|
||||
</Flexbox>
|
||||
|
||||
_toolbarComponents: ->
|
||||
@state.stack.map (type, index) ->
|
||||
<Toolbar type={type}
|
||||
_toolbarElements: ->
|
||||
@state.stack.map (data, index) ->
|
||||
<Toolbar data={data}
|
||||
ref={"toolbar-#{index}"}
|
||||
depth={index}
|
||||
key={index} />
|
||||
|
||||
_sheetComponents: ->
|
||||
@state.stack.map (type, index) =>
|
||||
<Sheet type={type}
|
||||
_sheetElements: ->
|
||||
@state.stack.map (data, index) =>
|
||||
<Sheet data={data}
|
||||
depth={index}
|
||||
key={index}
|
||||
onColumnSizeChanged={@_onColumnSizeChanged} />
|
||||
|
|
|
@ -5,19 +5,17 @@ RetinaImg = require './components/retina-img.cjsx'
|
|||
Flexbox = require './components/flexbox.cjsx'
|
||||
ResizableRegion = require './components/resizable-region.cjsx'
|
||||
|
||||
FLEX = 10000
|
||||
|
||||
module.exports =
|
||||
Sheet = React.createClass
|
||||
displayName: 'Sheet'
|
||||
|
||||
propTypes:
|
||||
type: React.PropTypes.string.isRequired
|
||||
data: React.PropTypes.object.isRequired
|
||||
depth: React.PropTypes.number.isRequired
|
||||
columns: React.PropTypes.arrayOf(React.PropTypes.string)
|
||||
onColumnSizeChanged: React.PropTypes.func
|
||||
|
||||
getDefaultProps: ->
|
||||
columns: ['Left', 'Center', 'Right']
|
||||
|
||||
getInitialState: ->
|
||||
@_getStateFromStores()
|
||||
|
||||
|
@ -53,57 +51,67 @@ Sheet = React.createClass
|
|||
|
||||
<div name={"Sheet"}
|
||||
style={style}
|
||||
data-type={@props.type}>
|
||||
data-type={@props.data.type}>
|
||||
<Flexbox direction="row">
|
||||
{@_columnFlexboxComponents()}
|
||||
{@_columnFlexboxElements()}
|
||||
</Flexbox>
|
||||
</div>
|
||||
|
||||
_columnFlexboxComponents: ->
|
||||
@props.columns.map (column) =>
|
||||
classes = @state[column] || []
|
||||
return if classes.length is 0
|
||||
|
||||
components = classes.map ({name, view}) -> <view key={name} />
|
||||
|
||||
maxWidth = _.reduce classes, ((m,{view}) -> Math.min(view.maxWidth ? 10000, m)), 10000
|
||||
minWidth = _.reduce classes, ((m,{view}) -> Math.max(view.minWidth ? 0, m)), 0
|
||||
resizable = minWidth != maxWidth && column != 'Center'
|
||||
|
||||
if resizable
|
||||
if column is 'Left' then handle = ResizableRegion.Handle.Right
|
||||
if column is 'Right' then handle = ResizableRegion.Handle.Left
|
||||
<ResizableRegion key={"#{@props.type}:#{column}"}
|
||||
name={"#{@props.type}:#{column}"}
|
||||
data-column={column}
|
||||
_columnFlexboxElements: ->
|
||||
@state.columns.map ({entries, maxWidth, minWidth, handle, id}, idx) =>
|
||||
elements = entries.map ({name, view}) -> <view key={name} />
|
||||
if minWidth != maxWidth and maxWidth < FLEX
|
||||
<ResizableRegion key={"#{@props.type}:#{idx}"}
|
||||
name={"#{@props.type}:#{idx}"}
|
||||
className={"column-#{id}"}
|
||||
data-column={idx}
|
||||
onResize={ => @props.onColumnSizeChanged(@) }
|
||||
minWidth={minWidth}
|
||||
maxWidth={maxWidth}
|
||||
handle={handle}>
|
||||
<Flexbox direction="column">
|
||||
{components}
|
||||
{elements}
|
||||
</Flexbox>
|
||||
</ResizableRegion>
|
||||
else
|
||||
<Flexbox direction="column"
|
||||
key={"#{@props.type}:#{column}"}
|
||||
name={"#{@props.type}:#{column}"}
|
||||
data-column={column}
|
||||
key={"#{@props.type}:#{idx}"}
|
||||
name={"#{@props.type}:#{idx}"}
|
||||
className={"column-#{id}"}
|
||||
data-column={idx}
|
||||
style={flex: 1}>
|
||||
{components}
|
||||
{elements}
|
||||
</Flexbox>
|
||||
|
||||
_getStateFromStores: ->
|
||||
state = {}
|
||||
state.mode = WorkspaceStore.selectedLayoutMode()
|
||||
state =
|
||||
mode: WorkspaceStore.selectedLayoutMode()
|
||||
columns: []
|
||||
|
||||
for column in @props.columns
|
||||
views = []
|
||||
for entry in ComponentRegistry.findAllByRole("#{@props.type}:#{column}")
|
||||
continue if entry.mode? and entry.mode != state.mode
|
||||
views.push(entry)
|
||||
state["#{column}"] = views
|
||||
widest = -1
|
||||
widestWidth = -1
|
||||
|
||||
for location, idx in @props.data.columns[state.mode]
|
||||
entries = ComponentRegistry.findAllByLocationAndMode(location, state.mode)
|
||||
maxWidth = _.reduce entries, ((m,{view}) -> Math.min(view.maxWidth ? 10000, m)), 10000
|
||||
minWidth = _.reduce entries, ((m,{view}) -> Math.max(view.minWidth ? 0, m)), 0
|
||||
col = {entries, maxWidth, minWidth, id: location.id}
|
||||
state.columns.push(col)
|
||||
|
||||
if maxWidth > widestWidth
|
||||
widestWidth = maxWidth
|
||||
widest = idx
|
||||
|
||||
# Once we've accumulated all the React components for the columns,
|
||||
# ensure that at least one column has a huge max-width so that the columns
|
||||
# expand to fill the window. This may make items in the column unhappy, but
|
||||
# we pick the column with the highest max-width so the effect is minimal.
|
||||
state.columns[widest].maxWidth = FLEX
|
||||
|
||||
# Assign flexible edges based on whether items are to the left or right
|
||||
# of the flexible column (which has no edges)
|
||||
state.columns[i].handle = ResizableRegion.Handle.Right for i in [0..widest-1] by 1
|
||||
state.columns[i].handle = ResizableRegion.Handle.Left for i in [widest..state.columns.length-1] by 1
|
||||
state
|
||||
|
||||
_pop: ->
|
||||
|
|
|
@ -63,6 +63,8 @@ atom-workspace {
|
|||
order: -1000;
|
||||
min-width: 102px;
|
||||
width: 102px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
button {
|
||||
-webkit-app-region: no-drag;
|
||||
|
@ -146,6 +148,8 @@ body.is-blurred {
|
|||
order:-999;
|
||||
padding-top: 5px;
|
||||
padding-left: @spacing-three-quarters;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.btn-toolbar {
|
||||
|
|
Loading…
Reference in a new issue