sync develop with local dev

This commit is contained in:
Trevor Squillario 2014-04-05 11:53:30 -04:00
parent 09ac96526e
commit 149688b8ca
23 changed files with 496 additions and 157 deletions

View file

@ -51,22 +51,19 @@
<div id="header">
<div id="messages"></div>
<div id="loading"></div>
<a id="jslogo" title="Jamstash" href="#/queue"></a>
<a id="jslogo" title="Jamstash" class="showQueue" href=""></a>
<a id="sslogo" target="_blank" ng-show="settings.Server" ng-href="{{settings.Server}}" title="{{settings.Server}}"></a>
<div id="globalactions">
<a href="" class="button" title="Shuffle Queue" ng-click="queueShuffle()"><img src="images/fork_gd_11x12.png" /></a>
<a href="" class="button" id="action_Empty" title="Delete Queue" ng-click="queueEmpty()"><img src="images/trash_fill_gd_12x12.png" /></a>
<a href="" class="button" id="action_DeleteSelected" title="Delete Song(s) From Queue" ng-click="queueRemoveSelected()"><img src="images/minus_8x2.png" /></a>
<!--<a href="" class="button buttonvertical" id="action_QueueToPlaylist" title="Create Playlist From Queue"><img src="images/list_gd_12x11.png" /></a>-->
</div>
<div id="nav">
<ul class="tabs">
<li><a href="#/queue" class="first" title="Queue" class="active" ng-class="{'active': isActive('/queue')}"><img src="images/play_alt_gd_16x16.png"></a></li>
<li><a href="#/library" title="Library" ng-class="{'active': isActive('/library')}"><img src="images/headphones_gd_16x14.png" /></a></li>
<li><a href="#/playlists" title="Playlists" ng-class="{'active': isActive('/playlists')}"><img src="images/list_gd_16x14.png" /></a></li>
<li><a href="#/podcasts" title="Podcasts" ng-class="{'active': isActive('/podcasts')}"><img src="images/rss_16x16.png" /></a></li>
<li><a href="#/archive" class="" title="Archive.org - Live Music Archive" ng-class="{'active': isActive('/archive')}"><img src="images/archive_gd_16x16.png" /></a></li>
<li><a href="#/settings" class="last" title="Settings" ng-class="{'active': isActive('/settings')}"><img src="images/cog_16x16.png" /></a></li>
<li><a href="" class="first showQueue" id="action_Queue" title="Queue" class="active" ng-class="{'active': isActive('/queue')}"><img src="images/play_alt_gd_16x16.png"></a></li>
<li><a href="#/library" id="action_Library" title="Library" ng-class="{'active': isActive('/library')}"><img src="images/headphones_gd_16x14.png" /></a></li>
<li><a href="#/playlists" id="action_Playlists" title="Playlists" ng-class="{'active': isActive('/playlists')}"><img src="images/list_gd_16x14.png" /></a></li>
<li><a href="#/podcasts" id="action_Podcasts" title="Podcasts" ng-class="{'active': isActive('/podcasts')}"><img src="images/rss_16x16.png" /></a></li>
<li><a href="#/archive" id="action_Archive" class="" title="Archive.org - Live Music Archive" ng-class="{'active': isActive('/archive')}"><img src="images/archive_gd_16x16.png" /></a></li>
<li><a href="#/settings" id="action_Settings" class="last" title="Settings" ng-class="{'active': isActive('/settings')}"><img src="images/cog_16x16.png" /></a></li>
</ul>
</div>
</div>
@ -109,7 +106,7 @@
<a class="button" id="PauseTrack" title="Play/Pause" style="display: none;"><img src="images/pause_24x32.png" /></a>
<a class="button" id="NextTrack" title="Next Track" ng-click="nextTrack()"><img src="images/last_24x24.png" /></a>
</div>
<div id="songdetails" ng-click="go('/queue')">
<div id="songdetails">
<div id="coverart"><a class="coverartfancy" href="{{playingSong.coverartfull}}"><img ng-src="{{playingSong.coverartthumb}}" src="images/albumdefault_60.jpg" alt="" /></a></div>
<ul>
<li class="song" id="{{playingSong.id}}" ng-bind-html="playingSong.name"></li>
@ -151,7 +148,15 @@
</div>
</div> <!-- End container -->
<div id="footer">
<!--<a id="action_OpenQueue" class="pagetabcenter shadow" title="Open Queue" ng-click="toggleQueue()"></a>-->
<ul id="showqueue" class="simplelist songlist noselect" style="width: 1200px;" ng-if="queue.length > 0">
<div class="queueactions">
<a href="" class="button" title="Shuffle Queue" ng-click="queueShuffle()">Shuffle</a>
<a href="" class="button" id="action_Empty" title="Delete Queue" ng-click="queueEmpty()">Empty</a>
<a href="" class="button" id="action_DeleteSelected" title="Remove Selected From Queue" ng-click="queueRemoveSelected()">Remove</a>
<!--<a href="" class="button buttonvertical" id="action_QueueToPlaylist" title="Create Playlist From Queue"><img src="images/list_gd_12x11.png" /></a>-->
</div>
<div ng-repeat="song in [queue]" ng-include src="'js/partials/songs.html'" sortable></div>
</ul>
</div>
<script>
(function (i, s, o, g, r, a, m) {

274
js/_saved/api.js Normal file
View file

@ -0,0 +1,274 @@
function getGenres() {
var genres = 'Acid Rock,Acoustic,Alt Country,Alt/Indie,Alternative & Punk,Alternative Metal,Alternative,AlternRock,Awesome,Bluegrass,Blues,Blues-Rock,Classic Hard Rock,Classic Rock,Comedy,Country,Country-Rock,Dance,Dance-Rock,Deep Funk,Easy Listening,Electronic,Electronica,Electronica/Dance,Folk,Folk/Rock,Funk,Grunge,Hard Rock,Heavy Metal,Holiday,House,Improg,Indie Rock,Indie,International,Irish,Jam Band,Jam,Jazz Fusion,Jazz,Latin,Live Albums,Metal,Music,Oldies,Other,Pop,Pop/Rock,Post Rock,Progressive Rock,Psychedelic Rock,Psychedelic,Punk,R&B,Rap & Hip-Hop,Reggae,Rock & Roll,Rock,Rock/Pop,Roots,Ska,Soft Rock,Soul,Southern Rock,Thrash Metal,Unknown,Vocal,World';
var genresArr = genres.split(',');
var options = [];
options.push('<option value="">[Select Genre]</option>');
$.each(genresArr, function (i, genre) {
options.push('<option value="' + genre + '">' + genre + '</option>');
});
$('#Genres').html(options.join(''));
}
function loadAutoPlaylists(refresh) {
if (debug) { console.log("LOAD AUTO PLAYLISTS"); }
if (refresh) {
$('#AutoPlaylistContainer').empty();
}
var content = $('#AutoPlaylistContainer').html();
if (content == "") {
var genres = getValue('AutoPlaylists');
var genresArr = [];
if (genres) {
genresArr = genres.split(',');
genresArr.unshift('Random');
genresArr.unshift('Starred');
} else {
genresArr.push('Starred');
genresArr.push('Random');
}
$.each(genresArr, function (i, genre) {
genre = genre.trim();
if (genre != '') {
var html = "";
html += '<li class=\"item\" data-genre=\"' + genre + '\">';
html += '<span>' + genre + '</span>';
html += '<div class=\"floatright\"><a class=\"play\" href=\"\" data-genre=\"' + genre + '\" title=\"Play\"></a></div>';
html += '<div class=\"floatright\"><a class=\"add\" href=\"\" data-genre=\"' + genre + '\" title=\"Add To Play Queue\"></a></div>';
html += '</li>';
$(html).appendTo("#AutoPlaylistContainer");
}
});
}
}
function previewStarredCoverArt() {
$.ajax({
url: baseURL + '/getStarred.view?' + baseParams + '&size=25',
method: 'GET',
dataType: protocol,
timeout: 10000,
success: function (data) {
var coverarts = [];
if (data["subsonic-response"].starred !== undefined) {
var items = [];
if (data["subsonic-response"].starred.album !== undefined) {
if (data["subsonic-response"].starred.album.length > 0) {
items = data["subsonic-response"].starred.album;
} else {
items[0] = data["subsonic-response"].starred.album;
}
}
var html = "";
$.each(items, function (i, item) {
if (typeof item.coverArt !== "undefined") {
var coverSrc = baseURL + '/getCoverArt.view?' + baseParams + '&id=' + item.coverArt;
var title = item.artist + ' - ' + item.album;
html += '<a class=\"fancyboxcoverart\" rel=\"gallery1\" href=\"' + coverSrc + '\" title=\"' + title + '\"><img src=\"' + coverSrc + '\"></a>';
}
});
$('#preview').html(html);
$('#preview a').shuffle();
//var pick = Math.floor(Math.random() * coverarts.length) + 1;
//var href = baseURL + '/getCoverArt.view?' + baseParams + '&id=' + coverarts[pick];
$('a.fancyboxcoverart').fancybox({
autoPlay: true,
playSpeed: 10000,
preload: 5,
hideOnContentClick: true,
type: 'image',
openEffect: 'none',
closeEffect: 'none',
openSpeed: 'normal',
closeSpeed: 'slow',
afterLoad: function () {
$('div.fancybox-inner').click(function () {
//alert("test");
});
}
}).trigger('click');
//setInterval($('#preview a').fancybox.next(), 2000);
}
}
});
}
function previewCurrentCoverArt() {
var href = $('#coverartimage').attr('href');
var title = $('#songdetails_artist').html();
$("a#preview").fancybox({
hideOnContentClick: true,
type: 'image',
openEffect: 'none',
closeEffect: 'none',
href: href,
title: title
}).trigger('click');
}
var updaterNowPlaying;
var updaterNowPlayingIdList = [];
function updateNowPlaying(showPopup) {
updaterNowPlaying = $.periodic({ period: 4000, decay: 1.5, max_period: 30000 }, function () {
$.ajax({
periodic: this,
url: baseURL + '/getNowPlaying.view?' + baseParams,
method: 'GET',
dataType: protocol,
timeout: 10000,
success: function (data) {
if (data["subsonic-response"].nowPlaying.entry === undefined) {
this.periodic.increment();
$("#NowPlayingList").empty();
var chathtml = '<div class=\"msg\">';
chathtml += '<span class=\"user\">Nothing :(</span></br>';
chathtml += '</div>';
$(chathtml).appendTo("#NowPlayingList");
} else {
this.periodic.increment();
if (debug) { console.log('NowPlaying Delay: ' + this.periodic.cur_period); }
$("#NowPlayingList").empty();
var msgs = [];
if (data["subsonic-response"].nowPlaying.entry.length > 0) {
msgs = data["subsonic-response"].nowPlaying.entry;
} else {
msgs[0] = data["subsonic-response"].nowPlaying.entry;
}
var sorted = msgs.sort(function (a, b) {
return a.minutesAgo - b.minutesAgo;
});
$.each(sorted, function (i, msg) {
if (!showPopup) {
var chathtml = '<div class=\"msg\">';
chathtml += '<span class=\"user\">' + msg.username + '</span></br>';
chathtml += '<span class=\"artist\">' + msg.artist + '</span> - <span class=\"title\">' + msg.title + '</span>';
chathtml += '</div>';
$(chathtml).appendTo("#NowPlayingList");
}
var coverartSrc;
if (msg.coverArt === undefined) {
coverartSrc = 'images/albumdefault_50.jpg';
} else {
coverartSrc = baseURL + '/getCoverArt.view?' + baseParams + '&size=50&id=' + msg.coverArt;
}
if (getValue('Notification_NowPlaying')) {
var sid = msg.username + '-' + msg.id;
if (jQuery.inArray(sid, updaterNowPlayingIdList) === -1 && username != msg.username) {
showNotification(coverartSrc, toHTML.un(msg.username + ':' + msg.playerName), toHTML.un(msg.artist + ' - ' + msg.title), 'text', '');
updaterNowPlayingIdList.push(sid);
}
}
});
}
}
});
});
}
function stopUpdateNowPlaying() {
updaterNowPlaying.cancel();
}
function saveAutoFilter() {
if (browserStorageCheck) {
var item = localStorage.getItem('AutoFilter');
try {
localStorage.setItem('AutoFilter', item);
if (debug) { console.log('Saving Auto Filter: ' + item); }
} catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
alert('Quota exceeded!');
}
}
} else {
if (debug) { console.log('HTML5::loadStorage not supported on your browser' + html.length + ' characters'); }
}
}
function deleteAutoFilter() {
if (browserStorageCheck) {
localStorage.removeItem('AutoFilter');
if (debug) { console.log('Removing Auto Filter'); }
} else {
if (debug) { console.log('HTML5::loadStorage not supported on your browser' + html.length + ' characters'); }
}
}
function loadAutoFilter() {
if (browserStorageCheck) {
var item = localStorage.getItem('AutoFilter');
if (item != '' && item !== undefined && item !== null) {
var el = '#AutoFilter';
$(el).val(item);
if (debug) { console.log('Load Play Queue From localStorage: ' + item); }
}
} else {
if (debug) { console.log('HTML5::loadStorage not supported on your browser' + html.length + ' characters'); }
}
}
function downloadItem(id, type) {
var url;
if (type == 'item' && id) {
reqDownload = 'id=' + id;
}
if (type == 'playlist' && id) {
reqDownload = 'playlistUtf8Hex=' + id;
}
if (reqDownload) {
url = baseURL + '/download.view?' + baseParams + '&' + reqDownload;
window.location = url;
}
}
function loadVideos(refresh) {
if (debug) { console.log("LOAD VIDEOS"); }
if (refresh) {
$('#VideosContainer').empty();
}
var content = $('#VideosContainer').html();
if (content == "") {
// Load Videos
$.ajax({
url: baseURL + '/getVideos.view?' + baseParams,
method: 'GET',
dataType: protocol,
timeout: 10000,
success: function (data) {
if (data["subsonic-response"].videos != '') {
var videos = [];
if (data["subsonic-response"].videos.video.length > 0) {
videos = data["subsonic-response"].videos.video;
} else {
videos[0] = data["subsonic-response"].videos.video;
}
var rowcolor;
$.each(videos, function (i, video) {
var html;
if (i % 2 === 0) {
rowcolor = 'even';
} else {
rowcolor = 'odd';
}
var videoURL = baseURL + '/stream.view?' + baseParams + '&id=' + video.id;
html = '<tr class=\"row video\" childid=\"' + video.id + '\" parentid=\"' + video.parent + '\" bitrate=\"' + video.bitRate + '\" userrating=\"\">';
html += '<td class=\"itemactions\">';
//html += '<a class=\"add\" href=\"\" title=\"Add To Play Queue\"></a>';
//html += '<a class=\"remove\" href=\"\" title=\"Remove\"></a>';
html += '<a class=\"play\" href=\"' + videoURL + '\" title=\"Play (Opens In New Window)\" target=\"_blank\"></a>';
//html += '<a class=\"download\" href=\"\" title=\"Download\"></a>';
html += '</td>';
html += '<td class=\"track\"></td>';
html += '<td class=\"title\">' + video.title + '</td>';
html += '<td class=\"artist\"></td>';
var coverartSrc;
if (video.coverArt === undefined) {
coverartSrc = 'images/albumdefault_25.jpg';
} else {
coverartSrc = baseURL + '/getCoverArt.view?' + baseParams + '&size=25&id=' + video.coverArt;
}
var time = secondsToTime(video.duration);
html += '<td class=\"album\"><img src=\"' + coverartSrc + '\" />' + video.album + '</td>';
html += '<td class=\"time\">' + time + '</td>';
html += '</tr>';
$(html).appendTo("#VideosContainer");
});
}
}
});
}
}

61
js/_saved/chat.js Normal file
View file

@ -0,0 +1,61 @@
var starttime;
var updater;
function updateChatMessages() {
updater = $.periodic({ period: 1000, decay: 1.5, max_period: 1800000 }, function () {
$.ajax({
periodic: this,
url: baseURL + '/getChatMessages.view?' + baseParams + '&since=' + starttime,
method: 'GET',
dataType: protocol,
timeout: 10000,
success: function (data) {
if (data["subsonic-response"].chatMessages.chatMessage === undefined) {
if (debug) { console.log('ChatMessages Delay: ' + this.periodic.cur_period); }
this.periodic.increment();
} else {
var msgs = [];
if (data["subsonic-response"].chatMessages.chatMessage.length > 0) {
msgs = data["subsonic-response"].chatMessages.chatMessage;
} else {
msgs[0] = data["subsonic-response"].chatMessages.chatMessage;
}
this.periodic.reset();
var sorted = msgs.sort(function (a, b) {
return a.time - b.time;
});
var x = 1;
$.each(sorted, function (i, msg) {
var chathtml = '<div class=\"msg\">';
chathtml += '<span class=\"time\">' + $.format.date(new Date(parseInt(msg.time, 10)), 'hh:mm:ss a') + '</span> ';
chathtml += '<span class=\"user\">' + msg.username + '</span></br>';
chathtml += '<span class=\"msg\">' + msg.message + '</span>';
chathtml += '</div>';
$(chathtml).appendTo("#ChatMsgs");
if (x === sorted.length) {
starttime = msg.time;
}
x++;
});
$("#ChatMsgs").linkify();
$("#ChatMsgs").attr({ scrollTop: $("#ChatMsgs").attr("scrollHeight") });
}
}
});
});
}
function stopUpdateChatMessages() {
updater.cancel();
}
function addChatMessage(msg) {
$.ajax({
type: 'GET',
url: baseURL + '/addChatMessage.view?' + baseParams,
dataType: protocol,
timeout: 10000,
data: { message: msg },
success: function () {
updater.reset();
},
traditional: true // Fixes POST with an array in JQuery 1.4
});
}

View file

@ -0,0 +1,22 @@
<li class="row song" ng-repeat="o in song | limitTo:totalDisplayed" ng-click="selectSong(o)" ng-dblclick="playSong(false, o)" ng-class="{'selected': o.selected, 'playing': o.playing}" data-bind="attr: { id: id, title: description }">
<div class="itemactions">
<a class="add" href="" title="Add To Queue" ng-click="addSongToQueue(o)" stop-event="click"></a>
<a class="remove" href="" title="Remove From Queue"></a>
<a class="play" href="" title="Start Playing From This Song" ng-click="playFrom($index)" stop-event="click"></a>
<a class="download" href="" title="Download Song" ng-click="download(o.id)"></a>
<a href="" title="Favorite" ng-class="{'favorite': o.starred, 'rate': !o.starred}" ng-click="updateFavorite(o)" stop-event="click"></a>
<div class="clear"></div>
</div>
<div class="track floatleft" ng-bind-html="o.track"></div>
<div class="title floatleft" title="{{o.description}}" ng-bind-html="o.name"></div>
<span class="artist floatleft" ng-bind-html="o.artist"></span>
<div ng-show="o.album && itemType === 'ss'"><img src="{{o.coverartfull}}"><a class="albumblock floatleft" ng-bind-html="o.album" title="{{o.album}}"></a></div>
<div ng-show="o.album && itemType === 'pl'"><img src="{{o.coverartfull}}"><a ng-href="#/library/0/{{o.albumId}}" class="albumblock floatleft" stop-event="click" ng-bind-html="o.album" title="{{o.album}}"></a></div>
<a ng-href="#/archive/{{o.artist}}/{{o.parentid}}" class="albumblock floatleft" ng-show="o.album && itemType === 'archive'" stop-event="click" ng-bind-html="o.album" title="{{o.album}}"></a>
<div class="albumblock floatleft" ng-show="!o.album">&nbsp;</div>
<div class="time floatleft">{{o.time}}</div>
<div class="clear"></div>
</li>
<li class="row song" ng-show="song.length && (totalDisplayed < song.length)">
<a class="button blockbutton" ng-click="loadMore()">Load more</a>
</li>

View file

@ -28,19 +28,25 @@ JamStash.config(function ($routeProvider) {
.when('/archive/:artist/:album', { templateUrl: 'js/partials/archive.html', controller: 'ArchiveCtrl' })
.otherwise({ redirectTo: '/index' });
})
.run(['$rootScope', '$location', 'globals', function ($rootScope, $location, globals) {
.run(['$rootScope', '$location', 'globals', 'utils', function ($rootScope, $location, globals, utils) {
$rootScope.$on("$locationChangeStart", function (event, next, current) {
$rootScope.loggedIn = false;
var path = $location.path().replace(/^\/([^\/]*).*$/, '$1');
if (globals.settings.Username !== "" && globals.settings.Password !== "" && globals.settings.Server !== "" && path != 'archive') {
$rootScope.loggedIn = true;
$.fancybox.close();
}
if (!$rootScope.loggedIn && (path != 'settings' && path != 'archive')) {
$location.path('/settings');
var url = '/settings';
$location.path(url);
}
});
}]);
/*
JamStash.config(function ($locationProvider) {
$locationProvider.html5Mode(true);
})
JamStash.config(function ($httpProvider, globals) {
$httpProvider.defaults.timeout = globals.settings.Timeout;
})

View file

@ -181,7 +181,7 @@ function ArchiveCtrl($scope, $rootScope, $location, $routeParams, $http, utils,
}
});
};
utils.mapSong = function (key, song, server, dir, identifier, coverart) {
$scope.mapSong = function (key, song, server, dir, identifier, coverart) {
var url, time, track, title, rating, starred, contenttype, suffix;
var specs = '';
if (song.format == 'VBR MP3') {
@ -212,7 +212,7 @@ function ArchiveCtrl($scope, $rootScope, $location, $routeParams, $http, utils,
var items = data.files;
if (action == 'add') {
angular.forEach(items, function (item, key) {
var song = utils.mapSong(key, item, server, dir, identifier, coverart);
var song = $scope.mapSong(key, item, server, dir, identifier, coverart);
if (song) {
$rootScope.queue.push(song);
}
@ -223,7 +223,7 @@ function ArchiveCtrl($scope, $rootScope, $location, $routeParams, $http, utils,
} else if (action == 'play') {
$rootScope.queue = [];
angular.forEach(items, function (item, key) {
var song = utils.mapSong(key, item, server, dir, identifier, coverart);
var song = $scope.mapSong(key, item, server, dir, identifier, coverart);
if (song) {
$rootScope.queue.push(song);
}
@ -238,7 +238,7 @@ function ArchiveCtrl($scope, $rootScope, $location, $routeParams, $http, utils,
$scope.album = [];
$rootScope.song = [];
angular.forEach(items, function (item, key) {
var song = utils.mapSong(key, item, server, dir, identifier, coverart);
var song = $scope.mapSong(key, item, server, dir, identifier, coverart);
if (song) {
$rootScope.song.push(song);
}

View file

@ -159,7 +159,7 @@ function SubsonicCtrl($scope, $rootScope, $location, $window, $routeParams, util
} else {
type = 'bytag';
}
return new model.Album(album.id, album.parent, title, album.artist, album.artistId, coverartthumb, coverartfull, $.format.date(new Date(album.created), "yyyy-MM-dd h:mm a"), starred, '', '', type);
return new model.Album(album.id, album.parent, title, album.artist.toString(), album.artistId, coverartthumb, coverartfull, $.format.date(new Date(album.created), "yyyy-MM-dd h:mm a"), starred, '', '', type);
};
$scope.getAlbums = function (id, name) {
$scope.selectedAutoAlbum = null;
@ -255,7 +255,7 @@ function SubsonicCtrl($scope, $rootScope, $location, $window, $routeParams, util
$scope.album = [];
$rootScope.song = [];
$scope.album.push($scope.mapAlbum(data["subsonic-response"].album));
//$scope.album.push($scope.mapAlbum(data["subsonic-response"].album));
var items = [];
if (data["subsonic-response"].album.song.length > 0) {
@ -412,6 +412,7 @@ function SubsonicCtrl($scope, $rootScope, $location, $window, $routeParams, util
} else {
items[0] = data["subsonic-response"].searchResult2.song;
}
$scope.album = [];
$rootScope.song = [];
angular.forEach(items, function (item, key) {
$rootScope.song.push(utils.mapSong(item));
@ -427,6 +428,7 @@ function SubsonicCtrl($scope, $rootScope, $location, $window, $routeParams, util
items[0] = data["subsonic-response"].searchResult2.album;
}
$scope.album = [];
$rootScope.song = [];
angular.forEach(items, function (item, key) {
if (item.isDir) {
$scope.album.push($scope.mapAlbum(item));

View file

@ -118,14 +118,10 @@ function AppCtrl($scope, $rootScope, $document, $window, $location, $cookieStore
}
};
$rootScope.showQueue = function () {
var submenu = $('#QueuePreview');
submenu.fadeIn(400);
var timeout = globals.settings.Timeout;
setTimeout(function () { submenu.fadeOut(); }, timeout);
$.fancybox.open();
};
$rootScope.hideQueue = function () {
var submenu = $('#QueuePreview');
submenu.fadeOut();
$.fancybox.close();
};
$scope.toggleQueue = function () {
var submenu = $('#QueuePreview');
@ -149,9 +145,18 @@ function AppCtrl($scope, $rootScope, $document, $window, $location, $cookieStore
closeEffect: 'none'
});
$('#action_Welcome').fancybox({
$('.showQueue').fancybox({
href: '#showqueue',
autoWidth: false,
width: '100%',
//margin: [50, 10, 50, 10], // top, right, bottom, left
openEffect: 'none',
closeEffect: 'none'
closeEffect: 'none',
beforeLoad: function () {
if ($rootScope.queue == 0) {
this.close();
}
}
});
$('#audiocontainer .scrubber').mouseover(function (e) {
@ -232,21 +237,19 @@ function AppCtrl($scope, $rootScope, $document, $window, $location, $cookieStore
if (source != 'Search' && source != 'Source' && source != 'Description' && source != 'ChatMsg' && source != 'AutoPlaylists') {
var unicode = e.charCode ? e.charCode : e.keyCode;
if (globals.settings.Debug) { console.log('Keycode Triggered: ' + unicode); }
/*
if (unicode == 49) {
utils.changeTab('tabQueue');
if (unicode == 49) { // 1
$('#action_Queue').click();
} else if (unicode == 50) {
utils.changeTab('tabLibrary');
$('#action_Library').click();
} else if (unicode == 51) {
utils.changeTab('tabArchive');
$('#action_Playlists').click();
} else if (unicode == 52) {
utils.changeTab('tabPlaylists');
$('#action_Podcasts').click();
} else if (unicode == 53) {
utils.changeTab('tabPodcasts');
} else if (unicode == 54) {
utils.changeTab('tabSettings');
$('#action_Archive').click();
} else if (unicode == 54) { // 6
$('#action_Settings').click();
}
*/
if (unicode >= 65 && unicode <= 90 && $('#tabLibrary').is(':visible')) { // a-z
var key = utils.findKeyForCode(unicode);
if (key == 'x' || key == 'y' || key == 'z') {
@ -270,22 +273,22 @@ function AppCtrl($scope, $rootScope, $document, $window, $location, $cookieStore
var volume = utils.getValue('Volume') ? parseFloat(utils.getValue('Volume')) : 1;
if (volume <= 1 && volume > 0 && source === '') {
volume += -0.1;
$(player1).jPlayer({
$(globals.Player1).jPlayer({
volume: volume
});
utils.setValue('Volume', volume, true);
//updateMessage('Volume: ' + Math.round(volume * 100) + '%');
if (globals.settings.Debug) { console.log('Volume: ' + Math.round(volume * 100) + '%'); }
}
}
if (unicode == 187) { // equals - volume up
var volume = utils.getValue('Volume') ? parseFloat(utils.getValue('Volume')) : 1;
if (volume < 1 && volume >= 0 && source ==- '') {
volume += 0.1;
$(player1).jPlayer({
$(globals.Player1).jPlayer({
volume: volume
});
utils.setValue('Volume', volume, true);
//updateMessage('Volume: ' + Math.round(volume * 100) + '%');
if (globals.settings.Debug) { console.log('Volume: ' + Math.round(volume * 100) + '%'); }
}
}
}
@ -464,6 +467,7 @@ function AppCtrl($scope, $rootScope, $document, $window, $location, $cookieStore
$scope.queueEmpty = function () {
//self.selectedSongs([]);
$rootScope.queue = [];
$.fancybox.close();
};
$scope.queueTotal = function () {
var total = 0;
@ -510,7 +514,7 @@ function AppCtrl($scope, $rootScope, $document, $window, $location, $cookieStore
if (typeof folder == 'number' && folder !== '' && folder != 'all') {
//alert(folder);
folderParams = '&musicFolderId=' + folder;
} else if (typeof $rootScope.SelectedMusicFolder.id != 'undefined') {
} else if (typeof $rootScope.SelectedMusicFolder.id != 'undefined' && $rootScope.SelectedMusicFolder.id >= 0) {
//alert($rootScope.SelectedMusicFolder.id);
folderParams = '&musicFolderId=' + $rootScope.SelectedMusicFolder.id;
}

View file

@ -1,8 +1,7 @@
JamStash.controller('QueueCtrl',
function QueueCtrl($scope, $rootScope, $routeParams, $location, utils, globals, json, notifications) {
$scope.settings = globals.settings;
//$scope.song = $rootScope.queue;
//angular.copy($rootScope.queue, $scope.song);
$scope.song = $rootScope.queue;
//angular.copy($rootScope.queue, $scope.song);
$scope.itemType = 'pl';
});

View file

@ -1,5 +1,5 @@
JamStash.controller('SettingsCtrl',
function SettingsCtrl($scope, $routeParams, $location, utils, globals, json, notifications, player) {
function SettingsCtrl($rootScope, $scope, $routeParams, $location, utils, globals, json, notifications, player) {
$scope.settings = globals.settings;
$scope.Timeouts = [
{ id: 10000, name: 10 },
@ -26,9 +26,9 @@ function SettingsCtrl($scope, $routeParams, $location, utils, globals, json, not
$scope.reset = function () {
utils.setValue('Settings', null, true);
$scope.loadSettings();
}
};
$scope.save = function () {
if ($scope.settings.Password != '' && globals.settings.Password.substring(0, 4) != 'enc:') { $scope.settings.Password = 'enc:' + utils.HexEncode($scope.settings.Password); }
if ($scope.settings.Password !== '' && globals.settings.Password.substring(0, 4) != 'enc:') { $scope.settings.Password = 'enc:' + utils.HexEncode($scope.settings.Password); }
if ($scope.settings.NotificationSong) {
notifications.requestPermissionIfRequired();
if (!notifications.hasNotificationPermission()) {
@ -52,7 +52,7 @@ function SettingsCtrl($scope, $routeParams, $location, utils, globals, json, not
utils.setValue('Settings', $scope.settings, true);
notifications.updateMessage('Settings Updated!', true);
$scope.loadSettings();
if (globals.settings.Server != '' && globals.settings.Username != '' && globals.settings.Password != '') {
if (globals.settings.Server !== '' && globals.settings.Username !== '' && globals.settings.Password !== '') {
$scope.ping();
}
};
@ -64,7 +64,7 @@ function SettingsCtrl($scope, $routeParams, $location, utils, globals, json, not
json.getChangeLog(function (data) {
$scope.changeLog = data;
});
}
};
$scope.setupDemo = function () {
var Username = "android-guest";
var Password = "guest";
@ -77,8 +77,17 @@ function SettingsCtrl($scope, $routeParams, $location, utils, globals, json, not
//$scope.save();
$location.url('/library');
}
}
};
/* Load on Startup */
// https://tsquillario.dyndns.org:8443/Jamstash/beta/#/settings?url=https://tsquillario.dyndns.org:8443/subsonic&u=tsquillario
if (typeof $location.search()['url'] != 'undefined' && $scope.settings.Server === '') {
if (globals.settings.Debug) { console.log("Setting Provided: " + $location.search()['url']); }
$scope.settings.Server = $location.search()['url'];
}
if (typeof $location.search()['u'] != 'undefined' && $scope.settings.Username === '') {
if (globals.settings.Debug) { console.log("Setting Provided: " + $location.search()['u']); }
$scope.settings.Username = $location.search()['u'];
}
/* End Startup */
});

View file

@ -1,4 +1,16 @@
[
{
"date": "3/29/2014", "version": "3.3",
"changes": [
{ "text": "- Queue opens in modal window, feels easier to use. Other bug fixes." }
]
},
{
"date": "2/22/2014", "version": "3.2.3",
"changes": [
{ "text": "- Usability tweaks, reticulated splines" }
]
},
{
"date": "2/7/2014", "version": "3.2.2",
"changes": [

View file

@ -69,7 +69,7 @@
<div class="clear"></div>
</li>
</div>
<div ng-include src="'js/partials/songs.html'"></div>
<div ng-if="song.length > 0" ng-include src="'js/partials/songs.html'"></div>
</ul>
</div>
</div>

View file

@ -95,7 +95,7 @@
<div class="clear"></div>
</li>
</div>
<div ng-include src="'js/partials/songs.html'"></div>
<div ng-if="song.length > 0" ng-include src="'js/partials/songs.html'"></div>
</ul>
</div>
</div>

View file

@ -44,7 +44,7 @@
</ul>
<ul class="simplelist mainlist noselect">
<li class="index" id="folder">Folder Playlists</li>
<li class="item" ng-repeat="o in MusicFolders" ng-click="getRandomSongs('', '', o.id)" ng-class="{'selected': o.id == selectedAutoPlaylist}">
<li class="item" ng-repeat="o in MusicFolders | musicfolder" ng-click=" getRandomSongs('', '' , o.id)" ng-class="{'selected': o.id == selectedAutoPlaylist}">
<div class="itemactions">
<a class="add" href="" title="Add To Play Queue" ng-click="getRandomSongs('add', '', o.id)" stop-event="click"></a><a class="play" href="" title="Play" ng-click="getRandomSongs('play', '', o.id)" stop-event="click"></a>
</div>
@ -73,7 +73,7 @@
<div class="split-pane-divider" id="my-divider"></div>
<!-- Songs -->
<div id="right-component" class="split-pane-component lgcolumn noselect">
<ul class="songlist simplelist" ng-include src="'js/partials/songs.html'"></ul>
<ul class="songlist simplelist" ng-if="song.length > 0" ng-include src="'js/partials/songs.html'"></ul>
</div>
</div>
</div>

View file

@ -26,7 +26,7 @@
<div class="split-pane-divider" id="my-divider"></div>
<!-- Song -->
<div id="right-component" class="split-pane-component lgcolumn noselect">
<ul class="songlist simplelist" ng-include src="'js/partials/songs.html'"></ul>
<ul class="songlist simplelist" ng-if="song.length > 0" ng-include src="'js/partials/songs.html'"></ul>
</div>
</div>
</div>

View file

@ -1,5 +1,5 @@
<div id="queue" class="tabcontent">
<div class="section fullsection floatleft">
<ul class="songlist simplelist noselect" ng-include src="'js/partials/songs.html'" sortable></ul>
<ul class="songlist simplelist noselect" ng-if="song.length > 0" ng-include src="'js/partials/songs.html'" sortable></ul>
</div>
</div>

View file

@ -14,7 +14,6 @@
<label for="SubsonicVersion">Subsonic API: <span class="apiversion" id="SubsonicVersion">{{settings.ApiVersion}}</span></label><br />
<label for="SMStats">Audio State: <span id="SMStats"></span></label><br /><br />
<br />
<!--<a id="action_Welcome" href="#welcome">Launch Welcome</a><div id="welcome"><h2>Welcome</h2></div>-->
</div>
<div class="subsection floatleft">
<h3 class="title">Options</h3>
@ -111,7 +110,8 @@
</ul>
<h3 class="title">Keyboard Shortcuts</h3>
<ul class="preferences">
<!--<li><em>[1-6]</em> Switch to corresponding tab</li>-->
<li><em>Esc</em> Hide Queue</li>
<li><em>[1-6]</em> Switch to corresponding tab</li>
<li><em>[a-z]</em> Use to Quickly Browse to an Artist</li>
<li><em>Home</em> Scroll to Top of Artist List</li>
<li><em>Spacebar</em> Play/Pause</li>

View file

@ -1,4 +1,4 @@
<li class="row song" ng-repeat="o in song | limitTo:totalDisplayed" ng-click="selectSong(o)" ng-dblclick="playSong(false, o)" ng-class="{'selected': o.selected, 'playing': o.playing}" data-bind="attr: { id: id, title: description }">
<li class="row song" ng-repeat="o in song" ng-click="selectSong(o)" ng-dblclick="playSong(false, o)" ng-class="{'selected': o.selected, 'playing': o.playing}">
<div class="itemactions">
<a class="add" href="" title="Add To Queue" ng-click="addSongToQueue(o)" stop-event="click"></a>
<a class="remove" href="" title="Remove From Queue"></a>
@ -6,17 +6,13 @@
<a class="download" href="" title="Download Song" ng-click="download(o.id)"></a>
<a href="" title="Favorite" ng-class="{'favorite': o.starred, 'rate': !o.starred}" ng-click="updateFavorite(o)" stop-event="click"></a>
<div class="clear"></div>
</div>
</div>
<div class="track floatleft" ng-bind-html="o.track"></div>
<div class="title floatleft" title="{{o.description}}" ng-bind-html="o.name"></div>
<span class="artist floatleft" ng-bind-html="o.artist"></span>
<span class="albumblock floatleft" ng-show="o.album && itemType === 'ss'" ng-bind-html="o.album" title="{{o.album}}"></span>
<a ng-href="#/library/0/{{o.albumId}}" class="albumblock floatleft" ng-show="o.album && itemType === 'pl'" stop-event="click" ng-bind-html="o.album" title="{{o.album}}"></a>
<a ng-href="#/archive/{{o.artist}}/{{o.parentid}}" class="albumblock floatleft" ng-show="o.album && itemType === 'archive'" stop-event="click" ng-bind-html="o.album" title="{{o.album}}"></a>
<div ng-show="o.album && itemType !== 'archive'"><img src="{{o.coverartfull}}"><a ng-href="#/library/0/{{o.albumId}}" class="albumblock floatleft" stop-event="click" ng-bind-html="o.album" title="{{o.album}}"></a></div>
<a ng-show="o.album && itemType === 'archive'" ng-href="#/archive/{{o.artist}}/{{o.parentid}}" class="albumblock floatleft" stop-event="click" ng-bind-html="o.album" title="{{o.album}}"></a>
<div class="albumblock floatleft" ng-show="!o.album">&nbsp;</div>
<div class="time floatleft">{{o.time}}</div>
<div class="clear"></div>
</li>
<li class="row song" ng-show="song.length && (totalDisplayed < song.length)">
<a class="button blockbutton" ng-click="loadMore()">Load more</a>
</li>
</li>

View file

@ -39,7 +39,7 @@
</ul>
</div>
<!-- Song -->
<div class="ui-layout-east noselect hide" ng-include src="'js/partials/songs.html'"></div>
<div class="ui-layout-east noselect hide" ng-if="song.length > 0" ng-include src="'js/partials/songs.html'"></div>
</div>
</div>
<div class="clear"></div>

View file

@ -1,5 +1,5 @@
JamStash.service('player', function ($rootScope, $window, utils, globals, model, notifications) {
var player1 = '#playdeck_1';
var player1 = globals.Player1;
var player2 = '#playdeck_2';
var scrobbled = false;
var timerid = 0;
@ -13,8 +13,6 @@
if (next) {
$rootScope.playSong(false, next);
}
//$(player1).jPlayer("stop");
//$(player2).jPlayer("play");
};
$rootScope.previousTrack = function () {
var next = getNextSong(true);

View file

@ -128,6 +128,7 @@ JamStash.service('globals', function () {
};
this.SavedCollections = [];
this.SavedGenres = [];
this.Player1 = '#playdeck_1';
this.BaseURL = function () { return this.settings.Server + '/rest'; };
this.BaseParams = function () { return 'u=' + this.settings.Username + '&p=' + this.settings.Password + '&f=' + this.settings.Protocol + '&v=' + this.settings.ApiVersion + '&c=' + this.settings.ApplicationName; };
@ -360,6 +361,7 @@ JamStash.factory('json', function ($http) { // Deferred loading
}
};
});
/*
JamStash.factory('template', function ($http, $compile, $http, $templateCache) { // Deferred loading
return {
getCollections: function (callback) {
@ -374,6 +376,7 @@ JamStash.factory('template', function ($http, $compile, $http, $templateCache) {
}
};
});
*/
JamStash.factory('subsonic', function ($http, globals, utils) {
return {
getSongTemplate: function (callback) {
@ -417,6 +420,11 @@ JamStash.filter('capitalize', function () {
return input.substring(0, 1).toUpperCase() + input.substring(1);
};
});
JamStash.filter('musicfolder', function () {
return function (items, scope) {
return items.slice(1, items.length);
};
});
JamStash.service('notifications', function ($rootScope, globals) {
var msgIndex = 1;

View file

@ -46,7 +46,7 @@ JamStash.service('utils', function ($cookieStore, globals, model) {
};
this.mapSong = function (data) {
var song = data;
var url, title, track, rating, starred, contenttype, suffix, description;
var url, title, artist, track, rating, starred, contenttype, suffix, description;
var specs = '', coverartthumb = '', coverartfull = '';
if (typeof song.coverArt != 'undefined') {
coverartthumb = globals.BaseURL() + '/getCoverArt.view?' + globals.BaseParams() + '&size=60&id=' + song.coverArt;
@ -56,6 +56,7 @@ JamStash.service('utils', function ($cookieStore, globals, model) {
coverartfull = 'images/albumdefault_160.jpg';
}
if (typeof song.description == 'undefined') { description = ''; } else { description = song.description; }
if (typeof song.artist == 'undefined') { artist = '&nbsp;'; } else { artist = song.artist.toString(); }
if (typeof song.title == 'undefined') { title = '&nbsp;'; } else { title = song.title.toString(); }
if (typeof song.track == 'undefined') { track = '&nbsp;'; } else { track = song.track.toString(); }
if (typeof song.starred !== 'undefined') { starred = true; } else { starred = false; }
@ -65,7 +66,7 @@ JamStash.service('utils', function ($cookieStore, globals, model) {
if (suffix == 'ogg') { suffix = 'oga'; }
var salt = Math.floor(Math.random() * 100000);
url = globals.BaseURL() + '/stream.view?' + globals.BaseParams() + '&id=' + song.id + '&salt=' + salt;
return new model.Song(song.id, song.parent, track, title, song.artist, song.artistId, song.album, song.albumId, coverartthumb, coverartfull, song.duration, song.userRating, starred, suffix, specs, url, 0, description);
return new model.Song(song.id, song.parent, track, title, artist, song.artistId, song.album, song.albumId, coverartthumb, coverartfull, song.duration, song.userRating, starred, suffix, specs, url, 0, description);
};
this.confirmDelete = function (text) {
var question = confirm(text);

View file

@ -323,7 +323,8 @@ span.apiversion
{
color: #4B95E5;
float: right;
padding: 5px;
padding: 8px;
font-size: 13px;
margin: 2px 5px 2px 0;
background: #fff;
border: 1px solid #A6CBF3;
@ -396,7 +397,7 @@ ul.simplelist li
{
font-size: 13px;
cursor: pointer;
padding: 8px;
padding: 6px 8px;
border-bottom: 1px solid #f2f2f2;
}
ul.simplelist .item .itemactions
@ -547,6 +548,7 @@ ul.songlist
{
border-collapse: collapse;
padding: 4px;
text-align: left;
}
ul.songlist .album:hover
{
@ -599,6 +601,8 @@ ul.songlist .album .albumart
{
padding: 0;
float: left;
overflow: hidden;
max-height: 170px;
}
ul.songlist .album .albumart img
{
@ -709,12 +713,13 @@ ul.songlist .row
{
cursor: pointer;
border-bottom: 1px solid #EFEFEF;
line-height: 30px;
font-size: 12px;
}
ul.songlist .row a
{
color: #7EA8D5;
text-decoration: none;
font-size: 12px;
}
ul.songlist .row a:hover
{
@ -724,8 +729,10 @@ ul.songlist .row span.albumblock
{
color: #7EA8D5;
font-size: 12px;
overflow: hidden;
height: 30px;
}
ul.songlist .row .album img
ul.songlist .row img
{
border: 1px solid #DEDEDE;
display: block;
@ -733,12 +740,13 @@ ul.songlist .row .album img
margin: 0 5px;
padding: 2px;
height: 25px;
width: 25px;
}
ul.songlist .row .itemactions
{
width: 20%; /* 20% */
float: left;
padding: 0 0 0 16px;
padding: 6px 0 0 16px;
}
ul.songlist .row .itemactions a
{
@ -760,6 +768,8 @@ ul.songlist .row .title
ul.songlist .row .albumblock
{
width: 25%; /* 80% */
overflow: hidden;
height: 30px;
}
ul.songlist .row .albumblock img
{
@ -841,7 +851,7 @@ ul.songlist li.selected
{
background-color: #D4E2F1;
background-image: url('../images/check_8x7.png');
background-position: 10px 16px;
background-position: 10px 19px;
background-repeat: no-repeat;
border-bottom: 1px solid #C0D5EB;
}
@ -946,10 +956,14 @@ ul.songlist li:hover
{
height: 29px;
/* width: 660px; */
margin: 5px 205px 0 0;
margin: 5px 75px 0 0;
padding: 0 0 0 5px;
float: right;
}
.queueactions {
padding: 0 0 5px 0;
text-align: left;
}
#globalactions
{
position: absolute;
@ -1102,82 +1116,10 @@ ul.songlist li:hover
{
}
#queue
{
}
#QueuePreview {
height: 131px;
width: 472px;
padding: 1px;
margin: 0;
z-index: 999;
/*background: #5b5b4e; */
background: rgba(91, 91, 78, 0.4) ;
list-style-type: none;
overflow-x: hidden;
overflow-y: hidden;
text-align: left;
white-space: nowrap;
position: absolute;
bottom: 6px;
left: 198px;
#showqueue {
width: 1200px;
display: none;
}
#QueuePreview li {
}
#QueuePreview li.selected {
background-color: #D4E2F1;
}
#QueuePreview li.playing {
background-image: none;
background-color: #528AC6;
color: #fff;
border-color: #294563;
}
#QueuePreview .row {
width: 92px;
height: 119px;
display: inline-block;
margin: 1px 1px;
padding: 4px 5px;
font-size: 11px;
text-align: center;
border: solid 1px #535353;
border-radius: 2px;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
overflow: hidden;
float: none;
background: #EFEFEE;
}
#QueuePreview .row .albumart img {
width: 60px;
height: 60px;
padding: 2px;
border: 1px solid #eee;
}
#QueuePreview .row .track {
width: auto;
}
#QueuePreview .row .title {
width: auto;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
margin: 0;
padding: 0;
}
#QueuePreview .row .albumtext {
width: auto;
white-space: nowrap;
overflow: hidden;
margin: 0;
padding: 0;
}
#QueuePreview .row .time {
width: auto;
}
/* Player Style */
#player