diff --git a/README.md b/README.md
index 6a92cd7..d564ac8 100644
--- a/README.md
+++ b/README.md
@@ -35,8 +35,8 @@ These are the contents of the script:
$ mkdir ~/Spotify ; cd ~/Spotify
$ rm -rf rama
$ rm -rf rama-spotify
-$ wget https://github.com/carsy/rama-spotify/releases/download/v0.6/rama_v0.6.tar.gz
-$ tar -xvf rama_v0.6.tar.gz
+$ wget https://github.com/carsy/rama-spotify/releases/download/v0.8/rama_v0.8.tar.gz
+$ tar -xvf rama_v0.8.tar.gz
$ open spotify:app:rama
```
You should now be in the app and seeing a graph thingy.
@@ -61,6 +61,11 @@ With no official release for the Spotify Desktop Client, there's nothing I can d
[Releases]
----
+[v0.8] - UX update
+ - Look and feel of nodes and buttons updated
+ - [bugfix] on double click node does not refresh graph
+ - new map button added to artist menu
+
[v0.6] - Artist menu
- Artist menu added
- Click on an artist node to view its info on the menu
@@ -107,6 +112,7 @@ José Bateira
[here]:https://github.com/carsy/rama-spotify/releases/latest
[Releases]:https://github.com/carsy/rama-spotify/releases/latest
[issues]:https://github.com/carsy/rama-spotify/issues
+[v0.8]:https://github.com/carsy/rama-spotify/releases/tag/v0.8
[v0.6]:https://github.com/carsy/rama-spotify/releases/tag/v0.6
[v0.5]:https://github.com/carsy/rama-spotify/releases/tag/v0.5
[v0.3]:https://github.com/carsy/rama-spotify/releases/tag/v0.3
diff --git a/css/main.css b/css/main.css
index 4b164db..e12adfb 100644
--- a/css/main.css
+++ b/css/main.css
@@ -295,7 +295,7 @@ a {
}
/* line 16, ../sass/_header.scss */
#header .header-text a {
- color: #bbb;
+ color: #dfe0e6;
}
/* line 21, ../sass/_header.scss */
#header .header-title {
@@ -342,8 +342,9 @@ a {
z-index: 2;
top: 65px;
right: 10px;
+ color: #dfe0e6;
}
-/* line 9, ../sass/_settings.scss */
+/* line 11, ../sass/_settings.scss */
#settings .settings-btn {
float: right;
width: 20px;
@@ -353,19 +354,19 @@ a {
background: url(../img/settings.png) no-repeat;
background-size: cover;
}
-/* line 20, ../sass/_settings.scss */
+/* line 22, ../sass/_settings.scss */
#settings .settings-btn:hover {
cursor: pointer;
}
-/* line 24, ../sass/_settings.scss */
+/* line 26, ../sass/_settings.scss */
#settings .settings-btn.opened {
opacity: 1;
}
-/* line 28, ../sass/_settings.scss */
+/* line 30, ../sass/_settings.scss */
#settings .settings-btn:active {
-webkit-transform: scale(0.9, 0.9);
}
-/* line 33, ../sass/_settings.scss */
+/* line 35, ../sass/_settings.scss */
#settings .settings-form {
display: none;
position: relative;
@@ -378,7 +379,7 @@ a {
border-color: #3e3e40;
border-style: solid;
}
-/* line 47, ../sass/_settings.scss */
+/* line 49, ../sass/_settings.scss */
#settings .settings-form .tri {
position: absolute;
top: -5px;
@@ -392,20 +393,20 @@ a {
border-style: solid;
-webkit-transform: rotate(45deg);
}
-/* line 64, ../sass/_settings.scss */
+/* line 66, ../sass/_settings.scss */
#settings .settings-form .option {
overflow: auto;
}
-/* line 67, ../sass/_settings.scss */
+/* line 69, ../sass/_settings.scss */
#settings .settings-form .option:not(.first-child) {
margin-top: 5px;
}
-/* line 71, ../sass/_settings.scss */
+/* line 73, ../sass/_settings.scss */
#settings .settings-form .option label {
float: left;
margin-right: 5px;
}
-/* line 75, ../sass/_settings.scss */
+/* line 77, ../sass/_settings.scss */
#settings .settings-form .option input {
padding: 2px;
width: 30px;
@@ -414,7 +415,7 @@ a {
border-width: 1px;
border-color: #3e3e40;
}
-/* line 83, ../sass/_settings.scss */
+/* line 85, ../sass/_settings.scss */
#settings .settings-form .option input[name=treemode] {
margin-top: 5px;
margin-left: 5px;
@@ -508,6 +509,11 @@ meter {
opacity: 0.95;
}
/* line 54, ../sass/_tracklist.scss */
+#tracklist .list-track:active {
+ border-color: #7fb701;
+ -webkit-transform: scale(0.98, 0.98);
+}
+/* line 59, ../sass/_tracklist.scss */
#tracklist .list-track a {
color: #dfe0e6;
}
@@ -517,7 +523,7 @@ meter {
position: absolute;
left: 0;
top: 20%;
- width: 151px;
+ width: 126px;
opacity: 0.9;
background-color: #222326;
border-color: #3e3e40;
@@ -526,32 +532,30 @@ meter {
border-left: 0;
color: #dfe0e6;
}
-/* line 20, ../sass/_artistmenu.scss */
+/* line 19, ../sass/_artistmenu.scss */
#artistmenu .artist-info-field {
margin: 5px;
}
-/* line 24, ../sass/_artistmenu.scss */
+/* line 23, ../sass/_artistmenu.scss */
#artistmenu #artist_albums {
width: 120px;
margin: 5px auto;
}
-/* line 28, ../sass/_artistmenu.scss */
+/* line 27, ../sass/_artistmenu.scss */
#artistmenu #artist_albums .artist-album {
display: inline-block;
margin: 5px;
}
-/* line 35, ../sass/_artistmenu.scss */
+/* line 33, ../sass/_artistmenu.scss */
#artistmenu #artist_controls {
display: none;
- position: absolute;
- bottom: 0;
width: 100%;
}
-/* line 41, ../sass/_artistmenu.scss */
+/* line 37, ../sass/_artistmenu.scss */
#artistmenu #artist_controls .control:first-child {
margin-top: 10px;
}
-/* line 44, ../sass/_artistmenu.scss */
+/* line 40, ../sass/_artistmenu.scss */
#artistmenu #artist_controls .control {
background-color: #2e2f33;
max-width: 80%;
@@ -564,7 +568,16 @@ meter {
cursor: pointer;
text-align: center;
}
+/* line 53, ../sass/_artistmenu.scss */
+#artistmenu #artist_controls .control#control_expand, #artistmenu #artist_controls .control#control_delete {
+ display: none;
+}
/* line 57, ../sass/_artistmenu.scss */
#artistmenu #artist_controls .control:hover {
opacity: 0.95;
}
+/* line 61, ../sass/_artistmenu.scss */
+#artistmenu #artist_controls .control:active {
+ border-color: #7fb701;
+ -webkit-transform: scale(0.98, 0.98);
+}
diff --git a/install.sh b/install.sh
index 344c3c6..fc7c3b1 100644
--- a/install.sh
+++ b/install.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-version="v0.6"
+version="v0.8"
mkdir ~/Spotify ; cd ~/Spotify
rm -rf rama-spotify
diff --git a/js/controllers/artistmenu.js b/js/controllers/artistmenu.js
index 41310bb..c3842ac 100644
--- a/js/controllers/artistmenu.js
+++ b/js/controllers/artistmenu.js
@@ -26,7 +26,6 @@ require([
this.artist = models.Artist.fromURI(
models.player.track.artists[0].uri);
-
this.updateView(this.artist);
this.bindEvents();
@@ -35,15 +34,29 @@ require([
bindEvents: function() {
this.graphcontroller.addGraphEvent('click',
this.onClickNode.bind(this));
+
+ var controls = {
+ expand: 'onBtnExpandClick',
+ new: 'onBtnNewClick',
+ delete: 'onBtnDeleteClick',
+ };
+
+ for (var control in controls) {
+ document.getElementById('control_' + control)
+ .onclick = this[controls[control]].bind(this);
+ }
},
updateView: function(artist) {
- if (!artist)
+ if (!artist || this.artist === artist.uri)
return;
+ this.artist = artist;
+
+
if (!this.image) {
this.image = Image.forArtist(artist, {
- width: 150,
- height: 100,
+ width: 125,
+ height: 80,
style: 'plain',
overlay: [artist.name],
player: true,
@@ -58,6 +71,7 @@ require([
this.image.setOverlay(artist.name);
this.jelement.find(this.selectors.albums).html('');
+ this.jelement.find(this.selectors.albumsTitle).html('');
artist.load(['popularity', 'years', 'albums'])
.done(this, function(artist) {
@@ -78,69 +92,120 @@ require([
this.jelement.find(this.selectors.years).html('');
var jalbums = this.jelement.find(this.selectors.albums);
- artist.albums.snapshot(0, 7).done(this, function(snapshot) {
-
- var albumLoaded = function(album) {
- var albumImage = Image.forAlbum(album, {
- width: 50,
- height: 50,
- style: 'plain',
- player: true,
- placeholder: 'album',
- link: 'auto',
- title: album.name
- });
- var albumElement = document.createElement('span');
- albumElement.className = 'artist-album';
-
- albumImage.node.className += ' artist-album-cover';
-
- $(albumElement).append(albumImage.node);
-
- jalbums.append(albumElement);
- };
-
- for (var i = 0; i <= 7; ++i) {
- if (snapshot.get(i)) {
- var album = snapshot.get(i).albums[0];
-
- if (album && album.playable) {
- album.load(['uri', 'name', 'popularity']).done(this, albumLoaded);
+ artist.albums.snapshot(0, 8).done(this,
+ function(snapshot) {
+ for (var i = 0; i <= 8; ++i) {
+ if (snapshot.get(i) && snapshot.get(i).albums[0] &&
+ snapshot.get(i).albums[0].playable) {
+ var album = snapshot.get(i).albums[0];
+
+ if (!jalbums.find("a[href='" + album.uri + "']")[0]) {
+ var albumImage = Image.forAlbum(album, {
+ width: 50,
+ height: 50,
+ style: 'plain',
+ player: true,
+ placeholder: 'album',
+ link: 'auto',
+ title: album.name
+ });
+
+ var albumElement = document.createElement('span');
+ albumElement.className = 'artist-album';
+ albumImage.node.className += ' artist-album-cover';
+ $(albumElement).append(albumImage.node);
+ jalbums.append(albumElement);
+ }
}
+ if (i === 8 && jalbums.html() !== '') {
+ this.jelement
+ .find(this.selectors.albumsTitle).html('Albums:
');
+ }
}
- }
-
- });
+ });
});
},
+ onPlayerChange: function() {
+ models.player.load('track').done(this, function(player) {
+
+ if (player.track.advertisement)
+ return;
+
+ var artist = models.Artist.fromURI(player.track.artists[0].uri);
+
+ if ((this.artist && this.artist.uri === artist.uri) ||
+ player.track.advertisement) {
+ return;
+ }
+
+
+ this.updateView(this.artist);
+
+ this.jelement.find(this.selectors.control_new).show();
+ });
+ },
onClickNode: function(data) {
var node = _.findWhere(
this.graphcontroller.artistGraph.data.nodes, {
id: parseInt(data.nodes[0])
});
- if (!node)
+ if (!node || node.artist.uri === this.artist.uri)
return;
+ if (node.id === 1) {
+ this.jelement.find(this.selectors.controls).hide();
+ } else {
+ $(this.selectors.control_new).show();
+ this.jelement.find(this.selectors.controls).show();
+ }
+
+ // if (node.isLeaf) {
+ // // this.jelement.find(this.selectors.control_expand).show();
+ // this.jelement.find(this.selectors.control_delete).show();
+ // } else {
+ // // this.jelement.find(this.selectors.control_expand).hide();
+ // this.jelement.find(this.selectors.control_delete).hide();
+ // }
+
this.updateView(node.artist);
},
- onPlayerChange: function() {
- models.player.load('track').done(this, function(player) {
- var artist = models.Artist.fromURI(
- models.Artist.fromURI(player.track.artists[0].uri)
- );
-
- if ((this.artist && this.artist.uri === artist.uri) ||
- player.track.advertisement) {
- return;
- }
+ onBtnExpandClick: function(event) {
+ // TODO expand node (depth one)
+ // try to save nodes positions
+ // then add nodes and edges
+ // create new graph with updated nodes and edges
+ // setPosition(savedPositions)
+ },
+ onBtnNewClick: function(event) {
+ this.graphcontroller.updateArtist(this.artist);
+ this.jelement.find(this.selectors.control_new).hide();
+ this.jelement.find(this.selectors.control_delete).hide();
+ },
+ onBtnDeleteClick: function(event) {
+ // TODO delete node from graph
+ // save nodes' positions
+ // delete node from graph
+ // create new graph from updated data
+ //
+ var node = _.findWhere(
+ this.graphcontroller.artistGraph.data.nodes, {
+ id: this.artist.nodeid
+ });
- this.artist = artist;
- this.updateView(this.artist);
+ var edges = _.where(this.graphcontroller.artistGraph.data.edges, {
+ to: this.artist.nodeid
});
+
+ var index = this.graphcontroller.artistGraph.data.nodes.indexOf(node);
+ this.graphcontroller.artistGraph.graph.setData(this.graphcontroller.artistGraph.data);
+ // this.graphcontroller.updateGraph();
+ console.log(this.artist);
+ console.log(this.artist.nodeid);
}
+
});
exports.artistmenu = ArtistMenu;
diff --git a/js/controllers/graphcontroller.js b/js/controllers/graphcontroller.js
index c505125..9be10c8 100644
--- a/js/controllers/graphcontroller.js
+++ b/js/controllers/graphcontroller.js
@@ -21,7 +21,10 @@ require([
afterLoad: function(settings) {
models.player.load('track')
- .done(this, this.setArtistGraph);
+ .done(this, function(player) {
+ this.nowplayingArtist = player.track.artists[0];
+ this.setArtistGraph(player);
+ });
var controller = this;
_.each(settings.inputs, function(input) {
@@ -61,6 +64,8 @@ require([
config.treemode = this.artistGraph.treemode;
}
+ this.artist = player.track.artists[0];
+
this.artistGraph = new ArtistGraph(
this.element,
player.track.artists[0],
@@ -72,6 +77,47 @@ require([
this.bindAllEvents();
},
+ updateArtist: function(artist) {
+ var config = {
+ options: this.options
+ };
+
+ config.branching = this.artistGraph.branching;
+ config.depth = this.artistGraph.depth;
+ config.treemode = this.artistGraph.treemode;
+
+ this.artist = artist;
+ this.artistGraph = new ArtistGraph(
+ this.element,
+ artist,
+ config
+ );
+
+ this.showThrobber();
+ this.artistGraph.buildGraph();
+
+ this.bindAllEvents();
+ },
+ updateGraph: function() {
+ var config = {
+ options: this.options
+ };
+
+ config.branching = this.artistGraph.branching;
+ config.depth = this.artistGraph.depth;
+ config.treemode = this.artistGraph.treemode;
+
+ this.artistGraph = new ArtistGraph(
+ this.element,
+ this.artist,
+ config
+ );
+
+ this.showThrobber();
+ this.artistGraph.buildGraph();
+
+ this.bindAllEvents();
+ },
showThrobber: function() {
if (this.artistGraph.throbber)
this.artistGraph.throbber.hide();
@@ -97,25 +143,19 @@ require([
});
},
onPlayerChange: function(player) {
- // TODO refactor same artist verification
- if (!this.artistGraph)
- this.setArtistGraph(player);
if (player.track.advertisement)
return;
- var oldArtistURI = this.artistGraph.artist.uri;
-
- if (player.track.artists[0].uri !== oldArtistURI) {
- this.setArtistGraph(player);
- }
+ this.nowplayingArtist = player.track.artists[0];
},
onNodeDoubleClick: function(data) {
var node = _.findWhere(this.artistGraph.data.nodes, {
id: parseInt(data.nodes[0])
});
- if (!node || node.id === 1)
+ if (!node || node.id === 1 ||
+ this.nowplayingArtist.uri === node.artist.uri)
return;
node.artist.load('compilations').done(function(artist) {
diff --git a/js/controllers/tracklist.js b/js/controllers/tracklist.js
index ff58b50..533cc8b 100644
--- a/js/controllers/tracklist.js
+++ b/js/controllers/tracklist.js
@@ -54,7 +54,7 @@
$(this.selector).find(this.selectors.cover);
$(wrapper).append(this.image.node);
- $(this.selectors.title).html('More popular tracks from ' + artist.name);
+ $(this.selectors.title).html('More popular tracks by ' + artist.name);
var compilations = models.Playlist.fromURI(artist.uri);
diff --git a/js/main.js b/js/main.js
index ec72748..1395a57 100644
--- a/js/main.js
+++ b/js/main.js
@@ -30,29 +30,33 @@ spotify.require([
options: {
nodes: {
color: {
- background: '#474747',
- border: '#555'
+ background: '#2e2f33',
+ border: '#3e3e40',
+ highlight: {
+ border: '#7fb701',
+ background: '#313336'
+ }
},
- fontColor: '#ddd',
+ fontColor: '#dfe0e6',
fontFace: '',
shape: 'box',
radius: 1
},
edges: {
color: {
- color: '#8f9096',
- highlight: '#8f9096'
+ color: '#3e3e40',
+ highlight: '#dfe0e6'
}
},
stabilize: true
//, clustering: true
},
},
- // eqbar: {
- // loadtemplate: false,
- // controller: controllers.EQBar,
- // numRows: 128
- // },
+ eqbar: {
+ loadtemplate: false,
+ controller: controllers.EQBar,
+ numRows: 128
+ },
tracklist: {
loadtemplate: true,
controller: controllers.TrackList,
@@ -70,8 +74,12 @@ spotify.require([
cover: '#artist_cover',
popularity: '#artist_pop',
years: '#artist_years',
+ albumsTitle: '#artist_albums_title',
albums: '#artist_albums',
controls: '#artist_controls',
+ control_expand: '#control_expand',
+ control_new: '#control_new',
+ control_delete: '#control_delete'
},
hasDependencies: true
}
diff --git a/js/models/artistgraph.js b/js/models/artistgraph.js
index 64d4035..188cf4f 100644
--- a/js/models/artistgraph.js
+++ b/js/models/artistgraph.js
@@ -31,8 +31,9 @@ var ArtistGraph = function(element, artist, config) {
var graph = this.graph;
this.graph.on('stabilized', function(iterations) { // Y U NO WORK
- graph.zoomExtent();
+ // graph.zoomExtent();
console.log(iterations);
+ // this.storePosition();
});
};
@@ -51,9 +52,13 @@ ArtistGraph.prototype = {
id: this.index,
label: this.artist.name,
artist: this.artist,
+ isLeaf: false,
fontColor: '#313336',
color: {
- background: '#afb0b6'
+ background: '#dfe0e6',
+ highlight: {
+ border: '#7fb701'
+ }
}
}],
edges: []
@@ -94,7 +99,6 @@ ArtistGraph.prototype = {
var extraEdge = {
from: rootArtist.nodeid,
to: duplicated.id,
- color: '#aaa'
};
this.extraEdges.push(extraEdge);
@@ -108,7 +112,8 @@ ArtistGraph.prototype = {
this.data.nodes.push({
id: nodeid,
label: artist.name,
- artist: artist
+ artist: artist,
+ isLeaf: depth <= 0
});
this.data.edges.push({
@@ -150,6 +155,7 @@ ArtistGraph.prototype = {
});
this.graph.start();
+ this.graph.storePosition();
this.bindAllEvents();
diff --git a/manifest.json b/manifest.json
index a648295..575f766 100644
--- a/manifest.json
+++ b/manifest.json
@@ -11,7 +11,7 @@
"track"
],
"BundleType": "Application",
- "BundleVersion": "0.2",
+ "BundleVersion": "0.8",
"Dependencies": {
"api": "1.0.0",
"views": "1.0.0",
diff --git a/sass/_artistmenu.scss b/sass/_artistmenu.scss
index d413e50..26aed59 100644
--- a/sass/_artistmenu.scss
+++ b/sass/_artistmenu.scss
@@ -1,12 +1,11 @@
#artistmenu {
- // display: none;
position: absolute;
left: 0;
top: 20%; // $header-height + 20px;
// height: 60%;
- width: 151px;
+ width: 126px;
opacity: 0.9;
background-color: $new-bg;
@@ -31,11 +30,8 @@
}
}
-
#artist_controls {
display: none;
- position: absolute;
- bottom: 0;
width: 100%;
.control:first-child {
@@ -54,9 +50,18 @@
cursor: pointer;
text-align: center;
+ control_expand, control_delete {
+ display: none;
+ }
+
&:hover {
opacity: 0.95;
}
+
+ &:active {
+ border-color: $green1;
+ -webkit-transform: scale(0.98, 0.98);
+ }
}
}
}
\ No newline at end of file
diff --git a/sass/_header.scss b/sass/_header.scss
index 5b7177a..bfff219 100644
--- a/sass/_header.scss
+++ b/sass/_header.scss
@@ -14,7 +14,7 @@
.header-text {
a {
- color: #bbb;
+ color: $new-white;
}
}
diff --git a/sass/_settings.scss b/sass/_settings.scss
index 4101df9..5a65b97 100644
--- a/sass/_settings.scss
+++ b/sass/_settings.scss
@@ -6,6 +6,8 @@
top: $header-height + 5px;
right: 10px;
+ color: $new-white;
+
.settings-btn {
float: right;
diff --git a/sass/_tracklist.scss b/sass/_tracklist.scss
index 20a0758..7974b3c 100644
--- a/sass/_tracklist.scss
+++ b/sass/_tracklist.scss
@@ -51,6 +51,11 @@ $width: $height; // omg its a square
opacity: 0.95;
}
+ &:active {
+ border-color: $green1;
+ -webkit-transform: scale(0.98, 0.98);
+ }
+
a {
color: $new-white;
}
diff --git a/views/artistmenu.html b/views/artistmenu.html
index 124181f..b0d4dd7 100644
--- a/views/artistmenu.html
+++ b/views/artistmenu.html
@@ -2,11 +2,11 @@