From 2d94a44e3edbfe810dce6e2644e642ac7d495666 Mon Sep 17 00:00:00 2001 From: flyingrub Date: Tue, 22 Mar 2016 19:07:49 +0100 Subject: [PATCH 01/10] [WIP] Refactor UI --- app/styles/content.styl | 132 ++++++++++++++++++++------------- app/views/templates/track.jst | 25 +++++-- app/views/templates/tracks.jst | 18 ++--- app/views/track.js | 16 +++- app/views/tracks.js | 13 +++- 5 files changed, 132 insertions(+), 72 deletions(-) diff --git a/app/styles/content.styl b/app/styles/content.styl index 0b05b82..71b2118 100644 --- a/app/styles/content.styl +++ b/app/styles/content.styl @@ -47,54 +47,68 @@ div[role='contentinfo'] button:active padding-top: 1px - table + div[role='rowheader'] width: 100% color: $text-light - - thead - color: $text-dark - font-family: 'Source Sans Pro' - font-weight: bold + display: flex + color: $text-dark + font-family: 'Source Sans Pro' + font-weight: bold + height: 36px + box-shadow: inset 0 -2px 0 0 #d5dce1 + font-size: 13px + text-transform: uppercase + + [role='gridcell'] + text-align: left + display: flex; + align-items: center + + .number-column-cell + justify-content: center + width: 42px + svg + display: none + width: 18px + height: 18px + path + fill: $red + + .song-column-cell + flex-grow: 1 + + .artist-column-cell + width: 200px + + .album-column-cell + position: relative + width: 200px + + .length-column-cell + width: 62px + + ul + .playing + color: $red + .song-column-cell + color: $red + .number-column-cell + svg + display: block + li + display: flex + cursor: pointer height: 41px - box-shadow: inset 0 -2px 0 0 #d5dce1 - font-size: 13px - line-height: 1.5 - - .number - box-sizing: border-box - width: 42px - text-align: center - - svg - width: 18px - height: 18px - - tbody + background-color: transparent + box-shadow: inset 0 -1px 0 0 #d5dce1 + font-size: 14px + color: $text-light - .title + .song-column-cell + flex-grow: 1 + font-size: 16px color: $text-dark - .playing * - color: $red - - tr - cursor: pointer - height: 41px - background-color: transparent - box-shadow: inset 0 -1px 0 0 #d5dce1 - - td - white-space: nowrap - overflow: hidden - position: relative - - .all - #delete-from-upnext - display: none - - .upNext - #add-to-upnext - display: none .actions height: 41px @@ -102,6 +116,7 @@ div[role='contentinfo'] position: absolute right: 18px top: 0px + button height: 100% width: 22px @@ -111,17 +126,28 @@ div[role='contentinfo'] path fill: #696d78 - .help - position: absolute - visibility: hidden + .all + #delete-from-upnext + display: none + + .upNext + #add-to-upnext + display: none + + .help + position: absolute + visibility: hidden - button:hover - .help - visibility: visibile + button:hover + .help + visibility: visibile - tr:hover - .actions - visibility: visible + .popup-menu + visibility: hidden + position: absolute + top: 37px - tr:hover - background-color: $background-dark + li:hover + background-color: $background-dark + .actions + visibility: visible diff --git a/app/views/templates/track.jst b/app/views/templates/track.jst index 13cb58c..23dd44c 100644 --- a/app/views/templates/track.jst +++ b/app/views/templates/track.jst @@ -1,7 +1,12 @@ -<%- number %> -<%- title %> -<%- artist %> -<%- album %> +
+ <%- number %> + + + +
+
<%- title %>
+
<%- artist %>
+
<%- album %>
- -<%- duration %> +
+
<%- duration %>
+ diff --git a/app/views/templates/tracks.jst b/app/views/templates/tracks.jst index eb050c7..4a9602e 100644 --- a/app/views/templates/tracks.jst +++ b/app/views/templates/tracks.jst @@ -1,10 +1,8 @@ - - - - - - - - - -
#SONGARTISTALBUMLENGTH
+
+
#
+
SONG
+
ARTIST
+
ALBUM
+
LENGTH
+
+ \ No newline at end of file diff --git a/app/views/track.js b/app/views/track.js index 01d239a..a35a1b7 100644 --- a/app/views/track.js +++ b/app/views/track.js @@ -7,14 +7,14 @@ const TrackView = Mn.ItemView.extend({ template: require('./templates/track'), - tagName: 'tr', + tagName: 'li', events: { 'click': 'play', 'click .delete': 'delete', 'click #menu': 'displayMenu', 'click #add-to-upnext':'addToUpNext', - 'click "delete-from-upnext': 'deleteFromUpNext' + 'click #delete-from-upnext': 'deleteFromUpNext' }, modelEvents: { @@ -48,6 +48,18 @@ const TrackView = Mn.ItemView.extend({ application.appState.set('currentTrack', this.model); }, + displayMenu(e) { + e.stopPropagation(); + }, + + addToUpNext(e) { + e.stopPropagation(); + }, + + deleteFromUpNext(e) { + e.stopPropagation(); + }, + delete(e) { let item = this.model; item.set('hidden', true); diff --git a/app/views/tracks.js b/app/views/tracks.js index 16fc23b..e973923 100644 --- a/app/views/tracks.js +++ b/app/views/tracks.js @@ -9,7 +9,18 @@ const TracksView = Mn.CompositeView.extend({ childViewContainer: '#track-list', - childView: TrackView + childView: TrackView, + + // Override + remove() { + this._removeElement(); + try { + this.stopListening(); // Weird Error + } catch (e) { + //console.log('views/tracks.js', e); + } + return this; + }, }); From 1283387242d605db743b002b3d89240253a72ec9 Mon Sep 17 00:00:00 2001 From: flyingrub Date: Wed, 23 Mar 2016 19:52:03 +0100 Subject: [PATCH 02/10] [WIP] Popup menu ALSO : * Notification fix * player volume fix --- app/collections/tracks.js | 9 +++-- app/libs/file.js | 7 ++-- app/libs/soundcloud.js | 20 ++++++++--- app/models/playlist.js | 7 +++- app/styles/content.styl | 53 +++++++++++++++++++++++++--- app/styles/toolbar.styl | 13 +++---- app/views/notification.js | 11 ++++-- app/views/player.js | 2 +- app/views/templates/notification.jst | 6 ++++ app/views/templates/track.jst | 31 +++++++++++++--- app/views/toolbar.js | 4 +-- app/views/track.js | 50 ++++++++++++++++++++++---- 12 files changed, 175 insertions(+), 38 deletions(-) diff --git a/app/collections/tracks.js b/app/collections/tracks.js index cc85d86..da14555 100644 --- a/app/collections/tracks.js +++ b/app/collections/tracks.js @@ -22,6 +22,7 @@ const Tracks = Backbone.Collection.extend({ this.shuffleUpNext ); } + this.on('change:hidden', this.removeTrack, this); }, // UpNext : shuffle @@ -51,6 +52,10 @@ const Tracks = Backbone.Collection.extend({ ); }, + removeTrack(track) { + this.remove(track); + }, + comparator(model) { if (this.type == 'upNext' && application.appState.get('shuffle')) { return undefined; @@ -60,8 +65,8 @@ const Tracks = Backbone.Collection.extend({ }, sync(method, model, options) { - if (method == 'read' && this.type) { - cozysdk.run('Track', this.type, {}, (err, res) => { + if (method == 'read' && this.type == "all") { + cozysdk.run('Track', 'playable', {}, (err, res) => { if (res) { let tracks = JSON.parse('' + res); for (let i = 0; i < tracks.length; i++) { diff --git a/app/libs/file.js b/app/libs/file.js index 2c20f27..0e4e61b 100644 --- a/app/libs/file.js +++ b/app/libs/file.js @@ -29,8 +29,11 @@ function getAllTracksFileId(musicFiles) { } saveTrack(musicFiles, tracksFileId); deleteTrack(allTracksFiles, musicFilesFileId); - let msg = t('all your audio files have been added'); - application.channel.request('notification', msg); + let notification = { + status: 'ok', + message: t('all your audio files have been added') + } + application.channel.request('notification', notification); } }); } diff --git a/app/libs/soundcloud.js b/app/libs/soundcloud.js index 3924ebb..554c57e 100644 --- a/app/libs/soundcloud.js +++ b/app/libs/soundcloud.js @@ -32,8 +32,11 @@ class Soundcloud { if (!exist) { this.importTrack(track); } else { - let msg = t('track is already in the database'); - application.channel.request('notification', msg); + let notification = { + status: 'ko', + message: t('track is already in the database') + } + application.channel.request('notification', notification); } } }); @@ -42,7 +45,11 @@ class Soundcloud { // Set the track's metas and save it. importTrack(track) { if (!track.streamable) { - alert('This track is not streamable'); + let notification = { + status: 'ko', + message: 'This track is not streamable' + } + application.channel.request('notification', notification); return; } let newTrack = new Track(); @@ -57,8 +64,11 @@ class Soundcloud { duration: track.duration }); application.allTracks.get('tracks').create(newTrack); - let msg = t('stream track imported'); - application.channel.request('notification', msg); + let notification = { + status: 'ok', + message: t('stream track imported') + } + application.channel.request('notification', notification); } // Add our clientID to the current url diff --git a/app/models/playlist.js b/app/models/playlist.js index 5689e0d..e4219a6 100644 --- a/app/models/playlist.js +++ b/app/models/playlist.js @@ -56,7 +56,12 @@ const Playlist = Backbone.Model.extend({ // Add a track to the playlist addTrack(track) { - this.set('tracks', this.get('tracks').push(track)); + this.get('tracks').push(track); + }, + + // Remove a track to the playlist + removeTrack(track) { + this.get('tracks').remove(track); } }); diff --git a/app/styles/content.styl b/app/styles/content.styl index 71b2118..85796cc 100644 --- a/app/styles/content.styl +++ b/app/styles/content.styl @@ -103,6 +103,7 @@ div[role='contentinfo'] box-shadow: inset 0 -1px 0 0 #d5dce1 font-size: 14px color: $text-light + position: relative .song-column-cell flex-grow: 1 @@ -117,6 +118,16 @@ div[role='contentinfo'] right: 18px top: 0px + .active + path + fill: #f14a53 + + button:hover:not(.active) + .help + visibility: visibile + path + fill: #32363f + button height: 100% width: 22px @@ -125,6 +136,8 @@ div[role='contentinfo'] width: 20px path fill: #696d78 + -webkit-transition: fill 0.2s; /* Safari */ + transition: fill 0.2s; .all #delete-from-upnext @@ -138,14 +151,46 @@ div[role='contentinfo'] position: absolute visibility: hidden - button:hover - .help - visibility: visibile - .popup-menu visibility: hidden position: absolute + z-index: 99 top: 37px + right: 50px + padding: 14px 0px + border-radius: 10px + background-color: white + box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.1), 0 1px 3px 0 rgba(0, 0, 0, 0.2) + + .small + width: 14px + height: 14px + opacity: 0.3 + position: absolute + right: 14px + svg + path + fill: #696d78 + ul + li + font-size: 16px + padding: 0px 20px + height: 36px + box-shadow: none + color: $text-dark + align-items: center + + svg + height: 20px + width: 20px + padding-right: 14px + path + fill: #696d78 + + li:hover + background-color: $background-dark; + .popup-menu.show + visibility: visible li:hover background-color: $background-dark diff --git a/app/styles/toolbar.styl b/app/styles/toolbar.styl index fe28315..f675056 100644 --- a/app/styles/toolbar.styl +++ b/app/styles/toolbar.styl @@ -198,23 +198,20 @@ div[role='toolbar'] background-color: #696d78 box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.1) opacity: 0 - visibility: hidden + visibility: visible + display: flex + align-items: center p - position: absolute - top: 10px - left: 64px + padding-left: 14px padding-right: 32px - height: 42px font-family: "Source Sans Pro" font-size: 16px line-height: 1.3 color: #ffffff svg - position: absolute - left: 14px - top: 13px + padding-left: 14px width: 40px height: 40px diff --git a/app/views/notification.js b/app/views/notification.js index 128ad6a..f7ae800 100644 --- a/app/views/notification.js +++ b/app/views/notification.js @@ -9,17 +9,22 @@ const Notification = Mn.ItemView.extend({ notification: '.notification', }, - initialize(options) { - this.message = options.message; + initialize(notification) { + this.message = notification.message; + this.status = notification.status; }, onRender() { this.ui.notification.addClass('notify'); + setTimeout(() => { // Prevent animation to replay after reopening the app + this.ui.notification.removeClass('notify'); + }, 4000); }, serializeData() { return { - message: this.message + message: this.message, + status: this.status } } }); diff --git a/app/views/player.js b/app/views/player.js index 50e9ae2..10cc675 100644 --- a/app/views/player.js +++ b/app/views/player.js @@ -71,7 +71,7 @@ const Player = Mn.LayoutView.extend({ audio.ontimeupdate = this.onTimeUpdate; audio.onended = this.next; audio.onvolumechange = this.onVolumeChange; - audio.volume = 0.5; + audio.volume = application.appState.get('currentVolume'); }, load(track) { diff --git a/app/views/templates/notification.jst b/app/views/templates/notification.jst index 8d852f0..6f9b903 100644 --- a/app/views/templates/notification.jst +++ b/app/views/templates/notification.jst @@ -1,6 +1,12 @@
+ <% if (status == 'ok') { %> + <% } else { %> + + + + <% } %>

<%= message %>

\ No newline at end of file diff --git a/app/views/templates/track.jst b/app/views/templates/track.jst index 23dd44c..33d48c5 100644 --- a/app/views/templates/track.jst +++ b/app/views/templates/track.jst @@ -29,9 +29,32 @@
<%- duration %>
diff --git a/app/views/toolbar.js b/app/views/toolbar.js index a5ad965..dd375d2 100644 --- a/app/views/toolbar.js +++ b/app/views/toolbar.js @@ -87,10 +87,10 @@ const Toolbar = Mn.LayoutView.extend({ } }, - showNotification(msg) { + showNotification(notification) { this.showChildView( 'notification', - new NotificationView({ message: msg }) + new NotificationView(notification) ); } }); diff --git a/app/views/track.js b/app/views/track.js index a35a1b7..2739d21 100644 --- a/app/views/track.js +++ b/app/views/track.js @@ -9,12 +9,21 @@ const TrackView = Mn.ItemView.extend({ tagName: 'li', + ui: { + 'menu': '#menu', + 'popupMenu': '.popup-menu' + }, + events: { 'click': 'play', - 'click .delete': 'delete', - 'click #menu': 'displayMenu', + 'click @ui.menu': 'toggleMenu', 'click #add-to-upnext':'addToUpNext', - 'click #delete-from-upnext': 'deleteFromUpNext' + 'click #add-to-playlist':'addToPlaylist', + 'click #album-to-upnext':'albumToUpNext', + 'click #edit-details':'editDetails', + 'click #delete':'delete', + 'click #delete-from-upnext': 'deleteFromUpNext', + 'mouseleave': 'hidePopupMenu' }, modelEvents: { @@ -28,8 +37,8 @@ const TrackView = Mn.ItemView.extend({ }, onRender() { - let currentPlaylist = application.currentPlaylist; - let type = currentPlaylist ? currentPlaylist.get('tracks').type : 'all' + let currentPlaylist = application.appState.get('currentPlaylist'); + let type = currentPlaylist.get('tracks').type; switch (type) { // Can be refactored ? case 'upNext': this.$('.actions').addClass('upNext'); @@ -48,16 +57,45 @@ const TrackView = Mn.ItemView.extend({ application.appState.set('currentTrack', this.model); }, - displayMenu(e) { + toggleMenu(e) { + e.stopPropagation(); + this.ui.popupMenu.toggleClass('show'); + this.ui.menu.toggleClass('active'); + }, + + hidePopupMenu(e) { + this.ui.popupMenu.removeClass('show'); + this.ui.menu.removeClass('active'); + }, + + addToPlaylist(e) { e.stopPropagation(); }, addToUpNext(e) { e.stopPropagation(); + application.upNext.addTrack(this.model); + + let notification = { + status: 'ok', + message: 'Added to Up Next' + } + application.channel.request('notification', notification); }, deleteFromUpNext(e) { e.stopPropagation(); + application.upNext.removeTrack(this.model); + }, + + // TO DO + albumToUpNext(e) { + e.stopPropagation(); + }, + + // TO DO + editDetails(e) { + e.stopPropagation(); }, delete(e) { From e648358d3d0075d6e76b9c94c6e3ab8cb13643ad Mon Sep 17 00:00:00 2001 From: flyingrub Date: Thu, 24 Mar 2016 13:42:38 +0100 Subject: [PATCH 03/10] [ADD] Improve volume & track progress experience --- app/views/player.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/views/player.js b/app/views/player.js index 10cc675..8780a44 100644 --- a/app/views/player.js +++ b/app/views/player.js @@ -26,8 +26,8 @@ const Player = Mn.LayoutView.extend({ 'click #prev': 'prev', 'click #play': 'toggle', 'click #next': 'next', - 'click @ui.progressBar': 'skip', - 'click @ui.volumeBar': 'changeVol', + 'mousedown @ui.progressBar': 'skip', + 'mousedown @ui.volumeBar': 'changeVol', 'click @ui.shuffle': 'toggleShuffle', 'click @ui.repeat': 'toggleRepeat', 'click @ui.speaker': 'toggleVolume' @@ -64,6 +64,17 @@ const Player = Mn.LayoutView.extend({ break; } }); + $(document).mousemove((e) => { + if (this.volumeDown) { + this.changeVol(e); + } else if (this.progressDown) { + this.skip(e); + } + }); + $(document).mouseup((e) => { + this.volumeDown = false; + this.progressDown = false; + }); }, onRender() { @@ -211,6 +222,7 @@ const Player = Mn.LayoutView.extend({ // Go to a certain time in the track skip(e) { + this.progressDown = true; let audio = this.ui.player.get(0); let bar = this.ui.progressBar.get(0); let newTime = audio.duration * ((e.pageX - bar.offsetLeft) / bar.clientWidth); @@ -238,6 +250,7 @@ const Player = Mn.LayoutView.extend({ // Change the volume changeVol(e) { + this.volumeDown = true; let audio = this.ui.player.get(0); let bar = this.ui.volumeBar.get(0); let volume = (e.pageX - bar.offsetLeft) / bar.clientWidth; From ba612f5732e56c20790a77f887c8c9df5213f54b Mon Sep 17 00:00:00 2001 From: flyingrub Date: Thu, 24 Mar 2016 15:07:21 +0100 Subject: [PATCH 04/10] [CLEAN] Styles --- app/styles/app.styl | 7 +- app/styles/content.styl | 198 ------------------------- app/styles/header.styl | 48 ++++++ app/styles/player.styl | 25 ++-- app/styles/popup-menu.styl | 45 ++++++ app/styles/toolbar.styl | 14 +- app/styles/track-actions.styl | 40 +++++ app/styles/tracks.styl | 68 +++++++++ app/views/popupPlaylists.js | 31 ++++ app/views/templates/playlists.jst | 2 +- app/views/templates/popupPlaylists.jst | 9 ++ 11 files changed, 267 insertions(+), 220 deletions(-) delete mode 100644 app/styles/content.styl create mode 100644 app/styles/header.styl create mode 100644 app/styles/popup-menu.styl create mode 100644 app/styles/track-actions.styl create mode 100644 app/styles/tracks.styl create mode 100644 app/views/popupPlaylists.js create mode 100644 app/views/templates/popupPlaylists.jst diff --git a/app/styles/app.styl b/app/styles/app.styl index e4096de..f208bcc 100644 --- a/app/styles/app.styl +++ b/app/styles/app.styl @@ -7,6 +7,8 @@ $text-dark = #32363f $text-light = #788195 $text = #92a0b2 $red = #ef4c57 +$svg = #696d78 +$svg-red = #f14a53 @import 'reset' global-reset() @@ -45,6 +47,9 @@ placeholder() &:-ms-input-placeholder {block} -@import 'content' +@import 'tracks' +@import 'header' +@import 'track-actions' +@import 'popup-menu' @import 'toolbar' @import 'player' diff --git a/app/styles/content.styl b/app/styles/content.styl deleted file mode 100644 index 85796cc..0000000 --- a/app/styles/content.styl +++ /dev/null @@ -1,198 +0,0 @@ -div[role='contentinfo'] - background-color: white - padding: 25px 33px - flex-grow: 1 - overflow: auto - margin-bottom: 71px; - - div[role='complementary'] - - h3 - font-size: 24px - line-height: 0.8 - height: 31px - color: $text-dark - display: inline-block - - em - color: $text-light - - button - padding: 0px 12px - height: 32px - float: right - display: inline-block - cursor: pointer - font-family: 'Source Sans Pro' - font-weight: bold - color: $text-light - background-color: $background-dark - border-radius: 2px - position: relative - padding-left: 32px - text-transform: uppercase - font-size: 16px - - svg - position: absolute - height: 20px - left: 9px - width: 20px - top: 6px - - path - fill: #696d78 - stroke: 2px - - button:active - padding-top: 1px - - div[role='rowheader'] - width: 100% - color: $text-light - display: flex - color: $text-dark - font-family: 'Source Sans Pro' - font-weight: bold - height: 36px - box-shadow: inset 0 -2px 0 0 #d5dce1 - font-size: 13px - text-transform: uppercase - - [role='gridcell'] - text-align: left - display: flex; - align-items: center - - .number-column-cell - justify-content: center - width: 42px - svg - display: none - width: 18px - height: 18px - path - fill: $red - - .song-column-cell - flex-grow: 1 - - .artist-column-cell - width: 200px - - .album-column-cell - position: relative - width: 200px - - .length-column-cell - width: 62px - - ul - .playing - color: $red - .song-column-cell - color: $red - .number-column-cell - svg - display: block - li - display: flex - cursor: pointer - height: 41px - background-color: transparent - box-shadow: inset 0 -1px 0 0 #d5dce1 - font-size: 14px - color: $text-light - position: relative - - .song-column-cell - flex-grow: 1 - font-size: 16px - color: $text-dark - - - .actions - height: 41px - visibility: hidden - position: absolute - right: 18px - top: 0px - - .active - path - fill: #f14a53 - - button:hover:not(.active) - .help - visibility: visibile - path - fill: #32363f - - button - height: 100% - width: 22px - svg - height: 20px - width: 20px - path - fill: #696d78 - -webkit-transition: fill 0.2s; /* Safari */ - transition: fill 0.2s; - - .all - #delete-from-upnext - display: none - - .upNext - #add-to-upnext - display: none - - .help - position: absolute - visibility: hidden - - .popup-menu - visibility: hidden - position: absolute - z-index: 99 - top: 37px - right: 50px - padding: 14px 0px - border-radius: 10px - background-color: white - box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.1), 0 1px 3px 0 rgba(0, 0, 0, 0.2) - - .small - width: 14px - height: 14px - opacity: 0.3 - position: absolute - right: 14px - svg - path - fill: #696d78 - ul - li - font-size: 16px - padding: 0px 20px - height: 36px - box-shadow: none - color: $text-dark - align-items: center - - svg - height: 20px - width: 20px - padding-right: 14px - path - fill: #696d78 - - li:hover - background-color: $background-dark; - .popup-menu.show - visibility: visible - - li:hover - background-color: $background-dark - .actions - visibility: visible diff --git a/app/styles/header.styl b/app/styles/header.styl new file mode 100644 index 0000000..0068366 --- /dev/null +++ b/app/styles/header.styl @@ -0,0 +1,48 @@ +div[role='contentinfo'] + background-color: white + padding: 25px 33px + flex-grow: 1 + overflow: auto + margin-bottom: 71px; + + div[role='complementary'] + + h3 + font-size: 24px + line-height: 0.8 + height: 31px + color: $text-dark + display: inline-block + + em + color: $text-light + + button + padding: 0px 12px + height: 32px + float: right + display: inline-block + cursor: pointer + font-family: 'Source Sans Pro' + font-weight: bold + color: $text-light + background-color: $background-dark + border-radius: 2px + position: relative + padding-left: 32px + text-transform: uppercase + font-size: 16px + + svg + position: absolute + height: 20px + left: 9px + width: 20px + top: 6px + + path + fill: $svg + stroke: 2px + + button:active + padding-top: 1px \ No newline at end of file diff --git a/app/styles/player.styl b/app/styles/player.styl index 421224e..0a5f9fc 100644 --- a/app/styles/player.styl +++ b/app/styles/player.styl @@ -5,8 +5,8 @@ left:0 height: 72px width: 100% - background-color: #eff1f4 - border: solid 1px #cedae4 + background-color: $background-dark + border: solid 1px $border-color audio position: absolute @@ -42,7 +42,7 @@ padding-left: 28px path - fill: #696d78 + fill: $svg .timeline margin-left: 32px @@ -63,7 +63,7 @@ color: $text-light p - color: #92a0b2 + color: $text height: 20px font-family: "Source Sans Pro" font-weight: bold @@ -77,7 +77,7 @@ #progress-bar margin-top: 8px - background-color: #cedae4 + background-color: $border-color width: 100% height: 4px border-radius: 2px @@ -87,8 +87,7 @@ width: 0% height: 4px border-radius: 2px - background-color: #0dbabe - + background-color: $blue .controls width: 280px @@ -97,7 +96,7 @@ width: 90px height: 4px border-radius: 2px - background-color: #cedae4 + background-color: $border-color display: inline-block position: absolute top: 34px @@ -107,7 +106,7 @@ width: 100% height: 4px border-radius: 2px - background-color: #696d78 + background-color: $svg svg width: 20px @@ -117,17 +116,17 @@ display: inline-block path - fill: #92a0b2 + fill: $text .active path - fill: #f14a53 + fill: $svg-red #repeat-one-sm path - fill: #f14a53 + fill: $svg-red #broadcast margin-left: 100px path - fill: #f14a53 + fill: $svg-red diff --git a/app/styles/popup-menu.styl b/app/styles/popup-menu.styl new file mode 100644 index 0000000..fce3277 --- /dev/null +++ b/app/styles/popup-menu.styl @@ -0,0 +1,45 @@ +#tracks + .popup-menu + visibility: hidden + position: absolute + z-index: 99 + top: 37px + right: 50px + padding: 14px 0px + border-radius: 10px + background-color: white + box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.1), 0 1px 3px 0 rgba(0, 0, 0, 0.2) + + .small + width: 14px + height: 14px + opacity: 0.3 + position: absolute + right: 14px + svg + path + fill: $svg + ul + li + font-size: 16px + padding: 0px 20px + height: 36px + box-shadow: none + color: $text-dark + align-items: center + + svg + height: 20px + width: 20px + padding-right: 14px + path + fill: $svg + + li:hover + background-color: $background-dark; + + #add-playlist + border-top: 1px solid #d5dce1; + + .popup-menu.show + visibility: visible diff --git a/app/styles/toolbar.styl b/app/styles/toolbar.styl index f675056..0bb3560 100644 --- a/app/styles/toolbar.styl +++ b/app/styles/toolbar.styl @@ -6,7 +6,7 @@ div[role='toolbar'] flex-basis: 280px display: flex flex-direction: column - background-color: #eff1f4 + background-color: $background-dark border: solid 1px #cedae4 .tools @@ -35,7 +35,7 @@ div[role='toolbar'] top: 6px path - fill: white + fill: $white p position: relative @@ -45,7 +45,7 @@ div[role='toolbar'] margin-top: 9px margin-bottom: 10px height: 20px - color: white + color: $white display: inline-block text-transform: uppercase @@ -131,7 +131,7 @@ div[role='toolbar'] top: 4px path - fill: #92a0b2 + fill: $text .input border: solid 1px $blue @@ -183,7 +183,7 @@ div[role='toolbar'] cursor: pointer li.selected - color: white + color: $white border-top-right-radius: 2px border-bottom-right-radius: 2px background-color: #f14a53 @@ -208,7 +208,7 @@ div[role='toolbar'] font-family: "Source Sans Pro" font-size: 16px line-height: 1.3 - color: #ffffff + color: $white svg padding-left: 14px @@ -216,7 +216,7 @@ div[role='toolbar'] height: 40px path - fill: white + fill: $white .notify animation-timing-function: ease; diff --git a/app/styles/track-actions.styl b/app/styles/track-actions.styl new file mode 100644 index 0000000..2e13d9e --- /dev/null +++ b/app/styles/track-actions.styl @@ -0,0 +1,40 @@ +#tracks + .actions + height: 41px + visibility: hidden + position: absolute + right: 18px + top: 0px + + .active + path + fill: $svg-red + + button:hover:not(.active) + .help + visibility: visibile + path + fill: $text-dark + + button + height: 100% + width: 22px + svg + height: 20px + width: 20px + path + fill: $svg + -webkit-transition: fill 0.2s; /* Safari */ + transition: fill 0.2s; + + .all + #delete-from-upnext + display: none + + .upNext + #add-to-upnext + display: none + + .help + position: absolute + visibility: hidden diff --git a/app/styles/tracks.styl b/app/styles/tracks.styl new file mode 100644 index 0000000..0db194e --- /dev/null +++ b/app/styles/tracks.styl @@ -0,0 +1,68 @@ +#tracks + div[role='rowheader'] + width: 100% + color: $text-light + display: flex + color: $text-dark + font-family: 'Source Sans Pro' + font-weight: bold + height: 36px + box-shadow: inset 0 -2px 0 0 #d5dce1 + font-size: 13px + text-transform: uppercase + + [role='gridcell'] + text-align: left + display: flex; + align-items: center + + .number-column-cell + justify-content: center + width: 42px + svg + display: none + width: 18px + height: 18px + path + fill: $red + + .song-column-cell + flex-grow: 1 + + .artist-column-cell + width: 200px + + .album-column-cell + position: relative + width: 200px + + .length-column-cell + width: 62px + + ul + .playing + color: $red + .song-column-cell + color: $red + .number-column-cell + svg + display: block + li + display: flex + cursor: pointer + height: 41px + background-color: transparent + box-shadow: inset 0 -1px 0 0 #d5dce1 + font-size: 14px + color: $text-light + position: relative + + .song-column-cell + flex-grow: 1 + font-size: 16px + color: $text-dark + + li:hover + background-color: $background-dark + .actions + visibility: visible diff --git a/app/views/popupPlaylists.js b/app/views/popupPlaylists.js new file mode 100644 index 0000000..2adc797 --- /dev/null +++ b/app/views/popupPlaylists.js @@ -0,0 +1,31 @@ +import Mn from 'backbone.marionette'; +import PlaylistView from './playlist'; +import application from '../application'; +import Playlist from '../models/playlist'; + + +const Playlists = Mn.CompositeView.extend({ + + template: require('./templates/popupPlaylists'), + + childViewContainer: '#playlist-list', + + childView: PlaylistView, + + ui: { + addPlaylist: '#add-playlist', + playlistText: '#playlist-text', + }, + + events: { + + }, + + initialize() { + }, + + +}); + +export default Playlists; + diff --git a/app/views/templates/playlists.jst b/app/views/templates/playlists.jst index 3505326..1daa371 100644 --- a/app/views/templates/playlists.jst +++ b/app/views/templates/playlists.jst @@ -10,7 +10,7 @@ - +

<%= t('add playlist') %>

\ No newline at end of file diff --git a/app/views/templates/popupPlaylists.jst b/app/views/templates/popupPlaylists.jst new file mode 100644 index 0000000..48cecfc --- /dev/null +++ b/app/views/templates/popupPlaylists.jst @@ -0,0 +1,9 @@ + \ No newline at end of file From 639ef6fb251209cc224c4bc00a234872b28012a3 Mon Sep 17 00:00:00 2001 From: flyingrub Date: Thu, 24 Mar 2016 17:48:36 +0100 Subject: [PATCH 05/10] [WIP] Playlist & popup --- app/models/playlist.js | 7 ++++ app/styles/app.styl | 2 + app/styles/popup-menu.styl | 25 +++++++++++- app/views/playlist.js | 6 ++- app/views/playlists.js | 15 +++---- app/views/popupPlaylists.js | 56 ++++++++++++++++++++++++-- app/views/templates/popupPlaylists.jst | 2 +- app/views/templates/track.jst | 3 +- app/views/track.js | 28 ++++++++++--- 9 files changed, 121 insertions(+), 23 deletions(-) diff --git a/app/models/playlist.js b/app/models/playlist.js index e4219a6..525b192 100644 --- a/app/models/playlist.js +++ b/app/models/playlist.js @@ -62,6 +62,13 @@ const Playlist = Backbone.Model.extend({ // Remove a track to the playlist removeTrack(track) { this.get('tracks').remove(track); + }, + + parse(attrs) { + console.log('parse', attrs); + return { + + } } }); diff --git a/app/styles/app.styl b/app/styles/app.styl index f208bcc..d7b3e72 100644 --- a/app/styles/app.styl +++ b/app/styles/app.styl @@ -28,6 +28,8 @@ div[role='application'] ::-moz-focus-inner border: 0 +input + all: unset button all: unset cursor: pointer diff --git a/app/styles/popup-menu.styl b/app/styles/popup-menu.styl index fce3277..ab79f68 100644 --- a/app/styles/popup-menu.styl +++ b/app/styles/popup-menu.styl @@ -38,8 +38,29 @@ li:hover background-color: $background-dark; + .show + visibility: visible + + #playlist-popup-menu + z-index: 100 + right: 200px + top: 0px + min-width: 200px + #add-playlist border-top: 1px solid #d5dce1; + height: 40px + display: flex + align-items: center + padding: 0px 20px - .popup-menu.show - visibility: visible + input + width: 100% + height: 100% + display:none + + #add-playlist.input + p + display:none + input + display: block diff --git a/app/views/playlist.js b/app/views/playlist.js index 9396b3e..ae1ca2c 100644 --- a/app/views/playlist.js +++ b/app/views/playlist.js @@ -10,7 +10,11 @@ const PlaylistView = Mn.ItemView.extend({ className: 'playlist', - modelEvents: { change: 'render' } + modelEvents: { change: 'render' }, + + onRender() { + this.$el.attr('data-id', this.model.get('_id')); + } }); export default PlaylistView; \ No newline at end of file diff --git a/app/views/playlists.js b/app/views/playlists.js index 766fb23..db12fdc 100644 --- a/app/views/playlists.js +++ b/app/views/playlists.js @@ -65,19 +65,16 @@ const Playlists = Mn.CompositeView.extend({ }, changePlaylist(e) { - let playlist = $(e.currentTarget); - let playlists = this.$('.playlist'); - let index = playlists.index(playlist) - 2; - playlists.removeClass('selected'); - playlist.addClass('selected'); + this.$('.playlist').removeClass('selected'); + $(e.currentTarget).addClass('selected'); - if (playlist.attr('id') == "up-next") { + if ($(e.currentTarget).attr('id') == "up-next") { application.appState.set('currentPlaylist', application.upNext); - } else if (playlist.attr('id') == "all-song") { + } else if ($(e.currentTarget).attr('id') == "all-song") { application.appState.set('currentPlaylist', application.allTracks); } else { - this.currentIndex = index; - let playlist = application.allPlaylists.at(index); + let id = e.currentTarget.dataset.id; + let playlist = application.allPlaylists.get(id); application.appState.set('currentPlaylist', playlist); } } diff --git a/app/views/popupPlaylists.js b/app/views/popupPlaylists.js index 2adc797..a4367be 100644 --- a/app/views/popupPlaylists.js +++ b/app/views/popupPlaylists.js @@ -4,7 +4,7 @@ import application from '../application'; import Playlist from '../models/playlist'; -const Playlists = Mn.CompositeView.extend({ +const PopupPlaylists = Mn.CompositeView.extend({ template: require('./templates/popupPlaylists'), @@ -15,17 +15,67 @@ const Playlists = Mn.CompositeView.extend({ ui: { addPlaylist: '#add-playlist', playlistText: '#playlist-text', + playlistPopup: '#playlist-popup-menu' }, events: { - + 'click li': 'addToPlaylist', + 'click @ui.addPlaylist': 'showInput', + 'keyup @ui.playlistText': 'keyupPlaylistText', }, initialize() { + this.listenTo( + application.channel, + 'playlistPopup:show', + this.showPopup + ); + this.listenTo( + application.channel, + 'playlistPopup:hide', + this.hidePopup + ); + }, + + showPopup(model) { + if (this.model == model) { + this.ui.playlistPopup.addClass('show'); + } + }, + + hidePopup(model) { + if (this.model == model) { + this.ui.playlistPopup.removeClass('show'); + } + }, + + addToPlaylist(e) { + e.stopPropagation(); + let id = e.currentTarget.dataset.id; + let playlist = application.allPlaylists.get(id); + playlist.addTrack(this.model); + }, + + showInput(e) { + e.stopPropagation(); + this.ui.addPlaylist.addClass('input'); + this.ui.playlistText.focus(); + }, + + // Create the playlist when `Enter` is pressed + keyupPlaylistText(e) { + let title = this.ui.playlistText.val(); + if(e.keyCode == 13) { + let newPlaylist = new Playlist({ title: title }); + newPlaylist.addTrack(this.model); + application.allPlaylists.create(newPlaylist); + this.ui.playlistText.val(''); + this.focusoutAddPlaylist(); + } }, }); -export default Playlists; +export default PopupPlaylists; diff --git a/app/views/templates/popupPlaylists.jst b/app/views/templates/popupPlaylists.jst index 48cecfc..8ba2c81 100644 --- a/app/views/templates/popupPlaylists.jst +++ b/app/views/templates/popupPlaylists.jst @@ -1,4 +1,4 @@ -