Skip to content

Commit

Permalink
Refactor follow+sub buttons, remove ChannelMixin
Browse files Browse the repository at this point in the history
- Refactor these buttons into a component
  - Follow Channel
  - Subscribe Channel
  - Open Chat
  - Share Channel
  - Follow Game
- Remove ChannelMixin and ChannelViewMixin
- Add store.findExistingRecord
  • Loading branch information
bastimeyer committed Sep 1, 2015
1 parent 49d64dd commit 5623be7
Show file tree
Hide file tree
Showing 24 changed files with 406 additions and 315 deletions.
5 changes: 5 additions & 0 deletions src/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ define(function( require ) {
StatsRowComponent: require( "components/StatsRowComponent" ),
LangFilterComponent: require( "components/LangFilterComponent" ),
PreviewImageComponent: require( "components/PreviewImageComponent" ),
OpenChatComponent: require( "components/OpenChatComponent" ),
ShareChannelComponent: require( "components/ShareChannelComponent" ),
SubscribeChannelComponent: require( "components/SubscribeChannelComponent" ),
FollowChannelComponent: require( "components/FollowChannelComponent" ),
FollowGameComponent: require( "components/FollowGameComponent" ),


// Content
Expand Down
24 changes: 24 additions & 0 deletions src/app/components/FollowChannelComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
define([
"Ember",
"components/FormButtonComponent",
"mixins/FollowButtonMixin"
], function(
Ember,
FormButtonComponent,
FollowButtonMixin
) {

var alias = Ember.computed.alias;

return FormButtonComponent.extend( FollowButtonMixin, {
modelName: "twitchUserFollowsChannel",

// model alias (component attribute)
model : alias( "channel" ),
// save the data on the channel record instead of the component
record : alias( "channel.followed" ),
// use the channel's display_name
name : alias( "channel.display_name" )
});

});
22 changes: 22 additions & 0 deletions src/app/components/FollowGameComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
define([
"Ember",
"components/FormButtonComponent",
"mixins/FollowButtonMixin"
], function(
Ember,
FormButtonComponent,
FollowButtonMixin
) {

var alias = Ember.computed.alias;

return FormButtonComponent.extend( FollowButtonMixin, {
modelName: "twitchUserFollowsGame",

// model alias (component attribute)
model : alias( "game" ),
// model is a string, no game record (just use the game name as ID)
id : alias( "model" )
});

});
40 changes: 40 additions & 0 deletions src/app/components/OpenChatComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
define([
"Ember",
"nwjs/nwGui",
"components/FormButtonComponent"
], function(
Ember,
nwGui,
FormButtonComponent
) {

var get = Ember.get;

return FormButtonComponent.extend({
metadata: Ember.inject.service(),

"class" : "btn-hint",
icon : "fa-comments",
title : "Open chat",
iconanim: true,

action: "chat",

actions: {
"chat": function( callback ) {
var url = get( this, "metadata.config.twitch-chat-url" );
var name = get( this, "channel.id" );

if ( url && name ) {
url = url.replace( "{channel}", name );
nwGui.Shell.openExternal( url );

if ( callback instanceof Function ) {
callback();
}
}
}
}
});

});
39 changes: 39 additions & 0 deletions src/app/components/ShareChannelComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
define([
"Ember",
"nwjs/nwGui",
"components/FormButtonComponent"
], function(
Ember,
nwGui,
FormButtonComponent
) {

var get = Ember.get;

return FormButtonComponent.extend({
metadata: Ember.inject.service(),

"class" : "btn-info",
icon : "fa-share-alt",
title : "Copy channel url to clipboard",
iconanim: true,

action: "share",

actions: {
"share": function( callback ) {
var url = get( this, "channel.url" );
var cb = nwGui.Clipboard.get();

if ( url && cb ) {
cb.set( url, "text" );

if ( callback instanceof Function ) {
callback();
}
}
}
}
});

});
65 changes: 65 additions & 0 deletions src/app/components/SubscribeChannelComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
define([
"Ember",
"nwjs/nwGui",
"components/FormButtonComponent",
"mixins/TwitchInteractButtonMixin"
], function(
Ember,
nwGui,
FormButtonComponent,
TwitchInteractButtonMixin
) {

var get = Ember.get;
var alias = Ember.computed.alias;

return FormButtonComponent.extend( TwitchInteractButtonMixin, {
metadata: Ember.inject.service(),

modelName: "twitchUserSubscription",

// model alias (component attribute)
model : alias( "channel" ),
// save the data on the channel record instead of the component
record : alias( "channel.subscribed" ),
// use the channel's display_name
name : alias( "channel.display_name" ),

action: "subscribe",
openBrowser: "openBrowser",

classLoading: "btn-primary",
classSuccess: "btn-success",
classFailure: "btn-primary",
iconLoading : "fa-credit-card",
iconSuccess : "fa-credit-card",
iconFailure : "fa-credit-card",
titleLoading: "",
titleSuccess: function() {
var name = get( this, "name" );
return "You are subscribed to %@".fmt( name );
}.property( "name" ),
titleFailure: function() {
var name = get( this, "name" );
return "Subscribe to %@ now".fmt( name );
}.property( "name" ),


actions: {
"subscribe": function( callback ) {
var url = get( this, "metadata.config.twitch-subscribe-url" );
var name = get( this, "id" );

if ( url && name ) {
url = url.replace( "{channel}", name );
nwGui.Shell.openExternal( url );

if ( callback instanceof Function ) {
callback();
}
}
}
}
});

});
13 changes: 2 additions & 11 deletions src/app/controllers/ChannelIndexController.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
define([
"Ember",
"mixins/ChannelMixin"
], function( Ember, ChannelMixin ) {
define( [ "Ember" ], function( Ember ) {

var get = Ember.get;
var alias = Ember.computed.alias;
var or = Ember.computed.or;

return Ember.Controller.extend( ChannelMixin, {
return Ember.Controller.extend({
metadata: Ember.inject.service(),

stream : alias( "model.stream" ),
channel: alias( "model.channel" ),

previewImage: or( "stream.preview.large_nocache", "channel.video_banner" ),

_loadSubscriptionAndFollowingData: function() {
var channel = get( this, "channel" );
this.checkUserSubscribesChannel( channel );
this.checkUserFollowsChannel( channel );
}.observes( "channel" ),

age: function() {
var createdAt = get( this, "channel.created_at" );
return ( new Date() - createdAt ) / ( 24 * 3600 * 1000 );
Expand Down
78 changes: 1 addition & 77 deletions src/app/controllers/GamesGameController.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,7 @@
define( [ "Ember" ], function( Ember ) {

var get = Ember.get;
var set = Ember.set;
var bool = Ember.computed.bool;

return Ember.ArrayController.extend({
auth : Ember.inject.service(),
store: Ember.inject.service(),

game: null,

following: null,
isFollowing: bool( "following" ),
isFollowingLoading: false,
isFollowingLocked: false,


_checkUserFollowsGame: function() {
var isLoggedIn = get( this, "auth.session.isLoggedIn" );
var game = get( this, "game" );
if ( !isLoggedIn || !game ) { return; }

set( this, "following", null );
set( this, "isFollowingLoading", true );
set( this, "isFollowingLocked", true );

var store = get( this, "store" );
return store.findRecord( "twitchUserFollowsGame", game )
.catch(function() {
// unload the generated empty record
var record = store.peekRecord( "twitchUserFollowsGame", game );
if ( record ) {
store.unloadRecord( record );
}
return false;
})
.then(function( record ) {
set( this, "following", record );
set( this, "isFollowingLoading", false );
set( this, "isFollowingLocked", false );
}.bind( this ) );
}.observes( "auth.session.isLoggedIn", "game" ),


actions: {
"followGame": function( callback ) {
if ( get( this, "isFollowingLocked" ) ) { return; }
set( this, "isFollowingLocked", true );

var self = this;
var store = get( this, "store" );
var game = get( this, "game" );
var following = get( this, "following" );

function unlock() { set( self, "isFollowingLocked", false ); }

if ( !following ) {
// create a new record and save it
following = store.createRecord( "twitchUserFollowsGame", { id: game });
following.save()
.then(function( record ) {
set( self, "following", record );
})
.then( callback )
.then( unlock, unlock );

} else {
// delete the record and save it
following.destroyRecord()
.then(function() {
set( self, "following", null );
// also unload it
store.unloadRecord( following );
})
.then( callback )
.then( unlock, unlock );
}
}
}
game: null
});

});
9 changes: 1 addition & 8 deletions src/app/controllers/LivestreamerController.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ define([
"Ember",
"nwjs/nwGui",
"nwjs/nwWindow",
"mixins/ChannelMixin",
"mixins/ChannelSettingsMixin",
"utils/fs/which",
"utils/fs/stat",
Expand All @@ -12,7 +11,6 @@ define([
Ember,
nwGui,
nwWindow,
ChannelMixin,
ChannelSettingsMixin,
which,
stat,
Expand Down Expand Up @@ -66,7 +64,7 @@ define([
}


return Ember.Controller.extend( ChannelMixin, ChannelSettingsMixin, {
return Ember.Controller.extend( ChannelSettingsMixin, {
metadata: Ember.inject.service(),
store : Ember.inject.service(),
settings: Ember.inject.service(),
Expand Down Expand Up @@ -135,11 +133,6 @@ define([
});
return this.launchLivestreamer( exec, livestreamer );
}.bind( this ) )
// independently check whether the user is following / subscribing the channel
.then(function() {
this.checkUserSubscribesChannel( channel );
this.checkUserFollowsChannel( channel );
}.bind( this ) )
// setup stream refresh interval
.then( this.refreshStream.bind( this, livestreamer ) )
// success/failure
Expand Down
1 change: 1 addition & 0 deletions src/app/initializers/initializers.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
define([
"initializers/localstorage",
"initializers/nwjs",
"initializers/store",
"initializers/window"
], function() {} );
32 changes: 32 additions & 0 deletions src/app/initializers/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
define( [ "Ember", "EmberData" ], function( Ember, DS ) {

// no initializer here: just upgrade the application store

var merge = Ember.merge;

DS.Store.reopen({
/**
* Find a record and unload the generated record
* @param {string} modelName
* @param {string|number} id
* @param {Object?} options
* @param {boolean?} options.reload
* @returns {Promise.<DS.Model?>}
*/
findExistingRecord: function( modelName, id, options ) {
var store = this;
options = merge( { reload: true }, options );

return store.findRecord( modelName, id, options )
.catch(function() {
// unload the generated empty record
var record = store.peekRecord( modelName, id );
if ( record ) {
store.unloadRecord( record );
}
return Promise.reject();
});
}
});

});
Loading

0 comments on commit 5623be7

Please sign in to comment.