Adds angular-locker dependency.
- It makes it easier to use localStorage and sessionStorage "the angular way". It also does all the error handling so we don't need to. - Adds back the automatic saving of the current track's position and playing queue in localStorage. It's fully unit tested. - Adds back the notifications. Every time we change songs (if the setting is true), it displays a notification. Clicking on it goes to the next song, just like before. - Bumps up the versions to the actual value on the various json files.
This commit is contained in:
parent
2e97e25f25
commit
83869b7808
12 changed files with 346 additions and 205 deletions
13
app/app.js
13
app/app.js
|
@ -1,11 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
/* Declare app level module */
|
||||
angular.module('JamStash', ['ngCookies', 'ngRoute', 'ngSanitize',
|
||||
'jamstash.subsonic.controller', 'jamstash.archive.controller', 'jamstash.player.controller', 'jamstash.queue.controller'])
|
||||
'jamstash.subsonic.controller', 'jamstash.archive.controller', 'jamstash.player.controller', 'jamstash.queue.controller', 'angular-locker'])
|
||||
|
||||
.config(['$routeProvider',function($routeProvider) {
|
||||
'use strict';
|
||||
|
||||
$routeProvider
|
||||
.when('/index', { redirectTo: '/library' })
|
||||
.when('/settings', { templateUrl: 'settings/settings.html', controller: 'SettingsController' })
|
||||
|
@ -21,8 +20,6 @@ angular.module('JamStash', ['ngCookies', 'ngRoute', 'ngSanitize',
|
|||
}])
|
||||
|
||||
.config(['$httpProvider',function($httpProvider) {
|
||||
'use strict';
|
||||
|
||||
$httpProvider.interceptors.push(['$rootScope', '$location', '$q', 'globals', function ($rootScope, $location, $q, globals) {
|
||||
return {
|
||||
'request': function (request) {
|
||||
|
@ -51,4 +48,10 @@ angular.module('JamStash', ['ngCookies', 'ngRoute', 'ngSanitize',
|
|||
}
|
||||
};
|
||||
}]);
|
||||
}])
|
||||
|
||||
.config(['lockerProvider', function (lockerProvider) {
|
||||
lockerProvider.setDefaultDriver('local')
|
||||
.setDefaultNamespace('jamstash')
|
||||
.setEventsEnabled(false);
|
||||
}]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('JamStash')
|
||||
.controller('AppController', ['$scope', '$rootScope', '$document', '$window', '$location', '$cookieStore', '$http', 'utils', 'globals', 'model', 'notifications', 'player',
|
||||
function($scope, $rootScope, $document, $window, $location, $cookieStore, $http, utils, globals, model, notifications, player) {
|
||||
angular.module('JamStash')
|
||||
.controller('AppController', ['$scope', '$rootScope', '$document', '$window', '$location', '$cookieStore', '$http', 'utils', 'globals', 'model', 'notifications', 'player', 'locker',
|
||||
function($scope, $rootScope, $document, $window, $location, $cookieStore, $http, utils, globals, model, notifications, player, locker) {
|
||||
'use strict';
|
||||
|
||||
$rootScope.settings = globals.settings;
|
||||
|
@ -444,31 +444,23 @@
|
|||
};
|
||||
|
||||
$scope.loadTrackPosition = function () {
|
||||
if (utils.browserStorageCheck()) {
|
||||
// Load Saved Song
|
||||
var song = angular.fromJson(localStorage.getItem('CurrentSong'));
|
||||
var song = locker.get('CurrentSong');
|
||||
if (song) {
|
||||
player.load(song);
|
||||
}
|
||||
} else {
|
||||
if (globals.settings.Debug) { console.log('HTML5::loadStorage not supported on your browser'); }
|
||||
}
|
||||
};
|
||||
|
||||
$scope.loadQueue = function () {
|
||||
if(utils.browserStorageCheck()) {
|
||||
// load Saved queue
|
||||
var queue = angular.fromJson(localStorage.getItem('CurrentQueue'));
|
||||
var queue = locker.get('CurrentQueue');
|
||||
if (queue) {
|
||||
player.queue = queue;
|
||||
player.addSongs(queue);
|
||||
if (player.queue.length > 0) {
|
||||
notifications.updateMessage(player.queue.length + ' Saved Song(s)', true);
|
||||
}
|
||||
if (globals.settings.Debug) { console.log('Play Queue Loaded From localStorage: ' + player.queue.length + ' song(s)'); }
|
||||
}
|
||||
} else {
|
||||
if (globals.settings.Debug) { console.log('HTML5::loadStorage not supported on your browser'); }
|
||||
}
|
||||
};
|
||||
|
||||
/* Launch on Startup */
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
describe("Main controller", function() {
|
||||
'use strict';
|
||||
|
||||
var scope, $rootScope, utils, globals, model, notifications, player;
|
||||
var scope, $rootScope, utils, globals, notifications, player, locker;
|
||||
beforeEach(function() {
|
||||
module('JamStash');
|
||||
|
||||
inject(function ($controller, _$rootScope_, _$document_, _$window_, _$location_, _$cookieStore_, _utils_, _globals_, _model_, _notifications_, _player_) {
|
||||
inject(function ($controller, _$rootScope_, _$document_, _$window_, _$location_, _$cookieStore_, _utils_, _globals_, _model_, _notifications_, _player_, _locker_) {
|
||||
$rootScope = _$rootScope_;
|
||||
scope = $rootScope.$new();
|
||||
utils = _utils_;
|
||||
globals = _globals_;
|
||||
model = _model_;
|
||||
notifications = _notifications_;
|
||||
player = _player_;
|
||||
locker = _locker_;
|
||||
|
||||
$controller('AppController', {
|
||||
$scope: scope,
|
||||
|
@ -23,9 +23,10 @@ describe("Main controller", function() {
|
|||
$cookieStore: _$cookieStore_,
|
||||
utils: utils,
|
||||
globals: globals,
|
||||
model: model,
|
||||
model: _model_,
|
||||
notifications: notifications,
|
||||
player: player
|
||||
player: player,
|
||||
locker: locker
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -62,7 +63,7 @@ describe("Main controller", function() {
|
|||
beforeEach(function() {
|
||||
fakeStorage = {};
|
||||
|
||||
spyOn(localStorage, "getItem").and.callFake(function(key) {
|
||||
spyOn(locker, "get").and.callFake(function(key) {
|
||||
return fakeStorage[key];
|
||||
});
|
||||
spyOn(utils, "browserStorageCheck").and.returnValue(true);
|
||||
|
@ -86,13 +87,13 @@ describe("Main controller", function() {
|
|||
|
||||
scope.loadTrackPosition();
|
||||
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith('CurrentSong');
|
||||
expect(locker.get).toHaveBeenCalledWith('CurrentSong');
|
||||
expect(player.load).toHaveBeenCalledWith(song);
|
||||
});
|
||||
|
||||
it("Given that we didn't save anything in local Storage, it doesn't load anything", function() {
|
||||
scope.loadTrackPosition();
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith('CurrentSong');
|
||||
expect(locker.get).toHaveBeenCalledWith('CurrentSong');
|
||||
expect(player.load).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -100,7 +101,10 @@ describe("Main controller", function() {
|
|||
describe("loadQueue -", function() {
|
||||
beforeEach(function() {
|
||||
spyOn(notifications, "updateMessage");
|
||||
player.queue = [];
|
||||
spyOn(player, "addSongs").and.callFake(function (songs) {
|
||||
// Update the queue length so that notifications work
|
||||
player.queue.length += songs.length;
|
||||
});
|
||||
});
|
||||
|
||||
it("Given that we previously saved the playing queue in local Storage, it fills the player's queue with what we saved and notifies the user", function() {
|
||||
|
@ -115,16 +119,16 @@ describe("Main controller", function() {
|
|||
|
||||
scope.loadQueue();
|
||||
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith('CurrentQueue');
|
||||
expect(player.queue).toEqual(queue);
|
||||
expect(locker.get).toHaveBeenCalledWith('CurrentQueue');
|
||||
expect(player.addSongs).toHaveBeenCalledWith(queue);
|
||||
expect(notifications.updateMessage).toHaveBeenCalledWith('3 Saved Song(s)', true);
|
||||
});
|
||||
|
||||
it("Given that we didn't save anything in local Storage, it doesn't load anything", function() {
|
||||
scope.loadQueue();
|
||||
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith('CurrentQueue');
|
||||
expect(player.queue).toEqual([]);
|
||||
expect(locker.get).toHaveBeenCalledWith('CurrentQueue');
|
||||
expect(player.addSongs).not.toHaveBeenCalled();
|
||||
expect(notifications.updateMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
*
|
||||
* Provides access to the notification UI.
|
||||
*/
|
||||
angular.module('jamstash.notifications', [])
|
||||
angular.module('jamstash.notifications', ['jamstash.player.service'])
|
||||
|
||||
.service('notifications', ['$rootScope', 'globals', function($rootScope, globals) {
|
||||
.service('notifications', ['$rootScope', 'globals', 'player', function($rootScope, globals, player) {
|
||||
'use strict';
|
||||
|
||||
var msgIndex = 1;
|
||||
|
@ -37,10 +37,12 @@ angular.module('jamstash.notifications', [])
|
|||
if (this.hasNotificationPermission()) {
|
||||
//closeAllNotifications()
|
||||
var settings = {};
|
||||
if (bind = '#NextTrack') {
|
||||
if (bind === '#NextTrack') {
|
||||
settings.notifyClick = function () {
|
||||
$rootScope.nextTrack();
|
||||
player.nextTrack();
|
||||
this.close();
|
||||
//TODO: Hyz: This should be in a directive, so we wouldn't have to use this.
|
||||
$rootScope.$apply();
|
||||
};
|
||||
}
|
||||
if (type === 'text') {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
<link rel="stylesheet" href="bower_components/fancybox/source/jquery.fancybox.css" />
|
||||
<!-- endbower -->
|
||||
<!-- endbuild -->
|
||||
<!--<link href="vendor/jquery-split-pane.css" rel="stylesheet" />-->
|
||||
<link href="styles/Style.css" rel="stylesheet" type="text/css" data-name="main" />
|
||||
<link href="styles/Mobile.css" rel="stylesheet" type="text/css" data-name="main" />
|
||||
<link href="" rel="stylesheet" type="text/css" data-name="theme" />
|
||||
|
@ -103,6 +102,7 @@
|
|||
<script src="bower_components/jquery.scrollTo/jquery.scrollTo.js"></script>
|
||||
<script src="bower_components/underscore/underscore.js"></script>
|
||||
<script src="bower_components/angular-underscore/angular-underscore.js"></script>
|
||||
<script src="bower_components/angular-locker/dist/angular-locker.min.js"></script>
|
||||
<!-- endbower -->
|
||||
<script src="vendor/jquery.base64.js"></script>
|
||||
<script src="vendor/jquery.dateFormat-1.0.js"></script>
|
||||
|
|
|
@ -4,15 +4,17 @@
|
|||
* Encapsulates the jPlayer plugin. It watches the player service for the song to play, load or restart.
|
||||
* It also enables jPlayer to attach event handlers to our UI through css Selectors.
|
||||
*/
|
||||
angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstash.settings', 'jamstash.subsonic.service'])
|
||||
angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstash.settings', 'jamstash.subsonic.service', 'jamstash.notifications', 'jamstash.utils', 'angular-locker'])
|
||||
|
||||
.directive('jplayer', ['player', 'globals', 'subsonic', function(playerService, globals, subsonic) {
|
||||
.directive('jplayer', ['player', 'globals', 'subsonic', 'notifications', 'utils', 'locker', '$window',
|
||||
function(playerService, globals, subsonic, notifications, utils, locker, $window) {
|
||||
'use strict';
|
||||
return {
|
||||
restrict: 'EA',
|
||||
template: '<div></div>',
|
||||
link: function(scope, element) {
|
||||
|
||||
var timerid;
|
||||
var $player = element.children('div');
|
||||
var audioSolution = 'html,flash';
|
||||
if (globals.settings.ForceFlash) {
|
||||
|
@ -41,12 +43,10 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
duration: '#duration'
|
||||
},
|
||||
play: function() {
|
||||
console.log('jplayer play');
|
||||
scope.revealControls();
|
||||
scope.scrobbled = false;
|
||||
},
|
||||
ended: function() {
|
||||
console.log('jplayer ended');
|
||||
// We do this here and not on the service because we cannot create
|
||||
// a circular dependency between the player and subsonic services
|
||||
if(playerService.isLastSongPlaying() && globals.settings.AutoPlay) {
|
||||
|
@ -69,23 +69,21 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
});
|
||||
};
|
||||
|
||||
updatePlayer();
|
||||
|
||||
scope.currentSong = {};
|
||||
scope.scrobbled = false;
|
||||
|
||||
scope.$watch(function () {
|
||||
return playerService.getPlayingSong();
|
||||
}, function (newVal) {
|
||||
console.log('playingSong changed !');
|
||||
scope.currentSong = newVal;
|
||||
$player.jPlayer('setMedia', {'mp3': newVal.url});
|
||||
}, function (newSong) {
|
||||
scope.currentSong = newSong;
|
||||
$player.jPlayer('setMedia', {'mp3': newSong.url});
|
||||
if(playerService.loadSong === true) {
|
||||
// Do not play, only load
|
||||
playerService.loadSong = false;
|
||||
scope.revealControls();
|
||||
$player.jPlayer('pause', newSong.position);
|
||||
} else {
|
||||
$player.jPlayer('play');
|
||||
if(globals.settings.NotificationSong) {
|
||||
notifications.showNotification(newSong.coverartthumb, utils.toHTML.un(newSong.name), utils.toHTML.un(newSong.artist + ' - ' + newSong.album), 'text', '#NextTrack');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -93,7 +91,6 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
return playerService.restartSong;
|
||||
}, function (newVal) {
|
||||
if(newVal === true) {
|
||||
console.log('restartSong changed !');
|
||||
$player.jPlayer('play', 0);
|
||||
playerService.restartSong = false;
|
||||
}
|
||||
|
@ -104,6 +101,51 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
$('#songdetails').css('visibility', 'visible');
|
||||
};
|
||||
|
||||
scope.saveTrackPosition = function () {
|
||||
var audio = $player.data('jPlayer');
|
||||
if (audio !== undefined && scope.currentSong !== undefined) {
|
||||
var position = audio.status.currentTime;
|
||||
if (position !== null) {
|
||||
scope.currentSong.position = position;
|
||||
locker.put('CurrentSong', scope.currentSong);
|
||||
if (globals.settings.Debug) { console.log('Saving Current Position: ', scope.currentSong); }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scope.saveQueue = function () {
|
||||
locker.put('CurrentQueue', playerService.queue);
|
||||
if (globals.settings.Debug) { console.log('Saving Queue: ' + playerService.queue.length + ' songs'); }
|
||||
};
|
||||
|
||||
scope.startSavePosition = function () {
|
||||
if (globals.settings.SaveTrackPosition) {
|
||||
if (timerid !== 0) {
|
||||
$window.clearInterval(timerid);
|
||||
}
|
||||
timerid = $window.setInterval(function () {
|
||||
var audio = $player.data('jPlayer');
|
||||
if (globals.settings.SaveTrackPosition && audio.status.currentTime > 0 && audio.status.paused === false) {
|
||||
$('#action_SaveProgress')
|
||||
.fadeTo("slow", 0).delay(500)
|
||||
.fadeTo("slow", 1).delay(500)
|
||||
.fadeTo("slow", 0).delay(500)
|
||||
.fadeTo("slow", 1);
|
||||
scope.saveTrackPosition();
|
||||
scope.saveQueue();
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
};
|
||||
|
||||
// Startup
|
||||
timerid = 0;
|
||||
scope.currentSong = {};
|
||||
scope.scrobbled = false;
|
||||
|
||||
updatePlayer();
|
||||
scope.startSavePosition();
|
||||
|
||||
} //end link
|
||||
};
|
||||
}]);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
describe("jplayer directive", function() {
|
||||
'use strict';
|
||||
|
||||
var element, scope, playerService, mockGlobals, subsonic, $player, playingSong;
|
||||
var element, scope, $player, playingSong,
|
||||
playerService, mockGlobals, subsonic, notifications, locker, $window;
|
||||
|
||||
beforeEach(function() {
|
||||
playingSong = {};
|
||||
|
@ -20,15 +21,23 @@ describe("jplayer directive", function() {
|
|||
$delegate.nextTrack = jasmine.createSpy('nextTrack');
|
||||
$delegate.songEnded = jasmine.createSpy('songEnded');
|
||||
$delegate.isLastSongPlaying = jasmine.createSpy('isLastSongPlaying');
|
||||
|
||||
return $delegate;
|
||||
});
|
||||
//TODO: Hyz: We shouldn't have to know the utils service just for that. Remove these calls and deal with this in the Notifications service.
|
||||
// Mock the utils service
|
||||
$provide.decorator('utils', function ($delegate) {
|
||||
$delegate.toHTML.un = jasmine.createSpy('un');
|
||||
return $delegate;
|
||||
});
|
||||
$provide.value('globals', mockGlobals);
|
||||
});
|
||||
|
||||
inject(function($rootScope, $compile, _player_, _subsonic_) {
|
||||
inject(function($rootScope, $compile, _player_, _subsonic_, _notifications_, _locker_, _$window_) {
|
||||
playerService = _player_;
|
||||
subsonic = _subsonic_;
|
||||
notifications = _notifications_;
|
||||
locker = _locker_;
|
||||
$window = _$window_;
|
||||
// Compile the directive
|
||||
scope = $rootScope.$new();
|
||||
element = '<div id="playdeck_1" jplayer></div>';
|
||||
|
@ -52,24 +61,36 @@ describe("jplayer directive", function() {
|
|||
expect(scope.currentSong).toEqual(playingSong);
|
||||
});
|
||||
|
||||
it("if the player service's loadSong flag is true, it does not play the song and it displays the player controls", function() {
|
||||
it("if the player service's loadSong flag is true, it does not play the song, it displays the player controls and sets the player to the song's supplied position", function() {
|
||||
spyOn(scope, "revealControls");
|
||||
playingSong.position = 42.2784;
|
||||
|
||||
playerService.loadSong = true;
|
||||
scope.$apply();
|
||||
|
||||
expect($player.jPlayer).not.toHaveBeenCalledWith('play');
|
||||
expect($player.jPlayer).toHaveBeenCalledWith('pause', playingSong.position);
|
||||
expect(playerService.loadSong).toBeFalsy();
|
||||
expect(scope.revealControls).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("otherwise, it plays it", function() {
|
||||
describe("if the player service's loadSong flag is false,", function() {
|
||||
it("it plays the song", function() {
|
||||
playerService.loadSong = false;
|
||||
scope.$apply();
|
||||
|
||||
expect($player.jPlayer).toHaveBeenCalledWith('play');
|
||||
expect(playerService.loadSong).toBeFalsy();
|
||||
});
|
||||
|
||||
it("if the global setting NotificationSong is true, it displays a notification", function() {
|
||||
spyOn(notifications, "showNotification");
|
||||
mockGlobals.settings.NotificationSong = true;
|
||||
scope.$apply();
|
||||
|
||||
expect(notifications.showNotification).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("When the player service's restartSong flag is true, it restarts the current song and resets the flag to false", function() {
|
||||
|
@ -168,4 +189,79 @@ describe("jplayer directive", function() {
|
|||
expect(scope.scrobbled).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("save to localStorage -", function() {
|
||||
beforeEach(function() {
|
||||
spyOn(locker, "put");
|
||||
});
|
||||
|
||||
it("it saves the current song and its position to localStorage", function() {
|
||||
var position = 48.0773;
|
||||
$player.data('jPlayer').status.currentTime = position;
|
||||
scope.currentSong = {
|
||||
id: 419
|
||||
};
|
||||
|
||||
scope.saveTrackPosition();
|
||||
|
||||
expect(scope.currentSong.position).toBe(position);
|
||||
expect(locker.put).toHaveBeenCalledWith('CurrentSong', scope.currentSong);
|
||||
});
|
||||
|
||||
it("it saves the player queue to localStorage", function() {
|
||||
var queue = [
|
||||
{id: 2313},
|
||||
{id: 4268},
|
||||
{id: 5470}
|
||||
];
|
||||
playerService.queue = queue;
|
||||
|
||||
scope.saveQueue();
|
||||
|
||||
expect(locker.put).toHaveBeenCalledWith('CurrentQueue', queue);
|
||||
});
|
||||
|
||||
describe("Given that the global setting SaveTrackPosition is true,", function() {
|
||||
beforeEach(function() {
|
||||
jasmine.clock().install();
|
||||
mockGlobals.settings.SaveTrackPosition = true;
|
||||
spyOn(scope, "saveTrackPosition");
|
||||
spyOn(scope, "saveQueue");
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
it("every 30 seconds, it saves the current song and queue", function() {
|
||||
$player.data('jPlayer').status.currentTime = 35.3877;
|
||||
$player.data('jPlayer').status.paused = false;
|
||||
|
||||
scope.startSavePosition();
|
||||
jasmine.clock().tick(30001);
|
||||
|
||||
expect(scope.saveTrackPosition).toHaveBeenCalled();
|
||||
expect(scope.saveQueue).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("if the song is not playing, it does not save anything", function() {
|
||||
$player.data('jPlayer').status.currentTime = 0.0;
|
||||
$player.data('jPlayer').status.paused = true;
|
||||
|
||||
scope.startSavePosition();
|
||||
jasmine.clock().tick(30001);
|
||||
|
||||
expect(scope.saveTrackPosition).not.toHaveBeenCalled();
|
||||
expect(scope.saveQueue).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("if there was already a watcher, it clears it before watching", function() {
|
||||
spyOn($window, "clearInterval");
|
||||
|
||||
scope.startSavePosition();
|
||||
scope.startSavePosition();
|
||||
expect($window.clearInterval).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
}
|
||||
}
|
||||
if ($scope.settings.SaveTrackPosition) {
|
||||
player.saveTrackPosition();
|
||||
//TODO: Hyz: player.saveTrackPosition();
|
||||
} else {
|
||||
player.deleteCurrentQueue();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jamstash",
|
||||
"version": "4.3",
|
||||
"version": "4.3.1",
|
||||
"description": "HTML5 Audio Streamer for Subsonic, Archive.org browsing and streaming",
|
||||
"authors": [
|
||||
"tsquillario (https://github.com/tsquillario)",
|
||||
|
@ -38,7 +38,8 @@
|
|||
"notify.js": "<=1.2.2",
|
||||
"jquery.scrollTo": "~1.4.5",
|
||||
"underscore": "~1.7.0",
|
||||
"angular-underscore": "~0.5.0"
|
||||
"angular-underscore": "~0.5.0",
|
||||
"angular-locker": "~1.0.2"
|
||||
},
|
||||
"overrides": {
|
||||
"fancybox": {
|
||||
|
|
|
@ -32,6 +32,7 @@ module.exports = function(config) {
|
|||
'bower_components/jquery.scrollTo/jquery.scrollTo.js',
|
||||
'bower_components/underscore/underscore.js',
|
||||
'bower_components/angular-underscore/angular-underscore.js',
|
||||
'bower_components/angular-locker/dist/angular-locker.min.js',
|
||||
'bower_components/angular-mocks/angular-mocks.js',
|
||||
'bower_components/jasmine-promise-matchers/dist/jasmine-promise-matchers.js',
|
||||
'bower_components/jasmine-fixture/dist/jasmine-fixture.js',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "Jamstash",
|
||||
"description": "HTML5 Player for Subsonic & Archive.org",
|
||||
"version": "4.2.3",
|
||||
"version": "4.3.1",
|
||||
"app": {
|
||||
"launch": {
|
||||
"web_url": "http://jamstash.com"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jamstash",
|
||||
"version": "4.3",
|
||||
"version": "4.3.1",
|
||||
"description": "HTML5 Audio Streamer for Subsonic, Archive.org browsing and streaming",
|
||||
"author": "Trevor Squillario (https://github.com/tsquillario)",
|
||||
"contributors": [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue