mirror of
https://github.com/jellyfin/jellyfin-web.git
synced 2024-11-17 10:58:20 -07:00
commit
4de9be40e9
@ -21,8 +21,6 @@ jobs:
|
||||
BuildConfiguration: development
|
||||
Production:
|
||||
BuildConfiguration: production
|
||||
Standalone:
|
||||
BuildConfiguration: standalone
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
@ -49,13 +47,9 @@ jobs:
|
||||
condition: eq(variables['BuildConfiguration'], 'development')
|
||||
|
||||
- script: 'yarn build:production'
|
||||
displayName: 'Build Bundle'
|
||||
displayName: 'Build Production'
|
||||
condition: eq(variables['BuildConfiguration'], 'production')
|
||||
|
||||
- script: 'yarn build:standalone'
|
||||
displayName: 'Build Standalone'
|
||||
condition: eq(variables['BuildConfiguration'], 'standalone')
|
||||
|
||||
- script: 'test -d dist'
|
||||
displayName: 'Check Build'
|
||||
|
||||
|
44
.eslintrc.js
44
.eslintrc.js
@ -27,30 +27,30 @@ module.exports = {
|
||||
'plugin:compat/recommended'
|
||||
],
|
||||
rules: {
|
||||
'block-spacing': ["error"],
|
||||
'brace-style': ["error"],
|
||||
'comma-dangle': ["error", "never"],
|
||||
'comma-spacing': ["error"],
|
||||
'eol-last': ["error"],
|
||||
'indent': ["error", 4, { "SwitchCase": 1 }],
|
||||
'keyword-spacing': ["error"],
|
||||
'max-statements-per-line': ["error"],
|
||||
'no-floating-decimal': ["error"],
|
||||
'no-multi-spaces': ["error"],
|
||||
'no-multiple-empty-lines': ["error", { "max": 1 }],
|
||||
'no-trailing-spaces': ["error"],
|
||||
'one-var': ["error", "never"],
|
||||
'quotes': ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": false }],
|
||||
'semi': ["error"],
|
||||
'space-before-blocks': ["error"],
|
||||
"space-infix-ops": "error"
|
||||
'block-spacing': ['error'],
|
||||
'brace-style': ['error'],
|
||||
'comma-dangle': ['error', 'never'],
|
||||
'comma-spacing': ['error'],
|
||||
'eol-last': ['error'],
|
||||
'indent': ['error', 4, { 'SwitchCase': 1 }],
|
||||
'keyword-spacing': ['error'],
|
||||
'max-statements-per-line': ['error'],
|
||||
'no-floating-decimal': ['error'],
|
||||
'no-multi-spaces': ['error'],
|
||||
'no-multiple-empty-lines': ['error', { 'max': 1 }],
|
||||
'no-trailing-spaces': ['error'],
|
||||
'one-var': ['error', 'never'],
|
||||
'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }],
|
||||
'semi': ['error'],
|
||||
'space-before-blocks': ['error'],
|
||||
'space-infix-ops': 'error'
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
'./src/**/*.js'
|
||||
],
|
||||
parser: "babel-eslint",
|
||||
parser: 'babel-eslint',
|
||||
env: {
|
||||
node: false,
|
||||
amd: true,
|
||||
@ -98,11 +98,11 @@ module.exports = {
|
||||
},
|
||||
rules: {
|
||||
// TODO: Fix warnings and remove these rules
|
||||
'no-redeclare': ["warn"],
|
||||
'no-unused-vars': ["warn"],
|
||||
'no-useless-escape': ["warn"],
|
||||
'no-redeclare': ['warn'],
|
||||
'no-unused-vars': ['warn'],
|
||||
'no-useless-escape': ['warn'],
|
||||
// TODO: Remove after ES6 migration is complete
|
||||
'import/no-unresolved': ["off"]
|
||||
'import/no-unresolved': ['off']
|
||||
},
|
||||
settings: {
|
||||
polyfills: [
|
||||
|
36
gulpfile.js
36
gulpfile.js
@ -16,7 +16,6 @@ const stream = require('webpack-stream');
|
||||
const inject = require('gulp-inject');
|
||||
const postcss = require('gulp-postcss');
|
||||
const sass = require('gulp-sass');
|
||||
const gulpif = require('gulp-if');
|
||||
const lazypipe = require('lazypipe');
|
||||
|
||||
sass.compiler = require('node-sass');
|
||||
@ -68,7 +67,7 @@ function serve() {
|
||||
}
|
||||
});
|
||||
|
||||
watch(options.apploader.query, apploader(true));
|
||||
watch(options.apploader.query, apploader());
|
||||
|
||||
watch('src/bundle.js', webpack);
|
||||
|
||||
@ -131,18 +130,12 @@ function javascript(query) {
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
function apploader(standalone) {
|
||||
function task() {
|
||||
return src(options.apploader.query, { base: './src/' })
|
||||
.pipe(gulpif(standalone, concat('scripts/apploader.js')))
|
||||
.pipe(pipelineJavascript())
|
||||
.pipe(dest('dist/'))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
task.displayName = 'apploader';
|
||||
|
||||
return task;
|
||||
function apploader() {
|
||||
return src(options.apploader.query, { base: './src/' })
|
||||
.pipe(concat('scripts/apploader.js'))
|
||||
.pipe(pipelineJavascript())
|
||||
.pipe(dest('dist/'))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
function webpack() {
|
||||
@ -181,12 +174,6 @@ function copy(query) {
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
function copyIndex() {
|
||||
return src(options.injectBundle.query, { base: './src/' })
|
||||
.pipe(dest('dist/'))
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
function injectBundle() {
|
||||
return src(options.injectBundle.query, { base: './src/' })
|
||||
.pipe(inject(
|
||||
@ -196,10 +183,5 @@ function injectBundle() {
|
||||
.pipe(browserSync.stream());
|
||||
}
|
||||
|
||||
function build(standalone) {
|
||||
return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy));
|
||||
}
|
||||
|
||||
exports.default = series(build(false), copyIndex);
|
||||
exports.standalone = series(build(true), injectBundle);
|
||||
exports.serve = series(exports.standalone, serve);
|
||||
exports.default = series(clean, parallel(javascript, apploader, webpack, css, html, images, copy), injectBundle);
|
||||
exports.serve = series(exports.default, serve);
|
||||
|
@ -146,7 +146,6 @@
|
||||
"prepare": "gulp --production",
|
||||
"build:development": "gulp --development",
|
||||
"build:production": "gulp --production",
|
||||
"build:standalone": "gulp standalone --development",
|
||||
"lint": "eslint \".\"",
|
||||
"stylelint": "stylelint \"src/**/*.css\""
|
||||
}
|
||||
|
@ -215,24 +215,7 @@ export class BookPlayer {
|
||||
Id: item.Id
|
||||
}
|
||||
};
|
||||
if (!item.Path.endsWith('.epub')) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let errorDialog = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
autoFocus: false,
|
||||
removeOnClose: true
|
||||
});
|
||||
|
||||
errorDialog.innerHTML = '<h1 class="bookplayerErrorMsg">This book type is not supported yet</h1>';
|
||||
|
||||
this.stop();
|
||||
|
||||
dialogHelper.open(errorDialog);
|
||||
loading.hide();
|
||||
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
let serverId = item.ServerId;
|
||||
let apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
@ -283,6 +266,13 @@ export class BookPlayer {
|
||||
canPlayMediaType(mediaType) {
|
||||
return (mediaType || '').toLowerCase() === 'book';
|
||||
}
|
||||
|
||||
canPlayItem(item) {
|
||||
if (item.Path && (item.Path.endsWith('epub'))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default BookPlayer;
|
||||
|
@ -229,7 +229,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
var options = {
|
||||
Limit: limit,
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path',
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||
ParentId: parentId
|
||||
@ -667,7 +667,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getNextUpEpisodes({
|
||||
Limit: enableScrollX() ? 24 : 15,
|
||||
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo',
|
||||
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo,Path',
|
||||
UserId: apiClient.getCurrentUserId(),
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
|
||||
|
@ -1129,7 +1129,6 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla
|
||||
}
|
||||
|
||||
self.canPlay = function (item) {
|
||||
|
||||
var itemType = item.Type;
|
||||
|
||||
if (itemType === 'PhotoAlbum' || itemType === 'MusicGenre' || itemType === 'Season' || itemType === 'Series' || itemType === 'BoxSet' || itemType === 'MusicAlbum' || itemType === 'MusicArtist' || itemType === 'Playlist') {
|
||||
@ -1143,7 +1142,6 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla
|
||||
}
|
||||
|
||||
if (itemType === 'Program') {
|
||||
|
||||
if (!item.EndDate || !item.StartDate) {
|
||||
return false;
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ define(['globalize', 'listView', 'layoutManager', 'userSettings', 'focusManager'
|
||||
return apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, {
|
||||
StartIndex: startIndex,
|
||||
Limit: limit,
|
||||
Fields: 'PrimaryImageAspectRatio,SortName',
|
||||
Fields: 'PrimaryImageAspectRatio,SortName,Path',
|
||||
ImageTypeLimit: 1,
|
||||
ParentId: item.Id,
|
||||
SortBy: sortBy
|
||||
|
@ -62,7 +62,7 @@
|
||||
<input is="emby-input" type="text" id="txtLoginDisclaimer" label="${LabelLoginDisclaimer}" />
|
||||
<div class="fieldDescription">${LabelLoginDisclaimerHelp}</div>
|
||||
</div>
|
||||
<div class="inputContainer">
|
||||
<div class="inputContainer customCssContainer">
|
||||
<textarea is="emby-textarea" id="txtCustomCss" label="${LabelCustomCss}" class="textarea-mono"></textarea>
|
||||
<div class="fieldDescription">${LabelCustomCssHelp}</div>
|
||||
</div>
|
||||
|
@ -55,6 +55,7 @@ define(['layoutManager', 'browser', 'css!./emby-textarea', 'registerElement', 'e
|
||||
newHeight = textarea.scrollHeight/* - offset*/;
|
||||
hasGrown = true;
|
||||
}
|
||||
$('.customCssContainer').css('height', newHeight + 'px');
|
||||
textarea.style.height = newHeight + 'px';
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"AddToCollection": "Aldoni al kolekto",
|
||||
"Actor": "Aktoro",
|
||||
"Absolute": "Absoluto"
|
||||
"Absolute": "Absoluta"
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1455,8 +1455,8 @@
|
||||
"MessageConfirmAppExit": "Vuoi uscire?",
|
||||
"HeaderNavigation": "Navigazione",
|
||||
"CopyStreamURLError": "Si è verificato un errore nel copiare l'indirizzo.",
|
||||
"EnableFastImageFadeInHelp": "Abilita la dissolvenza veloce per le immagini caricate",
|
||||
"EnableFastImageFadeIn": "Dissolvenza immagine veloce",
|
||||
"EnableFastImageFadeInHelp": "Mostra i poster e le altre immagini con una dissolvenza veloce alla fine del caricamento.",
|
||||
"EnableFastImageFadeIn": "Dissolvenza Immagine Veloce",
|
||||
"PlaybackErrorNoCompatibleStream": "Il client è incompatibile con il media e il server non sta inviando un formato compatibile.",
|
||||
"OptionForceRemoteSourceTranscoding": "Forza la transcodifica da fonti di media remoti (come LiveTV)",
|
||||
"NoCreatedLibraries": "Sembra che tu non abbia ancora creato delle librerie. {0}Vuoi crearne una adesso?{1}",
|
||||
@ -1520,5 +1520,37 @@
|
||||
"TabDVR": "DVR",
|
||||
"SaveChanges": "Salva modifiche",
|
||||
"HeaderDVR": "DVR",
|
||||
"LabelNightly": "Nightly"
|
||||
"LabelNightly": "Nightly",
|
||||
"SyncPlayAccessHelp": "Scegli il livello d'accesso di questo utente a SyncPlay. SyncPlay ti permette di riprodurre contemporaneamente su diversi dispositivi.",
|
||||
"MessageSyncPlayErrorMedia": "Impossibile abilitare SyncPlay! Errore media.",
|
||||
"MessageSyncPlayErrorMissingSession": "Impossibile abilitare SyncPlay! Sessione mancante.",
|
||||
"MessageSyncPlayErrorNoActivePlayer": "Nessun player attivo. SyncPlay è stato disabilitato.",
|
||||
"MessageSyncPlayErrorAccessingGroups": "Errore durante l'accesso alla lista dei gruppi.",
|
||||
"MessageSyncPlayLibraryAccessDenied": "L'accesso a questo contenuto è negato.",
|
||||
"MessageSyncPlayJoinGroupDenied": "E' Necessario il permesso per l'utilizzo di SyncPlay.",
|
||||
"MessageSyncPlayCreateGroupDenied": "E' necessario il permesso di creazione di un gruppo.",
|
||||
"MessageSyncPlayGroupDoesNotExist": "Impossibile unirsi al gruppo perchè non esiste.",
|
||||
"MessageSyncPlayPlaybackPermissionRequired": "Permesso di riproduzione necessario.",
|
||||
"MessageSyncPlayNoGroupsAvailable": "Nessun gruppo disponibile. Inizia a riprodurre qualcosa.",
|
||||
"MessageSyncPlayGroupWait": "<b>{0}</b> sta bufferizzando...",
|
||||
"MessageSyncPlayUserLeft": "<b>{0}</b> ha lasciato il gruppo.",
|
||||
"MessageSyncPlayUserJoined": "<b>{0}</b> si è unito al gruppo.",
|
||||
"MessageSyncPlayDisabled": "SyncPlay disabilitato.",
|
||||
"MessageSyncPlayEnabled": "SyncPlay abilitato.",
|
||||
"LabelSyncPlayAccess": "Accesso SyncPlay",
|
||||
"LabelSyncPlayAccessNone": "Disabilitato per questo utente",
|
||||
"LabelSyncPlayAccessJoinGroups": "Permetti all'utente di unirsi ai gruppi",
|
||||
"LabelSyncPlayAccessCreateAndJoinGroups": "Permetti all'utente di creare e unirsi ai gruppi",
|
||||
"LabelSyncPlayLeaveGroupDescription": "Disabilita SyncPlay",
|
||||
"LabelSyncPlayLeaveGroup": "Lascia il gruppo",
|
||||
"LabelSyncPlayNewGroupDescription": "Crea un nuovo gruppo",
|
||||
"LabelSyncPlayNewGroup": "Nuovo gruppo",
|
||||
"LabelSyncPlaySyncMethod": "Metodo Sync:",
|
||||
"LabelSyncPlayPlaybackDiff": "Differenza oraria nella riproduzione:",
|
||||
"MillisecondsUnit": "ms",
|
||||
"LabelSyncPlayTimeOffset": "Differenza temporale con il server:",
|
||||
"HeaderSyncPlayEnabled": "SyncPlay abilitato",
|
||||
"HeaderSyncPlaySelectGroup": "Unisciti a un gruppo",
|
||||
"EnableDetailsBannerHelp": "Mostra il banner nella parte superiore della pagina di dettaglio dell'elemento.",
|
||||
"EnableDetailsBanner": "Banner Dettagli"
|
||||
}
|
||||
|
@ -1102,13 +1102,13 @@
|
||||
"AllowedRemoteAddressesHelp": "Lista separada por vírgula de endereços IP ou entradas de máscara de IP/rede para redes que terão permissão para se conectar remotamente. Se deixado em branco, todos os endereços remotos serão permitidos.",
|
||||
"AllowRemoteAccessHelp": "Se desmarcada, todas as conexões remotas serão bloqueadas.",
|
||||
"AllowRemoteAccess": "Permitir ligações remotas a este Servidor Jellyfin.",
|
||||
"AllowOnTheFlySubtitleExtractionHelp": "Legendas integradas podem ser extraídas do vídeo e enviadas como texto simples para os clientes para evitar transcodificação. Em certos dispositivos, é uma operação demorada e pode causar paragens de reprodução durante o processo de extracção. Desactive esta opção para que as legendas sejam integradas no vídeo durante a conversão para um formato suportado pelo dispositivo de destino.",
|
||||
"AllowOnTheFlySubtitleExtractionHelp": "Legendas integradas podem ser extraídas do vídeo e enviadas como texto simples para os clientes de forma a evitar transcodificação. Em certos dispositivos, esta operação pode demorar algum tempo e causar paragens de reprodução durante o processo de extração. Desative esta opção para que as legendas sejam integradas no vídeo durante a conversão para um formato suportado pelo dispositivo de destino.",
|
||||
"AllowOnTheFlySubtitleExtraction": "Permitir a extração de legendas em tempo real",
|
||||
"AllowHWTranscodingHelp": "Permita que o sintonizador transcodifique os fluxos em tempo real. Isso pode ajudar a reduzir a transcodificação exigida pelo servidor.",
|
||||
"AllLibraries": "Todas as bibliotecas",
|
||||
"AllLanguages": "Todos os idiomas",
|
||||
"AllEpisodes": "Todos os episódios",
|
||||
"AllComplexFormats": "Todos os formatos complexos (ASS, SSA, VOBSUB, PGS, SUB/IDX, etc.)",
|
||||
"AllComplexFormats": "Todos os formatos complexos (ASS, SSA, VOBSUB, PGS, SUB, IDX, etc.)",
|
||||
"AllChannels": "Todos os canais",
|
||||
"All": "Todos",
|
||||
"Alerts": "Alertas",
|
||||
|
@ -250,7 +250,7 @@
|
||||
"ButtonSubmit": "Trimite",
|
||||
"Collections": "Colecții",
|
||||
"AllowRemoteAccess": "Permite conexiuni externe către acest server Jellyfin.",
|
||||
"AllowRemoteAccessHelp": "Dacă este nebifat, toate conexiunile externe vor fi blocate.",
|
||||
"AllowRemoteAccessHelp": "Dacă este neselectat, toate conexiunile externe vor fi blocate.",
|
||||
"AlwaysPlaySubtitles": "Întotdeauna arată",
|
||||
"AnyLanguage": "Orice Limbă",
|
||||
"Anytime": "Oricând",
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"AccessRestrictedTryAgainLater": "目前访问受限。请稍后再试。",
|
||||
"AccessRestrictedTryAgainLater": "目前访问受限,请稍后再试。",
|
||||
"Actor": "演员",
|
||||
"Add": "添加",
|
||||
"AddItemToCollectionHelp": "通过搜索项目并右键或轻触得到的弹出菜单来将项目添加到集合中。",
|
||||
@ -1464,7 +1464,7 @@
|
||||
"HeaderNavigation": "导航",
|
||||
"CopyStreamURLError": "复制URL地址时发生错误。",
|
||||
"MessageConfirmAppExit": "你要退出吗?",
|
||||
"EnableFastImageFadeIn": "快速图片淡入",
|
||||
"EnableFastImageFadeIn": "快速图片淡入淡出",
|
||||
"EnableFastImageFadeInHelp": "为已加载的图片启用更快的图片淡入动画",
|
||||
"OptionForceRemoteSourceTranscoding": "强制远程转码(像电视直播一样)",
|
||||
"NoCreatedLibraries": "看上去您还未创建任何资料库。{0} 您想现在创建一个吗? {1}",
|
||||
@ -1524,5 +1524,25 @@
|
||||
"LabelEnableHttps": "启用 HTTPS",
|
||||
"LabelChromecastVersion": "Chromecast版本",
|
||||
"HeaderDVR": "DVR",
|
||||
"LabelNightly": "Nightly"
|
||||
"LabelNightly": "Nightly",
|
||||
"MessageSyncPlayErrorAccessingGroups": "访问群组列表时发生错误。",
|
||||
"MessageSyncPlayLibraryAccessDenied": "搜限制的访问权限。",
|
||||
"MessageSyncPlayCreateGroupDenied": "需要权限创建该组。",
|
||||
"MessageSyncPlayGroupDoesNotExist": "无法加入群组,该群组不存在。",
|
||||
"MessageSyncPlayPlaybackPermissionRequired": "需要播放权限。",
|
||||
"MessageSyncPlayGroupWait": "<b>{0}</b> 正在缓冲...",
|
||||
"MessageSyncPlayUserLeft": "<b>{0}</b> 已离开小组。",
|
||||
"MessageSyncPlayUserJoined": "<b>{0}</b> 已加入该小组。",
|
||||
"LabelSyncPlayAccessNone": "禁用此用户",
|
||||
"LabelSyncPlayAccessJoinGroups": "允许用户加入群组",
|
||||
"LabelSyncPlayAccessCreateAndJoinGroups": "允许用户创建和加入群组",
|
||||
"LabelSyncPlayLeaveGroup": "离开组",
|
||||
"LabelSyncPlayNewGroupDescription": "创建一个新组",
|
||||
"LabelSyncPlayNewGroup": "新组",
|
||||
"LabelSyncPlaySyncMethod": "同步方式:",
|
||||
"MillisecondsUnit": "毫秒",
|
||||
"LabelSyncPlayTimeOffset": "服务器时间偏移:",
|
||||
"HeaderSyncPlayEnabled": "同步播放已启用",
|
||||
"HeaderSyncPlaySelectGroup": "加入群组",
|
||||
"EnableDetailsBannerHelp": "在项目详细信息页面的顶部显示横幅图片。"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user