mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
update video osd
This commit is contained in:
parent
e9b1b4ad5f
commit
0444d44461
6 changed files with 128 additions and 222 deletions
|
@ -14,12 +14,12 @@
|
|||
},
|
||||
"devDependencies": {},
|
||||
"ignore": [],
|
||||
"version": "1.4.461",
|
||||
"_release": "1.4.461",
|
||||
"version": "1.4.462",
|
||||
"_release": "1.4.462",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.4.461",
|
||||
"commit": "4f817f597ac06d80fe41e3d7d096f4fd5d9b7be2"
|
||||
"tag": "1.4.462",
|
||||
"commit": "1beaad6a5a112a404e518ad16acfbdc6ca0c57cb"
|
||||
},
|
||||
"_source": "https://github.com/MediaBrowser/emby-webcomponents.git",
|
||||
"_target": "^1.2.1",
|
||||
|
|
|
@ -294,9 +294,10 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusMana
|
|||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
|
||||
var item = items[i];
|
||||
var serverId = item.ServerId || options.serverId;
|
||||
|
||||
if (item.ServerId !== lastServerId) {
|
||||
lastServerId = item.ServerId;
|
||||
if (serverId !== lastServerId) {
|
||||
lastServerId = serverId;
|
||||
apiClient = connectionManager.getApiClient(lastServerId);
|
||||
}
|
||||
|
||||
|
@ -440,7 +441,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusMana
|
|||
}
|
||||
|
||||
var cardClass = className;
|
||||
currentItemHtml += buildCard(i, renderItem, connectionManager.getApiClient(renderItem.ServerId), options, cardClass);
|
||||
currentItemHtml += buildCard(i, renderItem, connectionManager.getApiClient(renderItem.ServerId || options.serverId), options, cardClass);
|
||||
|
||||
itemsInRow++;
|
||||
|
||||
|
|
|
@ -220,9 +220,9 @@ _:-ms-input-placeholder, :root .mdl-slider {
|
|||
|
||||
.sliderBubble {
|
||||
position: absolute;
|
||||
top: -3.7em;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: .5em 1em;
|
||||
transform: translate3d(-48%, -115%, 0);
|
||||
background: #282828;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
|
@ -232,4 +232,5 @@ _:-ms-input-placeholder, :root .mdl-slider {
|
|||
|
||||
.sliderBubbleText {
|
||||
margin: 0;
|
||||
padding: .5em .75em;
|
||||
}
|
||||
|
|
|
@ -38,15 +38,20 @@
|
|||
|
||||
function updateBubble(range, value, bubble, bubbleText) {
|
||||
|
||||
bubble.style.left = (value - 1) + '%';
|
||||
bubble.style.left = value + '%';
|
||||
|
||||
if (range.getBubbleHtml) {
|
||||
value = range.getBubbleHtml(value);
|
||||
} else {
|
||||
if (range.getBubbleText) {
|
||||
value = range.getBubbleText(value);
|
||||
} else {
|
||||
value = Math.round(value);
|
||||
}
|
||||
value = '<h1 class="sliderBubbleText">' + value + '</h1>';
|
||||
}
|
||||
|
||||
bubbleText.innerHTML = value;
|
||||
bubble.innerHTML = value;
|
||||
}
|
||||
|
||||
EmbySliderPrototype.attachedCallback = function () {
|
||||
|
@ -73,21 +78,20 @@
|
|||
htmlToInsert += '<div class="mdl-slider__background-flex"><div class="mdl-slider__background-lower"></div><div class="mdl-slider__background-upper"></div></div>';
|
||||
}
|
||||
|
||||
htmlToInsert += '<div class="sliderBubble hide"><h1 class="sliderBubbleText"></h1></div>';
|
||||
htmlToInsert += '<div class="sliderBubble hide"></div>';
|
||||
|
||||
containerElement.insertAdjacentHTML('beforeend', htmlToInsert);
|
||||
|
||||
var backgroundLower = containerElement.querySelector('.mdl-slider__background-lower');
|
||||
var backgroundUpper = containerElement.querySelector('.mdl-slider__background-upper');
|
||||
var sliderBubble = containerElement.querySelector('.sliderBubble');
|
||||
var sliderBubbleText = containerElement.querySelector('.sliderBubbleText');
|
||||
|
||||
var hasHideClass = sliderBubble.classList.contains('hide');
|
||||
|
||||
dom.addEventListener(this, 'input', function (e) {
|
||||
this.dragging = true;
|
||||
|
||||
updateBubble(this, this.value, sliderBubble, sliderBubbleText);
|
||||
updateBubble(this, this.value, sliderBubble);
|
||||
|
||||
if (hasHideClass) {
|
||||
sliderBubble.classList.remove('hide');
|
||||
|
@ -117,7 +121,7 @@
|
|||
var clientX = e.clientX;
|
||||
var bubbleValue = (clientX - rect.left) / rect.width;
|
||||
bubbleValue *= 100;
|
||||
updateBubble(this, bubbleValue, sliderBubble, sliderBubbleText);
|
||||
updateBubble(this, bubbleValue, sliderBubble);
|
||||
|
||||
if (hasHideClass) {
|
||||
sliderBubble.classList.remove('hide');
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
var currentRuntimeTicks = 0;
|
||||
var lastUpdateTime = 0;
|
||||
var isEnabled;
|
||||
var currentItem;
|
||||
|
||||
var nowPlayingVolumeSlider = view.querySelector('.osdVolumeSlider');
|
||||
var nowPlayingVolumeSliderContainer = view.querySelector('.osdVolumeSliderContainer');
|
||||
|
@ -98,8 +99,6 @@
|
|||
var nowPlayingDurationText = view.querySelector('.osdDurationText');
|
||||
var endsAtText = view.querySelector('.endsAtText');
|
||||
|
||||
var scenePicker = view.querySelector('.scenePicker');
|
||||
var isScenePickerRendered;
|
||||
var btnRewind = view.querySelector('.btnRewind');
|
||||
var btnFastForward = view.querySelector('.btnFastForward');
|
||||
|
||||
|
@ -115,10 +114,8 @@
|
|||
|
||||
function updateNowPlayingInfo(state) {
|
||||
|
||||
scenePicker.innerHTML = '';
|
||||
isScenePickerRendered = false;
|
||||
|
||||
var item = state.NowPlayingItem;
|
||||
currentItem = item;
|
||||
|
||||
setPoster(item);
|
||||
|
||||
|
@ -380,10 +377,10 @@
|
|||
|
||||
function updateFullscreenIcon() {
|
||||
if (playbackManager.isFullscreen(currentPlayer)) {
|
||||
view.querySelector('.btnFullscreen').setAttribute('title', globalize.translate('core#ExitFullscreen'));
|
||||
view.querySelector('.btnFullscreen').setAttribute('title', globalize.translate('ExitFullscreen'));
|
||||
view.querySelector('.btnFullscreen i').innerHTML = '';
|
||||
} else {
|
||||
view.querySelector('.btnFullscreen').setAttribute('title', globalize.translate('core#Fullscreen'));
|
||||
view.querySelector('.btnFullscreen').setAttribute('title', globalize.translate('Fullscreen'));
|
||||
view.querySelector('.btnFullscreen i').innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
@ -712,10 +709,10 @@
|
|||
}
|
||||
|
||||
if (isMuted) {
|
||||
view.querySelector('.buttonMute').setAttribute('title', globalize.translate('core#Unmute'));
|
||||
view.querySelector('.buttonMute').setAttribute('title', globalize.translate('Unmute'));
|
||||
view.querySelector('.buttonMute i').innerHTML = '';
|
||||
} else {
|
||||
view.querySelector('.buttonMute').setAttribute('title', globalize.translate('core#Mute'));
|
||||
view.querySelector('.buttonMute').setAttribute('title', globalize.translate('Mute'));
|
||||
view.querySelector('.buttonMute i').innerHTML = '';
|
||||
}
|
||||
|
||||
|
@ -955,7 +952,6 @@
|
|||
|
||||
nowPlayingPositionSlider.addEventListener('change', function () {
|
||||
|
||||
stopScenePickerTimer();
|
||||
if (currentPlayer) {
|
||||
|
||||
var newPercent = parseFloat(this.value);
|
||||
|
@ -964,7 +960,65 @@
|
|||
}
|
||||
});
|
||||
|
||||
nowPlayingPositionSlider.getBubbleText = function (value) {
|
||||
function getImgUrl(item, chapter, index, maxWidth, apiClient) {
|
||||
|
||||
if (chapter.ImageTag) {
|
||||
|
||||
return apiClient.getScaledImageUrl(item.Id, {
|
||||
maxWidth: maxWidth,
|
||||
tag: chapter.ImageTag,
|
||||
type: "Chapter",
|
||||
index: index
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getChapterBubbleHtml(apiClient, item, chapters, positionTicks) {
|
||||
|
||||
var chapter;
|
||||
var index = -1;
|
||||
|
||||
for (var i = 0, length = chapters.length; i < length; i++) {
|
||||
|
||||
var currentChapter = chapters[i];
|
||||
|
||||
if (positionTicks >= currentChapter.StartPositionTicks) {
|
||||
chapter = currentChapter;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chapter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var src = getImgUrl(item, chapter, index, 400, apiClient);
|
||||
|
||||
if (src) {
|
||||
|
||||
var html = '<div class="chapterThumbContainer">';
|
||||
html += '<img class="chapterThumb" src="' + src + '" />';
|
||||
|
||||
html += '<div class="chapterThumbTextContainer">';
|
||||
html += '<div class="chapterThumbText chapterThumbText-dim">';
|
||||
html += chapter.Name;
|
||||
html += '</div>';
|
||||
html += '<h1 class="chapterThumbText">';
|
||||
html += datetime.getDisplayRunningTime(positionTicks);
|
||||
html += '</h1>';
|
||||
html += '</div>';
|
||||
|
||||
html += '</div>';
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
nowPlayingPositionSlider.getBubbleHtml = function (value) {
|
||||
|
||||
if (!currentRuntimeTicks) {
|
||||
return '--:--';
|
||||
|
@ -974,7 +1028,16 @@
|
|||
ticks /= 100;
|
||||
ticks *= value;
|
||||
|
||||
return datetime.getDisplayRunningTime(ticks);
|
||||
var item = currentItem;
|
||||
if (item && item.Chapters && item.Chapters[0].ImageTag) {
|
||||
var html = getChapterBubbleHtml(connectionManager.getApiClient(item.ServerId), item, item.Chapters, ticks);
|
||||
|
||||
if (html) {
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
return '<h1 class="sliderBubbleText">' + datetime.getDisplayRunningTime(ticks) + '</h1>';
|
||||
};
|
||||
|
||||
view.querySelector('.btnPreviousTrack').addEventListener('click', function () {
|
||||
|
@ -1005,112 +1068,6 @@
|
|||
view.querySelector('.btnAudio').addEventListener('click', showAudioTrackSelection);
|
||||
view.querySelector('.btnSubtitles').addEventListener('click', showSubtitleTrackSelection);
|
||||
|
||||
function getChapterHtml(item, chapter, index, maxWidth, apiClient) {
|
||||
|
||||
var html = '';
|
||||
|
||||
var src = getImgUrl(item, chapter, index, maxWidth, apiClient);
|
||||
|
||||
if (src) {
|
||||
|
||||
var pct = currentRuntimeTicks ? (chapter.StartPositionTicks / currentRuntimeTicks) : 0;
|
||||
pct *= 100;
|
||||
chapterPcts[index] = pct;
|
||||
|
||||
html += '<img data-index="' + index + '" class="chapterThumb" src="' + src + '" />';
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function getImgUrl(item, chapter, index, maxWidth, apiClient) {
|
||||
|
||||
if (chapter.ImageTag) {
|
||||
|
||||
return apiClient.getScaledImageUrl(item.Id, {
|
||||
maxWidth: maxWidth,
|
||||
tag: chapter.ImageTag,
|
||||
type: "Chapter",
|
||||
index: index
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function renderScenePicker(progressPct) {
|
||||
|
||||
chapterPcts = [];
|
||||
var item = playbackManager.currentItem(currentPlayer);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
var chapters = item.Chapters || [];
|
||||
|
||||
var currentIndex = -1;
|
||||
|
||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
|
||||
scenePicker.innerHTML = chapters.map(function (chapter) {
|
||||
currentIndex++;
|
||||
return getChapterHtml(item, chapter, currentIndex, 400, apiClient);
|
||||
}).join('');
|
||||
|
||||
imageLoader.lazyChildren(scenePicker);
|
||||
fadeIn(scenePicker, progressPct);
|
||||
}
|
||||
|
||||
var hideScenePickerTimeout;
|
||||
var chapterPcts = [];
|
||||
|
||||
function showScenePicker() {
|
||||
|
||||
var progressPct = nowPlayingPositionSlider.value;
|
||||
|
||||
if (!isScenePickerRendered) {
|
||||
isScenePickerRendered = true;
|
||||
renderScenePicker();
|
||||
} else {
|
||||
fadeIn(scenePicker, progressPct);
|
||||
}
|
||||
|
||||
if (hideScenePickerTimeout) {
|
||||
clearTimeout(hideScenePickerTimeout);
|
||||
}
|
||||
hideScenePickerTimeout = setTimeout(hideScenePicker, 1600);
|
||||
}
|
||||
|
||||
function hideScenePicker() {
|
||||
fadeOut(scenePicker);
|
||||
}
|
||||
|
||||
var showScenePickerTimeout;
|
||||
|
||||
function startScenePickerTimer() {
|
||||
if (!showScenePickerTimeout) {
|
||||
showScenePickerTimeout = setTimeout(showScenePicker, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function stopScenePickerTimer() {
|
||||
if (showScenePickerTimeout) {
|
||||
clearTimeout(showScenePickerTimeout);
|
||||
showScenePickerTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
dom.addEventListener(nowPlayingPositionSlider, 'input', function () {
|
||||
|
||||
if (scenePicker.classList.contains('hide')) {
|
||||
startScenePickerTimer();
|
||||
} else {
|
||||
showScenePicker();
|
||||
}
|
||||
}, {
|
||||
passive: true
|
||||
});
|
||||
|
||||
function onViewHideStopPlayback() {
|
||||
|
||||
if (playbackManager.isPlayingVideo()) {
|
||||
|
@ -1129,67 +1086,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
function fadeIn(elem, pct) {
|
||||
|
||||
if (!elem.classList.contains('hide')) {
|
||||
selectChapterThumb(elem, pct);
|
||||
return;
|
||||
}
|
||||
|
||||
elem.classList.remove('hide');
|
||||
|
||||
var keyframes = [
|
||||
{ opacity: '0', offset: 0 },
|
||||
{ opacity: '1', offset: 1 }
|
||||
];
|
||||
var timing = { duration: 300, iterations: 1 };
|
||||
elem.animate(keyframes, timing).onfinish = function () {
|
||||
selectChapterThumb(elem, pct);
|
||||
};
|
||||
}
|
||||
|
||||
function selectChapterThumb(elem, pct) {
|
||||
var index = -1;
|
||||
for (var i = 0, length = chapterPcts.length; i < length; i++) {
|
||||
|
||||
if (pct >= chapterPcts[i]) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (index === -1) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
var selected = elem.querySelector('.selectedChapterThumb');
|
||||
var newSelected = elem.querySelector('.chapterThumb[data-index="' + index + '"]');
|
||||
|
||||
if (selected !== newSelected) {
|
||||
if (selected) {
|
||||
selected.classList.remove('selectedChapterThumb');
|
||||
}
|
||||
|
||||
newSelected.classList.add('selectedChapterThumb');
|
||||
scrollHelper.toCenter(elem, newSelected, true);
|
||||
}
|
||||
}
|
||||
|
||||
function fadeOut(elem) {
|
||||
|
||||
if (elem.classList.contains('hide')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var keyframes = [
|
||||
{ opacity: '1', offset: 0 },
|
||||
{ opacity: '0', offset: 1 }
|
||||
];
|
||||
var timing = { duration: 300, iterations: 1 };
|
||||
elem.animate(keyframes, timing).onfinish = function () {
|
||||
elem.classList.add('hide');
|
||||
};
|
||||
}
|
||||
|
||||
function enableStopOnBack(enabled) {
|
||||
|
||||
view.removeEventListener('viewbeforehide', onViewHideStopPlayback);
|
||||
|
|
|
@ -27,33 +27,39 @@
|
|||
opacity: 0;
|
||||
}
|
||||
|
||||
.scenePicker {
|
||||
position: fixed;
|
||||
left: 12%;
|
||||
bottom: 20%;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.chapterThumb {
|
||||
height: 24vh;
|
||||
background-position: center center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
.chapterThumbContainer {
|
||||
-moz-box-shadow: 0 0 1.9vh #000;
|
||||
-webkit-box-shadow: 0 0 1.9vh #000;
|
||||
box-shadow: 0 0 1.9vh #000;
|
||||
border: solid 1px #222;
|
||||
margin: 1vh;
|
||||
transition: opacity ease-out .3s;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chapterThumb:not(.selectedChapterThumb) {
|
||||
height: 22vh;
|
||||
opacity: .2;
|
||||
border-color: black;
|
||||
.chapterThumb {
|
||||
background-position: center center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
border: 0;
|
||||
height: 20vh;
|
||||
}
|
||||
|
||||
.chapterThumbTextContainer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
padding: .25em .5em;
|
||||
}
|
||||
|
||||
.chapterThumbText {
|
||||
padding: .25em 0;
|
||||
margin: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chapterThumbText-dim {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.videoOsdBottom {
|
||||
|
@ -181,8 +187,6 @@
|
|||
</style>
|
||||
<div class="pageContainer flex">
|
||||
|
||||
</div>
|
||||
<div class="scenePicker hide hiddenScrollX">
|
||||
</div>
|
||||
<div class="videoOsdBottom">
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue