4.4.4 Prevents global shortcuts on inputs
- Adds a control on the origin of keyboard shortcuts This prevents pausing the song when typing "space" in the search input. - Moves volume management to player-service. Adds getters and setters. The setter also checks the volume so it stays between 0 and 1.
This commit is contained in:
parent
91a5c6d3c3
commit
faf004b5b0
10 changed files with 170 additions and 75 deletions
|
@ -309,38 +309,52 @@ angular.module('JamStash')
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the target of this event is an input
|
||||
* @param {jQuery event} event
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function isTargetInput (event) {
|
||||
return (event && event.target.tagName === "INPUT");
|
||||
}
|
||||
|
||||
/* We define player-related methods here instead of in player controller
|
||||
in order to bind keypresses to <body> and have global shortcuts */
|
||||
$scope.togglePause = function () {
|
||||
in order to bind keypresses to <body> and have global shortcuts.
|
||||
We also check the event so we don't do anything if it's on an input */
|
||||
$scope.togglePause = function (event) {
|
||||
if(!isTargetInput(event)) {
|
||||
if(globals.settings.Jukebox) {
|
||||
$scope.sendToJukebox('stop');
|
||||
} else {
|
||||
player.togglePause();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.turnVolumeUp = function () {
|
||||
var volume = player.volume;
|
||||
if ((volume+0.1) > 1 || volume < 0) {
|
||||
volume = 0.9;
|
||||
}
|
||||
volume += 0.1;
|
||||
player.volume = volume;
|
||||
persistence.saveVolume(volume);
|
||||
};
|
||||
|
||||
$scope.turnVolumeDown = function () {
|
||||
var volume = player.volume;
|
||||
if (volume > 1 || (volume-0.1) < 0) {
|
||||
volume = 0.1;
|
||||
$scope.turnVolumeUp = function (event) {
|
||||
if(!isTargetInput(event)) {
|
||||
var volume = player.turnVolumeUp();
|
||||
persistence.saveVolume(volume);
|
||||
}
|
||||
volume -= 0.1;
|
||||
player.volume = volume;
|
||||
persistence.saveVolume(volume);
|
||||
};
|
||||
|
||||
$scope.nextTrack = player.nextTrack;
|
||||
$scope.previousTrack = player.previousTrack;
|
||||
$scope.turnVolumeDown = function (event) {
|
||||
if(!isTargetInput(event)) {
|
||||
var volume = player.turnVolumeDown();
|
||||
persistence.saveVolume(volume);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.nextTrack = function (event) {
|
||||
if(!isTargetInput(event)) {
|
||||
player.nextTrack();
|
||||
}
|
||||
};
|
||||
$scope.previousTrack = function (event) {
|
||||
if(!isTargetInput(event)) {
|
||||
player.previousTrack();
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.addToJukebox = function (id) {
|
||||
if (globals.settings.Debug) { console.log("LOAD JUKEBOX"); }
|
||||
|
@ -410,7 +424,7 @@ angular.module('JamStash')
|
|||
persistence.loadQueue();
|
||||
persistence.loadTrackPosition();
|
||||
}
|
||||
player.volume = persistence.getVolume();
|
||||
player.setVolume(persistence.getVolume());
|
||||
}
|
||||
/* End Startup */
|
||||
}]);
|
||||
|
|
|
@ -17,9 +17,8 @@ describe("Main controller", function() {
|
|||
});
|
||||
|
||||
// Mock the player service
|
||||
player = jasmine.createSpyObj("player", ["togglePause"]);
|
||||
player = jasmine.createSpyObj("player", ["togglePause", "turnVolumeUp", "turnVolumeDown", "nextTrack", "previousTrack", "setVolume"]);
|
||||
player.queue = [];
|
||||
player.volume = 1.0;
|
||||
|
||||
// Mock the persistence service
|
||||
persistence = jasmine.createSpyObj("persistence", ["loadQueue", "loadTrackPosition", "getVolume", "saveVolume"]);
|
||||
|
@ -108,41 +107,63 @@ describe("Main controller", function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe("When I turn the volume up,", function() {
|
||||
it("it sets the player's volume up by 10% and saves it using the persistence service", function() {
|
||||
player.volume = 0.5;
|
||||
|
||||
it("When I turn the volume up, it sets the player's volume up and saves it using the persistence service", function() {
|
||||
player.turnVolumeUp.and.returnValue(0.6);
|
||||
scope.turnVolumeUp();
|
||||
|
||||
expect(player.volume).toBe(0.6);
|
||||
expect(player.turnVolumeUp).toHaveBeenCalled();
|
||||
expect(persistence.saveVolume).toHaveBeenCalledWith(0.6);
|
||||
});
|
||||
|
||||
it("if the player's resulting volume won't be between 0 and 1, it sets it to 1", function() {
|
||||
player.volume = 5.91488;
|
||||
|
||||
scope.turnVolumeUp();
|
||||
|
||||
expect(player.volume).toBe(1.0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("When I turn the volume down,", function() {
|
||||
it("it sets the player's volume down by 10% and saves it using the persistence service", function() {
|
||||
player.volume = 0.5;
|
||||
|
||||
it("When I turn the volume down, it sets the player's volume down and saves it using the persistence service", function() {
|
||||
player.turnVolumeDown.and.returnValue(0.4);
|
||||
scope.turnVolumeDown();
|
||||
|
||||
expect(player.volume).toBe(0.4);
|
||||
expect(player.turnVolumeDown).toHaveBeenCalled();
|
||||
expect(persistence.saveVolume).toHaveBeenCalledWith(0.4);
|
||||
});
|
||||
|
||||
it("if the player's resulting volume won't be between 0 and 1, it sets it to 0", function() {
|
||||
player.volume = 5.91488;
|
||||
it("When I go to the next track, it calls next track on the player", function() {
|
||||
scope.nextTrack();
|
||||
expect(player.nextTrack).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
scope.turnVolumeDown();
|
||||
it("When I go to the previous track, it calls previous track on the player", function() {
|
||||
scope.previousTrack();
|
||||
expect(player.previousTrack).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
expect(player.volume).toBe(0);
|
||||
describe("Given that I am targeting an input,", function() {
|
||||
var event;
|
||||
beforeEach(function() {
|
||||
event = { target: { tagName: "INPUT" } };
|
||||
});
|
||||
|
||||
it("when I use a shortcut to toggle pause, it doesn't do anything", function() {
|
||||
scope.togglePause(event);
|
||||
expect(player.togglePause).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when I use a shortcut to turn the volume up, it doesn't do anything", function() {
|
||||
scope.turnVolumeUp(event);
|
||||
expect(player.turnVolumeUp).not.toHaveBeenCalled();
|
||||
expect(persistence.saveVolume).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when I use a shortcut to turn the volume down, it doesn't do anything", function() {
|
||||
scope.turnVolumeDown(event);
|
||||
expect(player.turnVolumeDown).not.toHaveBeenCalled();
|
||||
expect(persistence.saveVolume).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when I use a shortcut to go to the next track, it doesn't do anything", function() {
|
||||
scope.nextTrack(event);
|
||||
expect(player.nextTrack).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("when I use a shortcut to go to the previous track, it doesn't do anything", function() {
|
||||
scope.previousTrack(event);
|
||||
expect(player.previousTrack).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -154,7 +175,7 @@ describe("Main controller", function() {
|
|||
$controller('AppController', controllerParams);
|
||||
|
||||
expect(persistence.getVolume).toHaveBeenCalled();
|
||||
expect(player.volume).toBe(0.551835);
|
||||
expect(player.setVolume).toHaveBeenCalledWith(0.551835);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<link href="styles/Mobile.css" rel="stylesheet" type="text/css" data-name="main" />
|
||||
<link href="" rel="stylesheet" type="text/css" data-name="theme" />
|
||||
</head>
|
||||
<body ui-keypress="{'32 179': 'togglePause()', '43 61 187': 'turnVolumeUp()', '45 95 189': 'turnVolumeDown()'}" ui-keydown="{'right 176': 'nextTrack()', 'left 177': 'previousTrack()'}">
|
||||
<body ui-keypress="{'32 179': 'togglePause($event)', '43 61 187': 'turnVolumeUp($event)', '45 95 189': 'turnVolumeDown($event)'}" ui-keydown="{'right 176': 'nextTrack($event)', 'left 177': 'previousTrack($event)'}">
|
||||
<div id="container">
|
||||
<div id="header">
|
||||
<div id="messages">
|
||||
|
|
|
@ -160,7 +160,7 @@ angular.module('jamstash.player.directive', ['jamstash.player.service', 'jamstas
|
|||
});
|
||||
|
||||
scope.$watch(function () {
|
||||
return playerService.volume;
|
||||
return playerService.getVolume();
|
||||
}, function (newVal) {
|
||||
$player.jPlayer('volume', newVal);
|
||||
if (globals.settings.Debug) { console.log('Volume: ' + Math.round(newVal * 100) + '%'); }
|
||||
|
|
|
@ -22,10 +22,10 @@ describe("jplayer directive", function() {
|
|||
$delegate.pauseSong = false;
|
||||
$delegate.restartSong = false;
|
||||
$delegate.loadSong = false;
|
||||
$delegate.volume = 1.0;
|
||||
$delegate.getPlayingSong = jasmine.createSpy('getPlayingSong').and.callFake(function() {
|
||||
return playingSong;
|
||||
});
|
||||
$delegate.getVolume = jasmine.createSpy('getVolume').and.returnValue(1.0);
|
||||
$delegate.nextTrack = jasmine.createSpy('nextTrack');
|
||||
$delegate.songEnded = jasmine.createSpy('songEnded');
|
||||
$delegate.isLastSongPlaying = jasmine.createSpy('isLastSongPlaying');
|
||||
|
@ -170,7 +170,7 @@ describe("jplayer directive", function() {
|
|||
});
|
||||
|
||||
it("When the player service's volume changes, it sets jPlayer's volume", function() {
|
||||
playerService.volume = 0.2034;
|
||||
playerService.getVolume.and.returnValue(0.2034);
|
||||
scope.$apply();
|
||||
expect($player.jPlayer).toHaveBeenCalledWith('volume', 0.2034);
|
||||
});
|
||||
|
|
|
@ -8,6 +8,8 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
.factory('player', ['globals', function (globals) {
|
||||
'use strict';
|
||||
|
||||
var playerVolume = 1.0;
|
||||
|
||||
var player = {
|
||||
// playingIndex and playingSong aren't meant to be used, they only are public for unit-testing purposes
|
||||
_playingIndex: -1,
|
||||
|
@ -16,9 +18,8 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
pauseSong: false,
|
||||
restartSong: false,
|
||||
loadSong: false,
|
||||
volume: 1.0,
|
||||
|
||||
play: function(song) {
|
||||
play: function (song) {
|
||||
// Find the song's index in the queue, if it's in there
|
||||
var index = player.indexOfSong(song);
|
||||
player._playingIndex = (index !== undefined) ? index : -1;
|
||||
|
@ -31,7 +32,7 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
}
|
||||
},
|
||||
|
||||
togglePause: function() {
|
||||
togglePause: function () {
|
||||
if (player.pauseSong) {
|
||||
player.pauseSong = false;
|
||||
} else {
|
||||
|
@ -39,22 +40,22 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
}
|
||||
},
|
||||
|
||||
playFirstSong: function() {
|
||||
playFirstSong: function () {
|
||||
player._playingIndex = 0;
|
||||
player.play(player.queue[0]);
|
||||
},
|
||||
|
||||
load: function(song) {
|
||||
load: function (song) {
|
||||
player.loadSong = true;
|
||||
player.play(song);
|
||||
},
|
||||
|
||||
restart: function() {
|
||||
restart: function () {
|
||||
player.restartSong = true;
|
||||
},
|
||||
|
||||
// Called from the player directive at the end of the current song
|
||||
songEnded: function() {
|
||||
songEnded: function () {
|
||||
if (globals.settings.Repeat) {
|
||||
// repeat current track
|
||||
player.restart();
|
||||
|
@ -68,7 +69,7 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
}
|
||||
},
|
||||
|
||||
nextTrack: function() {
|
||||
nextTrack: function () {
|
||||
// Find the song's index in the queue, in case it changed (with a drag & drop)
|
||||
var index = player.indexOfSong(player._playingSong);
|
||||
player._playingIndex = (index !== undefined) ? index : -1;
|
||||
|
@ -80,7 +81,7 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
}
|
||||
},
|
||||
|
||||
previousTrack: function() {
|
||||
previousTrack: function () {
|
||||
// Find the song's index in the queue, in case it changed (with a drag & drop)
|
||||
var index = player.indexOfSong(player._playingSong);
|
||||
player._playingIndex = (index !== undefined) ? index : -1;
|
||||
|
@ -94,17 +95,17 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
}
|
||||
},
|
||||
|
||||
emptyQueue: function() {
|
||||
emptyQueue: function () {
|
||||
player.queue = [];
|
||||
return player;
|
||||
},
|
||||
|
||||
shuffleQueue: function() {
|
||||
shuffleQueue: function () {
|
||||
player.queue = _(player.queue).shuffle();
|
||||
return player;
|
||||
},
|
||||
|
||||
addSong: function(song) {
|
||||
addSong: function (song) {
|
||||
player.queue.push(song);
|
||||
return player;
|
||||
},
|
||||
|
@ -114,7 +115,7 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
return player;
|
||||
},
|
||||
|
||||
removeSong: function(song) {
|
||||
removeSong: function (song) {
|
||||
var index = player.queue.indexOf(song);
|
||||
player.queue.splice(index, 1);
|
||||
return player;
|
||||
|
@ -125,21 +126,52 @@ angular.module('jamstash.player.service', ['angular-underscore/utils', 'jamstash
|
|||
return player;
|
||||
},
|
||||
|
||||
getPlayingSong: function() {
|
||||
getPlayingSong: function () {
|
||||
return player._playingSong;
|
||||
},
|
||||
|
||||
isLastSongPlaying: function() {
|
||||
isLastSongPlaying: function () {
|
||||
return ((player._playingIndex +1) === player.queue.length);
|
||||
},
|
||||
|
||||
indexOfSong: function(song) {
|
||||
indexOfSong: function (song) {
|
||||
for (var i = player.queue.length - 1; i >= 0; i--) {
|
||||
if (angular.equals(song, player.queue[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
turnVolumeUp: function () {
|
||||
var volume = playerVolume;
|
||||
if ((volume + 0.1) > 1 || volume < 0) {
|
||||
volume = 0.9;
|
||||
}
|
||||
volume += 0.1;
|
||||
playerVolume = Math.round(volume * 100) / 100;
|
||||
return volume;
|
||||
},
|
||||
|
||||
turnVolumeDown: function () {
|
||||
var volume = playerVolume;
|
||||
if (volume > 1 || (volume - 0.1) < 0) {
|
||||
volume = 0.1;
|
||||
}
|
||||
volume -= 0.1;
|
||||
playerVolume = Math.round(volume * 100) / 100;
|
||||
return volume;
|
||||
},
|
||||
|
||||
getVolume: function () {
|
||||
return playerVolume;
|
||||
},
|
||||
|
||||
setVolume: function (volume) {
|
||||
if (volume > 1) { volume = 1; }
|
||||
else if(volume < 0) { volume = 0; }
|
||||
playerVolume = Math.round(volume * 100) / 100;
|
||||
return player;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -277,4 +277,32 @@ describe("Player service -", function() {
|
|||
expect(player._playingIndex).toBe(-1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("When I turn the volume up,", function() {
|
||||
it("it sets the player's volume up by 10%", function() {
|
||||
player.setVolume(0.5);
|
||||
player.turnVolumeUp();
|
||||
expect(player.getVolume()).toBe(0.6);
|
||||
});
|
||||
|
||||
it("if the player's resulting volume won't be between 0 and 1, it sets it to 1", function() {
|
||||
player.setVolume(5.91488);
|
||||
player.turnVolumeUp();
|
||||
expect(player.getVolume()).toBe(1.0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("When I turn the volume down,", function() {
|
||||
it("it sets the player's volume down by 10%", function() {
|
||||
player.setVolume(0.5);
|
||||
player.turnVolumeDown();
|
||||
expect(player.getVolume()).toBe(0.4);
|
||||
});
|
||||
|
||||
it("if the player's resulting volume won't be between 0 and 1, it sets it to 0", function() {
|
||||
player.setVolume(0.05);
|
||||
player.turnVolumeDown();
|
||||
expect(player.getVolume()).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jamstash",
|
||||
"version": "4.4.3",
|
||||
"version": "4.4.4",
|
||||
"description": "HTML5 Audio Streamer for Subsonic, Archive.org browsing and streaming",
|
||||
"authors": [
|
||||
"tsquillario (https://github.com/tsquillario)",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "Jamstash",
|
||||
"description": "HTML5 Player for Subsonic & Archive.org",
|
||||
"version": "4.4.3",
|
||||
"version": "4.4.4",
|
||||
"app": {
|
||||
"launch": {
|
||||
"web_url": "http://jamstash.com"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jamstash",
|
||||
"version": "4.4.3",
|
||||
"version": "4.4.4",
|
||||
"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