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

Merge branch 'master' into eslint-no-sequences

This commit is contained in:
San 2022-05-20 01:40:57 -07:00 committed by GitHub
commit a2fe92f192
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
80 changed files with 2166 additions and 1116 deletions

View file

@ -237,7 +237,7 @@ import cardBuilder from '../../components/cardbuilder/cardBuilder';
value: 'books',
message: getLink('BookLibraryHelp', 'https://docs.jellyfin.org/general/server/media/books.html')
}, {
name: globalize.translate('Photos'),
name: globalize.translate('HomeVideosPhotos'),
value: 'homevideos'
}, {
name: globalize.translate('MusicVideos'),

View file

@ -42,39 +42,64 @@ function saveList(page) {
}
function populateList(options) {
let html = '';
const paperList = document.createElement('div');
paperList.className = 'paperList';
html += '<div class="paperList">';
for (let i = 0; i < options.repositories.length; i++) {
html += getRepositoryHtml(options.repositories[i]);
}
options.repositories.forEach(repo => {
paperList.appendChild(getRepositoryElement(repo));
});
html += '</div>';
if (!options.repositories.length) {
options.noneElement.classList.remove('hide');
} else {
options.noneElement.classList.add('hide');
}
options.listElement.innerHTML = html;
options.listElement.innerHTML = '';
options.listElement.appendChild(paperList);
loading.hide();
}
function getRepositoryHtml(repository) {
let html = '';
function getRepositoryElement(repository) {
const listItem = document.createElement('div');
listItem.className = 'listItem listItem-border';
html += '<div class="listItem listItem-border">';
html += `<a is="emby-linkbutton" style="margin:0;padding:0" class="clearLink listItemIconContainer" href="${repository.Url}" rel="noopener noreferrer" target="_blank">`;
html += '<span class="material-icons listItemIcon open_in_new" aria-hidden="true"></span>';
html += '</a>';
html += '<div class="listItemBody two-line">';
html += `<h3 class="listItemBodyText">${repository.Name}</h3>`;
html += `<div class="listItemBodyText secondary">${repository.Url}</div>`;
html += '</div>';
html += `<button type="button" is="paper-icon-button-light" id="${repository.Url}" class="btnDelete" title="${globalize.translate('Delete')}"><span class="material-icons delete" aria-hidden="true"></span></button>`;
html += '</div>';
const repoLink = document.createElement('a');
repoLink.setAttribute('is', 'emby-linkbutton');
repoLink.className = 'clearLink listItemIconContainer';
repoLink.style.margin = '0';
repoLink.style.padding = '0';
repoLink.rel = 'noopener noreferrer';
repoLink.target = '_blank';
repoLink.href = repository.Url;
repoLink.innerHTML = '<span class="material-icons listItemIcon open_in_new" aria-hidden="true"></span>';
listItem.appendChild(repoLink);
return html;
const body = document.createElement('div');
body.className = 'listItemBody two-line';
const name = document.createElement('h3');
name.className = 'listItemBodyText';
name.innerText = repository.Name;
body.appendChild(name);
const url = document.createElement('div');
url.className = 'listItemBodyText secondary';
url.innerText = repository.Url;
body.appendChild(url);
listItem.appendChild(body);
const button = document.createElement('button');
button.type = 'button';
button.setAttribute('is', 'paper-icon-button-light');
button.className = 'btnDelete';
button.id = repository.Url;
button.title = globalize.translate('Delete');
button.innerHTML = '<span class="material-icons delete" aria-hidden="true"></span>';
listItem.appendChild(button);
return listItem;
}
function getTabs() {

View file

@ -23,7 +23,13 @@ import '../../../elements/emby-button/emby-button';
tasks = tasks.sort(function(a, b) {
a = a.Category + ' ' + a.Name;
b = b.Category + ' ' + b.Name;
return a == b ? 0 : a < b ? -1 : 1;
if (a > b) {
return 1;
} else if (a < b) {
return -1;
} else {
return 0;
}
});
let currentCategory;

View file

@ -791,7 +791,7 @@ function renderDetailImage(elem, item, imageLoader) {
imageLoader.lazyChildren(elem);
// Avoid breaking the design by preventing focus of the poster using the keyboard.
elem.querySelector('a').tabIndex = -1;
elem.querySelector('a, button').tabIndex = -1;
}
function renderImage(page, item) {

View file

@ -3,6 +3,7 @@
<div class="pageTabContent" id="moviesTab" data-index="0">
<div class="flex align-items-center justify-content-center flex-wrap-wrap padded-top padded-left padded-right padded-bottom focuscontainer-x">
<div class="paging"></div>
<button is="paper-icon-button-light" class="btnShuffle autoSize hide" title="${Shuffle}"><span class="material-icons shuffle" aria-hidden="true"></span></button>
<button is="paper-icon-button-light" class="btnSelectView autoSize" title="${ButtonSelectView}"><span class="material-icons view_comfy" aria-hidden="true"></span></button>
<button is="paper-icon-button-light" class="btnSort autoSize" title="${Sort}"><span class="material-icons sort_by_alpha" aria-hidden="true"></span></button>
<button is="paper-icon-button-light" class="btnFilter autoSize" title="${Filter}"><span class="material-icons filter_list" aria-hidden="true"></span></button>

View file

@ -6,6 +6,7 @@ import { AlphaPicker } from '../../components/alphaPicker/alphaPicker';
import listView from '../../components/listview/listview';
import cardBuilder from '../../components/cardbuilder/cardBuilder';
import globalize from '../../scripts/globalize';
import { playbackManager } from '../../components/playback/playbackmanager';
import '../../elements/emby-itemscontainer/emby-itemscontainer';
/* eslint-disable indent */
@ -29,6 +30,15 @@ import '../../elements/emby-itemscontainer/emby-itemscontainer';
return ApiClient.getItems(ApiClient.getCurrentUserId(), query);
}
function shuffle() {
ApiClient.getItem(
ApiClient.getCurrentUserId(),
params.topParentId
).then((item) => {
playbackManager.shuffle(item);
});
}
const afterRefresh = (result) => {
function onNextPageClick() {
if (isLoading) {
@ -77,6 +87,8 @@ import '../../elements/emby-itemscontainer/emby-itemscontainer';
elem.addEventListener('click', onPreviousPageClick);
}
tabContent.querySelector('.btnShuffle').classList.toggle('hide', result.TotalRecordCount < 1);
isLoading = false;
loading.hide();
@ -243,6 +255,8 @@ import '../../elements/emby-itemscontainer/emby-itemscontainer';
onViewStyleChange();
itemsContainer.refreshItems();
});
tabContent.querySelector('.btnShuffle').addEventListener('click', shuffle);
};
let itemsContainer = tabContent.querySelector('.itemsContainer');

View file

@ -66,7 +66,7 @@ import Dashboard from '../../utils/dashboard';
SortOrder: 'Descending',
IncludeItemTypes: 'Movie',
Filters: 'IsResumable',
Limit: screenWidth >= 1920 ? 5 : screenWidth >= 1600 ? 5 : 3,
Limit: screenWidth >= 1600 ? 5 : 3,
Recursive: true,
Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
CollapseBoxSetItems: false,
@ -157,10 +157,17 @@ import Dashboard from '../../utils/dashboard';
function loadSuggestions(page, userId) {
const screenWidth = dom.getWindowSize().innerWidth;
let itemLimit = 5;
if (screenWidth >= 1600) {
itemLimit = 8;
} else if (screenWidth >= 1200) {
itemLimit = 6;
}
const url = ApiClient.getUrl('Movies/Recommendations', {
userId: userId,
categoryLimit: 6,
ItemLimit: screenWidth >= 1920 ? 8 : screenWidth >= 1600 ? 8 : screenWidth >= 1200 ? 6 : 5,
ItemLimit: itemLimit,
Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb'

View file

@ -27,6 +27,8 @@ import LibraryMenu from '../../../scripts/libraryMenu';
import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components/backdrop/backdrop';
/* eslint-disable indent */
const TICKS_PER_MINUTE = 600000000;
const TICKS_PER_SECOND = 10000000;
function getOpenedDialog() {
return document.querySelector('.dialogContainer .dialog.opened');
@ -210,7 +212,18 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
itemName = parentName || '';
}
LibraryMenu.setTitle(itemName);
// Display the item with its premiere date if it has one
let title = itemName;
if (item.PremiereDate) {
try {
const year = datetime.parseISO8601Date(item.PremiereDate).getFullYear();
title += ` (${year})`;
} catch (e) {
console.error(e);
}
}
LibraryMenu.setTitle(title);
const documentTitle = parentName || (item ? item.Name : null);
@ -587,11 +600,16 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
function showComingUpNextIfNeeded(player, currentItem, currentTimeTicks, runtimeTicks) {
if (runtimeTicks && currentTimeTicks && !comingUpNextDisplayed && !currentVisibleMenu && currentItem.Type === 'Episode' && userSettings.enableNextVideoInfoOverlay()) {
const showAtSecondsLeft = runtimeTicks >= 3e10 ? 40 : runtimeTicks >= 24e9 ? 35 : 30;
const showAtTicks = runtimeTicks - 1e3 * showAtSecondsLeft * 1e4;
let showAtSecondsLeft = 30;
if (runtimeTicks >= 50 * TICKS_PER_MINUTE) {
showAtSecondsLeft = 40;
} else if (runtimeTicks >= 40 * TICKS_PER_MINUTE) {
showAtSecondsLeft = 35;
}
const showAtTicks = runtimeTicks - showAtSecondsLeft * TICKS_PER_SECOND;
const timeRemainingTicks = runtimeTicks - currentTimeTicks;
if (currentTimeTicks >= showAtTicks && runtimeTicks >= 6e9 && timeRemainingTicks >= 2e8) {
if (currentTimeTicks >= showAtTicks && runtimeTicks >= (10 * TICKS_PER_MINUTE) && timeRemainingTicks >= (20 * TICKS_PER_SECOND)) {
showComingUpNext(player);
}
}

View file

@ -98,7 +98,7 @@ import autoFocuser from '../../components/autoFocuser';
SortOrder: 'Descending',
IncludeItemTypes: 'Episode',
Filters: 'IsResumable',
Limit: screenWidth >= 1920 ? 5 : screenWidth >= 1600 ? 5 : 3,
Limit: screenWidth >= 1600 ? 5 : 3,
Recursive: true,
Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
CollapseBoxSetItems: false,

View file

@ -5,7 +5,7 @@
<div>${QuickConnectDescription}</div>
<br />
<div class="inputContainer">
<input is="emby-input" type="number" min="0" max="999999" required id="txtQuickConnectCode" label="${LabelQuickConnectCode}" autocomplete="off" />
<input is="emby-input" type="text" inputmode="numeric" pattern="[0-9\s]*" minlength="6" required id="txtQuickConnectCode" label="${LabelQuickConnectCode}" autocomplete="off" />
</div>
<button id="btnQuickConnectAuthorize" is="emby-button" type="submit" class="raised button-submit block">
<span>${Authorize}</span>

View file

@ -15,7 +15,9 @@ export default function (view) {
return;
}
authorize(codeElement.value);
// Remove spaces from code
const normalizedCode = codeElement.value.replace(/\s/g, '');
authorize(normalizedCode);
});
});
}