1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

re-enable mobile media controller

This commit is contained in:
Luke Pulverenti 2014-04-30 11:07:02 -04:00
parent 8a5cd4b491
commit 57d8c433c5
10 changed files with 246 additions and 38 deletions

View file

@ -131,3 +131,18 @@
.ui-nosvg .ui-icon-expand:after { .ui-nosvg .ui-icon-expand:after {
background-image: url("images/icons/expand.png"); background-image: url("images/icons/expand.png");
} }
.ui-icon-play-circle-o:after {
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M330.357%20250q0%2010.324-8.929%2015.346l-151.786%2089.286q-4.185%202.511-8.929%202.511-4.464%200-8.929-2.232-8.929-5.301-8.929-15.625v-178.571q0-10.324%208.929-15.625%209.208-5.022%2017.857%200.279l151.786%2089.286q8.929%205.022%208.929%2015.346zM366.071%20250q0-41.294-20.368-76.172t-55.246-55.246-76.172-20.368-76.172%2020.368-55.246%2055.246-20.368%2076.172%2020.368%2076.172%2055.246%2055.246%2076.172%2020.368%2076.172-20.368%2055.246-55.246%2020.368-76.172zM428.571%20250q0%2058.315-28.739%20107.562t-77.985%2077.985-107.562%2028.739-107.562-28.739-77.985-77.985-28.739-107.562%2028.739-107.562%2077.985-77.985%20107.562-28.739%20107.562%2028.739%2077.985%2077.985%2028.739%20107.562z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
background-repeat: no-repeat;
}
/* Fallback */
.ui-icon-tablet:after {
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M178.571%20392.857q0-7.254-5.301-12.556t-12.556-5.301-12.556%205.301-5.301%2012.556%205.301%2012.556%2012.556%205.301%2012.556-5.301%205.301-12.556zM285.714%20348.214v-267.857q0-3.627-2.651-6.278t-6.278-2.651h-232.143q-3.627%200-6.278%202.651t-2.651%206.278v267.857q0%203.627%202.651%206.278t6.278%202.651h232.143q3.627%200%206.278-2.651t2.651-6.278zM321.429%2080.357v303.571q0%2018.415-13.114%2031.529t-31.529%2013.114h-232.143q-18.415%200-31.529-13.114t-13.114-31.529v-303.571q0-18.415%2013.114-31.529t31.529-13.114h232.143q18.415%200%2031.529%2013.114t13.114%2031.529z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
background-repeat: no-repeat;
background-position: 6px 3px;
}
/* Fallback */

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View file

@ -1217,6 +1217,68 @@ a.itemTag:hover {
} }
} }
.nowPlayingPage .btnCommand { .nowPlayingPage .btnCommand, .nowPlayingPage .btnPlayStateCommand {
font-size: 30px;
}
.nowPlayingPageImage img {
height: 300px;
}
.nowPlayingPage .positionSliderContainer {
width: 350px;
}
.nowPlayingNavButtonContainer {
width: 400px;
}
@media all and (max-width: 600px) {
.nowPlayingPage .btnCommand, .nowPlayingPage .btnPlayStateCommand {
font-size: 26px;
}
.nowPlayingPageImage img {
height: 200px;
}
.nowPlayingPage .positionSliderContainer {
width: 300px;
}
}
@media all and (max-width: 500px) {
.nowPlayingPage .btnCommand, .nowPlayingPage .btnPlayStateCommand {
font-size: 22px;
}
.nowPlayingPageImage img {
height: 200px;
}
.nowPlayingPage .positionSliderContainer {
width: 300px;
}
}
@media all and (max-width: 400px) {
.nowPlayingPage .btnCommand, .nowPlayingPage .btnPlayStateCommand {
font-size: 19px; font-size: 19px;
} }
.nowPlayingPageImage img {
height: 200px;
}
.nowPlayingPage .positionSliderContainer {
width: 220px;
}
.nowPlayingNavButtonContainer {
width: 300px;
}
}

View file

@ -102,14 +102,12 @@
max-height: 100%; max-height: 100%;
} }
#mediaPlayer .ui-slider-track, .nowPlayingBar .ui-slider-track { #mediaPlayer .ui-slider-track, .nowPlayingBar .ui-slider-track, .nowPlayingPage .ui-slider-track {
border-color: #2ad !important; border-color: #2ad !important;
height: 2px!important; height: 2px!important;
} }
#mediaPlayer .ui-slider-handle, .nowPlayingBar .ui-slider-handle { #mediaPlayer .ui-slider-handle, .nowPlayingBar .ui-slider-handle, .nowPlayingPage .ui-slider-handle {
height: 10px !important;
margin-top: -6px !important;
} }
#videoPlayer.fullscreenVideo #videoControls { #videoPlayer.fullscreenVideo #videoControls {

View file

@ -6,36 +6,52 @@
<body> <body>
<div id="nowPlayingPage" data-role="page" class="page libraryPage nowPlayingPage" data-theme="b"> <div id="nowPlayingPage" data-role="page" class="page libraryPage nowPlayingPage" data-theme="b">
<div data-role="content"> <div data-role="content" style="padding: 1em 0;">
<div data-role="controlgroup" data-type="horizontal" data-mini="true" style="text-align: center;"> <div data-role="controlgroup" data-type="horizontal" data-mini="true" style="text-align: center;">
<input type="radio" name="radioNowPlayingTab" class="radioTabButton" id="radioNowPlaying" value="tabNowPlaying"> <input type="radio" name="radioNowPlayingTab" class="radioTabButton" id="radioNowPlaying" value="tabNowPlaying">
<label for="radioNowPlaying">${TabNowPlaying}</label> <label for="radioNowPlaying">${TabNowPlaying}</label>
<input type="radio" name="radioNowPlayingTab" class="radioTabButton" id="radioNavigation" value="tabNavigation"> <input type="radio" name="radioNowPlayingTab" class="radioTabButton" id="radioNavigation" value="tabNavigation">
<label for="radioNavigation">${TabNavigation}</label> <label for="radioNavigation">${TabControls}</label>
</div> </div>
<br /> <br />
<div style="text-align: center;"> <div style="text-align: center;">
<div class="tabNowPlaying tabContent"> <div class="tabNowPlaying tabContent">
<div class="itemName" style="line-height: normal;"></div>
<div class="nowPlayingPageImage" style="margin: 1em 0;"></div>
<div>
<div class="positionTime" style="display: inline-block; vertical-align: top; padding-top: 1px;"></div>
<div class="positionSliderContainer sliderContainer" style="margin: 0 auto;">
<input type="range" style="display: none;" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" data-mini="true" data-theme="a" data-highlight="true" />
</div>
<div class="runtime" style="display: inline-block; vertical-align: top; padding-top: 1px;"></div>
</div>
<div data-role="controlgroup" data-type="horizontal"> <div data-role="controlgroup" data-type="horizontal">
<button data-icon="previous-track" data-inline="true" data-iconpos="notext" title="${ButtonPreviousTrack}" class="btnPreviousTrack btnPlayStateCommand" data-command="GoHome">${ButtonPreviousTrack}</button> <button data-icon="previous-track" data-inline="true" data-iconpos="notext" title="${ButtonPreviousTrack}" class="btnPreviousTrack btnPlayStateCommand">${ButtonPreviousTrack}</button>
<button data-icon="pause" data-inline="true" data-iconpos="notext" title="${ButtonPause}" class="btnPause btnPlayStateCommand" data-command="GoHome">${ButtonPause}</button> <button data-icon="pause" data-inline="true" data-iconpos="notext" title="${ButtonPause}" class="btnPause btnPlayStateCommand">${ButtonPause}</button>
<button data-icon="play" data-inline="true" data-iconpos="notext" title="${ButtonPlay}" class="btnPlay btnPlayStateCommand" data-command="GoHome">${ButtonPlay}</button> <button data-icon="play" data-inline="true" data-iconpos="notext" title="${ButtonPlay}" class="btnPlay btnPlayStateCommand">${ButtonPlay}</button>
<button data-icon="stop" data-inline="true" data-iconpos="notext" title="${ButtonStop}" class="btnStop btnPlayStateCommand" data-command="GoHome">${ButtonStop}</button> <button data-icon="stop" data-inline="true" data-iconpos="notext" title="${ButtonStop}" class="btnStop btnPlayStateCommand">${ButtonStop}</button>
<button data-icon="next-track" data-inline="true" data-iconpos="notext" title="${ButtonNextTrack}" class="btnNextTrack btnPlayStateCommand" data-command="GoToSearch">${ButtonNextTrack}</button> <button data-icon="next-track" data-inline="true" data-iconpos="notext" title="${ButtonNextTrack}" class="btnNextTrack btnPlayStateCommand">${ButtonNextTrack}</button>
</div> </div>
<div data-role="controlgroup" data-type="horizontal"> <div data-role="controlgroup" data-type="horizontal">
<button data-icon="audiocd" data-inline="true" data-iconpos="notext" title="${ButtonAudioTracks}" class="btnAudioTracks btnPlayStateCommand" data-command="GoToSearch">${ButtonAudioTracks}</button> <button data-icon="volume-up" data-inline="true" data-iconpos="notext" title="${ButtonVolumeUp}" class="btnCommand" data-command="VolumeUp">${ButtonVolumeUp}</button>
<button data-icon="subtitles" data-inline="true" data-iconpos="notext" title="${ButtonSubtitles}" class="btnSubtitles btnPlayStateCommand" data-command="GoToSearch">${ButtonSubtitles}</button> <button data-icon="volume-off" data-inline="true" data-iconpos="notext" title="${ButtonMute}" class="btnCommand" data-command="ToggleMute">${ButtonMute}</button>
<button data-icon="video" data-inline="true" data-iconpos="notext" title="${ButtonScenes}" class="btnChapters btnPlayStateCommand" data-command="GoToSearch">${ButtonScenes}</button> <button data-icon="expand" data-inline="true" data-iconpos="notext" title="${ButtonFullscreen}" class="btnToggleFullscreen btnPlayStateCommand" data-command="ToggleFullscreen" style="visibility:hidden;">${ButtonFullscreen}</button>
<button data-icon="expand" data-inline="true" data-iconpos="notext" title="${ButtonFullscreen}" class="btnToggleFullscreen btnPlayStateCommand" data-command="ToggleFullscreen">${ButtonFullscreen}</button> <button data-icon="expand" data-inline="true" data-iconpos="notext" title="${ButtonFullscreen}" class="btnToggleFullscreen videoButton btnPlayStateCommand" data-command="ToggleFullscreen">${ButtonFullscreen}</button>
</div>
<div data-role="controlgroup" data-type="horizontal">
<button data-icon="volume-down" data-inline="true" data-iconpos="notext" title="${ButtonVolumeDown}" class="btnCommand" data-command="VolumeDown">${ButtonVolumeDown}</button>
<button data-icon="audiocd" data-inline="true" data-iconpos="notext" title="${ButtonAudioTracks}" class="btnAudioTracks videoButton btnPlayStateCommand" data-command="GoToSearch">${ButtonAudioTracks}</button>
<button data-icon="subtitles" data-inline="true" data-iconpos="notext" title="${ButtonSubtitles}" class="btnSubtitles videoButton btnPlayStateCommand" data-command="GoToSearch">${ButtonSubtitles}</button>
<button data-icon="video" data-inline="true" data-iconpos="notext" title="${ButtonScenes}" class="btnChapters videoButton btnPlayStateCommand" data-command="GoToSearch">${ButtonScenes}</button>
</div> </div>
</div> </div>
<div class="tabNavigation tabContent"> <div class="tabNavigation tabContent" style="display: none;">
<div data-role="controlgroup" data-type="horizontal"> <div data-role="controlgroup" data-type="horizontal">
<button data-icon="arrow-u" data-inline="true" data-iconpos="notext" title="${ButtonArrowUp}" class="btnArrowUp btnCommand" data-command="MoveUp">${ButtonArrowUp}</button> <button data-icon="arrow-u" data-inline="true" data-iconpos="notext" title="${ButtonArrowUp}" class="btnArrowUp btnCommand" data-command="MoveUp">${ButtonArrowUp}</button>
@ -68,6 +84,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</body> </body>
</html> </html>

View file

@ -16,7 +16,7 @@
html += '<a class="desktopHomeLink" href="index.html"><img src="css/images/mblogoicon.png" /></a>'; html += '<a class="desktopHomeLink" href="index.html"><img src="css/images/mblogoicon.png" /></a>';
html += '<a class="viewMenuRemoteControlButton" href="nowplaying.html" data-role="button" data-icon="play" data-inline="true" data-iconpos="notext" title="Now Playing" style="display:none;">Remote Control</a>'; html += '<a class="viewMenuRemoteControlButton" href="nowplaying.html" data-role="button" data-icon="play" data-inline="true" data-iconpos="notext" title="Now Playing">Remote Control</a>';
if (user.Configuration.IsAdministrator) { if (user.Configuration.IsAdministrator) {
html += '<a class="editorMenuLink" href="edititemmetadata.html" data-role="button" data-icon="edit" data-inline="true" data-iconpos="notext" title="Metadata Manager">Metadata Manager</a>'; html += '<a class="editorMenuLink" href="edititemmetadata.html" data-role="button" data-icon="edit" data-inline="true" data-iconpos="notext" title="Metadata Manager">Metadata Manager</a>';

View file

@ -107,14 +107,17 @@
var currentSrc = element.currentSrc; var currentSrc = element.currentSrc;
var transcodingExtension = self.getTranscodingExtension();
var isStatic;
if (currentItem.MediaType == "Video") { if (currentItem.MediaType == "Video") {
if (params.AudioStreamIndex != null) { if (params.AudioStreamIndex != null) {
currentSrc = replaceQueryString(currentSrc, 'AudioStreamIndex', params.AudioStreamIndex); currentSrc = replaceQueryString(currentSrc, 'AudioStreamIndex', params.AudioStreamIndex);
} }
if (params.SubtitleStreamIndex != null) { if (params.SubtitleStreamIndex != null) {
currentSrc = replaceQueryString(currentSrc, 'SubtitleStreamIndex', (params.SubtitleStreamIndex == -1 ? '' : params.SubtitleStreamIndex)); currentSrc = replaceQueryString(currentSrc, 'SubtitleStreamIndex', (params.SubtitleStreamIndex == -1 ? '' : params.SubtitleStreamIndex));
} }
}
var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc); var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc);
var audioStreamIndex = params.AudioStreamIndex == null ? getParameterByName('AudioStreamIndex', currentSrc) : params.AudioStreamIndex; var audioStreamIndex = params.AudioStreamIndex == null ? getParameterByName('AudioStreamIndex', currentSrc) : params.AudioStreamIndex;
@ -123,11 +126,6 @@
var audioBitrate = parseInt(getParameterByName('AudioBitrate', currentSrc) || '0'); var audioBitrate = parseInt(getParameterByName('AudioBitrate', currentSrc) || '0');
var bitrate = params.Bitrate || (videoBitrate + audioBitrate); var bitrate = params.Bitrate || (videoBitrate + audioBitrate);
var transcodingExtension = self.getTranscodingExtension();
var isStatic;
if (currentItem.MediaType == "Video") {
var finalParams = self.getFinalVideoParams(currentMediaSource, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension); var finalParams = self.getFinalVideoParams(currentMediaSource, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension);
currentSrc = replaceQueryString(currentSrc, 'MaxWidth', finalParams.maxWidth); currentSrc = replaceQueryString(currentSrc, 'MaxWidth', finalParams.maxWidth);
@ -1176,7 +1174,9 @@
IsPaused: currentMediaElement.paused, IsPaused: currentMediaElement.paused,
IsMuted: currentMediaElement.volume == 0, IsMuted: currentMediaElement.volume == 0,
VolumeLevel: currentMediaElement.volume * 100, VolumeLevel: currentMediaElement.volume * 100,
PositionTicks: self.getCurrentTicks() PositionTicks: self.getCurrentTicks(),
CanSeek: currentMediaSource.RunTimeTicks && currentMediaSource.RunTimeTicks > 0
}); });
} }
@ -1186,7 +1186,7 @@
clearTimeout(currentProgressInterval); clearTimeout(currentProgressInterval);
currentProgressInterval = null; currentProgressInterval = null;
} }
}; }
function canPlayWebm() { function canPlayWebm() {

View file

@ -163,7 +163,7 @@
function updatePlayerState(state) { function updatePlayerState(state) {
if (state.NowPlayingItem) { if (state.NowPlayingItem && !$($.mobile.activePage).hasClass('nowPlayingPage')) {
showNowPlayingBar(); showNowPlayingBar();
} else { } else {
hideNowPlayingBar(); hideNowPlayingBar();
@ -231,16 +231,22 @@
var nowPlayingItem = state.NowPlayingItem || {}; var nowPlayingItem = state.NowPlayingItem || {};
if (!isPositionSliderActive) { if (!isPositionSliderActive) {
if (playState.CanSeek) { if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
var pct = playState.PositionTicks / nowPlayingItem.RunTimeTicks; var pct = playState.PositionTicks / nowPlayingItem.RunTimeTicks;
pct *= 100; pct *= 100;
positionSlider.val(pct).slider("enable"); positionSlider.val(pct);
} else { } else {
positionSlider.val(0).slider("disable"); positionSlider.val(0);
}
if (playState.CanSeek) {
positionSlider.slider("enable");
} else {
positionSlider.slider("disable");
} }
positionSlider.slider('refresh'); positionSlider.slider('refresh');

View file

@ -2,6 +2,7 @@
var currentPlayer; var currentPlayer;
var lastPlayerState; var lastPlayerState;
var isPositionSliderActive;
function bindEvents(page) { function bindEvents(page) {
@ -44,6 +45,23 @@
currentPlayer.previousTrack(); currentPlayer.previousTrack();
}); });
$('.positionSlider', page).on('slidestart', function () {
isPositionSliderActive = true;
}).on('slidestop', function () {
isPositionSliderActive = false;
if (currentPlayer && lastPlayerState) {
var newPercent = parseFloat(this.value);
var newPositionTicks = (newPercent / 100) * lastPlayerState.NowPlayingItem.RunTimeTicks;
currentPlayer.seek(Math.floor(newPositionTicks));
}
});
} }
function onPlaybackStart(e, state) { function onPlaybackStart(e, state) {
@ -62,6 +80,8 @@
player.endPlayerUpdates(); player.endPlayerUpdates();
onStateChanged.call(player, e, state); onStateChanged.call(player, e, state);
$('.itemName', page).html('');
} }
function onStateChanged(e, state) { function onStateChanged(e, state) {
@ -113,6 +133,96 @@
hideButton(btnPlay); hideButton(btnPlay);
} }
if (!isPositionSliderActive) {
var positionSlider = $('.positionSlider', page);
if (item && item.RunTimeTicks) {
var pct = playState.PositionTicks / item.RunTimeTicks;
pct *= 100;
positionSlider.val(pct);
} else {
positionSlider.val(0);
}
if (playState.CanSeek) {
positionSlider.slider("enable");
} else {
positionSlider.slider("disable");
}
positionSlider.slider('refresh');
}
if (playState.PositionTicks == null) {
$('.positionTime', page).html('--:--');
} else {
$('.positionTime', page).html(Dashboard.getDisplayTime(playState.PositionTicks));
}
if (item && item.RunTimeTicks != null) {
$('.runtime', page).html(Dashboard.getDisplayTime(item.RunTimeTicks));
} else {
$('.runtime', page).html('--:--');
}
if (item && item.MediaType == 'Video') {
$('.videoButton', page).css('visibility', 'visible');
} else {
$('.videoButton', page).css('visibility', 'hidden');
}
updateNowPlayingInfo(page, state);
}
var currentImgUrl;
function updateNowPlayingInfo(page, state) {
var item = state.NowPlayingItem;
$('.itemName', page).html(item ? MediaPlayer.getNowPlayingNameHtml(state) : '');
var url;
if (!item) {
}
else if (item.PrimaryImageTag) {
url = ApiClient.getImageUrl(item.PrimaryImageItemId, {
type: "Primary",
height: 600,
tag: item.PrimaryImageTag
});
}
else if (item.BackdropImageTag) {
url = ApiClient.getImageUrl(item.BackdropItemId, {
type: "Backdrop",
height: 600,
tag: item.BackdropImageTag,
index: 0
});
} else if (item.ThumbImageTag) {
url = ApiClient.getImageUrl(item.ThumbImageItemId, {
type: "Thumb",
height: 600,
tag: item.ThumbImageTag
});
}
if (url == currentImgUrl) {
return;
}
currentImgUrl = url;
$('.nowPlayingPageImage', page).html(url ? '<img src="' + url + '" />' : '');
} }
function updateSupportedCommands(page, commands) { function updateSupportedCommands(page, commands) {