DataView => ListDataSource

This commit is contained in:
Ben Gotow 2016-01-14 12:26:54 -08:00
parent c52e4bcd19
commit ff01c3a502
18 changed files with 129 additions and 128 deletions

View file

@ -29,11 +29,11 @@ Here's a quick look at standard components you can require from `nylas-component
- **{RetinaImg}**: Replacement for standard `<img>` tags which automatically resolves the best version of the image for the user's display and can apply many image transforms.
- **{ListTabular}**: Component for creating a list of items backed by a paginating ModelView.
- **{ListTabular}**: Component for creating a list of items backed by a paginating ListDataSource.
- **{MultiselectList}**: Component for creating a list that supports multi-selection. (Internally wraps ListTabular)
- **{MultiselectActionBar}**: Component for creating a contextual toolbar that is activated when the user makes a selection on a ModelView.
- **{MultiselectActionBar}**: Component for creating a contextual toolbar that is activated when the user makes a selection on a ListDataSource.
- **{ResizableRegion}**: Component that renders it's children inside a resizable region with a draggable handle.

View file

@ -6,7 +6,7 @@ _ = require 'underscore'
Actions,
AccountStore,
MutableQuerySubscription,
QueryResultSetView,
ObservableListDataSource,
FocusedPerspectiveStore,
DatabaseStore} = require 'nylas-exports'
@ -17,7 +17,7 @@ class DraftListStore extends NylasStore
@subscription = new MutableQuerySubscription(@_queryForCurrentAccount(), {asResultSet: true})
$resultSet = Rx.Observable.fromPrivateQuerySubscription('draft-list', @subscription)
@_view = new QueryResultSetView $resultSet, ({start, end}) =>
@_view = new ObservableListDataSource $resultSet, ({start, end}) =>
@subscription.replaceQuery(@_queryForCurrentAccount().page(start, end))
view: =>

View file

@ -69,7 +69,7 @@ class EmptyState extends React.Component
@displayName = 'EmptyState'
@propTypes =
visible: React.PropTypes.bool.isRequired
dataView: React.PropTypes.object
dataSource: React.PropTypes.object
constructor: (@props) ->
@state =
@ -85,9 +85,9 @@ class EmptyState extends React.Component
@setState(active:true)
shouldComponentUpdate: (nextProps, nextState) ->
# Avoid deep comparison of dataView, which is a very complex object
# Avoid deep comparison of dataSource, which is a very complex object
return true if nextProps.visible isnt @props.visible
return true if nextProps.dataView isnt @props.dataView
return true if nextProps.dataSource isnt @props.dataSource
return not _.isEqual(nextState, @state)
componentWillUnmount: ->

View file

@ -5,7 +5,7 @@ Rx = require 'rx-lite'
DatabaseStore,
QuerySubscription,
QueryResultSet,
QueryResultSetView,
ObservableListDataSource,
MutableQuerySubscription} = require 'nylas-exports'
PaginatingSearch = require './paginating-search'
@ -85,7 +85,7 @@ module.exports = ThreadListViewFactory =
search = new PaginatingSearch(terms, accountId)
$resultSet = _flatMapJoiningMessages(search.observable())
return new QueryResultSetView $resultSet, ({start, end}) =>
return new ObservableListDataSource $resultSet, ({start, end}) =>
search.setRange({start, end})
viewForQuery: (query) =>
@ -93,5 +93,5 @@ module.exports = ThreadListViewFactory =
$resultSet = Rx.Observable.fromPrivateQuerySubscription('thread-list', subscription)
$resultSet = _flatMapJoiningMessages($resultSet)
return new QueryResultSetView $resultSet, ({start, end}) =>
return new ObservableListDataSource $resultSet, ({start, end}) =>
subscription.replaceQuery(query.clone().page(start, end))

View file

@ -15,7 +15,7 @@ describe "MultiselectListInteractionHandler", ->
data = [@item, @itemFocus, @itemAfterFocus, @itemKeyboardFocus, @itemAfterKeyboardFocus]
@dataView =
@dataSource =
selection:
toggle: jasmine.createSpy('toggle')
expandTo: jasmine.createSpy('expandTo')
@ -29,7 +29,7 @@ describe "MultiselectListInteractionHandler", ->
count: -> data.length
@collection = 'threads'
@handler = new MultiselectListInteractionHandler(@dataView, @collection)
@handler = new MultiselectListInteractionHandler(@dataSource, @collection)
@isRootSheet = true
spyOn(WorkspaceStore, 'topSheet').andCallFake => {root: @isRootSheet}
@ -52,7 +52,7 @@ describe "MultiselectListInteractionHandler", ->
describe "onMetaClick", ->
it "shoud toggle selection", ->
@handler.onMetaClick(@item)
expect(@dataView.selection.toggle).toHaveBeenCalledWith(@item)
expect(@dataSource.selection.toggle).toHaveBeenCalledWith(@item)
it "should focus the keyboard on the clicked item", ->
@handler.onMetaClick(@item)
@ -61,7 +61,7 @@ describe "MultiselectListInteractionHandler", ->
describe "onShiftClick", ->
it "should expand selection", ->
@handler.onShiftClick(@item)
expect(@dataView.selection.expandTo).toHaveBeenCalledWith(@item)
expect(@dataSource.selection.expandTo).toHaveBeenCalledWith(@item)
it "should focus the keyboard on the clicked item", ->
@handler.onShiftClick(@item)
@ -77,13 +77,13 @@ describe "MultiselectListInteractionHandler", ->
it "should toggle the selection of the keyboard item", ->
@isRootSheet = true
@handler.onSelect()
expect(@dataView.selection.toggle).toHaveBeenCalledWith(@itemKeyboardFocus)
expect(@dataSource.selection.toggle).toHaveBeenCalledWith(@itemKeyboardFocus)
describe "on the thread view", ->
it "should toggle the selection of the focused item", ->
@isRootSheet = false
@handler.onSelect()
expect(@dataView.selection.toggle).toHaveBeenCalledWith(@itemFocus)
expect(@dataSource.selection.toggle).toHaveBeenCalledWith(@itemFocus)
describe "onShift", ->
describe "on the root view", ->
@ -96,7 +96,7 @@ describe "MultiselectListInteractionHandler", ->
it "should walk selection if the select option is passed", ->
@handler.onShift(1, select: true)
expect(@dataView.selection.walk).toHaveBeenCalledWith({current: @itemKeyboardFocus, next: @itemAfterKeyboardFocus})
expect(@dataSource.selection.walk).toHaveBeenCalledWith({current: @itemKeyboardFocus, next: @itemAfterKeyboardFocus})
describe "on the thread view", ->
beforeEach ->

View file

@ -15,7 +15,7 @@ describe "MultiselectSplitInteractionHandler", ->
data = [@item, @itemFocus, @itemAfterFocus, @itemKeyboardFocus, @itemAfterKeyboardFocus]
@selection = []
@dataView =
@dataSource =
selection:
toggle: jasmine.createSpy('toggle')
expandTo: jasmine.createSpy('expandTo')
@ -35,7 +35,7 @@ describe "MultiselectSplitInteractionHandler", ->
count: -> data.length
@collection = 'threads'
@handler = new MultiselectSplitInteractionHandler(@dataView, @collection)
@handler = new MultiselectSplitInteractionHandler(@dataSource, @collection)
@isRootSheet = true
spyOn(WorkspaceStore, 'topSheet').andCallFake => {root: @isRootSheet}
@ -70,7 +70,7 @@ describe "MultiselectSplitInteractionHandler", ->
it "should turn the focused item into the first selected item", ->
@handler.onMetaClick(@item)
expect(@dataView.selection.add).toHaveBeenCalledWith(@itemFocus)
expect(@dataSource.selection.add).toHaveBeenCalledWith(@itemFocus)
it "should clear the focus", ->
@handler.onMetaClick(@item)
@ -78,7 +78,7 @@ describe "MultiselectSplitInteractionHandler", ->
it "should toggle selection", ->
@handler.onMetaClick(@item)
expect(@dataView.selection.toggle).toHaveBeenCalledWith(@item)
expect(@dataSource.selection.toggle).toHaveBeenCalledWith(@item)
it "should call _checkSelectionAndFocusConsistency", ->
spyOn(@handler, '_checkSelectionAndFocusConsistency')
@ -93,7 +93,7 @@ describe "MultiselectSplitInteractionHandler", ->
it "should turn the focused item into the first selected item", ->
@handler.onMetaClick(@item)
expect(@dataView.selection.add).toHaveBeenCalledWith(@itemFocus)
expect(@dataSource.selection.add).toHaveBeenCalledWith(@itemFocus)
it "should clear the focus", ->
@handler.onMetaClick(@item)
@ -101,7 +101,7 @@ describe "MultiselectSplitInteractionHandler", ->
it "should expand selection", ->
@handler.onShiftClick(@item)
expect(@dataView.selection.expandTo).toHaveBeenCalledWith(@item)
expect(@dataSource.selection.expandTo).toHaveBeenCalledWith(@item)
it "should call _checkSelectionAndFocusConsistency", ->
spyOn(@handler, '_checkSelectionAndFocusConsistency')
@ -127,13 +127,13 @@ describe "MultiselectSplitInteractionHandler", ->
spyOn(FocusedContentStore, 'focused').andCallFake => @itemFocus
spyOn(FocusedContentStore, 'focusedId').andCallFake -> 'focus'
@handler.onShift(1, {select: true})
expect(@dataView.selection.add).toHaveBeenCalledWith(@itemFocus)
expect(@dataSource.selection.add).toHaveBeenCalledWith(@itemFocus)
it "should walk the selection to the shift target", ->
spyOn(FocusedContentStore, 'focused').andCallFake => @itemFocus
spyOn(FocusedContentStore, 'focusedId').andCallFake -> 'focus'
@handler.onShift(1, {select: true})
expect(@dataView.selection.walk).toHaveBeenCalledWith({current: @itemFocus, next: @itemAfterFocus})
expect(@dataSource.selection.walk).toHaveBeenCalledWith({current: @itemFocus, next: @itemAfterFocus})
describe "when one or more items is selected", ->
it "should move the keyboard cursor", ->
@ -160,5 +160,5 @@ describe "MultiselectSplitInteractionHandler", ->
it "should clear the selection and make the item focused", ->
@handler._checkSelectionAndFocusConsistency()
expect(@dataView.selection.clear).toHaveBeenCalled()
expect(@dataSource.selection.clear).toHaveBeenCalled()
expect(Actions.setFocus).toHaveBeenCalledWith({collection: @collection, item: @item})

View file

@ -1,30 +1,30 @@
_ = require 'underscore'
Thread = require '../src/flux/models/thread'
ModelView = require '../src/flux/stores/model-view'
ModelViewSelection = require '../src/flux/stores/model-view-selection'
ListDataSource = require '../src/flux/stores/list-data-source'
ListSelection = require '../src/flux/stores/list-selection'
describe "ModelViewSelection", ->
describe "ListSelection", ->
beforeEach ->
@trigger = jasmine.createSpy('trigger')
@items = []
@items.push(new Thread(id: "#{ii}")) for ii in [0..99]
@view = new ModelView()
@view = new ListDataSource()
@view.indexOfId = jasmine.createSpy('indexOfId').andCallFake (id) =>
_.findIndex(@items, _.matcher({id}))
@view.get = jasmine.createSpy('get').andCallFake (idx) =>
@items[idx]
@selection = new ModelViewSelection(@view, @trigger)
@selection = new ListSelection(@view, @trigger)
it "should initialize with an empty set", ->
expect(@selection.items()).toEqual([])
expect(@selection.ids()).toEqual([])
it "should throw an exception if a view is not provided", ->
expect( => new ModelViewSelection(null, @trigger)).toThrow()
expect( => new ListSelection(null, @trigger)).toThrow()
describe "set", ->
it "should replace the current selection with the provided models", ->

View file

@ -70,7 +70,7 @@ describe "MutableQueryResultSet", ->
'C': {id: 'C', clientId: 'C-local'},
})
fdescribe "addIdsInRange", ->
describe "addIdsInRange", ->
describe "when the set is currently empty", ->
it "should set the result set to the provided one", ->
@set = new MutableQueryResultSet()

View file

@ -68,7 +68,7 @@ class ListTabular extends React.Component
@displayName = 'ListTabular'
@propTypes =
columns: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
dataView: React.PropTypes.object
dataSource: React.PropTypes.object
itemPropsProvider: React.PropTypes.func
itemHeight: React.PropTypes.number
onSelect: React.PropTypes.func
@ -93,7 +93,7 @@ class ListTabular extends React.Component
componentDidUpdate: (prevProps, prevState) =>
# If our view has been swapped out for an entirely different one,
# reset our scroll position to the top.
if prevProps.dataView isnt @props.dataView
if prevProps.dataSource isnt @props.dataSource
@refs.container.scrollTop = 0
unless @updateRangeStateFiring
@ -120,7 +120,7 @@ class ListTabular extends React.Component
# Expand the start/end so that you can advance the keyboard cursor fast and
# we have items to move to and then scroll to.
rangeStart = Math.max(0, rangeStart - 2)
rangeEnd = Math.min(rangeEnd + 2, @props.dataView.count() + 1)
rangeEnd = Math.min(rangeEnd + 2, @props.dataSource.count() + 1)
# Final sanity check to prevent needless work
return if rangeStart is @state.renderedRangeStart and
@ -128,7 +128,7 @@ class ListTabular extends React.Component
@updateRangeStateFiring = true
@props.dataView.setRetainedRange
@props.dataSource.setRetainedRange
start: rangeStart
end: rangeEnd
@ -138,7 +138,7 @@ class ListTabular extends React.Component
render: =>
innerStyles =
height: @props.dataView.count() * @props.itemHeight
height: @props.dataSource.count() * @props.itemHeight
<ScrollRegion
ref="container"
@ -155,7 +155,7 @@ class ListTabular extends React.Component
rows = []
for idx in [@state.renderedRangeStart..@state.renderedRangeEnd-1]
item = @props.dataView.get(idx)
item = @props.dataSource.get(idx)
continue unless item
itemProps = {}

View file

@ -43,7 +43,7 @@ class MultiselectActionBar extends React.Component
###
Public: React `props` supported by MultiselectActionBar:
- `dataStore` An instance of a {ModelView}.
- `dataStore` An instance of a {ListDataSource}.
- `collection` The name of the collection. The collection name is used for the text
that appears in the bar "1 thread selected" and is also used to find components
in the component registry that should appear in the bar (`thread` => `thread:BulkAtion`)

View file

@ -5,7 +5,7 @@ _ = require 'underscore'
module.exports =
class MultiselectListInteractionHandler
constructor: (@dataView, @collection) ->
constructor: (@dataSource, @collection) ->
cssClass: ->
'handler-list'
@ -20,35 +20,35 @@ class MultiselectListInteractionHandler
Actions.setFocus({collection: @collection, item: item})
onMetaClick: (item) ->
@dataView.selection.toggle(item)
@dataSource.selection.toggle(item)
Actions.setCursorPosition({collection: @collection, item: item})
onShiftClick: (item) ->
@dataView.selection.expandTo(item)
@dataSource.selection.expandTo(item)
Actions.setCursorPosition({collection: @collection, item: item})
onEnter: ->
keyboardCursorId = FocusedContentStore.keyboardCursorId(@collection)
if keyboardCursorId
item = @dataView.getById(keyboardCursorId)
item = @dataSource.getById(keyboardCursorId)
Actions.setFocus({collection: @collection, item: item})
onSelect: ->
{id} = @_keyboardContext()
return unless id
@dataView.selection.toggle(@dataView.getById(id))
@dataSource.selection.toggle(@dataSource.getById(id))
onShift: (delta, options = {}) ->
{id, action} = @_keyboardContext()
current = @dataView.getById(id)
index = @dataView.indexOfId(id)
index = Math.max(0, Math.min(index + delta, @dataView.count() - 1))
next = @dataView.get(index)
current = @dataSource.getById(id)
index = @dataSource.indexOfId(id)
index = Math.max(0, Math.min(index + delta, @dataSource.count() - 1))
next = @dataSource.get(index)
action({collection: @collection, item: next})
if options.select
@dataView.selection.walk({current, next})
@dataSource.selection.walk({current, next})
_keyboardContext: ->
if WorkspaceStore.topSheet().root

View file

@ -16,7 +16,7 @@ MultiselectSplitInteractionHandler = require './multiselect-split-interaction-ha
###
Public: MultiselectList wraps {ListTabular} and makes it easy to present a
{ModelView} with selection support. It adds a checkbox column to the columns
{ListDataSource} with selection support. It adds a checkbox column to the columns
you provide, and also handles:
- Command-clicking individual items
@ -98,7 +98,7 @@ class MultiselectList extends React.Component
otherProps = _.omit(@props, _.keys(@constructor.propTypes))
className = @props.className
if @state.dataView and @state.handler
if @state.dataSource and @state.handler
className += " " + @state.handler.cssClass()
@itemPropsProvider ?= (item) =>
@ -114,7 +114,7 @@ class MultiselectList extends React.Component
if @props.emptyComponent
emptyElement = <@props.emptyComponent
visible={@state.loaded and @state.empty}
dataView={@state.dataView} />
dataSource={@state.dataSource} />
spinnerElement = <Spinner visible={!@state.loaded and @state.empty} />
@ -124,7 +124,7 @@ class MultiselectList extends React.Component
ref="list"
columns={@state.computedColumns}
scrollTooltipComponent={@props.scrollTooltipComponent}
dataView={@state.dataView}
dataSource={@state.dataSource}
itemPropsProvider={@itemPropsProvider}
itemHeight={@props.itemHeight}
onSelect={@_onClickItem}
@ -157,12 +157,12 @@ class MultiselectList extends React.Component
_onSelectAll: =>
return unless @state.handler
items = @state.dataView.itemsCurrentlyInViewMatching -> true
@state.dataView.selection.set(items)
items = @state.dataSource.itemsCurrentlyInViewMatching -> true
@state.dataSource.selection.set(items)
_onDeselect: =>
return unless @_visible() and @state.dataView
@state.dataView.selection.clear()
return unless @_visible() and @state.dataSource
@state.dataSource.selection.clear()
_onShift: (delta, options = {}) =>
return unless @state.handler
@ -216,7 +216,7 @@ class MultiselectList extends React.Component
else
handler = new MultiselectSplitInteractionHandler(view, props.collection)
dataView: view
dataSource: view
handler: handler
columns: props.columns
computedColumns: computedColumns

View file

@ -5,7 +5,7 @@ _ = require 'underscore'
module.exports =
class MultiselectSplitInteractionHandler
constructor: (@dataView, @collection) ->
constructor: (@dataSource, @collection) ->
cssClass: ->
'handler-split'
@ -14,21 +14,21 @@ class MultiselectSplitInteractionHandler
true
shouldShowKeyboardCursor: ->
@dataView.selection.count() > 1
@dataSource.selection.count() > 1
onClick: (item) ->
Actions.setFocus({collection: @collection, item: item, usingClick: true})
@dataView.selection.clear()
@dataSource.selection.clear()
@_checkSelectionAndFocusConsistency()
onMetaClick: (item) ->
@_turnFocusIntoSelection()
@dataView.selection.toggle(item)
@dataSource.selection.toggle(item)
@_checkSelectionAndFocusConsistency()
onShiftClick: (item) ->
@_turnFocusIntoSelection()
@dataView.selection.expandTo(item)
@dataSource.selection.expandTo(item)
@_checkSelectionAndFocusConsistency()
onEnter: ->
@ -40,39 +40,39 @@ class MultiselectSplitInteractionHandler
if options.select
@_turnFocusIntoSelection()
if @dataView.selection.count() > 0
selection = @dataView.selection
if @dataSource.selection.count() > 0
selection = @dataSource.selection
keyboardId = FocusedContentStore.keyboardCursorId(@collection)
id = keyboardId ? @dataView.selection.top().id
id = keyboardId ? @dataSource.selection.top().id
action = Actions.setCursorPosition
else
id = FocusedContentStore.focusedId(@collection)
action = Actions.setFocus
current = @dataView.getById(id)
index = @dataView.indexOfId(id)
index = Math.max(0, Math.min(index + delta, @dataView.count() - 1))
next = @dataView.get(index)
current = @dataSource.getById(id)
index = @dataSource.indexOfId(id)
index = Math.max(0, Math.min(index + delta, @dataSource.count() - 1))
next = @dataSource.get(index)
action({collection: @collection, item: next})
if options.select
@dataView.selection.walk({current, next})
@dataSource.selection.walk({current, next})
@_checkSelectionAndFocusConsistency()
_turnFocusIntoSelection: ->
focused = FocusedContentStore.focused(@collection)
Actions.setFocus({collection: @collection, item: null})
@dataView.selection.add(focused)
@dataSource.selection.add(focused)
_checkSelectionAndFocusConsistency: ->
focused = FocusedContentStore.focused(@collection)
selection = @dataView.selection
selection = @dataSource.selection
if focused and selection.count() > 0
@dataView.selection.add(focused)
@dataSource.selection.add(focused)
Actions.setFocus({collection: @collection, item: null})
if selection.count() is 1 and !focused
Actions.setFocus({collection: @collection, item: selection.items()[0]})
@dataView.selection.clear()
@dataSource.selection.clear()

View file

@ -0,0 +1,46 @@
_ = require 'underscore'
EventEmitter = require('events').EventEmitter
ListSelection = require './list-selection'
module.exports =
class ListDataSource
constructor: ->
@_emitter = new EventEmitter()
@selection = new ListSelection(@, @trigger)
@
# Accessing Data
trigger: (arg) =>
@_emitter.emit('trigger', arg)
listen: (callback, bindContext) ->
eventHandler = ->
callback.apply(bindContext, arguments)
@_emitter.addListener('trigger', eventHandler)
return => @_emitter.removeListener('trigger', eventHandler)
loaded: ->
throw new Error("ListDataSource base class does not implement loaded()")
empty: ->
throw new Error("ListDataSource base class does not implement empty()")
get: (idx) ->
throw new Error("ListDataSource base class does not implement get()")
getById: (id) ->
throw new Error("ListDataSource base class does not implement getById()")
indexOfId: (id) ->
throw new Error("ListDataSource base class does not implement indexOfId()")
count: ->
throw new Error("ListDataSource base class does not implement count()")
itemsCurrentlyInViewMatching: (matchFn) ->
throw new Error("ListDataSource base class does not implement itemsCurrentlyInViewMatching()")
setRetainedRange: ({start, end}) ->
throw new Error("ListDataSource base class does not implement setRetainedRange()")

View file

@ -2,10 +2,10 @@ Model = require '../models/model'
_ = require 'underscore'
module.exports =
class ModelViewSelection
class ListSelection
constructor: (@_view, @trigger) ->
throw new Error("new ModelViewSelection(): You must provide a view.") unless @_view
throw new Error("new ListSelection(): You must provide a view.") unless @_view
@_items = []
count: ->

View file

@ -1,46 +0,0 @@
_ = require 'underscore'
EventEmitter = require('events').EventEmitter
ModelViewSelection = require './model-view-selection'
module.exports =
class ModelView
constructor: ->
@_emitter = new EventEmitter()
@selection = new ModelViewSelection(@, @trigger)
@
# Accessing Data
trigger: (arg) =>
@_emitter.emit('trigger', arg)
listen: (callback, bindContext) ->
eventHandler = ->
callback.apply(bindContext, arguments)
@_emitter.addListener('trigger', eventHandler)
return => @_emitter.removeListener('trigger', eventHandler)
loaded: ->
throw new Error("ModelView base class does not implement loaded()")
empty: ->
throw new Error("ModelView base class does not implement empty()")
get: (idx) ->
throw new Error("ModelView base class does not implement get()")
getById: (id) ->
throw new Error("ModelView base class does not implement getById()")
indexOfId: (id) ->
throw new Error("ModelView base class does not implement indexOfId()")
count: ->
throw new Error("ModelView base class does not implement count()")
itemsCurrentlyInViewMatching: (matchFn) ->
throw new Error("ModelView base class does not implement itemsCurrentlyInViewMatching()")
setRetainedRange: ({start, end}) ->
throw new Error("ModelView base class does not implement setRetainedRange()")

View file

@ -5,7 +5,7 @@ Message = require '../models/message'
QuerySubscriptionPool = require '../models/query-subscription-pool'
QuerySubscription = require '../models/query-subscription'
MutableQuerySubscription = require '../models/mutable-query-subscription'
ModelView = require './model-view'
ListDataSource = require './list-data-source'
###
This class takes an observable which vends QueryResultSets and adapts it so that
@ -14,7 +14,7 @@ you can make it the data source of a MultiselectList.
When the MultiselectList is refactored to take an Observable, this class should
go away!
###
class QueryResultSetView extends ModelView
class ObservableListDataSource extends ListDataSource
constructor: ($resultSetObservable, @_setRetainedRange) ->
super
@ -31,6 +31,7 @@ class QueryResultSetView extends ModelView
previousResultSet = @_resultSet
@_resultSet = nextResultSet
@selection.updateModelReferences(@_resultSet.models())
@trigger({previous: previousResultSet, next: nextResultSet})
setRetainedRange: ({start, end}) ->
@ -64,4 +65,4 @@ class QueryResultSetView extends ModelView
@_resultSet.models().filter(matchFn)
module.exports = QueryResultSetView
module.exports = ObservableListDataSource

View file

@ -54,7 +54,7 @@ class NylasExports
@load "DatabaseStore", 'flux/stores/database-store'
@load "DatabaseTransaction", 'flux/stores/database-transaction'
@load "QueryResultSet", 'flux/models/query-result-set'
@load "QueryResultSetView", 'flux/stores/query-result-set-view'
@load "ObservableListDataSource", 'flux/stores/observable-list-data-source'
@load "QuerySubscription", 'flux/models/query-subscription'
@load "MutableQuerySubscription", 'flux/models/mutable-query-subscription'
@load "QuerySubscriptionPool", 'flux/models/query-subscription-pool'