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

Merge branch 'jellyfin:master' into add/device-logos

This commit is contained in:
photonconvergence 2022-10-25 17:25:30 -07:00 committed by GitHub
commit 7ab1edd3c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 70 additions and 20 deletions

View file

@ -305,10 +305,16 @@
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
pointer-events: none;
[dir="rtl"] & { [dir="rtl"] & {
transition: right ease-in-out 0.3s, padding ease-in-out 0.3s; transition: right ease-in-out 0.3s, padding ease-in-out 0.3s;
} }
> .page {
// Fix pointer events being swallowed by the react root when a dashboard page is not rendered by react
pointer-events: all;
}
} }
.centerMessage { .centerMessage {

View file

@ -77,6 +77,7 @@ import cardBuilder from '../../components/cardbuilder/cardBuilder';
import('../../components/prompt/prompt').then(({default: prompt}) => { import('../../components/prompt/prompt').then(({default: prompt}) => {
prompt({ prompt({
label: globalize.translate('LabelNewName'), label: globalize.translate('LabelNewName'),
description: globalize.translate('MessageRenameMediaFolder'),
confirmText: globalize.translate('ButtonRename') confirmText: globalize.translate('ButtonRename')
}).then(function (newName) { }).then(function (newName) {
if (newName && newName != virtualFolder.Name) { if (newName && newName != virtualFolder.Name) {

View file

@ -1,6 +1,9 @@
<div id="pluginCatalogPage" data-role="page" class="page type-interior pluginConfigurationPage withTabs fullWidthContent"> <div id="pluginCatalogPage" data-role="page" class="page type-interior pluginConfigurationPage withTabs fullWidthContent">
<div> <div>
<div class="content-primary"> <div class="content-primary">
<div class="inputContainer">
<input id="txtSearchPlugins" name="txtSearchPlugins" type="text" is="emby-input" label="${Search}" />
</div>
<div id="noPlugins" class="hide">${MessageNoAvailablePlugins}</div> <div id="noPlugins" class="hide">${MessageNoAvailablePlugins}</div>
<div id="pluginTiles" style="text-align:left;"></div> <div id="pluginTiles" style="text-align:left;"></div>
</div> </div>

View file

@ -86,10 +86,37 @@ function populateList(options) {
options.noItemsElement.classList.remove('hide'); options.noItemsElement.classList.remove('hide');
} }
const searchBar = document.getElementById('txtSearchPlugins');
if (searchBar) {
searchBar.addEventListener('input', () => onSearchBarType(searchBar));
}
options.catalogElement.innerHTML = html; options.catalogElement.innerHTML = html;
loading.hide(); loading.hide();
} }
function onSearchBarType(searchBar) {
const filter = searchBar.value.toLowerCase();
for (const header of document.querySelectorAll('div .verticalSection')) {
// keep track of shown cards after each search
let shown = 0;
for (const card of header.querySelectorAll('div .card')) {
if (filter && filter != '' && !card.textContent.toLowerCase().includes(filter)) {
card.style.display = 'none';
} else {
card.style.display = 'unset';
shown++;
}
}
// hide title if no cards are shown
if (shown <= 0) {
header.style.display = 'none';
} else {
header.style.display = 'unset';
}
}
}
function getPluginHtml(plugin, options, installedPlugins) { function getPluginHtml(plugin, options, installedPlugins) {
let html = ''; let html = '';
let href = plugin.externalUrl ? plugin.externalUrl : '#/addplugin.html?name=' + encodeURIComponent(plugin.name) + '&guid=' + plugin.guid; let href = plugin.externalUrl ? plugin.externalUrl : '#/addplugin.html?name=' + encodeURIComponent(plugin.name) + '&guid=' + plugin.guid;

View file

@ -1,6 +1,9 @@
<div id="pluginsPage" data-role="page" class="page type-interior pluginConfigurationPage withTabs fullWidthContent"> <div id="pluginsPage" data-role="page" class="page type-interior pluginConfigurationPage withTabs fullWidthContent">
<div> <div>
<div class="content-primary"> <div class="content-primary">
<div class="inputContainer">
<input id="txtSearchPlugins" name="txtSearchPlugins" type="text" is="emby-input" label="${Search}" />
</div>
<div class="installedPlugins"></div> <div class="installedPlugins"></div>
</div> </div>
</div> </div>

View file

@ -112,7 +112,6 @@ function populateList(page, plugins, pluginConfigurationPages) {
if (plugin1.Name > plugin2.Name) { if (plugin1.Name > plugin2.Name) {
return 1; return 1;
} }
return -1; return -1;
}); });
@ -136,6 +135,12 @@ function populateList(page, plugins, pluginConfigurationPages) {
html += '</div>'; html += '</div>';
} }
// add search box listener
const searchBar = page.querySelector('#txtSearchPlugins');
if (searchBar) {
searchBar.addEventListener('input', () => onFilterType(page, searchBar));
}
installedPluginsElement.innerHTML = html; installedPluginsElement.innerHTML = html;
loading.hide(); loading.hide();
} }
@ -239,6 +244,17 @@ function onInstalledPluginsClick(e) {
} }
} }
function onFilterType(page, searchBar) {
const filter = searchBar.value.toLowerCase();
for (const card of page.querySelectorAll('.card')) {
if (filter && filter != '' && !card.textContent.toLowerCase().includes(filter)) {
card.style.display = 'none';
} else {
card.style.display = 'unset';
}
}
}
pageIdOn('pageshow', 'pluginsPage', function () { pageIdOn('pageshow', 'pluginsPage', function () {
libraryMenu.setTabs('plugins', 0, getTabs); libraryMenu.setTabs('plugins', 0, getTabs);
reloadList(this); reloadList(this);

View file

@ -28,24 +28,15 @@ import cardBuilder from '../../../components/cardbuilder/cardBuilder';
const items = servers.map(function (server) { const items = servers.map(function (server) {
return { return {
name: server.Name, name: server.Name,
showIcon: true, icon: 'storage',
icon: 'cast',
cardType: '', cardType: '',
id: server.Id, id: server.Id,
server: server server: server
}; };
}); });
let html = items.map(function (item) { let html = items.map(function (item) {
let cardImageContainer;
if (item.showIcon) {
cardImageContainer = '<span class="cardImageIcon material-icons ' + item.icon + '" aria-hidden="true"></span>';
} else {
cardImageContainer = '<div class="cardImage" style="' + item.cardImageStyle + '"></div>';
}
// TODO move card creation code to Card component // TODO move card creation code to Card component
const cardImageContainer = '<span class="cardImageIcon material-icons ' + item.icon + '" aria-hidden="true"></span>';
let cssClass = 'card overflowSquareCard loginSquareCard scalableCard overflowSquareCard-scalable'; let cssClass = 'card overflowSquareCard loginSquareCard scalableCard overflowSquareCard-scalable';
if (layoutManager.tv) { if (layoutManager.tv) {

View file

@ -14,7 +14,7 @@
<a is="emby-linkbutton" data-ripple="false" href="#" style="display:block;padding:0;margin:0;" class="lnkQuickConnectPreferences listItem-border hide"> <a is="emby-linkbutton" data-ripple="false" href="#" style="display:block;padding:0;margin:0;" class="lnkQuickConnectPreferences listItem-border hide">
<div class="listItem"> <div class="listItem">
<span class="material-icons listItemIcon listItemIcon-transparent tap_and_play" aria-hidden="true"></span> <span class="material-icons listItemIcon listItemIcon-transparent phonelink_lock" aria-hidden="true"></span>
<div class="listItemBody"> <div class="listItemBody">
<div class="listItemBodyText">${QuickConnect}</div> <div class="listItemBodyText">${QuickConnect}</div>
</div> </div>
@ -98,7 +98,7 @@
<h2 class="sectionTitle" style="padding-left:.25em;">${HeaderUser}</h2> <h2 class="sectionTitle" style="padding-left:.25em;">${HeaderUser}</h2>
<a is="emby-linkbutton" data-ripple="false" href="#" style="display:block;padding:0;margin:0;" class="selectServer hide listItem-border"> <a is="emby-linkbutton" data-ripple="false" href="#" style="display:block;padding:0;margin:0;" class="selectServer hide listItem-border">
<div class="listItem"> <div class="listItem">
<span class="material-icons listItemIcon listItemIcon-transparent wifi" aria-hidden="true"></span> <span class="material-icons listItemIcon listItemIcon-transparent storage" aria-hidden="true"></span>
<div class="listItemBody"> <div class="listItemBody">
<div class="listItemBodyText">${SelectServer}</div> <div class="listItemBodyText">${SelectServer}</div>
</div> </div>

View file

@ -2,7 +2,7 @@ import appSettings from '../../scripts/settings/appSettings';
import * as userSettings from '../../scripts/settings/userSettings'; import * as userSettings from '../../scripts/settings/userSettings';
import { playbackManager } from '../../components/playback/playbackmanager'; import { playbackManager } from '../../components/playback/playbackmanager';
import globalize from '../../scripts/globalize'; import globalize from '../../scripts/globalize';
import castSenderApiLoader from '../../components/castSenderApi'; import castSenderApiLoader from './castSenderApi';
import ServerConnections from '../../components/ServerConnections'; import ServerConnections from '../../components/ServerConnections';
import alert from '../../components/alert'; import alert from '../../components/alert';
import Events from '../../utils/events.ts'; import Events from '../../utils/events.ts';

View file

@ -325,7 +325,7 @@ import '../assets/css/flexstyles.scss';
html += '</h3>'; html += '</h3>';
if (appHost.supports('multiserver')) { if (appHost.supports('multiserver')) {
html += `<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder btnSelectServer" data-itemid="selectserver" href="#"><span class="material-icons navMenuOptionIcon wifi" aria-hidden="true"></span><span class="navMenuOptionText">${globalize.translate('SelectServer')}</span></a>`; html += `<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder btnSelectServer" data-itemid="selectserver" href="#"><span class="material-icons navMenuOptionIcon storage" aria-hidden="true"></span><span class="navMenuOptionText">${globalize.translate('SelectServer')}</span></a>`;
} }
html += `<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder btnSettings" data-itemid="settings" href="#"><span class="material-icons navMenuOptionIcon settings" aria-hidden="true"></span><span class="navMenuOptionText">${globalize.translate('Settings')}</span></a>`; html += `<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder btnSettings" data-itemid="settings" href="#"><span class="material-icons navMenuOptionIcon settings" aria-hidden="true"></span><span class="navMenuOptionText">${globalize.translate('Settings')}</span></a>`;

View file

@ -1679,5 +1679,6 @@
"IgnoreDtsHelp": "Vypnutím se mohou vyřešit některé problémy, např. chybějící zvuk u kanálů s oddělenými zvukovými a video stopami.", "IgnoreDtsHelp": "Vypnutím se mohou vyřešit některé problémy, např. chybějící zvuk u kanálů s oddělenými zvukovými a video stopami.",
"IgnoreDts": "Ignorovat DTS (časové razítko dekódování)", "IgnoreDts": "Ignorovat DTS (časové razítko dekódování)",
"OptionDateEpisodeAdded": "Datum přidání epizody", "OptionDateEpisodeAdded": "Datum přidání epizody",
"OptionDateShowAdded": "Datum přidání pořadu" "OptionDateShowAdded": "Datum přidání pořadu",
"MessageRenameMediaFolder": "Přejmenování knihovny médií způsobí ztrátu všech metadat, postupujte proto s opatrností."
} }

View file

@ -1085,6 +1085,7 @@
"MessagePluginInstalled": "The plugin has been successfully installed. The server will need to be restarted for changes to take effect.", "MessagePluginInstalled": "The plugin has been successfully installed. The server will need to be restarted for changes to take effect.",
"MessagePluginInstallError": "An error occurred while installing the plugin.", "MessagePluginInstallError": "An error occurred while installing the plugin.",
"MessageReenableUser": "See below to reenable", "MessageReenableUser": "See below to reenable",
"MessageRenameMediaFolder": "Renaming a media library will cause all metadata to be lost, proceed with caution.",
"MessageSent": "Message sent.", "MessageSent": "Message sent.",
"MessageSyncPlayCreateGroupDenied": "Permission required to create a group.", "MessageSyncPlayCreateGroupDenied": "Permission required to create a group.",
"MessageSyncPlayDisabled": "SyncPlay disabled.", "MessageSyncPlayDisabled": "SyncPlay disabled.",

View file

@ -1679,5 +1679,6 @@
"IgnoreDtsHelp": "La désactivation de cette option peut résoudre certains problèmes, par ex. audio manquant sur les canaux avec des flux audio et vidéo séparés.", "IgnoreDtsHelp": "La désactivation de cette option peut résoudre certains problèmes, par ex. audio manquant sur les canaux avec des flux audio et vidéo séparés.",
"OptionDateShowAdded": "Date d'ajout de la série", "OptionDateShowAdded": "Date d'ajout de la série",
"OptionDateEpisodeAdded": "Date d'ajout de l'épisode", "OptionDateEpisodeAdded": "Date d'ajout de l'épisode",
"IgnoreDts": "Ignorer DTS (horodatage de décodage)" "IgnoreDts": "Ignorer DTS (horodatage de décodage)",
"MessageRenameMediaFolder": "Renommer une médiathèque entraînera la perte de toutes les métadonnées, procédez avec prudence."
} }

View file

@ -582,7 +582,7 @@
"Image": "Зображення", "Image": "Зображення",
"Identify": "Ідентифікувати", "Identify": "Ідентифікувати",
"Horizontal": "Горизонтально", "Horizontal": "Горизонтально",
"Home": "Домівка", "Home": "Головна",
"HideWatchedContentFromLatestMedia": "Приховати переглянуте з останніх медіа", "HideWatchedContentFromLatestMedia": "Приховати переглянуте з останніх медіа",
"Hide": "Приховати", "Hide": "Приховати",
"Help": "Допомога", "Help": "Допомога",

View file

@ -109,7 +109,7 @@ const config = {
if (packageName.startsWith('@')) { if (packageName.startsWith('@')) {
const parts = module.context const parts = module.context
.substring(module.context.lastIndexOf(packageName)) .substring(module.context.lastIndexOf(packageName))
.split('/'); .split(/[\\/]/);
return `node_modules.${parts[0]}.${parts[1]}`; return `node_modules.${parts[0]}.${parts[1]}`;
} }