Skip to content

Commit

Permalink
Refactored selectionBar, needs test cases though
Browse files Browse the repository at this point in the history
  • Loading branch information
MeoMix committed May 18, 2015
1 parent 0b5e598 commit 376d72c
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 201 deletions.
1 change: 1 addition & 0 deletions Streamus Chrome Extension.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
<Content Include="src\js\test\foreground\view\behavior\sortable.spec.js" />
<Content Include="src\js\test\foreground\view\behavior\tooltipable.spec.js" />
<Content Include="src\js\test\foreground\foregroundSpecLoader.js" />
<Content Include="src\js\test\foreground\view\behavior\viewModelContainer.spec.js" />
<Content Include="src\js\test\foreground\view\contextMenu\contextMenuItemsView.spec.js" />
<Content Include="src\js\test\foreground\view\contextMenu\contextMenuItemView.spec.js" />
<Content Include="src\js\test\foreground\view\contextMenu\contextMenuRegion.spec.js" />
Expand Down
2 changes: 1 addition & 1 deletion src/js/background/model/signInManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
initialize: function() {
this.on('change:signedInUser', this._onChangeSignedInUser);
this.on('change:signInFailed', this._onChangeSignInFailed);
this.listenTo(Streamus.channels.backgroundArea.vent, 'rendered', this._onBackgroundAreaRendered);
//this.listenTo(Streamus.channels.backgroundArea.vent, 'rendered', this._onBackgroundAreaRendered);
chrome.runtime.onMessage.addListener(this._onChromeRuntimeMessage.bind(this));
chrome.runtime.onMessageExternal.addListener(this._onChromeRuntimeMessageExternal.bind(this));
chrome.identity.onSignInChanged.addListener(this._onChromeIdentitySignInChanged.bind(this));
Expand Down
159 changes: 143 additions & 16 deletions src/js/foreground/model/selectionBar/selectionBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,161 @@
var SelectionBar = Backbone.Model.extend({
defaults: {
// A reference to the collection which currently has selected models. Only one collection can have selected models at a time.
activeCollection: null
//canAdd: false,
//canDelete: false,
//canSave: false,
//canPlay: false
activeCollection: null,
selectedCount: 0,
canAdd: false,
canDelete: false,
canSave: false,
canPlay: false,
signInManager: null,
streamItems: null,
searchResults: null
},

streamItemsEvents: {
'add:completed': '_onStreamItemsAddCompleted',
'remove': '_onStreamItemsRemove',
'reset': '_onStreamItemsReset'
},

multiSelectCollectionEvents: {
'change:selected': '_onMultiSelectCollectionChangeSelected',
'remove': '_onMultiSelectCollectionRemove'
},

playlistsEvents: {
'change:active': '_onPlaylistsChangeActive'
},

initialize: function () {
//this._setState(this.get('activeCollection'));
//this.on('change:activeCollection', this._onChangeActiveCollection);
initialize: function() {
var signInManager = this.get('signInManager');
var signedInUser = signInManager.get('signedInUser');
var activeCollection = this.get('activeCollection');
this._setState(activeCollection, signInManager.get('signedInUser'));

// If user is currently signed in then listen to their activePlaylist's selection events.
if (signedInUser !== null) {
this._setUserBindings(signedInUser, true);
}

Marionette.bindEntityEvents(this, this.get('streamItems'), this.multiSelectCollectionEvents);
Marionette.bindEntityEvents(this, this.get('searchResults'), this.multiSelectCollectionEvents);
this.on('change:activeCollection', this._onChangeActiveCollection);
this.listenTo(signInManager, 'change:signedInUser', this._onSignInManagerChangeSignedInUser);

// TODO: Make bindEntityEvents a part of BB model
Marionette.bindEntityEvents(this, this.get('streamItems'), this.streamItemsEvents);
},

_onChangeActiveCollection: function(model, activeCollection) {
this._setState(activeCollection);
var signedInUser = this.get('signInManager').get('signedInUser');
this._setState(activeCollection, signedInUser);
},

_onSignInManagerChangeSignedInUser: function(model, signedInUser) {
var activeCollection = this.get('activeCollection');
this._setState(activeCollection, signedInUser);

// Bind/unbind listeners as appropriate whenver the signedInUser changes.
if (signedInUser === null) {
this._setUserBindings(model.previous('signedInUser'), false);
} else {
this._setUserBindings(signedInUser, true);
}
},

// Keep track of which multi-select collection is currently holding selected items
_onMultiSelectCollectionChangeSelected: function(model, selected) {
this._setActiveCollection(model.collection, selected);
this._setSelectedCount();
this._setCanAddState(this.get('activeCollection'));
},

// If a selected model is removed from a collection then a 'change:selected' event does not fire.
_onMultiSelectCollectionRemove: function(model, collection) {
this._setActiveCollection(collection, false);
this._setSelectedCount();
},

// Bind/unbind listeners as appropriate whenever the active playlist changes.
_onPlaylistsChangeActive: function(model, active) {
if (active) {
Marionette.bindEntityEvents(this, model.get('items'), this.multiSelectCollectionEvents);
} else {
Marionette.unbindEntityEvents(this, model.get('items'), this.multiSelectCollectionEvents);
}
},

_onStreamItemsAddCompleted: function() {
this._setCanAddState(this.get('activeCollection'));
},

_onStreamItemsRemove: function() {
this._setCanAddState(this.get('activeCollection'));
},

_onStreamItemsReset: function() {
this._setCanAddState(this.get('activeCollection'));
},

_setState: function (activeCollection) {
_setState: function (activeCollection, signedInUser) {
var activeCollectionExists = activeCollection !== null;
var isSignedIn = signedInUser !== null;

this.set('canSave', activeCollectionExists);
this.set('canPlay', activeCollectionExists);

// Search results are unable to be deleted
this.set('canSave', activeCollectionExists && isSignedIn);
// Some collections, such as search results, contain models which should not be deleted.
this.set('canDelete', activeCollectionExists && !activeCollection.isImmutable);

// TODO: I need to be able to check streamItems for duplicates with the activeCollection and also if streamItems has items added/removed I need to re-update canAdd
// var duplicatesInfo = this.streamItems.getDuplicatesInfo(activeCollection.getSelectedSongs());
//this.set('canAdd', activeCollectionExists);
this._setCanAddState(activeCollection);
},

_setCanAddState: function(activeCollection) {
var canAdd = activeCollection !== null;

if (canAdd) {
var selectedSongs = activeCollection.getSelectedSongs();
var duplicatesInfo = this.get('streamItems').getDuplicatesInfo(selectedSongs);
canAdd = !duplicatesInfo.allDuplicates;
}

this.set('canAdd', canAdd);
},

// Keep track of which collection currently has selected songs by handling selection & deselection events.
_setActiveCollection: function(collection, isSelecting) {
var hasSelectedItems = collection.selected().length > 0;

if (hasSelectedItems) {
// isSelecting is necessary because if one collection has 2 models selected and the user then selects a model in a different collection
// the first collection will de-select one of its models after the second collection has selected one of its own.
// This results in two collections both having selected models and the activeCollection is incorrect.
// By checking isSelecting we know that one collection is not the active collection - it's just in the process of de-selecting all of its models.
if (isSelecting) {
this.set('activeCollection', collection);
}
} else if (this.get('activeCollection') === collection) {
this.set('activeCollection', null);
}
},

// Update the number of songs which are currently selected
_setSelectedCount: function() {
var activeCollection = this.get('activeCollection');
var songCount = activeCollection === null ? 0 : activeCollection.selected().length;
this.set('selectedCount', songCount);
},

// Bind or unbind entity events to a user's playlists and activePlaylist's items.
// Useful for when a user is signing in/out.
_setUserBindings: function(user, isBinding) {
var bindingAction = isBinding ? Marionette.bindEntityEvents : Marionette.unbindEntityEvents;

var playlists = user.get('playlists');
bindingAction.call(this, this, playlists, this.playlistsEvents);

var playlistItems = playlists.getActivePlaylist().get('items');
bindingAction.call(this, this, playlistItems, this.multiSelectCollectionEvents);
}
});

Expand Down
4 changes: 2 additions & 2 deletions src/js/foreground/view/behavior/tooltipable.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
},

_onMouseEnter: function(event) {
this._ensureHovered(event.target);
this._ensureHovered(event.currentTarget);
},

_onMouseLeave: function(event) {
$(event.target).data('is-hovered', false);
$(event.currentTarget).data('is-hovered', false);
this._hideTooltip();
},

Expand Down
2 changes: 0 additions & 2 deletions src/js/foreground/view/element/simpleMenuView.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@
var centering = (listItemHeight - offsetData.itemHeight) / 2 - paddingTop;
var topOffset = offsetData.itemOffset + centering;

console.log('this.$el height and scroll', this.el.offsetHeight, this.el.scrollHeight);

this.$el.css('top', topOffset);
}
});
Expand Down
8 changes: 5 additions & 3 deletions src/js/foreground/view/selectionBar/selectionBarRegion.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
},

_onForegroundAreaIdle: function() {
var selectionBar = new SelectionBar();
this.show(new SelectionBarView({
var selectionBar = new SelectionBar({
streamItems: Streamus.backgroundPage.stream.get('items'),
searchResults: Streamus.backgroundPage.search.get('results'),
signInManager: Streamus.backgroundPage.signInManager,
signInManager: Streamus.backgroundPage.signInManager
});

this.show(new SelectionBarView({
model: selectionBar
}));

Expand Down

0 comments on commit 376d72c

Please sign in to comment.