From 41f5d1f99b52b4c87ab82f9c525a625001adec0f Mon Sep 17 00:00:00 2001 From: Filipe Lopes Date: Wed, 7 Feb 2024 18:37:44 +0000 Subject: [PATCH 001/118] Translated using Weblate (Portuguese (Portugal)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/pt_PT/ --- src/strings/pt-pt.json | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/strings/pt-pt.json b/src/strings/pt-pt.json index 64762207c6..4376ca3641 100644 --- a/src/strings/pt-pt.json +++ b/src/strings/pt-pt.json @@ -822,7 +822,7 @@ "Schedule": "Agendamentos", "ScanForNewAndUpdatedFiles": "Procurar ficheiros novos ou atualizados", "SaveSubtitlesIntoMediaFoldersHelp": "Guardar ficheiros de legendas junto aos ficheiros vídeo facilita a gestão.", - "SaveSubtitlesIntoMediaFolders": "Guardar legendas nas pastas multimédia", + "SaveSubtitlesIntoMediaFolders": "Guardar legendas nas pastas multimídia", "Runtime": "Duração", "ResumeAt": "Retomar a partir de {0}", "ReplaceAllMetadata": "Substituir todos os metadados", @@ -1766,5 +1766,16 @@ "LabelBackdropScreensaverIntervalHelp": "O tempo em segundos entre diferentes cenários ao usar o protetor de ecrã de cenário.", "LabelBackdropScreensaverInterval": "Intervalo do fundo do protetor de ecrã", "HeaderAllRecordings": "Todas as Gravações", - "SelectAudioNormalizationHelp": "Ganho de faixa - ajusta o volume de cada faixa para que sejam reproduzidas com o mesmo volume. Ganho do álbum - ajusta o volume de todas as faixas apenas de um álbum, mantendo a faixa dinâmica do álbum." + "SelectAudioNormalizationHelp": "Ganho de faixa - ajusta o volume de cada faixa para que sejam reproduzidas com o mesmo volume. Ganho do álbum - ajusta o volume de todas as faixas apenas de um álbum, mantendo a faixa dinâmica do álbum.", + "LogoScreensaver": "Logotipo de proteção de ecrã", + "TonemappingModeHelp": "Selecione o modo de mapeamento de tons. Se você tiver destaques estourados, tente mudar para o modo RGB.", + "MachineTranslated": "Traduzido Automaticamente", + "ForeignPartsOnly": "Apenas partes forçadas/externas", + "PreferEmbeddedExtrasTitlesOverFileNamesHelp": "Os extras geralmente têm o mesmo nome incorporado do parente, marque isto para usar títulos incorporados de qualquer maneira.", + "SaveRecordingImagesHelp": "Guardar imagens do fornecedor de listagens EPG junto com a mídia.", + "MessageRepositoryInstallDisclaimer": "AVISO: Instalar um repositório de plugins de terceiros traz riscos. Ele pode conter código instável ou malicioso e pode mudar a qualquer momento. Instale apenas repositórios de autores em quem você confia.", + "SaveRecordingNFO": "Guardar metadados EPG da gravação no NFO", + "SaveRecordingNFOHelp": "Guardar metadados do fornecedor de listagens EPG junto com a mídia.", + "SaveRecordingImages": "Guardar imagens da gravação EPG", + "LabelTrackGain": "Ganho da Faixa" } From 4de61d8872a3825369896c984d72aca91ffcb0ed Mon Sep 17 00:00:00 2001 From: Filipe Lopes Date: Wed, 7 Feb 2024 18:56:05 +0000 Subject: [PATCH 002/118] Translated using Weblate (Portuguese) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/pt/ --- src/strings/pt.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/strings/pt.json b/src/strings/pt.json index 9300f0f596..1467b0963d 100644 --- a/src/strings/pt.json +++ b/src/strings/pt.json @@ -1471,5 +1471,19 @@ "PasswordRequiredForAdmin": "É necessária uma palavra passe para contas de administrador.", "PleaseConfirmRepositoryInstallation": "Clique em OK para confirmar que leu o texto acima e deseja prosseguir com a instalação do repositório de plug-ins.", "LabelThrottleDelaySecondsHelp": "Tempo em segundos após o qual o transcodificador será limitado. Deve ser grande o suficiente para que o cliente mantenha um buffer saudável. Só funciona se a limitação estiver ligada.", - "QuickConnectAuthorizeFail": "Código 'Quick Connect' desconhecido" + "QuickConnectAuthorizeFail": "Código 'Quick Connect' desconhecido", + "TonemappingAlgorithmHelp": "O mapeamento de tons pode ser ajustado. Se você não estiver familiarizado com essas opções, mantenha o padrão. O valor recomendado é 'BT.2390'.", + "UseEpisodeImagesInNextUp": "Use imagens de episódios nas seções 'Próximo' e 'Continuar a assistir'", + "UseEpisodeImagesInNextUpHelp": "As seções 'Próximo' e 'Continuar a assistir' usarão imagens dos episódios como miniaturas em vez da miniatura principal do programa.", + "Yadif": "YADIF", + "IntelLowPowerEncHelp": "A codificação de baixo consumo pode manter uma sincronização CPU-GPU desnecessária. No Linux eles devem ser desativados se o firmware i915 HuC não estiver configurado.", + "LabelTonemappingThresholdHelp": "Os parâmetros do algoritmo de mapeamento de tom são ajustados para cada cena. Um limite é usado para detectar se a cena mudou ou não. Se a distância entre o brilho médio do quadro atual e a média atual exceder um valor limite, recalcularíamos a média da cena e o brilho máximo. Os valores recomendados e padrão são 0,8 e 0,2.", + "SyncPlayAccessHelp": "O recurso SyncPlay permite sincronizar a reprodução com outros dispositivos. Selecione o nível de acesso que este usuário tem ao SyncPlay.", + "AllowVppTonemappingHelp": "Mapeamento de tons completo baseado no driver Intel. Atualmente funciona apenas em determinados hardwares com vídeos HDR10. Isto tem uma prioridade mais alta em comparação com outra implementação OpenCL.", + "LabelSyncPlaySettingsMinDelaySkipToSyncHelp": "Atraso mínimo de reprodução (em ms) após o qual SkipToSync tenta corrigir a posição de reprodução.", + "OptionMaxActiveSessions": "Definir o número máximo de sessões de usuário simultâneas.", + "LabelSyncPlaySettingsSpeedToSyncDurationHelp": "Quantidade de milissegundos usados pelo SpeedToSync para corrigir a posição de reprodução.", + "SubtitleAppearanceSettingsDisclaimer": "As configurações a seguir não se aplicam às legendas gráficas mencionadas acima ou às legendas ASS/SSA que incorporam seus próprios estilos.", + "UnsupportedPlayback": "Jellyfin não pode desencriptar conteúdo protegido por DRM, mas todo o conteúdo será testado de qualquer maneira, incluindo títulos protegidos. Alguns arquivos podem aparecer completamente pretos devido à encriptação ou a outros recursos não suportados, como títulos interativos.", + "MessageSyncPlayGroupWait": "{0} está a armazenar em buffer…" } From 9c14a575fcbd2b2882164ecb28dc7076a5fa2200 Mon Sep 17 00:00:00 2001 From: fernospam Date: Thu, 8 Feb 2024 09:43:13 +0000 Subject: [PATCH 003/118] Translated using Weblate (Spanish) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/es/ --- src/strings/es.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/strings/es.json b/src/strings/es.json index 17d9793e06..09b8745099 100644 --- a/src/strings/es.json +++ b/src/strings/es.json @@ -733,7 +733,7 @@ "MessageReenableUser": "Mira abajo para reactivarlo", "MessageTheFollowingLocationWillBeRemovedFromLibrary": "Se eliminarán las siguientes ubicaciones de medios de tu biblioteca", "MessageUnableToConnectToServer": "No podemos conectar con el servidor seleccionado ahora mismo. Por favor, asegúrate de que esta funcionando e inténtalo otra vez.", - "MessageUnsetContentHelp": "El contenido se mostrará como carpetas planas. Para tener mejores resultados utiliza el gestor de metadatos para establecer los tipos de contenidos de las sub-carpetas.", + "MessageUnsetContentHelp": "El contenido se mostrará como carpetas simples. Para tener mejores resultados utiliza el gestor de metadatos para establecer los tipos de contenidos de las sub-carpetas.", "MessageYouHaveVersionInstalled": "Actualmente tienes la versión {0} instalada.", "Metadata": "Metadatos", "MetadataManager": "Administrador de Metadatos", @@ -801,7 +801,7 @@ "OptionDisableUserHelp": "El servidor no aceptará conexiones de este usuario. Si existen conexiones de este usuario, finalizarán inmediatamente.", "OptionDislikes": "No me gusta", "OptionDisplayFolderView": "Mostrar una vista de carpeta para ver las carpetas de medios en plano", - "OptionDisplayFolderViewHelp": "Mostrar carpetas junto con tus otras bibliotecas de medios. Esto es útil si te gustar tener una vista plana de carpetas.", + "OptionDisplayFolderViewHelp": "Mostrar carpetas junto con tus otras bibliotecas de medios. Esto es útil si te gustar tener una vista simple de carpetas.", "OptionDownloadImagesInAdvance": "Descargar imágenes con antelación", "OptionDownloadImagesInAdvanceHelp": "Por defecto, la mayoría de las imágenes solo se descargan cuando son solicitadas por un cliente. Activa esta opción para descargar todas las imágenes por adelantado, a medida que se importan nuevos medios. Esto puede causar escaneos de biblioteca significativamente más largos.", "OptionEmbedSubtitles": "Integrado con el contenedor", @@ -1781,5 +1781,6 @@ "SelectAudioNormalizationHelp": "Ganancia de pista - ajusta el volumen de cada pista para que suenen al mismo volumen. Ganancia de álbum - ajusta el volumen de todas las pistas de un álbum, manteniendo el rango dinámico del álbum.", "LabelAlbumGain": "Ganancia de Álbum", "LabelSelectAudioNormalization": "Normalización de audio", - "LabelTrackGain": "Ganancia de pista" + "LabelTrackGain": "Ganancia de pista", + "HeaderAllRecordings": "Todas las grabaciones" } From 16c88bf792758c439b09e206a19dde5e04938f18 Mon Sep 17 00:00:00 2001 From: dLay-iOS Date: Thu, 8 Feb 2024 11:34:44 +0000 Subject: [PATCH 004/118] Translated using Weblate (Malayalam) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ml/ --- src/strings/ml.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/strings/ml.json b/src/strings/ml.json index ada97d9bcf..0a197d5011 100644 --- a/src/strings/ml.json +++ b/src/strings/ml.json @@ -1585,5 +1585,7 @@ "ButtonExitApp": "അപ്ലിക്കേഷനിൽ നിന്ന് പുറത്തു വരുക", "ButtonClose": "അടയ്ക്കുക", "ButtonBackspace": "ബാക്ക്സ്പേസ്", - "AddToFavorites": "പ്രിയപ്പെട്ടതിലേക്ക് ചേർക്കുക" + "AddToFavorites": "പ്രിയപ്പെട്ടതിലേക്ക് ചേർക്കുക", + "AllowCollectionManagement": "ശേഖരങ്ങൾ നിയന്ത്രിക്കാൻ ഈ ഉപയോക്താവിനെ അനുവദിക്കുക", + "AllowSegmentDeletion": "സെഗ്‌മെൻ്റുകൾ ഇല്ലാതാക്കുക" } From 675a59adc452db412c09a0c2dbb260b095b961da Mon Sep 17 00:00:00 2001 From: hatsiko panado Date: Fri, 9 Feb 2024 08:29:16 +0000 Subject: [PATCH 005/118] Translated using Weblate (Filipino) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/fil/ --- src/strings/fil.json | 79 ++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/src/strings/fil.json b/src/strings/fil.json index d4cf54c815..1316c9f528 100644 --- a/src/strings/fil.json +++ b/src/strings/fil.json @@ -468,7 +468,7 @@ "LabelSelectAudioChannels": "Mga channel", "LabelAllowedAudioChannels": "Pinakamataas na Mga Pinahihintulutang Audio Channel", "AllowHevcEncoding": "Payagan ang pag-encode sa HEVC na format", - "PreferFmp4HlsContainerHelp": "Mas gustong gamitin ang fMP4 bilang default na lalagyan para sa HLS, na ginagawang posible na idirekta ang pag-stream ng HEVC na nilalaman sa mga sinusuportahang device.", + "PreferFmp4HlsContainerHelp": "Mas gustong gamitin ang fMP4 bilang default na lalagyan para sa HLS, na ginagawang posible na idirekta ang pag-stream ng HEVC at AV1 na nilalaman sa mga sinusuportahang device.", "PreferFmp4HlsContainer": "Mas gusto ang fMP4-HLS Media Container", "LabelSyncPlayInfo": "Impormasyon ng SyncPlay", "LabelOriginalMediaInfo": "Orihinal na Impormasyon ng Media", @@ -485,7 +485,7 @@ "AspectRatioCover": "Cover", "EnableFallbackFontHelp": "I-enable ang mga custom alternate font. Maiiwasan nito ang problema ng maling pag-render ng subtitle.", "EnableFallbackFont": "I-enable ang mga fallback na font", - "LabelFallbackFontPathHelp": "Tumukoy ng path na naglalaman ng mga fallback na font para sa pag-render ng mga subtitle ng ASS/SSA. Ang maximum na pinapayagang kabuuang laki ng font ay 20 MB. Inirerekomenda ang magaan at web-friendly na mga format ng font gaya ng woff2.", + "LabelFallbackFontPathHelp": "Ang mga fonts na ito ay ginagamit ng ilang kilyente para magrender ng mga subtitulo. Pakiusap at sumangguni sa dokyumentasyon para sa karagdagang impormasyon.", "LabelFallbackFontPath": "Path ng Fallback font folder", "HeaderSelectFallbackFontPathHelp": "Mag-browse o ilagay ang path ng fallback font folder na gagamitin para sa pag-render ng mga subtitle ng ASS/SSA.", "MoveRight": "Lumipat pakanan", @@ -621,7 +621,7 @@ "LabelDisplayOrder": "Order ng Display", "LabelDisplayName": "Ang Display name", "LabelDisplayLanguageHelp": "Ang pagsasalin ng Jellyfin ay isang patuloy na proyekto.", - "LabelDisplayLanguage": "Display language", + "LabelDisplayLanguage": "Ipakita ang lingwahe", "LabelDiscNumber": "Numero ng disc", "LabelDisableCustomCss": "I-disable ang custom na CSS code para sa theming/branding na ibinigay mula sa server.", "LabelDidlMode": "Mode ng DIDL", @@ -652,7 +652,7 @@ "LabelCommunityRating": "Rating ng komunidad", "LabelColorTransfer": "Color transfer", "LabelColorSpace": "Color space", - "LabelColorPrimaries": "Color primaries", + "LabelColorPrimaries": "Mga primerang kulay", "LabelCollection": "Koleksyon", "LabelChromecastVersion": "Bersyon ng Google Cast", "LabelChannels": "Mga Channel", @@ -714,7 +714,7 @@ "QuickConnectInvalidCode": "Di-wastong Quick Connect code", "QuickConnectDescription": "Upang mag-sign in gamit ang Quick Connect, piliin ang button na 'Quick Connect' sa device kung saan ka nagla-log in at ilagay ang ipinapakitang code sa ibaba.", "QuickConnectDeactivated": "Na-deactivate ang Quick Connect bago maaprubahan ang kahilingan sa pag-log in", - "QuickConnectAuthorizeSuccess": "Pinahintulutan ang kahilingan", + "QuickConnectAuthorizeSuccess": "Matagumpay mong na pahitululang ang iyong device!", "QuickConnectAuthorizeFail": "Hindi kilalang Quick Connect code", "QuickConnectAuthorizeCode": "Ipasok ang code {0} upang mag-login", "QuickConnectActivationSuccessful": "Matagumpay na na-activate", @@ -826,7 +826,7 @@ "HeaderResponseProfile": "Response Profile", "HeaderRemoveMediaLocation": "Alisin ang Lokasyon ng Media", "HeaderRemoveMediaFolder": "Alisin ang Media Folder", - "HeaderRemoteControl": "Remote Control", + "HeaderRemoteControl": "Remote Kontrol", "HeaderRemoteAccessSettings": "Mga Setting ng Remote Access", "HeaderRecordingPostProcessing": "Pagre-record ng Post Processing", "HeaderRecordingOptions": "Mga Opsyon sa Pagre-record", @@ -958,11 +958,11 @@ "MessageSent": "Naipadala ang mensahe.", "MessagePluginInstallError": "Nagkaroon ng error habang ini-install ang plugin.", "MessagePluginInstalled": "Matagumpay na na-install ang plugin. Kailangang i-restart ang server para magkabisa ang mga pagbabago.", - "MessagePluginInstallDisclaimer": "Ang mga plugin na ginawa ng mga miyembro ng komunidad ay isang mahusay na paraan upang mapahusay ang iyong karanasan sa mga karagdagang feature at benepisyo. Bago i-install, mangyaring magkaroon ng kamalayan sa mga epekto na maaaring mayroon sila sa iyong server, tulad ng mas mahabang pag-scan sa library, karagdagang pagproseso sa background, at pagbaba ng katatagan ng system.", + "MessagePluginInstallDisclaimer": "BABALA: Ang pagiinstall ng mga third party plugins ay may kaakibat na peligro. Ito'y maaring maglalaman ng unstable o malisyosong code, at pwedeng magbago anumang oras. Mag install lamang ng mga plugins galing sa mga may-akdang iyong pinagkakatiwalaan, at pakiusap na alamin ang mga posibleng epekto na kaakibat nito, kasama ang panlabas na service queries, mas matagal na scans ng aklatan, o karagdagan background processing.", "MessagePluginConfigurationRequiresLocalAccess": "Upang i-set up ang plugin na ito mangyaring mag-sign in nang direkta sa iyong lokal na server.", "MessagePleaseEnsureInternetMetadata": "Pakitiyak na ang pag-download ng metadata sa internet ay maka-enable.", "MessagePlayAccessRestricted": "Ang pag-playback ng nilalamang ito ay kasalukuyang pinaghihigpitan. Mangyaring makipag-ugnayan sa administrator ng iyong server para sa higit pang impormasyon.", - "MessagePasswordResetForUsers": "Na-reset ng mga sumusunod na user ang kanilang mga password. Maaari na silang mag-sign in gamit ang Easy PIN code na ginamit para gawin ang pag-reset.", + "MessagePasswordResetForUsers": "Na-reset ng mga sumusunod na user ang kanilang mga password. Maaari na silang mag-sign in gamit ang PIN code na ginamit para gawin ang pag-reset.", "MessageNoTrailersFound": "I-install ang trailers channel upang mapahusay ang iyong karanasan sa pelikula sa pamamagitan ng pagdaragdag ng library ng mga trailer sa internet.", "MessageNothingHere": "Walang nakalagay dito.", "MessageNoServersAvailable": "Walang nahanap na mga server gamit ang awtomatikong pagtuklas ng server.", @@ -1084,7 +1084,7 @@ "LabelRefreshMode": "Mode ng pag-refresh", "LabelRecordingPathHelp": "Tukuyin ang default na lokasyon upang i-save ang mga pag-record. Kung iniwang walang laman, gagamitin ang folder ng data ng programa ng server.", "LabelRecordingPath": "Default na path ng pag-record", - "LabelRecord": "Record", + "LabelRecord": "Rekord", "LabelReasonForTranscoding": "Dahilan ng transcoding", "LabelQuickConnectCode": "Quick Connect code", "LabelPublishedServerUriHelp": "I-override ang URI na ginagamit ng Jellyfin, batay sa interface, o IP address ng kliyente.", @@ -1098,7 +1098,7 @@ "LabelProtocol": "Protocol", "LabelProfileVideoCodecs": "Mga Video codec", "LabelProfileContainersHelp": "Pinaghiwalay ng kuwit. Maaari itong iwanang walang laman upang mailapat sa lahat ng container.", - "LabelProfileContainer": "Container", + "LabelProfileContainer": "Lalagyan", "LabelProfileCodecsHelp": "Pinaghiwalay ng kuwit. Maaari itong iwanang walang laman upang mailapat sa lahat ng mga codec.", "LabelProfileCodecs": "Mga codec", "LabelProfileAudioCodecs": "Codecs ng Audio", @@ -1116,13 +1116,13 @@ "LabelPlaceOfBirth": "Lugar ng kapanganakan", "LabelPersonRoleHelp": "Halimbawa: Ice cream truck driver", "LabelPersonRole": "Role", - "LabelPath": "Path", + "LabelPath": "Pagdaraanan", "LabelPasswordResetProvider": "Provider ng Password Reset", "LabelPasswordRecoveryPinCode": "PIN code", "LabelPasswordConfirm": "Password (kumpirmahin)", "LabelPassword": "Password", "LabelParentNumber": "Numbero ng Parent", - "LabelParentalRating": "Parental rating", + "LabelParentalRating": "Rating ng patnubay", "LabelOverview": "Pangkalahatang-ideya", "LabelOriginalTitle": "Orihinal na pamagat", "LabelOriginalName": "Orihinal na pangalan", @@ -1159,7 +1159,7 @@ "LabelMinBackdropDownloadWidth": "Minimum na lapad ng pag-download ng backdrop", "LabelMinAudiobookResumeHelp": "Ang mga pamagat ay ipinapalagay na hindi nai-play kung huminto bago ang oras na ito.", "LabelMinAudiobookResume": "Minimum sa pag-resume ng Audiobook sa ilang minuto", - "LabelMethod": "Method", + "LabelMethod": "Metodolohiya", "LabelMetadataSaversHelp": "Piliin ang mga format ng file na gagamitin kapag sine-save ang iyong metadata.", "LabelMetadataSavers": "Mga metadata saver", "LabelMetadataReadersHelp": "I-rank ang iyong ginustong lokal na pinagmumulan ng metadata ayon sa priyoridad. Ang unang file na natagpuan ay babasahin.", @@ -1179,12 +1179,12 @@ "LabelMaxParentalRating": "Pinakamataas na pinapayagang parental rating", "LabelMaxMuxingQueueSizeHelp": "Maximum na bilang ng mga packet na maaaring i-buffer habang naghihintay na magsimula ang lahat ng stream. Subukang dagdagan ito kung matugunan mo pa rin ang error na \"Too many packets buffered for output stream\" sa mga log ng FFmpeg. Ang inirerekomendang halaga ay 2048.", "LabelMaxMuxingQueueSize": "Size ng Max muxing queue", - "LabelMaxChromecastBitrate": "Google Cast streaming quality", + "LabelMaxChromecastBitrate": "Kalidad ng Google Cast streaming", "LabelMaxBackdropsPerItem": "Maximum na bilang ng mga backdrop bawat item", "LabelMaxAudiobookResume": "Natitirang minuto ng Audiobook upang ma-resume", "LabelMatchType": "Uri ng Match", "LabelManufacturerUrl": "URL ng Manufacturer", - "LabelManufacturer": "Manufacturer", + "LabelManufacturer": "Pabrikante", "LabelLogs": "Mga log", "LabelLoginDisclaimerHelp": "Isang mensahe na ipapakita sa ibaba ng pahina ng pag-login.", "LabelLoginDisclaimer": "Disclaimer sa pag-login", @@ -1275,8 +1275,8 @@ "ErrorAddingMediaPathToVirtualFolder": "Nagkaroon ng error sa pagdaragdag ng media path. Pakitiyak na wasto ang landas at may access ang Jellyfin sa lokasyong iyon.", "ErrorAddingListingsToSchedulesDirect": "Nagkaroon ng error sa pagdaragdag ng lineup sa iyong Schedules Direct account. Nagbibigay-daan lang ang Schedules Direct ng limitadong bilang ng mga lineup sa bawat account. Maaaring kailanganin mong mag-log in sa Schedules Direct website at alisin ang iba pang mga listahan mula sa iyong account bago magpatuloy.", "Episodes": "Mga episode", - "Episode": "Episode", - "Engineer": "Sound engineer", + "Episode": "Episodyo", + "Engineer": "Inhinyerong pantunog", "EndsAtValue": "Magtatapos sa {0}", "Ended": "Natapos na", "EncoderPresetHelp": "Pumili ng isang mas mabilis na halaga upang mapabuti ang pagganap, o isang mas mabagal na halaga upang mapabuti ang kalidad.", @@ -1292,20 +1292,20 @@ "EnableFasterAnimations": "Mas mabilis na mga animation", "EnableExternalVideoPlayersHelp": "Lalabas ang external player menu kapag sinisimulan ang pag-playback ng video.", "EnableExternalVideoPlayers": "Mga external na video player", - "EnableDisplayMirroring": "Display mirroring", + "EnableDisplayMirroring": "Pagsasalamin ng Display", "EnableDetailsBannerHelp": "Magpakita ng larawan ng banner sa tuktok ng pahina ng mga detalye ng item.", "EnableDetailsBanner": "Banner ng Mga Detalye", "EnableColorCodedBackgrounds": "Mga background na may color code", - "EnableCinemaMode": "Cinema mode", + "EnableCinemaMode": "Takada ng takilya", "EnableBlurHashHelp": "Ang mga larawang nilo-load pa rin ay ipapakita na may natatanging placeholder.", "EnableBackdropsHelp": "Ipakita ang mga backdrop sa background ng ilang page habang nagba-browse sa library.", - "EnableAutoCast": "Itakda bilang Default", + "EnableAutoCast": "Itakda bilang default", "EditSubtitles": "I-edit ang mga subtitle", "EditMetadata": "I-edit ang metadata", "EditImages": "I-edit ang mga larawan", "Edit": "I-edit", "EasyPasswordHelp": "Ang iyong Easy PIN code ay ginagamit para sa offline na pag-access sa mga sinusuportahang kliyente at maaari ding gamitin para sa madaling pag-sign in sa network.", - "DropShadow": "Drop Shadow", + "DropShadow": "Lalim ng Anino", "DrmChannelsNotImported": "Hindi mai-import ang mga channel na may DRM.", "DownloadsValue": "{0} (na) pag-download", "Download": "I-download", @@ -1315,13 +1315,13 @@ "DisplayMissingEpisodesWithinSeasons": "Ipakita ang mga nawawalang episode sa loob ng mga season", "DisplayInOtherHomeScreenSections": "Magpakita sa home screen ng mga seksyon gaya ng 'Bagong Media' at 'Ituloy ang Panonood'", "DisplayInMyMedia": "Ipakita sa home screen", - "Display": "Display", + "Display": "Ipakita", "Disconnect": "Idiskonekta", "Disc": "Disc", "DirectStreaming": "Direktang streaming", "DirectStreamHelp2": "Ang power na na-consume sa pamamagitan ng direktang streaming ay karaniwang nakadepende sa audio profile. Tanging ang video stream ay lossless.", "DirectStreamHelp1": "Ang video stream ay tugma sa device, ngunit may hindi tugmang format ng audio (DTS, Dolby TrueHD, atbp.) o bilang ng mga audio channel. Ang video stream ay ire-repack nang walang pagkawala sa mabilisang bago ipadala sa device. Tanging ang audio stream lang ang ita-transcode.", - "DirectPlayHelp": "Ang source file ay ganap na tugma sa client na ito, at ang session ay tumatanggap ng file nang walang pagbabago.", + "DirectPlayHelp": "", "DirectPlaying": "Direktang pag-play", "Directors": "Mga direktor", "Director": "Direktor", @@ -1329,7 +1329,7 @@ "DetectingDevices": "Pag-detect ng mga device", "Desktop": "Desktop", "Descending": "Pababa", - "Depressed": "Depressed", + "Depressed": "Banguwas", "DeleteUserConfirmation": "Sigurado ka bang gusto mong tanggalin ang user na ito?", "DeleteUser": "Tanggalin ang User", "DeleteMedia": "Tanggalin ang media", @@ -1366,10 +1366,10 @@ "ConfirmDeleteImage": "Tanggalin ang larawan?", "ConfigureDateAdded": "I-set up kung paano tinutukoy ang metadata para sa 'Petsa ng idinagdag' sa Dashboard > Mga Library > Mga Setting ng NFO", "Conductor": "Konduktor", - "Composer": "Composer", + "Composer": "Kompositór", "CommunityRating": "Rating ng komunidad", - "ColorPrimaries": "Color primaries", - "ColorSpace": "Color space", + "ColorPrimaries": "Mga primerong kulay", + "ColorSpace": "Espasyo ng Kulay", "ColorTransfer": "Color transfer", "ClientSettings": "Mga Setting ng Client", "ClearQueue": "I-clear ang queue", @@ -1440,7 +1440,7 @@ "LabelVideoRange": "Range ng video", "LabelVideoCodec": "Codec ng video", "LabelVideoBitrate": "Bitrate ng video", - "LabelValue": "Value", + "LabelValue": "Halaga", "LabelVaapiDeviceHelp": "Ito ang render node na ginagamit para sa hardware acceleration.", "LabelVaapiDevice": "Device ng VA-API", "LabelUserRemoteClientBitrateLimitHelp": "I-override ang default na global value na itinakda sa mga setting ng server, tingnan ang Dashboard > Pag-playback > Streaming.", @@ -1503,7 +1503,7 @@ "LabelSyncPlaySettingsSyncCorrectionHelp": "Paganahin ang aktibong pag-sync ng playback sa pamamagitan ng pagpapabilis ng media o sa pamamagitan ng paghahanap sa tinantyang posisyon. Huwag paganahin ito sa kaso ng matinding pagkautal.", "LabelSyncPlaySettingsSyncCorrection": "Pagwawasto sa Sync", "LabelSyncPlaySettingsExtraTimeOffsetHelp": "Manu-manong isaayos ang time offset (sa ms) gamit ang napiling device para sa time sync. Tweak with care.", - "LabelSyncPlaySettingsExtraTimeOffset": "Extra time offset", + "LabelSyncPlaySettingsExtraTimeOffset": "Karagdagang time offset", "LabelSyncPlaySettingsDescription": "Baguhin ang mga kagustuhan sa SyncPlay", "LabelSyncPlayTimeSyncOffset": "Time offset", "LabelSyncPlayTimeSyncDevice": "Pag-sync ng oras sa", @@ -1540,7 +1540,7 @@ "ButtonPreviousTrack": "Previous na track", "ButtonRefreshGuideData": "I-refresh ang Guide Data", "ButtonQuickStartGuide": "Gabay sa Mabilis na Pagsisimula", - "ButtonPlayer": "Player", + "ButtonPlayer": "Pampatugtug", "ButtonPause": "I-pause", "ButtonOpen": "Buksan", "ButtonOk": "Ok", @@ -1573,7 +1573,7 @@ "BoxRear": "Kahon (likod)", "Box": "Kahon", "BookLibraryHelp": "Ang mga audio at text book ay suportado. Suriin ang {0} gabay sa pagpapangalan ng aklat {1}.", - "Blacklist": "Blacklist", + "Blacklist": "Di Pinahihintulutan", "BirthPlaceValue": "Lugar ng kapanganakan: {0}", "BirthLocation": "Lokasyon ng kapanganakan", "BirthDateValue": "Ipinanganak: {0}", @@ -1583,19 +1583,19 @@ "Auto": "Auto", "AuthProviderHelp": "Pumili ng provider ng pagpapatotoo na gagamitin upang patotohanan ang password ng user na ito.", "Authorize": "Pahintulutan", - "Audio": "Audio", - "AspectRatio": "Aspect Ratio", + "Audio": "Odyo", + "AspectRatio": "Aspektong Bahagimbilang", "AsManyAsPossible": "Bilang marami hangga't maaari", "AskAdminToCreateLibrary": "Hilingin sa isang administrator na gumawa ng library.", "Ascending": "Paakyat", "Artist": "Artista", "Art": "Clearart", - "Arranger": "Arranger", + "Arranger": "Nagsisi-ayos", "AroundTime": "Sa paligid ng {0}", "ApiKeysCaption": "Listahan ng mga kasalukuyang naka-enable na API key", "Anytime": "Kahit kailan", "AnyLanguage": "Anumang wika", - "AllowTonemappingHelp": "Maaaring baguhin ng tone-mapping ang dynamic range ng isang video mula sa HDR patungong SDR habang pinapanatili ang mga detalye at kulay ng larawan, na napakahalagang impormasyon para sa kumakatawan sa original scene. Kasalukuyang gumagana lang sa mga HDR10 o HLG na video. Nangangailangan ito ng kaukulang OpenCL o CUDA runtime.", + "AllowTonemappingHelp": "Ang Tone-mapping ay may kakahayang baguhin ang dynamic range ng isang bidyo mula HDR papuntang SDR habang minimintina ang detalye at kulay ng imahe, alin may napakaimportanteng impormasyon para sa pagrerepresenta ng orihinal na senaryo. Kasalukuyang gumagana lamang sa HDR10, HLG at DoVi na mga bidyo. Ito'y nangangailangan ng koresponding OpenCL at Cuda runtime.", "AgeValue": "({0} taong gulang)", "LabelHardwareEncodingOptions": "Mga opsyon sa hardware encoding", "IntelLowPowerEncHelp": "Maaaring panatilihin ng Low-Power Encoding ang hindi kinakailangang pag-sync ng CPU at GPU. Sa Linux dapat ito ay naka-disable kung ang i915 HuC firmware ay hindi na-configure.", @@ -1632,12 +1632,12 @@ "EnableCardLayout": "Magpakita ng cardbox", "ButtonBackspace": "Backspace", "ButtonClose": "Isara", - "ButtonSpace": "Space", + "ButtonSpace": "Puwang", "GoogleCastUnsupported": "Hindi suportado ang Google Cast", "Copied": "Nakopya", "Copy": "Kopyahin", "CopyFailed": "Di makopya", - "Digital": "Digital", + "Digital": "Dihital", "DownloadAll": "Idownload ang lahat", "HeaderDummyChapter": "Mga larawan kada kabanata", "AddToFavorites": "Idagdag sa mga paborito", @@ -1658,7 +1658,7 @@ "SubtitleWhite": "Puti", "SubtitleYellow": "Dilaw", "HeaderRecordingMetadataSaving": "Pagre-record ng Metadata", - "LabelDummyChapterDurationHelp": "Ang agwat ng pagkuha ng larawan ng kabanata sa segundo.", + "LabelDummyChapterDurationHelp": "Ang agwat ng bawat dummy chapters. I-set ng 0 para i-disable ang pag generate ng dummy chapter. Ang pagbago nito ay walang epekto sa nakairal ng dummy chapters.", "HomeVideosPhotos": "Mga Videos at Larawan sa Home", "IgnoreDts": "Ibalewala ang DTS (pag-decode ng timestamp)", "IgnoreDtsHelp": "Ang pag-disable ng option na ito ay maaring maglutas ng ilang isyu, hal. nawawalang audio sa mga channel na may magkahiwalay na audio at video streams.", @@ -1673,5 +1673,6 @@ "LabelThrottleDelaySeconds": "I-throttle pagkatapos", "LabelAlbumGain": "Gain na Album", "LabelThrottleDelaySecondsHelp": "Oras sa segundo pagkatapos babagal ang transcoder. Kailangan sapat ang laki upang mapanatili ng kliyente ang isang malusog ang buffer. Gumagana lang kung naka-enable ang throttling.", - "LabelSegmentKeepSeconds": "Oras upang panatilihin ang mga segmenta" + "LabelSegmentKeepSeconds": "Oras upang panatilihin ang mga segmenta", + "BackdropScreensaver": "Backdrop Screensaver" } From 03be323f08744f26ae4edea95f2fb9015769852b Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Sat, 10 Feb 2024 22:13:12 +0800 Subject: [PATCH 006/118] Update LabelCountry to ease the naming of controversial regions Signed-off-by: nyanmisaka --- src/strings/en-us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 1f282a2112..bf71f50583 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -598,7 +598,7 @@ "LabelCommunityRating": "Community rating", "LabelContentType": "Content type", "LabelCorruptedFrames": "Corrupted frames", - "LabelCountry": "Country", + "LabelCountry": "Country/Region", "LabelCreateHttpPortMap": "Enable automatic port mapping for HTTP traffic as well as HTTPS.", "LabelCreateHttpPortMapHelp": "Permit automatic port mapping to create a rule for HTTP traffic in addition to HTTPS traffic.", "LabelCriticRating": "Critics rating", From 9aa47336ee24ab4d8c175417e82856b54f3263e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Sun, 11 Feb 2024 06:24:37 +0000 Subject: [PATCH 007/118] Translated using Weblate (Czech) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/cs/ --- src/strings/cs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/cs.json b/src/strings/cs.json index d3a8897346..1ed61bbcc1 100644 --- a/src/strings/cs.json +++ b/src/strings/cs.json @@ -379,7 +379,7 @@ "LabelCollection": "Kolekce", "LabelCommunityRating": "Hodnocení komunity", "LabelContentType": "Typ obsahu", - "LabelCountry": "Země", + "LabelCountry": "Země/oblast", "LabelCriticRating": "Hodnocení kritiků", "LabelCurrentPassword": "Aktuální heslo", "LabelCustomCss": "Vlastní CSS", From 1f26e0b9b028ce9f6bb8f9bd54125bb293c4e2a1 Mon Sep 17 00:00:00 2001 From: Kityn Date: Sun, 11 Feb 2024 09:31:15 +0000 Subject: [PATCH 008/118] Translated using Weblate (Polish) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/pl/ --- src/strings/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/pl.json b/src/strings/pl.json index 545c4163fb..c8a75354ed 100644 --- a/src/strings/pl.json +++ b/src/strings/pl.json @@ -458,7 +458,7 @@ "LabelCollection": "Kolekcja", "LabelCommunityRating": "Ocena społeczności", "LabelContentType": "Typ zawartości", - "LabelCountry": "Kraj", + "LabelCountry": "Kraj/region", "LabelCriticRating": "Ocena krytyków", "LabelCurrentPassword": "Aktualne hasło", "LabelCustomCertificatePath": "Ścieżka do niestandardowego certyfikatu SSL", From 8e2f213ba70f2e611e75a481d9bb8331cad3c98f Mon Sep 17 00:00:00 2001 From: bene toffix Date: Sun, 11 Feb 2024 13:54:38 +0000 Subject: [PATCH 009/118] Translated using Weblate (Catalan) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ca/ --- src/strings/ca.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/ca.json b/src/strings/ca.json index 330af2b672..1952fc1bc0 100644 --- a/src/strings/ca.json +++ b/src/strings/ca.json @@ -223,7 +223,7 @@ "LabelCollection": "Col·lecció", "LabelCommunityRating": "Valoració de la comunitat", "LabelContentType": "Tipus de contingut", - "LabelCountry": "País", + "LabelCountry": "País/Regió", "LabelCriticRating": "Valoració dels сrítics", "LabelCurrentPassword": "Contrasenya actual", "LabelCustomCss": "Codi CSS propi", From f02fec98447639fbc00e7184df68afc353a16898 Mon Sep 17 00:00:00 2001 From: Bas Date: Sun, 11 Feb 2024 15:31:49 +0000 Subject: [PATCH 010/118] Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/nl/ --- src/strings/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/nl.json b/src/strings/nl.json index 7c48ddc035..86f8010e75 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -432,7 +432,7 @@ "LabelCollection": "Collectie", "LabelCommunityRating": "Beoordeling gemeenschap", "LabelContentType": "Inhoudstype", - "LabelCountry": "Land", + "LabelCountry": "Land/regio", "LabelCriticRating": "Beoordeling critici", "LabelCurrentPassword": "Huidig wachtwoord", "LabelCustomCertificatePath": "Aangepast SSL-certificaatpad", From 670440821664971ec566d4ad6f73e832e8bcb287 Mon Sep 17 00:00:00 2001 From: sleepycatcoding Date: Sun, 11 Feb 2024 15:03:59 +0000 Subject: [PATCH 011/118] Translated using Weblate (Estonian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/et/ --- src/strings/et.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/et.json b/src/strings/et.json index c379582a6c..19287de1da 100644 --- a/src/strings/et.json +++ b/src/strings/et.json @@ -98,7 +98,7 @@ "LabelCriticRating": "Kriitikute hinne", "LabelCreateHttpPortMap": "Luba automaatne pordikaardistus nii HTTP kui ka HTTPS liikluse jaoks.", "LabelCreateHttpPortMapHelp": "Luba automaatsel pordikaardistusel luua lisaks HTTP liiklusele ka HTTPS liikluse reegel.", - "LabelCountry": "Riik", + "LabelCountry": "Riik/piirkond", "LabelCorruptedFrames": "Rikutud kaadrid", "LabelContentType": "Sisu tüüp", "LabelCommunityRating": "Kogukonna hinne", From 8799485ce14795abe5a2825894d6245ce53d548f Mon Sep 17 00:00:00 2001 From: ram bahadur Date: Sun, 11 Feb 2024 13:43:26 +0000 Subject: [PATCH 012/118] Translated using Weblate (Nepali) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ne/ --- src/strings/ne.json | 54 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/strings/ne.json b/src/strings/ne.json index c28be47d57..37c172069f 100644 --- a/src/strings/ne.json +++ b/src/strings/ne.json @@ -33,5 +33,57 @@ "AddToFavorites": "मनपर्ने मा थप्नुहोस्", "Add": "थप्नुहोस्", "Actor": "अभिनेता", - "Absolute": "निरपेक्ष" + "Absolute": "निरपेक्ष", + "AddToCollection": "संग्रहमा थप्नुहोस्", + "AirDate": "प्रसारण मिति", + "Aired": "प्रसारित", + "ButtonAddImage": "चित्र थप्नुहोस्", + "ButtonResume": "सुचारु गर्नुहोस्", + "ButtonScanAllLibraries": "भन्डरमा खोज्नुहोस्", + "LatestFromLibrary": "हालसालै थपिएको", + "LabelTitle": "शीर्षक", + "LogLevel.Warning": "चेतावनी", + "ButtonOk": "हुन्छ", + "ButtonOpen": "खोल्नुहोस", + "ButtonPause": "रोक्नुहोस्", + "ButtonRename": "पुन: नामकरण", + "ButtonRemove": "हटाउनुहोस्", + "ButtonSend": "पठाउनुहोस्", + "ButtonShutdown": "बन्द गर्नुहोस्", + "ButtonSignIn": "", + "Lyricist": "गीतकार", + "LabelVideoInfo": "श्रव्यदृश्यको जानकारी", + "LabelTime": "समय", + "LiveTV": "प्रत्यक्ष टेलिभिजन", + "LiveBroadcasts": "प्रत्यक्ष प्रसारण", + "Localization": "स्थानीयकरण", + "LogLevel.Information": "जानकारी", + "LabelWeb": "संजल", + "LabelYear": "वर्ष", + "LabelSystem": "प्रणाली", + "LogLevel.Error": "त्रुटि", + "LogLevel.None": "", + "ButtonCancel": "रद्द गर्नुहोस्", + "Edit": "सम्पादन गर्नुहोस्", + "Controls": "नियन्त्रणहरू", + "LabelTimeLimitHours": "समय सीमा (घण्टा)", + "LabelYoureDone": "तपाईंले पूरा गर्नुभयो !", + "Live": "प्रत्यक्ष", + "List": "सूची", + "CommunityRating": "सामुदायिक मूल्याङ्कन", + "LabelTextColor": "अक्षरको रङ", + "LabelTextSize": "अक्षरको मोटाइ", + "LabelTextWeight": "अक्षरको बजन", + "BirthLocation": "जन्मस्थान", + "BirthPlaceValue": "जन्मथलो:{०}", + "Blacklist": "कालोसूची", + "ButtonAddUser": "प्रयोगकर्ता थप्नुहोस्", + "ButtonArrowLeft": "बायाँ", + "ButtonInfo": "जानकारी", + "ButtonStart": "सुरु गर्नुहोस्", + "ButtonStop": "रोक्नुहोस्", + "ButtonSubmit": "पेश गर्नुहोस्", + "AiTranslated": "कृत्रिम बौद्धिक अनुवाद", + "Categories": "श्रेणीहरू", + "ButtonArrowRight": "दायाँ" } From d702ad938a1c2fd4d34d6a5a4cc48621241d8bfc Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Sun, 11 Feb 2024 23:32:14 +0300 Subject: [PATCH 013/118] add show method for PlaylistEditor Class --- src/components/itemContextMenu.js | 3 ++- src/components/multiSelect/multiSelect.js | 14 ++++++++++---- src/components/playlisteditor/playlisteditor.js | 2 +- src/components/remotecontrol/remotecontrol.js | 7 ++++++- src/components/shortcuts.js | 8 ++++++-- src/controllers/list.js | 7 ++++++- src/scripts/playlists.js | 7 ++++++- 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index 69caf9cbce..6d1c3c24f5 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -339,7 +339,8 @@ function executeCommand(item, id, options) { break; case 'addtoplaylist': import('./playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { - new PlaylistEditor({ + const playlistEditor = new PlaylistEditor(); + playlistEditor.show({ items: [itemId], serverId: serverId }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); diff --git a/src/components/multiSelect/multiSelect.js b/src/components/multiSelect/multiSelect.js index 48cbce0e1f..d69c7b33bd 100644 --- a/src/components/multiSelect/multiSelect.js +++ b/src/components/multiSelect/multiSelect.js @@ -6,7 +6,6 @@ import dom from '../../scripts/dom'; import './multiSelect.scss'; import ServerConnections from '../ServerConnections'; import alert from '../alert'; -import PlaylistEditor from '../playlisteditor/playlisteditor'; import confirm from '../confirm/confirm'; import itemHelper from '../itemHelper'; import datetime from '../../scripts/datetime'; @@ -269,9 +268,16 @@ function showMenuForSelectedItems(e) { dispatchNeedsRefresh(); break; case 'playlist': - new PlaylistEditor({ - items: items, - serverId: serverId + import('../playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { + const playlistEditor = new PlaylistEditor(); + playlistEditor.show({ + items: items, + serverId: serverId + }).catch(() => { + // Dialog closed + }); + }).catch(err => { + console.error('[AddToPlaylist] failed to load playlist editor', err); }); hideSelections(); dispatchNeedsRefresh(); diff --git a/src/components/playlisteditor/playlisteditor.js b/src/components/playlisteditor/playlisteditor.js index ee7cd2b41a..625135a472 100644 --- a/src/components/playlisteditor/playlisteditor.js +++ b/src/components/playlisteditor/playlisteditor.js @@ -222,7 +222,7 @@ function centerFocus(elem, horiz, on) { } export class PlaylistEditor { - constructor(options) { + show(options) { const items = options.items || {}; currentServerId = options.serverId; diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index 1120e03c02..9406e16e2b 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -704,15 +704,20 @@ export default function () { import('../playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { getSaveablePlaylistItems().then(function (items) { const serverId = items.length ? items[0].ServerId : ApiClient.serverId(); - new PlaylistEditor({ + const playlistEditor = new PlaylistEditor(); + playlistEditor.show({ items: items.map(function (i) { return i.Id; }), serverId: serverId, enableAddToPlayQueue: false, defaultValue: 'new' + }).catch(() => { + // Dialog closed }); }); + }).catch(err => { + console.error('[savePlaylist] failed to load playlist editor', err); }); } diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 03418f3e21..cadb8cc20e 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -282,11 +282,15 @@ function executeAction(card, target, action) { function addToPlaylist(item) { import('./playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { - new PlaylistEditor().show({ + const playlistEditor = new PlaylistEditor(); + playlistEditor.show({ items: [item.Id], serverId: item.ServerId - + }).catch(() => { + // Dialog closed }); + }).catch(err => { + console.error('[addToPlaylist] failed to load playlist editor', err); }); } diff --git a/src/controllers/list.js b/src/controllers/list.js index c5497be276..69b713e150 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -401,10 +401,15 @@ function onNewItemClick() { const instance = this; import('../components/playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { - new PlaylistEditor({ + const playlistEditor = new PlaylistEditor(); + playlistEditor.show({ items: [], serverId: instance.params.serverId + }).catch(() => { + // Dialog closed }); + }).catch(err => { + console.error('[onNewItemClick] failed to load playlist editor', err); }); } diff --git a/src/scripts/playlists.js b/src/scripts/playlists.js index b8b7380b57..33963bf8a2 100644 --- a/src/scripts/playlists.js +++ b/src/scripts/playlists.js @@ -187,10 +187,15 @@ export default function (view) { view.querySelector('.btnNewPlaylist').addEventListener('click', function () { import('../components/playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { const serverId = ApiClient.serverInfo().Id; - new PlaylistEditor({ + const playlistEditor = new PlaylistEditor(); + playlistEditor.show({ items: [], serverId: serverId + }).catch(() => { + // Dialog closed }); + }).catch(err => { + console.error('[btnNewPlaylist] failed to load playlist editor', err); }); }); onViewStyleChange(); From 46885bbafe518641b58ac7d211fb0871460c919e Mon Sep 17 00:00:00 2001 From: felix920506 Date: Mon, 12 Feb 2024 02:24:55 +0000 Subject: [PATCH 014/118] Translated using Weblate (Chinese (Traditional)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/zh_Hant/ --- src/strings/zh-tw.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/zh-tw.json b/src/strings/zh-tw.json index 601878db02..ab2177b9f8 100644 --- a/src/strings/zh-tw.json +++ b/src/strings/zh-tw.json @@ -67,7 +67,7 @@ "LabelCachePath": "快取路徑", "LabelCollection": "收藏櫃", "LabelContentType": "內容類型", - "LabelCountry": "國家", + "LabelCountry": "國家/地區", "LabelCurrentPassword": "當前的密碼", "LabelDay": "星期", "LabelEnableDlnaClientDiscoveryInterval": "尋找用戶端時間間隔", From d9d6ca7aca94e08ec3c0183cf334a3e9411a6c10 Mon Sep 17 00:00:00 2001 From: hoanghuy309 Date: Mon, 12 Feb 2024 04:44:01 +0000 Subject: [PATCH 015/118] Translated using Weblate (Vietnamese) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/vi/ --- src/strings/vi.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/strings/vi.json b/src/strings/vi.json index f2341ee9ca..4588baae76 100644 --- a/src/strings/vi.json +++ b/src/strings/vi.json @@ -24,7 +24,7 @@ "HeaderSystemDlnaProfiles": "Cấu Hình Hệ Thống", "HeaderUsers": "Người dùng", "LabelAudioLanguagePreference": "Ngôn ngữ thoại ưa thích", - "LabelCountry": "Quốc gia", + "LabelCountry": "Quốc gia/Vùng", "LabelCurrentPassword": "Mật khẩu hiện tại", "LabelDay": "Ngày trong tuần", "LabelEnableDlnaPlayTo": "Bật tính năng 'Phát Với' DLNA", @@ -1765,5 +1765,9 @@ "GridView": "Xem Lưới", "ListView": "Xem Danh Sách", "SelectAudioNormalizationHelp": "Chỉnh nhạc - điều chỉnh âm lượng của mỗi bản nhạc để chúng phát lại với cùng một độ to. Chỉnh Album - điều chỉnh âm lượng của tất cả các bản nhạc trong một album, giữ nguyên dải động của album.", - "LabelAlbumGain": "Chỉnh Album" + "LabelAlbumGain": "Chỉnh Album", + "LabelSegmentKeepSecondsHelp": "Thời gian tính bằng giây mà các phân đoạn cần được giữ lại trước khi chúng bị ghi đè. Phải lớn hơn \"Throle after\". Chỉ hoạt động nếu tính năng xóa phân đoạn được bật.", + "MenuClose": "Đóng Menu", + "MenuOpen": "Mở Menu", + "UserMenu": "Menu Người Dùng" } From ed3e91086031171f3ab6f045f0bb962e46a8a034 Mon Sep 17 00:00:00 2001 From: Brad Beattie Date: Wed, 18 Oct 2023 10:10:35 -0700 Subject: [PATCH 016/118] Update search.tsx --- src/apps/stable/routes/search.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/stable/routes/search.tsx b/src/apps/stable/routes/search.tsx index c9285f6075..10583c381e 100644 --- a/src/apps/stable/routes/search.tsx +++ b/src/apps/stable/routes/search.tsx @@ -11,6 +11,7 @@ import globalize from '../../../scripts/globalize'; const Search: FunctionComponent = () => { const [ query, setQuery ] = useState(); const [ searchParams ] = useSearchParams(); + if (!query && searchParams.get('q')) setQuery(searchParams.get('q') || ''); return ( Date: Wed, 18 Oct 2023 10:15:04 -0700 Subject: [PATCH 017/118] Update search.tsx --- src/apps/stable/routes/search.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/stable/routes/search.tsx b/src/apps/stable/routes/search.tsx index 10583c381e..ca7764f309 100644 --- a/src/apps/stable/routes/search.tsx +++ b/src/apps/stable/routes/search.tsx @@ -11,7 +11,7 @@ import globalize from '../../../scripts/globalize'; const Search: FunctionComponent = () => { const [ query, setQuery ] = useState(); const [ searchParams ] = useSearchParams(); - if (!query && searchParams.get('q')) setQuery(searchParams.get('q') || ''); + if (!query && searchParams.get('query')) setQuery(searchParams.get('query') || ''); return ( Date: Wed, 18 Oct 2023 10:15:52 -0700 Subject: [PATCH 018/118] Update index.js --- src/controllers/itemDetails/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 58e780bd7b..99f6d76f05 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -1258,11 +1258,11 @@ function renderTags(page, item) { } for (let i = 0, length = tags.length; i < length; i++) { - tagElements.push(tags[i]); + tagElements.push('' + tags[i] + ''); } if (tagElements.length) { - itemTags.innerText = globalize.translate('TagsValue', tagElements.join(', ')); + itemTags.innerHTML = globalize.translate('TagsValue', tagElements.join(', ')); itemTags.classList.remove('hide'); } else { itemTags.innerHTML = ''; From 6a1706ba78c41f24261350d272ce62d8a4241df3 Mon Sep 17 00:00:00 2001 From: Brad Beattie Date: Thu, 19 Oct 2023 10:22:34 -0700 Subject: [PATCH 019/118] Update SearchFields.tsx --- src/components/search/SearchFields.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/search/SearchFields.tsx b/src/components/search/SearchFields.tsx index cdc8c69a3c..70bbb8a76f 100644 --- a/src/components/search/SearchFields.tsx +++ b/src/components/search/SearchFields.tsx @@ -31,17 +31,23 @@ const createInputElement = () => ({ const normalizeInput = (value = '') => value.trim(); type SearchFieldsProps = { + query: string, onSearch?: (query: string) => void }; // eslint-disable-next-line @typescript-eslint/no-empty-function -const SearchFields: FunctionComponent = ({ onSearch = () => {} }: SearchFieldsProps) => { +const SearchFields: FunctionComponent = ({ onSearch = () => {}, query }: SearchFieldsProps) => { const element = useRef(null); const getSearchInput = () => element?.current?.querySelector('.searchfields-txtSearch'); const debouncedOnSearch = useMemo(() => debounce(onSearch, 400), [onSearch]); + const initSearchInput = getSearchInput(); + if (initSearchInput) { + initSearchInput.value = query; + } + useEffect(() => { getSearchInput()?.addEventListener('input', e => { debouncedOnSearch(normalizeInput((e.target as HTMLInputElement).value)); From ba099a0e3d600ee11287d47a8e0d6ef7dffa35a4 Mon Sep 17 00:00:00 2001 From: Brad Beattie Date: Thu, 19 Oct 2023 10:23:16 -0700 Subject: [PATCH 020/118] Update search.tsx --- src/apps/stable/routes/search.tsx | 34 +++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/apps/stable/routes/search.tsx b/src/apps/stable/routes/search.tsx index ca7764f309..882e97d447 100644 --- a/src/apps/stable/routes/search.tsx +++ b/src/apps/stable/routes/search.tsx @@ -1,4 +1,4 @@ -import React, { FunctionComponent, useState } from 'react'; +import React, { FunctionComponent, useEffect, useRef, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import Page from '../../../components/Page'; @@ -7,11 +7,37 @@ import SearchResults from '../../../components/search/SearchResults'; import SearchSuggestions from '../../../components/search/SearchSuggestions'; import LiveTVSearchResults from '../../../components/search/LiveTVSearchResults'; import globalize from '../../../scripts/globalize'; +import { history } from '../../../components/router/appRouter'; + +function usePrevious(value: string) { + const ref = useRef(''); + useEffect(() => { + ref.current = value; + }); + return ref.current; +} const Search: FunctionComponent = () => { - const [ query, setQuery ] = useState(); const [ searchParams ] = useSearchParams(); - if (!query && searchParams.get('query')) setQuery(searchParams.get('query') || ''); + const [ query, setQuery ] = useState(searchParams.get('query') || ''); + const prevQuery = usePrevious(query); + + console.error('Search component initialized', { 'urlParam': searchParams.get('query'), 'obj.query': query, 'prevQuery': prevQuery }); + if (query == prevQuery && searchParams.get('query') != query) { + console.error('SET QUERY VIA URL', searchParams.get('query')); + setQuery(searchParams.get('query') || ''); + } + + useEffect(() => { + const newSearch = query ? `?query=${query}` : ''; + if (query != prevQuery && newSearch != history.location.search) { + /* Explicitly using `window.history.pushState` instead of `history.replace` as the use of the latter + triggers a re-rendering of this component, resulting in double-execution searches. If there's a + way to use `history` without this side effect, it would likely be preferable. */ + console.error('PUSH STATE VIA QUERY', query); + window.history.pushState({}, '', `/#${history.location.pathname}${newSearch}`); + } + }, [query, prevQuery]); return ( { title={globalize.translate('Search')} className='mainAnimatedPage libraryPage allLibraryPage noSecondaryNavPage' > - + {!query && Date: Thu, 19 Oct 2023 10:23:52 -0700 Subject: [PATCH 021/118] Update search.tsx --- src/apps/stable/routes/search.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/apps/stable/routes/search.tsx b/src/apps/stable/routes/search.tsx index 882e97d447..309e7820cf 100644 --- a/src/apps/stable/routes/search.tsx +++ b/src/apps/stable/routes/search.tsx @@ -22,9 +22,7 @@ const Search: FunctionComponent = () => { const [ query, setQuery ] = useState(searchParams.get('query') || ''); const prevQuery = usePrevious(query); - console.error('Search component initialized', { 'urlParam': searchParams.get('query'), 'obj.query': query, 'prevQuery': prevQuery }); if (query == prevQuery && searchParams.get('query') != query) { - console.error('SET QUERY VIA URL', searchParams.get('query')); setQuery(searchParams.get('query') || ''); } @@ -34,7 +32,6 @@ const Search: FunctionComponent = () => { /* Explicitly using `window.history.pushState` instead of `history.replace` as the use of the latter triggers a re-rendering of this component, resulting in double-execution searches. If there's a way to use `history` without this side effect, it would likely be preferable. */ - console.error('PUSH STATE VIA QUERY', query); window.history.pushState({}, '', `/#${history.location.pathname}${newSearch}`); } }, [query, prevQuery]); From d6b8ce0f49e011210c76f75c4c8c6abf16c9e15d Mon Sep 17 00:00:00 2001 From: Brad Beattie Date: Thu, 19 Oct 2023 14:51:11 -0700 Subject: [PATCH 022/118] Update search.tsx --- src/apps/stable/routes/search.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/stable/routes/search.tsx b/src/apps/stable/routes/search.tsx index 309e7820cf..095f735852 100644 --- a/src/apps/stable/routes/search.tsx +++ b/src/apps/stable/routes/search.tsx @@ -19,11 +19,12 @@ function usePrevious(value: string) { const Search: FunctionComponent = () => { const [ searchParams ] = useSearchParams(); - const [ query, setQuery ] = useState(searchParams.get('query') || ''); + const urlQuery = searchParams.get('query') || ''; + const [ query, setQuery ] = useState(urlQuery); const prevQuery = usePrevious(query); - if (query == prevQuery && searchParams.get('query') != query) { - setQuery(searchParams.get('query') || ''); + if (query == prevQuery && urlQuery != query) { + setQuery(urlQuery); } useEffect(() => { From bdecaa99306700d7385b2e2deb785ca5a1c51d92 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Tue, 13 Feb 2024 01:09:08 -0500 Subject: [PATCH 023/118] Fix issues with search url param --- package-lock.json | 29 +++- package.json | 1 + src/apps/stable/routes/search.tsx | 59 +++---- src/components/search/LiveTVSearchResults.tsx | 156 +++++++++--------- src/components/search/SearchFields.tsx | 96 ++++------- src/components/search/SearchResults.tsx | 28 ++-- src/elements/emby-input/Input.tsx | 59 +++++++ src/hooks/usePrevious.ts | 17 ++ 8 files changed, 256 insertions(+), 189 deletions(-) create mode 100644 src/elements/emby-input/Input.tsx create mode 100644 src/hooks/usePrevious.ts diff --git a/package-lock.json b/package-lock.json index cf80543d0a..c371ea7149 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,6 +58,7 @@ "screenfull": "6.0.2", "sortablejs": "1.15.2", "swiper": "11.0.5", + "usehooks-ts": "2.14.0", "webcomponents.js": "0.7.24", "whatwg-fetch": "3.6.20" }, @@ -12671,8 +12672,7 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -21900,6 +21900,20 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/usehooks-ts": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.14.0.tgz", + "integrity": "sha512-jnhrjTRJoJS7cFxz63tRYc5mzTKf/h+Ii8P0PDHymT9qDe4ZA2/gzDRmDR4WGausg5X8wMIdghwi3BBCN9JKow==", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -31866,8 +31880,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "lodash.memoize": { "version": "4.1.2", @@ -38668,6 +38681,14 @@ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", "requires": {} }, + "usehooks-ts": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.14.0.tgz", + "integrity": "sha512-jnhrjTRJoJS7cFxz63tRYc5mzTKf/h+Ii8P0PDHymT9qDe4ZA2/gzDRmDR4WGausg5X8wMIdghwi3BBCN9JKow==", + "requires": { + "lodash.debounce": "^4.0.8" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 91b87c28f3..ee026b811d 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "screenfull": "6.0.2", "sortablejs": "1.15.2", "swiper": "11.0.5", + "usehooks-ts": "2.14.0", "webcomponents.js": "0.7.24", "whatwg-fetch": "3.6.20" }, diff --git a/src/apps/stable/routes/search.tsx b/src/apps/stable/routes/search.tsx index 095f735852..da55e9d8e8 100644 --- a/src/apps/stable/routes/search.tsx +++ b/src/apps/stable/routes/search.tsx @@ -1,41 +1,36 @@ -import React, { FunctionComponent, useEffect, useRef, useState } from 'react'; -import { useSearchParams } from 'react-router-dom'; +import React, { type FC, useEffect, useState } from 'react'; +import { useNavigate, useSearchParams } from 'react-router-dom'; -import Page from '../../../components/Page'; -import SearchFields from '../../../components/search/SearchFields'; -import SearchResults from '../../../components/search/SearchResults'; -import SearchSuggestions from '../../../components/search/SearchSuggestions'; -import LiveTVSearchResults from '../../../components/search/LiveTVSearchResults'; -import globalize from '../../../scripts/globalize'; -import { history } from '../../../components/router/appRouter'; +import Page from 'components/Page'; +import SearchFields from 'components/search/SearchFields'; +import SearchResults from 'components/search/SearchResults'; +import SearchSuggestions from 'components/search/SearchSuggestions'; +import LiveTVSearchResults from 'components/search/LiveTVSearchResults'; +import { usePrevious } from 'hooks/usePrevious'; +import globalize from 'scripts/globalize'; -function usePrevious(value: string) { - const ref = useRef(''); - useEffect(() => { - ref.current = value; - }); - return ref.current; -} - -const Search: FunctionComponent = () => { - const [ searchParams ] = useSearchParams(); +const Search: FC = () => { + const navigate = useNavigate(); + const [ searchParams, setSearchParams ] = useSearchParams(); const urlQuery = searchParams.get('query') || ''; - const [ query, setQuery ] = useState(urlQuery); - const prevQuery = usePrevious(query); - - if (query == prevQuery && urlQuery != query) { - setQuery(urlQuery); - } + const [ query, setQuery ] = useState(urlQuery); + const prevQuery = usePrevious(query, ''); useEffect(() => { - const newSearch = query ? `?query=${query}` : ''; - if (query != prevQuery && newSearch != history.location.search) { - /* Explicitly using `window.history.pushState` instead of `history.replace` as the use of the latter - triggers a re-rendering of this component, resulting in double-execution searches. If there's a - way to use `history` without this side effect, it would likely be preferable. */ - window.history.pushState({}, '', `/#${history.location.pathname}${newSearch}`); + if (query !== prevQuery) { + if (query === '' && urlQuery !== '') { + // The query input has been cleared; navigate back to the search landing page + navigate(-1); + } else if (query !== urlQuery) { + // Update the query url param value + searchParams.set('query', query); + setSearchParams(searchParams, { replace: !!urlQuery }); + } + } else if (query !== urlQuery) { + // Update the query if the query url param has changed + setQuery(urlQuery); } - }, [query, prevQuery]); + }, [query, prevQuery, navigate, searchParams, setSearchParams, urlQuery]); return ( = ({ serverId = window.ApiClient.serverId(), parentId, collectionType, query }: LiveTVSearchResultsProps) => { +const LiveTVSearchResults: FC = ({ serverId = window.ApiClient.serverId(), parentId, collectionType, query }: LiveTVSearchResultsProps) => { const [ movies, setMovies ] = useState([]); const [ episodes, setEpisodes ] = useState([]); const [ sports, setSports ] = useState([]); @@ -38,23 +39,24 @@ const LiveTVSearchResults: FunctionComponent = ({ serv const [ news, setNews ] = useState([]); const [ programs, setPrograms ] = useState([]); const [ channels, setChannels ] = useState([]); + const [ debouncedQuery ] = useDebounceValue(query, 500); + + const getDefaultParameters = useCallback(() => ({ + ParentId: parentId, + searchTerm: debouncedQuery, + Limit: 24, + Fields: 'PrimaryImageAspectRatio,CanDelete,MediaSourceCount', + Recursive: true, + EnableTotalRecordCount: false, + ImageTypeLimit: 1, + IncludePeople: false, + IncludeMedia: false, + IncludeGenres: false, + IncludeStudios: false, + IncludeArtists: false + }), [ parentId, debouncedQuery ]); useEffect(() => { - const getDefaultParameters = () => ({ - ParentId: parentId, - searchTerm: query, - Limit: 24, - Fields: 'PrimaryImageAspectRatio,CanDelete,MediaSourceCount', - Recursive: true, - EnableTotalRecordCount: false, - ImageTypeLimit: 1, - IncludePeople: false, - IncludeMedia: false, - IncludeGenres: false, - IncludeStudios: false, - IncludeArtists: false - }); - const fetchItems = (apiClient: ApiClient, params = {}) => apiClient?.getItems( apiClient?.getCurrentUserId(), { @@ -73,65 +75,67 @@ const LiveTVSearchResults: FunctionComponent = ({ serv setPrograms([]); setChannels([]); - if (query && collectionType === CollectionType.Livetv) { - const apiClient = ServerConnections.getApiClient(serverId); - - // Movies row - fetchItems(apiClient, { - IncludeItemTypes: 'LiveTvProgram', - IsMovie: true - }) - .then(result => setMovies(result.Items || [])) - .catch(() => setMovies([])); - // Episodes row - fetchItems(apiClient, { - IncludeItemTypes: 'LiveTvProgram', - IsMovie: false, - IsSeries: true, - IsSports: false, - IsKids: false, - IsNews: false - }) - .then(result => setEpisodes(result.Items || [])) - .catch(() => setEpisodes([])); - // Sports row - fetchItems(apiClient, { - IncludeItemTypes: 'LiveTvProgram', - IsSports: true - }) - .then(result => setSports(result.Items || [])) - .catch(() => setSports([])); - // Kids row - fetchItems(apiClient, { - IncludeItemTypes: 'LiveTvProgram', - IsKids: true - }) - .then(result => setKids(result.Items || [])) - .catch(() => setKids([])); - // News row - fetchItems(apiClient, { - IncludeItemTypes: 'LiveTvProgram', - IsNews: true - }) - .then(result => setNews(result.Items || [])) - .catch(() => setNews([])); - // Programs row - fetchItems(apiClient, { - IncludeItemTypes: 'LiveTvProgram', - IsMovie: false, - IsSeries: false, - IsSports: false, - IsKids: false, - IsNews: false - }) - .then(result => setPrograms(result.Items || [])) - .catch(() => setPrograms([])); - // Channels row - fetchItems(apiClient, { IncludeItemTypes: 'TvChannel' }) - .then(result => setChannels(result.Items || [])) - .catch(() => setChannels([])); + if (!debouncedQuery || collectionType !== CollectionType.Livetv) { + return; } - }, [collectionType, parentId, query, serverId]); + + const apiClient = ServerConnections.getApiClient(serverId); + + // Movies row + fetchItems(apiClient, { + IncludeItemTypes: 'LiveTvProgram', + IsMovie: true + }) + .then(result => setMovies(result.Items || [])) + .catch(() => setMovies([])); + // Episodes row + fetchItems(apiClient, { + IncludeItemTypes: 'LiveTvProgram', + IsMovie: false, + IsSeries: true, + IsSports: false, + IsKids: false, + IsNews: false + }) + .then(result => setEpisodes(result.Items || [])) + .catch(() => setEpisodes([])); + // Sports row + fetchItems(apiClient, { + IncludeItemTypes: 'LiveTvProgram', + IsSports: true + }) + .then(result => setSports(result.Items || [])) + .catch(() => setSports([])); + // Kids row + fetchItems(apiClient, { + IncludeItemTypes: 'LiveTvProgram', + IsKids: true + }) + .then(result => setKids(result.Items || [])) + .catch(() => setKids([])); + // News row + fetchItems(apiClient, { + IncludeItemTypes: 'LiveTvProgram', + IsNews: true + }) + .then(result => setNews(result.Items || [])) + .catch(() => setNews([])); + // Programs row + fetchItems(apiClient, { + IncludeItemTypes: 'LiveTvProgram', + IsMovie: false, + IsSeries: false, + IsSports: false, + IsKids: false, + IsNews: false + }) + .then(result => setPrograms(result.Items || [])) + .catch(() => setPrograms([])); + // Channels row + fetchItems(apiClient, { IncludeItemTypes: 'TvChannel' }) + .then(result => setChannels(result.Items || [])) + .catch(() => setChannels([])); + }, [collectionType, debouncedQuery, getDefaultParameters, parentId, serverId]); return (
= ({ serv 'searchResults', 'padded-bottom-page', 'padded-top', - { 'hide': !query || collectionType !== CollectionType.Livetv } + { 'hide': !debouncedQuery || collectionType !== CollectionType.Livetv } )} > ({ - __html: `` -}); +import 'material-design-icons-iconfont'; -const normalizeInput = (value = '') => value.trim(); +import '../../styles/flexstyles.scss'; +import './searchfields.scss'; type SearchFieldsProps = { query: string, onSearch?: (query: string) => void }; -// eslint-disable-next-line @typescript-eslint/no-empty-function -const SearchFields: FunctionComponent = ({ onSearch = () => {}, query }: SearchFieldsProps) => { - const element = useRef(null); - - const getSearchInput = () => element?.current?.querySelector('.searchfields-txtSearch'); - - const debouncedOnSearch = useMemo(() => debounce(onSearch, 400), [onSearch]); - - const initSearchInput = getSearchInput(); - if (initSearchInput) { - initSearchInput.value = query; - } - - useEffect(() => { - getSearchInput()?.addEventListener('input', e => { - debouncedOnSearch(normalizeInput((e.target as HTMLInputElement).value)); - }); - getSearchInput()?.focus(); - - return () => { - debouncedOnSearch.cancel(); - }; - }, [debouncedOnSearch]); - +const SearchFields: FC = ({ + onSearch = () => { /* no-op */ }, + query +}: SearchFieldsProps) => { const onAlphaPicked = useCallback((e: Event) => { const value = (e as CustomEvent).detail.value; - const searchInput = getSearchInput(); - - if (!searchInput) { - console.error('Unexpected null reference'); - return; - } if (value === 'backspace') { - const currentValue = searchInput.value; - searchInput.value = currentValue.length ? currentValue.substring(0, currentValue.length - 1) : ''; + onSearch(query.length ? query.substring(0, query.length - 1) : ''); } else { - searchInput.value += value; + onSearch(query + value); } + }, [ onSearch, query ]); - searchInput.dispatchEvent(new CustomEvent('input', { bubbles: true })); - }, []); + const onChange = useCallback((e: ChangeEvent) => { + onSearch(e.target.value); + }, [ onSearch ]); return ( -
+
{layoutManager.tv && !browser.tv && diff --git a/src/components/search/SearchResults.tsx b/src/components/search/SearchResults.tsx index e267a4f5db..dbba7eb709 100644 --- a/src/components/search/SearchResults.tsx +++ b/src/components/search/SearchResults.tsx @@ -1,8 +1,9 @@ import type { BaseItemDto, BaseItemDtoQueryResult } from '@jellyfin/sdk/lib/generated-client'; import type { ApiClient } from 'jellyfin-apiclient'; import classNames from 'classnames'; -import React, { FunctionComponent, useCallback, useEffect, useState } from 'react'; +import React, { type FC, useCallback, useEffect, useState } from 'react'; import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type'; +import { useDebounceValue } from 'usehooks-ts'; import globalize from '../../scripts/globalize'; import ServerConnections from '../ServerConnections'; @@ -30,7 +31,7 @@ const isTVShows = (collectionType: string) => collectionType === CollectionType. /* * React component to display search result rows for global search and non-live tv library search */ -const SearchResults: FunctionComponent = ({ serverId = window.ApiClient.serverId(), parentId, collectionType, query }: SearchResultsProps) => { +const SearchResults: FC = ({ serverId = window.ApiClient.serverId(), parentId, collectionType, query }: SearchResultsProps) => { const [ movies, setMovies ] = useState([]); const [ shows, setShows ] = useState([]); const [ episodes, setEpisodes ] = useState([]); @@ -47,11 +48,12 @@ const SearchResults: FunctionComponent = ({ serverId = windo const [ books, setBooks ] = useState([]); const [ people, setPeople ] = useState([]); const [ collections, setCollections ] = useState([]); - const [isLoading, setIsLoading] = useState(false); + const [ isLoading, setIsLoading ] = useState(false); + const [ debouncedQuery ] = useDebounceValue(query, 500); const getDefaultParameters = useCallback(() => ({ ParentId: parentId, - searchTerm: query, + searchTerm: debouncedQuery, Limit: 100, Fields: 'PrimaryImageAspectRatio,CanDelete,MediaSourceCount', Recursive: true, @@ -62,7 +64,7 @@ const SearchResults: FunctionComponent = ({ serverId = windo IncludeGenres: false, IncludeStudios: false, IncludeArtists: false - }), [parentId, query]); + }), [ parentId, debouncedQuery ]); const fetchArtists = useCallback((apiClient: ApiClient, params = {}) => ( apiClient?.getArtists( @@ -97,6 +99,10 @@ const SearchResults: FunctionComponent = ({ serverId = windo ).then(ensureNonNullItems) ), [getDefaultParameters]); + useEffect(() => { + if (query) setIsLoading(true); + }, [ query ]); + useEffect(() => { // Reset state setMovies([]); @@ -116,13 +122,11 @@ const SearchResults: FunctionComponent = ({ serverId = windo setPeople([]); setCollections([]); - if (!query) { + if (!debouncedQuery) { setIsLoading(false); return; } - setIsLoading(true); - const apiClient = ServerConnections.getApiClient(serverId); const fetchPromises = []; @@ -230,7 +234,7 @@ const SearchResults: FunctionComponent = ({ serverId = windo console.error('An error occurred while fetching data:', error); setIsLoading(false); // Set loading to false even if an error occurs }); - }, [collectionType, fetchArtists, fetchItems, fetchPeople, query, serverId]); + }, [collectionType, fetchArtists, fetchItems, fetchPeople, debouncedQuery, serverId]); const allEmpty = [movies, shows, episodes, videos, programs, channels, playlists, artists, albums, songs, photoAlbums, photos, audioBooks, books, people, collections].every(arr => arr.length === 0); @@ -240,7 +244,7 @@ const SearchResults: FunctionComponent = ({ serverId = windo 'searchResults', 'padded-bottom-page', 'padded-top', - { 'hide': !query || collectionType === CollectionType.Livetv } + { 'hide': !debouncedQuery || collectionType === CollectionType.Livetv } )} > {isLoading ? ( @@ -335,8 +339,8 @@ const SearchResults: FunctionComponent = ({ serverId = windo cardOptions={{ coverImage: true }} /> - {allEmpty && query && !isLoading && ( -
{globalize.translate('SearchResultsEmpty', query)}
+ {allEmpty && debouncedQuery && !isLoading && ( +
{globalize.translate('SearchResultsEmpty', debouncedQuery)}
)} )} diff --git a/src/elements/emby-input/Input.tsx b/src/elements/emby-input/Input.tsx new file mode 100644 index 0000000000..327976dc79 --- /dev/null +++ b/src/elements/emby-input/Input.tsx @@ -0,0 +1,59 @@ +import React, { type DetailedHTMLProps, type InputHTMLAttributes, type FC, useState, useCallback } from 'react'; + +import './emby-input.scss'; +import classNames from 'classnames'; + +interface InputProps extends DetailedHTMLProps, HTMLInputElement> { + id: string, + label?: string +} + +const Input: FC = ({ + id, + label, + className, + onBlur, + onFocus, + ...props +}) => { + const [ isFocused, setIsFocused ] = useState(false); + + const onBlurInternal = useCallback(e => { + setIsFocused(false); + onBlur?.(e); + }, [ onBlur ]); + + const onFocusInternal = useCallback(e => { + setIsFocused(true); + onFocus?.(e); + }, [ onFocus ]); + + return ( + <> + + + + ); +}; + +export default Input; diff --git a/src/hooks/usePrevious.ts b/src/hooks/usePrevious.ts new file mode 100644 index 0000000000..c9e74361b9 --- /dev/null +++ b/src/hooks/usePrevious.ts @@ -0,0 +1,17 @@ +import { useEffect, useRef } from 'react'; + +/** + * A hook that returns the previous value of a stateful value. + * @param value A stateful value created by a `useState` hook. + * @param initialValue The default value. + * @returns The previous value. + */ +export function usePrevious(value: T, initialValue?: T): T | undefined { + const ref = useRef(initialValue); + + useEffect(() => { + ref.current = value; + }); + + return ref.current; +} From 48eba8953f1abe5d10146b8fce7061c386519b9f Mon Sep 17 00:00:00 2001 From: Andi Chandler Date: Tue, 13 Feb 2024 15:38:52 +0000 Subject: [PATCH 024/118] Translated using Weblate (English (United Kingdom)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/en_GB/ --- src/strings/en-gb.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/en-gb.json b/src/strings/en-gb.json index d28801c632..6849dc19f4 100644 --- a/src/strings/en-gb.json +++ b/src/strings/en-gb.json @@ -984,7 +984,7 @@ "LabelCustomCertificatePathHelp": "Path to a PKCS #12 file containing a certificate and private key to enable TLS support on a custom domain.", "LabelCurrentPassword": "Current password", "LabelCriticRating": "Critics rating", - "LabelCountry": "Country", + "LabelCountry": "Country/Region", "LabelContentType": "Content type", "LabelCommunityRating": "Community rating", "LabelCertificatePassword": "Certificate password", From dd79544593ab6284bcf7512f5653af9b6f97d1a5 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Tue, 13 Feb 2024 12:47:44 -0500 Subject: [PATCH 025/118] Babelify usehooks-ts --- webpack.common.js | 1 + 1 file changed, 1 insertion(+) diff --git a/webpack.common.js b/webpack.common.js index dd85d03183..45baccfb92 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -204,6 +204,7 @@ const config = { path.resolve(__dirname, 'node_modules/screenfull'), path.resolve(__dirname, 'node_modules/ssr-window'), path.resolve(__dirname, 'node_modules/swiper'), + path.resolve(__dirname, 'node_modules/usehooks-ts'), path.resolve(__dirname, 'src') ], use: [{ From 9fa0b4f5b2546df28469fea7e7a9115fbaa0dc14 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Tue, 13 Feb 2024 17:10:48 -0500 Subject: [PATCH 026/118] Escape html in tags --- src/controllers/itemDetails/index.js | 10 +++++++--- src/elements/emby-input/Input.tsx | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 99f6d76f05..e169a82c3a 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -1257,9 +1257,13 @@ function renderTags(page, item) { tags = []; } - for (let i = 0, length = tags.length; i < length; i++) { - tagElements.push('' + tags[i] + ''); - } + tags.forEach(tag => { + tagElements.push( + `` + + escapeHtml(tag) + + '' + ); + }); if (tagElements.length) { itemTags.innerHTML = globalize.translate('TagsValue', tagElements.join(', ')); diff --git a/src/elements/emby-input/Input.tsx b/src/elements/emby-input/Input.tsx index 327976dc79..63cde7084c 100644 --- a/src/elements/emby-input/Input.tsx +++ b/src/elements/emby-input/Input.tsx @@ -1,7 +1,7 @@ +import classNames from 'classnames'; import React, { type DetailedHTMLProps, type InputHTMLAttributes, type FC, useState, useCallback } from 'react'; import './emby-input.scss'; -import classNames from 'classnames'; interface InputProps extends DetailedHTMLProps, HTMLInputElement> { id: string, From 3b31d775e9833a07c899e1ad4550010c023682dd Mon Sep 17 00:00:00 2001 From: felix920506 Date: Tue, 13 Feb 2024 23:39:39 +0000 Subject: [PATCH 027/118] Translated using Weblate (Chinese (Traditional)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/zh_Hant/ --- src/strings/zh-tw.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/zh-tw.json b/src/strings/zh-tw.json index ab2177b9f8..114d756f80 100644 --- a/src/strings/zh-tw.json +++ b/src/strings/zh-tw.json @@ -264,7 +264,7 @@ "ButtonMore": "更多", "ButtonNetwork": "網路", "ButtonNextTrack": "下一首", - "ButtonOpen": "開", + "ButtonOpen": "開啟", "ButtonParentalControl": "家長控制", "ButtonPause": "暫停", "ButtonPreviousTrack": "上一首", From 3bbaf5626f9404949bc80d1c516a799f161085c7 Mon Sep 17 00:00:00 2001 From: AntonVucinic Date: Wed, 14 Feb 2024 12:10:15 +0000 Subject: [PATCH 028/118] Translated using Weblate (Croatian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/hr/ --- src/strings/hr.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/strings/hr.json b/src/strings/hr.json index 91789471a7..8c105b61d8 100644 --- a/src/strings/hr.json +++ b/src/strings/hr.json @@ -294,7 +294,7 @@ "LabelCollection": "Kolekcija", "LabelCommunityRating": "Ocjene zajednice", "LabelContentType": "Tip sadržaja", - "LabelCountry": "Zemlja", + "LabelCountry": "Zemlja/Regija", "LabelCriticRating": "Ocjena kritičara", "LabelCurrentPassword": "Trenutna lozinka", "LabelCustomCss": "Prilagođeni CSS kod", @@ -1512,5 +1512,8 @@ "ShowYear": "Prikaži godinu", "LabelLocalCustomCss": "Prilagođeni CSS kod za stil koji se odnosi samo na ovog klijenta. Možda ćete htjeti onemogućiti prilagođeni CSS kod poslužitelja.", "LabelPlayerDimensions": "Dimenzije izvođača", - "LabelSegmentKeepSecondsHelp": "Vrijeme u sekundama za koje se segmenti trebaju čuvati prije nego što se prebrišu. Mora biti veći od \"Throttle after\". Radi samo ako je omogućeno brisanje segmenta." + "LabelSegmentKeepSecondsHelp": "Vrijeme u sekundama za koje se segmenti trebaju čuvati prije nego što se prebrišu. Mora biti veći od \"Throttle after\". Radi samo ako je omogućeno brisanje segmenta.", + "LabelKnownProxies": "Poznati proxy-i", + "ButtonBackspace": "Backspace", + "LabelHomeScreenSectionValue": "{0}. odjeljak početne" } From a31f31fcd8433ed7d80e10998af873e9f2b6333a Mon Sep 17 00:00:00 2001 From: stanol Date: Wed, 14 Feb 2024 20:19:00 +0000 Subject: [PATCH 029/118] Translated using Weblate (Ukrainian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/uk/ --- src/strings/uk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/uk.json b/src/strings/uk.json index cc3925083f..46b82fc786 100644 --- a/src/strings/uk.json +++ b/src/strings/uk.json @@ -17,7 +17,7 @@ "HeaderUsers": "Користувачі", "LabelBirthDate": "Дата народження", "LabelBirthYear": "Рік народження", - "LabelCountry": "Країна", + "LabelCountry": "Країна/Регіон", "LabelCurrentPassword": "Поточний пароль", "LabelDeathDate": "Дата смерті", "LabelLanguage": "Мова", From 2d667cabbaa72e85588a3969f485bb4496ff6868 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Thu, 15 Feb 2024 11:28:10 -0500 Subject: [PATCH 030/118] Fix missing dependency in effect --- src/hooks/usePrevious.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/usePrevious.ts b/src/hooks/usePrevious.ts index c9e74361b9..a97ced0bd1 100644 --- a/src/hooks/usePrevious.ts +++ b/src/hooks/usePrevious.ts @@ -11,7 +11,7 @@ export function usePrevious(value: T, initialValue?: T): T | undefined { useEffect(() => { ref.current = value; - }); + }, [ value ]); return ref.current; } From dc11fd8b2ee1352aea38d4796051770ea20ea43e Mon Sep 17 00:00:00 2001 From: gearoidkeane Date: Thu, 15 Feb 2024 15:47:16 -0500 Subject: [PATCH 031/118] Added translation using Weblate (Irish) --- src/strings/ga.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/strings/ga.json diff --git a/src/strings/ga.json b/src/strings/ga.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/src/strings/ga.json @@ -0,0 +1 @@ +{} From 16844d4565e9d49016c25548defa3d50baca6247 Mon Sep 17 00:00:00 2001 From: gearoidkeane Date: Thu, 15 Feb 2024 20:51:01 +0000 Subject: [PATCH 032/118] Translated using Weblate (Irish) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ga/ --- src/strings/ga.json | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/strings/ga.json b/src/strings/ga.json index 0967ef424b..8dca7f76c4 100644 --- a/src/strings/ga.json +++ b/src/strings/ga.json @@ -1 +1,26 @@ -{} +{ + "Actor": "Aisteoir", + "Add": "Cuir le", + "AddedOnValue": "Curtha {0}", + "AddToFavorites": "Cur le ceanáin", + "AgeValue": "({0} bliana d'aois)", + "AirDate": "Dáta Croalta", + "Aired": "Craolta", + "AlbumArtist": "Ealaíontóir Albam", + "Albums": "Albaim", + "Alerts": "Foláirimh", + "AllChannels": "Gach cainéal", + "AllLanguages": "Gach teanga", + "AllEpisodes": "Gach eagrán", + "AllLibraries": "Gach leabharlann", + "AllowCollectionManagement": "Lig don úsáideoir seo bailiúcháin a bhainistiú", + "Absolute": "Absalóideach", + "AccessRestrictedTryAgainLater": "Tá rochtain srianta faoi láthair. Bain triail eile as ar ball.", + "All": "Uilig", + "Album": "Albam", + "AddToCollection": "Cur le bailiúcháin", + "AddToPlaylist": "Cur le seinnliosta", + "AddToPlayQueue": "Cur le scuaine seinnteoir", + "AllComplexFormats": "Gach formáid chasta (ASS, SSA, VobSub, PGS, SUB, IDX, ...)", + "AllowedRemoteAddressesHelp": "Liosta scartha camóg de seoltaí IP nó iontráil IP/netmask do líonraí a ligfear nascadh go cianda. Má fhágtar folamh é, ceadófar gach ciansheoladh." +} From eaab0364d7d40a00d126760e17221e923b41b498 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Fri, 16 Feb 2024 20:22:15 -0500 Subject: [PATCH 033/118] Fix weird navigation when changing query param --- src/apps/stable/routes/search.tsx | 35 ++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/apps/stable/routes/search.tsx b/src/apps/stable/routes/search.tsx index da55e9d8e8..34438c1334 100644 --- a/src/apps/stable/routes/search.tsx +++ b/src/apps/stable/routes/search.tsx @@ -9,25 +9,36 @@ import LiveTVSearchResults from 'components/search/LiveTVSearchResults'; import { usePrevious } from 'hooks/usePrevious'; import globalize from 'scripts/globalize'; +const COLLECTION_TYPE_PARAM = 'collectionType'; +const PARENT_ID_PARAM = 'parentId'; +const QUERY_PARAM = 'query'; +const SERVER_ID_PARAM = 'serverId'; + const Search: FC = () => { const navigate = useNavigate(); const [ searchParams, setSearchParams ] = useSearchParams(); - const urlQuery = searchParams.get('query') || ''; + const urlQuery = searchParams.get(QUERY_PARAM) || ''; const [ query, setQuery ] = useState(urlQuery); const prevQuery = usePrevious(query, ''); useEffect(() => { if (query !== prevQuery) { if (query === '' && urlQuery !== '') { - // The query input has been cleared; navigate back to the search landing page - navigate(-1); + // The query input has been cleared; remove the url param + searchParams.delete(QUERY_PARAM); + setSearchParams(searchParams, { replace: true }); } else if (query !== urlQuery) { // Update the query url param value - searchParams.set('query', query); - setSearchParams(searchParams, { replace: !!urlQuery }); + searchParams.set(QUERY_PARAM, query); + setSearchParams(searchParams, { replace: true }); } } else if (query !== urlQuery) { // Update the query if the query url param has changed + if (!urlQuery) { + searchParams.delete(QUERY_PARAM); + setSearchParams(searchParams, { replace: true }); + } + setQuery(urlQuery); } }, [query, prevQuery, navigate, searchParams, setSearchParams, urlQuery]); @@ -41,19 +52,19 @@ const Search: FC = () => { {!query && } From 96692e4693aab9c3ddd802c67ecb637424323c15 Mon Sep 17 00:00:00 2001 From: yanghong Date: Sat, 17 Feb 2024 06:53:10 +0000 Subject: [PATCH 034/118] Translated using Weblate (Chinese (Simplified)) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/zh_Hans/ --- src/strings/zh-cn.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/zh-cn.json b/src/strings/zh-cn.json index 9c8eff1b44..62243cba3d 100644 --- a/src/strings/zh-cn.json +++ b/src/strings/zh-cn.json @@ -272,7 +272,7 @@ "HeaderImageSettings": "图片设置", "HeaderInstall": "安装", "HeaderInstantMix": "速成合辑", - "HeaderKodiMetadataHelp": "要启用或禁用 NFO 元数据,请编辑库并找到“元数据保护程序”部分。", + "HeaderKodiMetadataHelp": "要启用或禁用 NFO 元数据,请编辑库并找到“元数据储存方式”部分。", "HeaderLatestEpisodes": "新增剧集", "HeaderLatestMedia": "新增媒体", "HeaderLatestMovies": "新增电影", From 798a93b20447372142a72cc1b579ca94aa152d95 Mon Sep 17 00:00:00 2001 From: queeup Date: Sat, 17 Feb 2024 21:15:21 +0000 Subject: [PATCH 035/118] Translated using Weblate (Turkish) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/tr/ --- src/strings/tr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strings/tr.json b/src/strings/tr.json index e1e0d98d0a..ec3f812470 100644 --- a/src/strings/tr.json +++ b/src/strings/tr.json @@ -68,7 +68,7 @@ "LabelCachePath": "Önbellek yolu", "LabelCachePathHelp": "Sunucunun resim vb. önbellek dosyalarını tutması için bir yer belirt. Öntanımlı yeri kullanmak için boş bırak.", "LabelContentType": "İçerik türü", - "LabelCountry": "Ülke", + "LabelCountry": "Ülke/Bölge", "LabelCurrentPassword": "Kullanımdaki parola", "LabelDay": "Haftanın günü", "LabelEnableDlnaServer": "DLNA sunucusunu etkinleştir", @@ -248,7 +248,7 @@ "ChannelNameOnly": "Yalnızca {0} kanalı", "ConfirmDeleteItems": "Bu ögeleri silmek, onları hem dosya sisteminden hem de medya kütüphanenizden siler. Devam etmek istediğinize emin misiniz?", "ConfirmDeletion": "Silme İşlemini Onayla", - "ConfirmEndPlayerSession": "Jellyfin'i {0} tarihinde kapatmak ister misiniz?", + "ConfirmEndPlayerSession": "{0} üzerindeki Jellyfin'i kapatmak ister misiniz?", "Connect": "Bağlan", "Disconnect": "Bağlantıyı Kes", "Display": "Görünüm", From ac29b9b3387f6838d9bd13b8ba8c41defc3adadd Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Sun, 18 Feb 2024 01:11:42 -0500 Subject: [PATCH 036/118] Remove unused variable and fix no results alignment --- src/apps/stable/routes/search.tsx | 5 ++--- src/components/search/SearchResults.tsx | 4 +++- src/components/search/searchfields.scss | 11 ----------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/apps/stable/routes/search.tsx b/src/apps/stable/routes/search.tsx index 34438c1334..5c483c9a8c 100644 --- a/src/apps/stable/routes/search.tsx +++ b/src/apps/stable/routes/search.tsx @@ -1,5 +1,5 @@ import React, { type FC, useEffect, useState } from 'react'; -import { useNavigate, useSearchParams } from 'react-router-dom'; +import { useSearchParams } from 'react-router-dom'; import Page from 'components/Page'; import SearchFields from 'components/search/SearchFields'; @@ -15,7 +15,6 @@ const QUERY_PARAM = 'query'; const SERVER_ID_PARAM = 'serverId'; const Search: FC = () => { - const navigate = useNavigate(); const [ searchParams, setSearchParams ] = useSearchParams(); const urlQuery = searchParams.get(QUERY_PARAM) || ''; const [ query, setQuery ] = useState(urlQuery); @@ -41,7 +40,7 @@ const Search: FC = () => { setQuery(urlQuery); } - }, [query, prevQuery, navigate, searchParams, setSearchParams, urlQuery]); + }, [query, prevQuery, searchParams, setSearchParams, urlQuery]); return ( = ({ serverId = window.ApiClient.ser /> {allEmpty && debouncedQuery && !isLoading && ( -
{globalize.translate('SearchResultsEmpty', debouncedQuery)}
+
+ {globalize.translate('SearchResultsEmpty', debouncedQuery)} +
)} )} diff --git a/src/components/search/searchfields.scss b/src/components/search/searchfields.scss index b93638bdf3..08d8515c86 100644 --- a/src/components/search/searchfields.scss +++ b/src/components/search/searchfields.scss @@ -9,14 +9,3 @@ font-size: 2em; align-self: flex-end; } - -.sorry-text { - font-size: 2em; - text-align: center; - font-family: inherit; - width: 100%; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); -} From a60683c1e232ea9a950a34ef64f5e1ff33fff11e Mon Sep 17 00:00:00 2001 From: hoanghuy309 Date: Sun, 18 Feb 2024 04:31:19 +0000 Subject: [PATCH 037/118] Translated using Weblate (Vietnamese) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/vi/ --- src/strings/vi.json | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/strings/vi.json b/src/strings/vi.json index 4588baae76..bad2068624 100644 --- a/src/strings/vi.json +++ b/src/strings/vi.json @@ -35,7 +35,7 @@ "LabelNewPassword": "Mật khẩu mới", "LabelNewPasswordConfirm": "Xác nhận mật khẩu mới", "LabelSaveLocalMetadata": "Lưu các ảnh bìa minh họa và dữ liệu mô tả vào trong các thư mục phương tiện", - "LabelSaveLocalMetadataHelp": "Lưu ảnh bìa minh họa vào các thư mục phương tiện giúp đưa chúng vào một nơi dễ chỉnh sửa hơn.", + "LabelSaveLocalMetadataHelp": "Lưu ảnh bìa minh họa vào thư mục phương tiện để đưa chúng vào nơi dễ chỉnh sửa hơn.", "LabelTime": "Thời gian", "LabelYoureDone": "Bạn đã hoàn thành!", "MaxParentalRatingHelp": "Nội dung với đánh giá cao hơn sẽ được ẩn đi từ người dùng này.", @@ -99,7 +99,7 @@ "ButtonGotIt": "Hiểu rồi", "ButtonFullscreen": "Toàn màn hình", "ButtonForgotPassword": "Quên mật khẩu", - "ButtonEditOtherUserPreferences": "Chỉnh sửa hồ sơ, ảnh và sở thích cá nhân của người dùng này.", + "ButtonEditOtherUserPreferences": "Sửa hồ sơ, ảnh và sở thích cá nhân của người dùng này.", "ButtonChangeServer": "Đổi máy chủ", "ButtonBack": "Quay lại", "ButtonAudioTracks": "Bản Ghi Âm Thanh", @@ -206,7 +206,7 @@ "BoxSet": "", "Box": "Hộp", "Banner": "Ảnh bìa", - "Art": "", + "Art": "Minh họa", "Artist": "Ca Sĩ", "AllowFfmpegThrottlingHelp": "Tạm dừng quá trình chuyển mã hoặc chuyển đổi định dạng để tiết kiệm tài nguyên máy chủ khi việc này đã đủ để phát so với vị trí hiện tại. Nó hữu ích khi xem mà không cần tua. Tắt tính năng này nếu bạn gặp sự cố phát lại.", "AllowFfmpegThrottling": "Điều tiết sự chuyển mã", @@ -235,7 +235,7 @@ "DeleteDeviceConfirmation": "Bạn có chắc chắn muốn xoá thiết bị này? Nó sẽ xuất hiện lại khi người dùng đăng nhập bằng thiết bị đó.", "DeinterlaceMethodHelp": "Chọn cách khử xen kẽ để dùng khi phần mềm chuyển mã xen kẽ nội dung. Khi hỗ trợ tăng tốc phần cứng khử xen kẽ được bật, trình khử xen kẽ phần cứng sẽ dùng cài đặt này.", "DefaultSubtitlesHelp": "Phụ đề được tải dựa trên mặc định và bắt buộc gắn cờ trong dữ liệu mô tả. Ngôn ngữ ưa thích được xem xét khi có nhiều lựa chọn.", - "DefaultMetadataLangaugeDescription": "Đây là thiết lập mặc định chung, bạn có thể tuỳ chỉnh thiết lập riêng cho từng thư viện.", + "DefaultMetadataLangaugeDescription": "Đây là mặc định của bạn và có thể tùy chỉnh trên cơ sở từng thư viện.", "DisplayModeHelp": "Chọn kiểu bố trí giao diện mà bạn muốn.", "Download": "Tải về", "Down": "Xuống", @@ -243,9 +243,9 @@ "EnableCinemaMode": "Chế độ rạp phim", "EnableBackdropsHelp": "Hiển thị phông nền trong nền của một số trang trong khi duyệt thư viện.", "EditSubtitles": "Chỉnh sửa phụ đề", - "EditMetadata": "Chỉnh sửa thông tin", - "EditImages": "Chỉnh sửa hình ảnh", - "Edit": "Chỉnh sửa", + "EditMetadata": "Sửa dữ liệu mô tả", + "EditImages": "Sửa ảnh", + "Edit": "Sửa", "EasyPasswordHelp": "Mã PIN Tiện Lợi dùng cho việc truy cập ngoại tuyến trên thiết bị hỗ trợ và cũng dùng để đăng nhập trong mạng dễ dàng.", "DropShadow": "Bóng đổ", "DrmChannelsNotImported": "Những kênh được bảo vệ bản quyền sẽ không được nhập vào.", @@ -405,7 +405,7 @@ "HeaderError": "Lỗi", "HeaderEnabledFieldsHelp": "Bỏ chọn một mục để khóa nó và ngăn dữ liệu của nó bị thay đổi.", "HeaderEnabledFields": "Những Mục Được Kích Hoạt", - "HeaderEditImages": "Chỉnh Sửa Hình Ảnh", + "HeaderEditImages": "Sửa Ảnh", "HeaderEasyPinCode": "Mã PIN Tiện Lợi", "HeaderDownloadSync": "Tải Xuống Và Đồng Bộ", "HeaderDirectPlayProfileHelp": "Thêm cấu hình phát lại trực tiếp để chỉ ra những định dạng mà thiết bị có thể xử lý nguyên bản.", @@ -439,7 +439,7 @@ "HeaderScenes": "Phân Cảnh", "HeaderRunningTasks": "Những Tác Vụ Hoạt Động", "HeaderRevisionHistory": "Lịch Sử Chỉnh Sửa", - "HeaderResponseProfileHelp": "Hồ sơ phản hồi là phương thức tuỳ chỉnh thông tin gửi về thiết bị phát khi phát một số nội dung nhất định.", + "HeaderResponseProfileHelp": "Cấu hình phản hồi là phương thức tuỳ chỉnh thông tin gửi về thiết bị phát khi phát một số loại phương tiện.", "HeaderResponseProfile": "Hồ Sơ Phản Hồi", "HeaderRemoveMediaLocation": "Xoá Đường Dẫn Nội Dung", "HeaderRemoveMediaFolder": "Xoá Thư Mục Phương Tiện", @@ -605,7 +605,7 @@ "HeaderDVR": "DVR", "LabelExtractChaptersDuringLibraryScanHelp": "Tạo hình ảnh phân cảnh khi video được nhập trong quá trình quét thư viện. Nếu không chúng sẽ được trích xuất thông qua những tác vụ định kì, giúp cho quá trình quét thư viện diễn ra nhanh hơn.", "LabelExtractChaptersDuringLibraryScan": "Trích xuất hình ảnh phân đoạn khi quét thư viện", - "LabelBaseUrlHelp": "Thêm một thư mục con tùy chỉnh vào đường dẫn máy chủ. Ví dụ: http://example.com/<baseurl>", + "LabelBaseUrlHelp": "Thêm một thư mục con tùy chỉnh vào URL máy chủ. Ví dụ: http://example.com/<baseurl>", "LabelLoginDisclaimerHelp": "Một thông báo sẽ được hiển thị ở cuối trang đăng nhập.", "LabelLoginDisclaimer": "Hiển thị khi đăng nhập", "LabelLockItemToPreventChanges": "Khoá mục này để ngăn những thay đổi trong tương lai", @@ -954,7 +954,7 @@ "LiveBroadcasts": "Chương trình phát sóng trực tiếp", "Live": "Trực tiếp", "List": "Danh sách", - "LibraryAccessHelp": "Chọn thư viện để chia sẻ với người dùng này. Quản trị viên có thể chỉnh sửa các thư mục bằng trình quản lý dữ liệu mô tả.", + "LibraryAccessHelp": "Chọn thư viện chia sẻ với người dùng này. Quản trị viên có thể sửa các thư mục bằng trình quản lý dữ liệu mô tả.", "LeaveBlankToNotSetAPassword": "Bạn có thể để trống trường này để không đặt mật khẩu.", "LearnHowYouCanContribute": "Tìm hiểu cách bạn có thể đóng góp.", "LatestFromLibrary": "{0} Đã Thêm Vào Gần Đây", @@ -999,7 +999,7 @@ "LabelTranscodingProgress": "Tiến trình chuyển mã", "LabelTranscodingFramerate": "Tốc độ khung hình chuyển mã", "LabelTranscodes": "Chuyển mã", - "LabelTranscodingTempPathHelp": "Chỉ định một đường dẫn tùy chỉnh cho các tệp chuyển mã được cung cấp cho máy khách. Để trống để sử dụng mặc định của máy chủ.", + "LabelTranscodingTempPathHelp": "Tùy chỉnh một đường dẫn cho các tệp chuyển mã để cung cấp cho máy khách. Để trống để dùng mặc định.", "LabelTranscodePath": "Đường dẫn chuyển mã", "LabelTrackNumber": "Số bản ghi", "LabelTitle": "Tiêu đề", @@ -1271,7 +1271,7 @@ "Transcoding": "Chuyển mã", "Trailers": "Đoạn giới thiệu", "TabAccess": "Truy cập", - "SystemDlnaProfilesHelp": "Cấu hình hệ thống ở chế độ chỉ đọc. Thay đổi cấu hình hệ thống sẽ được lưu vào cấu hình tùy chỉnh mới.", + "SystemDlnaProfilesHelp": "Cấu hình hệ thống là chỉ đọc. Thay đổi cấu hình hệ thống sẽ được lưu vào cấu hình tùy chỉnh mới.", "Sports": "Thể thao", "SpecialFeatures": "Các tính năng đặc biệt", "SortName": "Sắp xếp tên", @@ -1322,7 +1322,7 @@ "UnsupportedPlayback": "Jellyfin không thể giải mã nội dung bảo vệ DRM nhưng sẽ cố gắng thử với tất cả nội dung, bao gồm cả các tiêu đề được bảo vệ. Một số tệp có thể xuất hiện toàn màu đen do mã hóa hoặc tính năng không được hỗ trợ, chẳng hạn như tiêu đề tương tác.", "EnableBlurHashHelp": "Hình ảnh đang được tải sẽ được hiển thị với một trình giữ chỗ duy nhất.", "ButtonPlayer": "Trình Phát", - "LabelOpenclDeviceHelp": "Đây là thiết bị OpenCL dùng để chỉnh tông màu. Phía bên trái của dấu chấm là số nền tảng và phía bên phải là số thiết bị trên nền tảng. Mặc định là 0.0. Bắt buộc tệp ứng dụng FFmpeg phải có tính năng tăng tốc phần cứng OpenCL.", + "LabelOpenclDeviceHelp": "Đây là thiết bị OpenCL dùng để chỉnh tông màu. Phía bên trái của dấu chấm là số nền tảng và phía bên phải là số thiết bị trên nền tảng. Mặc định là 0.0. Cần có tệp ứng dụng FFmpeg chứa phương pháp tăng tốc phần cứng OpenCL.", "LabelMaxMuxingQueueSizeHelp": "Số gói tối đa có thể được lưu vào bộ đệm trong khi chờ tất cả các luồng khởi tạo. Hãy thử tăng lên nếu bạn vẫn gặp lỗi \"Quá nhiều gói được lưu vào bộ đệm cho luồng đầu ra\" trong nhật ký FFmpeg. Giá trị đề xuất là 2048.", "ClearQueue": "Xóa hàng đợi", "LabelTonemappingParamHelp": "Điều chỉnh thuật toán ánh xạ tông màu. Các giá trị được đề xuất và mặc định là NaN. Nói chung là để trống.", @@ -1427,7 +1427,7 @@ "HeaderDeleteDevices": "Xóa Tất Cả Thiết Bị", "DeleteDevicesConfirmation": "Bạn có chắc muốn xóa hết các thiết bị không? Tất cả các phiên khác sẽ được đăng xuất. Thiết bị sẽ xuất hiện lại vào lần tiếp theo khi người dùng đăng nhập.", "DeleteAll": "Xóa Hết", - "EnableFallbackFontHelp": "Bật phông chữ thay thế tùy chỉnh. Điều này có thể tránh sự cố hiển thị phụ đề không chính xác.", + "EnableFallbackFontHelp": "Bật phông chữ thay thế tùy chỉnh. Nó có thể tránh lỗi kết xuất phụ đề không chính xác.", "EnableFallbackFont": "Bật phông chữ dự phòng", "LabelFallbackFontPathHelp": "Những phông chữ này được một số máy khách sử dụng để hiển thị phụ đề. Vui lòng tham khảo tài liệu để biết thêm thông tin.", "LabelFallbackFontPath": "Đường dẫn thư mục phông chữ dự phòng", @@ -1665,7 +1665,7 @@ "VideoRangeTypeNotSupported": "Không hỗ trợ loại dải động của video", "Interview": "Phỏng vấn", "Sample": "Mẫu", - "Trailer": "", + "Trailer": "Đoạn giới thiệu", "TypeOptionPluralVideo": "Videos", "ButtonSpace": "Cách", "ButtonBackspace": "Xóa", @@ -1722,7 +1722,7 @@ "EnableAudioNormalization": "Chuẩn hóa âm thanh", "GetThePlugin": "Nhận phần bổ sung", "Notifications": "Thông báo", - "NotificationsMovedMessage": "Chức năng thông báo đã chuyển sang plugin Webhook.", + "NotificationsMovedMessage": "Chức năng thông báo đã được chuyển sang plugin Webhook.", "LabelEnableLUFSScan": "Bật tính năng quét LUFS", "LabelEnableLUFSScanHelp": "Khách hàng có thể bình thường hóa việc phát lại âm thanh để có được âm lượng như nhau trên các bản nhạc. Điều này sẽ khiến việc quét thư viện lâu hơn và tốn nhiều tài nguyên hơn.", "PasswordRequiredForAdmin": "Cần có mật khẩu cho tài khoản quản trị viên.", @@ -1761,13 +1761,14 @@ "LabelSelectAudioNormalization": "Chuẩn Hóa Âm Thanh", "SearchResultsEmpty": "Rất tiếc! Không có kết quả tìm thấy cho \"{0}\"", "HeaderAllRecordings": "Tất Cả Bản Ghi", - "LabelTrackGain": "Chỉnh Nhạc", + "LabelTrackGain": "Điều Chỉnh Nhạc", "GridView": "Xem Lưới", "ListView": "Xem Danh Sách", - "SelectAudioNormalizationHelp": "Chỉnh nhạc - điều chỉnh âm lượng của mỗi bản nhạc để chúng phát lại với cùng một độ to. Chỉnh Album - điều chỉnh âm lượng của tất cả các bản nhạc trong một album, giữ nguyên dải động của album.", - "LabelAlbumGain": "Chỉnh Album", + "SelectAudioNormalizationHelp": "Điều chỉnh nhạc - điều chỉnh âm lượng của mỗi bản nhạc để chúng phát lại với cùng một độ to. Điều chỉnh album - điều chỉnh âm lượng tất cả bản nhạc trong album, giữ nguyên dải động của album.", + "LabelAlbumGain": "Điều Chỉnh Album", "LabelSegmentKeepSecondsHelp": "Thời gian tính bằng giây mà các phân đoạn cần được giữ lại trước khi chúng bị ghi đè. Phải lớn hơn \"Throle after\". Chỉ hoạt động nếu tính năng xóa phân đoạn được bật.", "MenuClose": "Đóng Menu", "MenuOpen": "Mở Menu", - "UserMenu": "Menu Người Dùng" + "UserMenu": "Menu Người Dùng", + "LogLevel.Trace": "Dấu vết" } From fe7b425c874912f3b37b50ad38eed081c2e3fd58 Mon Sep 17 00:00:00 2001 From: David Stensland Date: Sun, 18 Feb 2024 12:38:15 -0800 Subject: [PATCH 038/118] convert actionSheet to TypeScript --- .../{actionSheet.js => actionSheet.ts} | 103 +++++++++++++++--- 1 file changed, 85 insertions(+), 18 deletions(-) rename src/components/actionSheet/{actionSheet.js => actionSheet.ts} (78%) diff --git a/src/components/actionSheet/actionSheet.js b/src/components/actionSheet/actionSheet.ts similarity index 78% rename from src/components/actionSheet/actionSheet.js rename to src/components/actionSheet/actionSheet.ts index 1114908fcf..eacd66f421 100644 --- a/src/components/actionSheet/actionSheet.js +++ b/src/components/actionSheet/actionSheet.ts @@ -9,8 +9,64 @@ import 'material-design-icons-iconfont'; import '../../styles/scrollstyles.scss'; import '../../components/listview/listview.scss'; -function getOffsets(elems) { - const results = []; +interface OptionItem { + asideText?: string; + divider?: boolean; + icon?: string; + id?: string; + innerText?: string; + name?: string; + secondaryText?: string; + selected?: boolean; + textContent?: string; + value?: string; +} + +interface Options { + items: OptionItem[]; + border?: boolean; + callback?: (id: string) => void; + dialogClass?: string; + enableHistory?: boolean; + entryAnimationDuration?: number; + entryAnimation?: string; + exitAnimationDuration?: number; + exitAnimation?: string; + menuItemClass?: string; + offsetLeft?: number; + offsetTop?: number; + positionTo?: Element | null; + positionY?: string; + resolveOnClick?: boolean | (string | null)[]; + shaded?: boolean; + showCancel?: boolean; + text?: string; + timeout?: number; + title?: string; +} + +interface Offset { + top: number; + left: number; + width: number; + height: number; +} + +interface DialogOptions { + autoFocus?: boolean; + enableHistory?: boolean; + entryAnimationDuration?: number; + entryAnimation?: string; + exitAnimationDuration?: number; + exitAnimation?: string; + modal?: boolean; + removeOnClose?: boolean; + scrollY?: boolean; + size?: string; +} + +function getOffsets(elems: Element[]): Offset[] { + const results: Offset[] = []; if (!document) { return results; @@ -30,12 +86,12 @@ function getOffsets(elems) { return results; } -function getPosition(options, dlg) { +function getPosition(positionTo: Element, options: Options, dlg: HTMLElement) { const windowSize = dom.getWindowSize(); const windowHeight = windowSize.innerHeight; const windowWidth = windowSize.innerWidth; - const pos = getOffsets([options.positionTo])[0]; + const pos = getOffsets([positionTo])[0]; if (options.positionY !== 'top') { pos.top += (pos.height || 0) / 2; @@ -71,19 +127,22 @@ function getPosition(options, dlg) { return pos; } -function centerFocus(elem, horiz, on) { +function centerFocus(elem: Element, horiz: boolean, on: boolean) { import('../../scripts/scrollHelper').then((scrollHelper) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); + }).catch(e => { + console.warn('Error in centerFocus', e); }); } -export function show(options) { +/* eslint-disable-next-line sonarjs/cognitive-complexity */ +export function show(options: Options) { // items // positionTo // showCancel // title - const dialogOptions = { + const dialogOptions: DialogOptions = { removeOnClose: true, enableHistory: options.enableHistory, scrollY: false @@ -239,7 +298,10 @@ export function show(options) { dlg.innerHTML = html; if (layoutManager.tv) { - centerFocus(dlg.querySelector('.actionSheetScroller'), false, true); + const scroller = dlg.querySelector('.actionSheetScroller'); + if (scroller) { + centerFocus(scroller, false, true); + } } const btnCloseActionSheet = dlg.querySelector('.btnCloseActionSheet'); @@ -249,9 +311,9 @@ export function show(options) { }); } - let selectedId; + let selectedId: string | null = null; - let timeout; + let timeout: ReturnType | undefined; if (options.timeout) { timeout = setTimeout(function () { dialogHelper.close(dlg); @@ -259,16 +321,16 @@ export function show(options) { } return new Promise(function (resolve, reject) { - let isResolved; + let isResolved = false; dlg.addEventListener('click', function (e) { - const actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem'); + const actionSheetMenuItem = dom.parentWithClass(e.target as HTMLElement, 'actionSheetMenuItem'); if (actionSheetMenuItem) { selectedId = actionSheetMenuItem.getAttribute('data-id'); if (options.resolveOnClick) { - if (options.resolveOnClick.indexOf) { + if (Array.isArray(options.resolveOnClick)) { if (options.resolveOnClick.indexOf(selectedId) !== -1) { resolve(selectedId); isResolved = true; @@ -285,12 +347,15 @@ export function show(options) { dlg.addEventListener('close', function () { if (layoutManager.tv) { - centerFocus(dlg.querySelector('.actionSheetScroller'), false, false); + const scroller = dlg.querySelector('.actionSheetScroller'); + if (scroller) { + centerFocus(scroller, false, false); + } } if (timeout) { clearTimeout(timeout); - timeout = null; + timeout = undefined; } if (!isResolved) { @@ -306,13 +371,15 @@ export function show(options) { } }); - dialogHelper.open(dlg); + dialogHelper.open(dlg).catch(e => { + console.warn('DialogHelper.open error', e); + }); - const pos = options.positionTo && dialogOptions.size !== 'fullscreen' ? getPosition(options, dlg) : null; + const pos = options.positionTo && dialogOptions.size !== 'fullscreen' ? getPosition(options.positionTo, options, dlg) : null; if (pos) { dlg.style.position = 'fixed'; - dlg.style.margin = 0; + dlg.style.margin = '0'; dlg.style.left = pos.left + 'px'; dlg.style.top = pos.top + 'px'; } From 3f84609fafcd3dba2444c8c458a3ba743e34f9ea Mon Sep 17 00:00:00 2001 From: David Stensland Date: Sun, 18 Feb 2024 12:46:34 -0800 Subject: [PATCH 039/118] convert scrollHelper to TypeScript --- .../{scrollHelper.js => scrollHelper.ts} | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) rename src/scripts/{scrollHelper.js => scrollHelper.ts} (81%) diff --git a/src/scripts/scrollHelper.js b/src/scripts/scrollHelper.ts similarity index 81% rename from src/scripts/scrollHelper.js rename to src/scripts/scrollHelper.ts index 9f6a870ed3..174510d26a 100644 --- a/src/scripts/scrollHelper.js +++ b/src/scripts/scrollHelper.ts @@ -2,17 +2,17 @@ import focusManager from '../components/focusManager'; import dom from './dom'; import '../styles/scrollstyles.scss'; -function getBoundingClientRect(elem) { +function getBoundingClientRect(elem: Element) { // Support: BlackBerry 5, iOS 3 (original iPhone) // If we don't have gBCR, just use 0,0 rather than error if (elem.getBoundingClientRect) { return elem.getBoundingClientRect(); } else { - return { top: 0, left: 0 }; + return { top: 0, left: 0, width: undefined, height: undefined }; } } -export function getPosition(scrollContainer, item, horizontal) { +export function getPosition(scrollContainer: HTMLElement, item: HTMLElement, horizontal: boolean) { const slideeOffset = getBoundingClientRect(scrollContainer); const itemOffset = getBoundingClientRect(item); @@ -41,7 +41,7 @@ export function getPosition(scrollContainer, item, horizontal) { }; } -export function toCenter(container, elem, horizontal, skipWhenVisible) { +export function toCenter(container: HTMLElement, elem: HTMLElement, horizontal: boolean, skipWhenVisible?: boolean) { const pos = getPosition(container, elem, horizontal); if (skipWhenVisible && pos.isVisible) { @@ -61,7 +61,7 @@ export function toCenter(container, elem, horizontal, skipWhenVisible) { } } -export function toStart(container, elem, horizontal, skipWhenVisible) { +export function toStart(container: HTMLElement, elem: HTMLElement, horizontal: boolean, skipWhenVisible?: boolean) { const pos = getPosition(container, elem, horizontal); if (skipWhenVisible && pos.isVisible) { @@ -81,7 +81,7 @@ export function toStart(container, elem, horizontal, skipWhenVisible) { } } -function centerOnFocus(e, scrollSlider, horizontal) { +function centerOnFocus(e: Event, scrollSlider: HTMLElement, horizontal: boolean) { const focused = focusManager.focusableParent(e.target); if (focused) { @@ -89,16 +89,16 @@ function centerOnFocus(e, scrollSlider, horizontal) { } } -function centerOnFocusHorizontal(e) { +function centerOnFocusHorizontal(this: HTMLElement, e: Event) { centerOnFocus(e, this, true); } -function centerOnFocusVertical(e) { +function centerOnFocusVertical(this: HTMLElement, e: Event) { centerOnFocus(e, this, false); } export const centerFocus = { - on: function (element, horizontal) { + on: function (element: Element, horizontal: boolean) { element.setAttribute(`data-scroll-mode-${horizontal ? 'x' : 'y'}`, 'custom'); if (horizontal) { @@ -113,7 +113,7 @@ export const centerFocus = { }); } }, - off: function (element, horizontal) { + off: function (element: Element, horizontal: boolean) { element.removeAttribute(`data-scroll-mode-${horizontal ? 'x' : 'y'}`); if (horizontal) { From 74f81f43274582cbe0963975991b4efbf684389b Mon Sep 17 00:00:00 2001 From: Csaba Seprenyi Date: Sun, 18 Feb 2024 21:00:52 +0000 Subject: [PATCH 040/118] Translated using Weblate (Hungarian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/hu/ --- src/strings/hu.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/strings/hu.json b/src/strings/hu.json index f79fab178f..60ac4513e9 100644 --- a/src/strings/hu.json +++ b/src/strings/hu.json @@ -170,7 +170,7 @@ "LabelCollection": "Gyűjtemény", "LabelCommunityRating": "Közösségi értékelés", "LabelContentType": "Tartalom típusa", - "LabelCountry": "Ország", + "LabelCountry": "Ország/Régió", "LabelCriticRating": "Kritikusok értékelése", "LabelCurrentPassword": "Jelenlegi jelszó", "LabelCustomDeviceDisplayNameHelp": "Adj meg egy egyedi nevet, vagy hagyd üresen a készülék által elküldött név használatához.", @@ -1781,5 +1781,6 @@ "LabelTrackGain": "Címnyereség", "ForeignPartsOnly": "Kényszerített/külföldi alkatrészek", "HearingImpairedShort": "HI/SDH", - "HeaderGuestCast": "Vendégsztárok" + "HeaderGuestCast": "Vendégsztárok", + "HeaderAllRecordings": "Összes Felvétel" } From 6c8967110eb97a27459948b6f757d935ae042a70 Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 19 Feb 2024 13:27:16 +0000 Subject: [PATCH 041/118] Translated using Weblate (German) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/de/ --- src/strings/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strings/de.json b/src/strings/de.json index 9b339775bd..283bca082f 100644 --- a/src/strings/de.json +++ b/src/strings/de.json @@ -428,7 +428,7 @@ "LabelCollection": "Sammlung", "LabelCommunityRating": "Community Bewertung", "LabelContentType": "Typ des Inhalts", - "LabelCountry": "Land", + "LabelCountry": "Land/Region", "LabelCriticRating": "Kritikerbewertung", "LabelCurrentPassword": "Aktuelles Passwort", "LabelCustomCertificatePath": "Benutzerdefinierter Pfad zum SSL-Zertifikat", From f7dc39e787726f85a123a9fdf18326d90815f4b5 Mon Sep 17 00:00:00 2001 From: btopherjohnson Date: Tue, 20 Feb 2024 20:42:36 +0000 Subject: [PATCH 042/118] Translated using Weblate (Malay) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ms/ --- src/strings/ms.json | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/strings/ms.json b/src/strings/ms.json index d950d6ff6c..bb6b6b71e8 100644 --- a/src/strings/ms.json +++ b/src/strings/ms.json @@ -258,5 +258,28 @@ "Cursive": "Sambung", "DefaultSubtitlesHelp": "Sari kata dimuatkan berdasarkan bendera lalai dan paksa dalam metadata yang disematkan. Keutamaan bahasa diambil kira apabila terdapat beberapa pilihan.", "LabelThrottleDelaySecondsHelp": "Masa dalam saat selepas mana transkoder akan dihadkan. Mesti cukup besar untuk klien mengekalkan penimbal yang sihat. Hanya berfungsi jika penghadan diaktifkan.", - "LabelSegmentKeepSeconds": "Masa untuk mengekalkan segmen" + "LabelSegmentKeepSeconds": "Masa untuk mengekalkan segmen", + "PreviousTrack": "Langkau ke sebelumnya", + "QuickConnectAuthorizeFail": "Kod Sambung Pantas tidak dikenali", + "AllowEmbeddedSubtitlesAllowImageOption": "Benarkan Imej", + "QuickConnect": "Sambung Pantas", + "Production": "Penerbitan", + "Primary": "Utama", + "Print": "Cetak", + "Producer": "Penerbit", + "Profile": "Profil", + "Quality": "Kualiti", + "ProductionLocations": "Lokasi penerbitan", + "QuickConnectNotActive": "Sambung Pantas tidak aktif pada pelayan ini", + "QuickConnectNotAvailable": "Minta pentadbir pelayan anda untuk mendayakan Sambung Pantas", + "Rate": "Kadar", + "PreviousChapter": "Bab sebelumnya", + "QuickConnectAuthorizeCode": "Masukkan kod {0} untuk log masuk", + "QuickConnectDeactivated": "Sambungan Pantas telah dinyahaktifkan sebelum permintaan log masuk dapat diluluskan", + "Previous": "Sebelumnya", + "LabelSegmentKeepSecondsHelp": "Masa dalam saat yang segmen harus disimpan sebelum ia ditulis ganti. Mesti melebihi \"Penghad laju setelah\". Hanya berfungsi jika pemadaman segmen didayakan.", + "AllowEmbeddedSubtitlesAllowAllOption": "Benarkan Semua", + "AllowEmbeddedSubtitlesAllowTextOption": "Benarkan Teks", + "QuickConnectDescription": "Untuk log masuk dengan Sambung Pantas, pilihlah butang 'Sambung Pantas' pada peranti yang anda menggunakan untuk log masuk dan memasukkan kod yang muncul di bawah.", + "QuickConnectInvalidCode": "Kod Sambung Pantas tidak sah" } From 08b922e1f75ebbb70c41de47e74abe76a0da4064 Mon Sep 17 00:00:00 2001 From: Filan Fisteku Date: Tue, 20 Feb 2024 20:31:22 +0000 Subject: [PATCH 043/118] Translated using Weblate (Albanian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/sq/ --- src/strings/sq.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/strings/sq.json b/src/strings/sq.json index 64f0afa9c9..de2b0a5ea6 100644 --- a/src/strings/sq.json +++ b/src/strings/sq.json @@ -581,5 +581,7 @@ "HeaderAutoDiscovery": "Zbulim ne rrjet", "HeaderStopRecording": "Ndaloni regjistrimin", "HeaderSubtitleProfilesHelp": "Profilet e titrave përshkruajnë formatin e titrave që suportohen nga paisja.", - "HeaderSyncPlaySelectGroup": "Bashkohuni një grupi" + "HeaderSyncPlaySelectGroup": "Bashkohuni një grupi", + "DirectStreamHelp2": "Energjia e konsumuar nga transmetimi i drejtpërdrejtë zakonisht varet nga profili i audios. Vetëm transmetimi i videove është pa humbje.", + "EnableDetailsBannerHelp": "Shfaqni një imazh baneri në krye të faqes së artikullit." } From 4a6efbe359ddb9900102e7e1081c84a78ef5341e Mon Sep 17 00:00:00 2001 From: btopherjohnson Date: Tue, 20 Feb 2024 22:42:17 +0000 Subject: [PATCH 044/118] Translated using Weblate (Malay) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/ms/ --- src/strings/ms.json | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/strings/ms.json b/src/strings/ms.json index bb6b6b71e8..19bee8014a 100644 --- a/src/strings/ms.json +++ b/src/strings/ms.json @@ -102,7 +102,7 @@ "AskAdminToCreateLibrary": "Minta pentadbir untuk membuat perpustakaan.", "Artist": "Artis", "ApiKeysCaption": "Senarai kunci API yang diaktifkan sekarang", - "AllowTonemappingHelp": "Pemetaan-tone dapat mengubah dinamik video daripada HDR ke SDR sambil mengekalkan perincian dan warna gambar, yang merupakan maklumat yang sangat penting untuk mewakili pemandangan asal. Pada masa ini ia hanya berfungsi dengan video 10bit HDR10, HLG dan Dolby Visoion. Ini memerlukan pemadanan bersesuian dengan OpenCL atau CUDA runtime.", + "AllowTonemappingHelp": "Pemetaan-tone dapat mengubah dinamik video daripada HDR ke SDR sambil mengekalkan perincian dan warna gambar, yang merupakan maklumat yang sangat penting untuk mewakili pemandangan asal. Pada masa ini ia hanya berfungsi dengan video 10bit HDR10, HLG, dan Dolby Vision. Ini memerlukan pemadanan bersesuian dengan OpenCL atau CUDA runtime.", "Songs": "Lagu-lagu", "Playlists": "Senarai ulangmain", "Photos": "Gambar-gambar", @@ -210,7 +210,7 @@ "DisplayInMyMedia": "Pamerkan di skrin utama", "DirectStreaming": "Mainkan secara terus", "DirectStreamHelp1": "Strim video ini serasi dengan peranti ini, tetapi ia mempunya format audio (DTS, Dolby TrueHD, dll.) ataupun jumlah saluran audio yang tidak sepadan. Strim video ini akan dipakej tanpa dimampatkan secara masa sebenar sebelum dihantar ke peranti. Hanya strim audio sahaja yang akan ditranskod.", - "DirectPlayHelp": "Fail sumber ini serasi sepenuhnya dengan klien ini, dan sesi ini menerima fail tanpa pengubahsuaian.", + "DirectPlayHelp": "Fail sumber ini serasi sepenuhnya dengan klien ini dan sesi ini menerima fail tanpa pengubahsuaian.", "DirectPlaying": "Mainkan secara terus", "Directors": "Pengarah", "Digital": "Digital", @@ -281,5 +281,19 @@ "AllowEmbeddedSubtitlesAllowAllOption": "Benarkan Semua", "AllowEmbeddedSubtitlesAllowTextOption": "Benarkan Teks", "QuickConnectDescription": "Untuk log masuk dengan Sambung Pantas, pilihlah butang 'Sambung Pantas' pada peranti yang anda menggunakan untuk log masuk dan memasukkan kod yang muncul di bawah.", - "QuickConnectInvalidCode": "Kod Sambung Pantas tidak sah" + "QuickConnectInvalidCode": "Kod Sambung Pantas tidak sah", + "EnableNextVideoInfoOverlay": "Tunjukkan informasi video seterusnya semasa main balik", + "EnablePhotosHelp": "Imej akan dikesan dan dipaparkan bersama fail media lain.", + "Help": "Bantuan", + "DownloadAll": "Muat Turun Semua", + "EnablePhotos": "Paparkan gambar", + "EnableQuickConnect": "Dayakan Sambung Pantas pada pelayan ini", + "DisplayMissingEpisodesWithinSeasonsHelp": "Ini juga mesti didayakan untuk perpustakaan TV dalam konfigurasi pelayan.", + "EnableExternalVideoPlayers": "Pemain video luaran", + "Desktop": "Desktop", + "EnableNextVideoInfoOverlayHelp": "Pada penghujung video, paparkan maklumat tentang video seterusnya yang muncul dalam senarai main semasa.", + "EnableCinemaMode": "Mod pawagam", + "DisableCustomCss": "Lumpuhkan kod CSS kustom yang disediakan oleh pelayan", + "EnablePlugin": "Dayakan", + "DisablePlugin": "Lumpuhkan" } From 1aabbae3a5176cb9ca979311f1e3bec99cb5afba Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Wed, 21 Feb 2024 00:47:03 -0500 Subject: [PATCH 045/118] Add build and web versions to dashboard --- .eslintrc.js | 6 ++- .../components/drawers/DrawerHeaderLink.tsx | 4 +- src/controllers/dashboard/dashboard.html | 14 ++++-- src/controllers/dashboard/dashboard.js | 45 +++++++++++-------- src/controllers/dashboard/dashboard.scss | 17 +++++++ src/global.d.ts | 4 ++ src/hooks/useSystemInfo.ts | 31 +++++++++---- src/index.jsx | 2 +- src/scripts/settings/webSettings.js | 2 +- src/strings/en-us.json | 5 ++- webpack.common.js | 4 ++ 11 files changed, 95 insertions(+), 39 deletions(-) create mode 100644 src/controllers/dashboard/dashboard.scss diff --git a/.eslintrc.js b/.eslintrc.js index a43399e96c..2b65ee767b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -261,7 +261,11 @@ module.exports = { 'ServerNotifications': 'writable', 'TaskButton': 'writable', 'UserParentalControlPage': 'writable', - 'Windows': 'readonly' + 'Windows': 'readonly', + // Build time definitions + __JF_BUILD_VERSION__: 'readonly', + __USE_SYSTEM_FONTS__: 'readonly', + __WEBPACK_SERVE__: 'readonly' }, rules: { '@typescript-eslint/prefer-string-starts-ends-with': ['error'] diff --git a/src/apps/experimental/components/drawers/DrawerHeaderLink.tsx b/src/apps/experimental/components/drawers/DrawerHeaderLink.tsx index 4515779763..a60dd2a6c7 100644 --- a/src/apps/experimental/components/drawers/DrawerHeaderLink.tsx +++ b/src/apps/experimental/components/drawers/DrawerHeaderLink.tsx @@ -3,15 +3,13 @@ import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; import React from 'react'; -import { useApi } from 'hooks/useApi'; import { useSystemInfo } from 'hooks/useSystemInfo'; import ListItemLink from 'components/ListItemLink'; import appIcon from 'assets/img/icon-transparent.png'; const DrawerHeaderLink = () => { - const { api } = useApi(); - const { data: systemInfo } = useSystemInfo(api); + const { data: systemInfo } = useSystemInfo(); return ( diff --git a/src/controllers/dashboard/dashboard.html b/src/controllers/dashboard/dashboard.html index aed6bb206f..4dd260877c 100644 --- a/src/controllers/dashboard/dashboard.html +++ b/src/controllers/dashboard/dashboard.html @@ -8,16 +8,22 @@ -
-

-

+
+
${LabelServerName}
+
+
${LabelServerVersion}
+
+
${LabelWebVersion}
+
+
${LabelBuildVersion}
+
- + +
+ +); + +export default DlnaPage; diff --git a/src/controllers/dashboard/dlna/profile.html b/src/controllers/dashboard/dlna/profile.html deleted file mode 100644 index 237874e156..0000000000 --- a/src/controllers/dashboard/dlna/profile.html +++ /dev/null @@ -1,584 +0,0 @@ -
-
-
-
-
-
-

${HeaderProfileInformation}

-
-
- -
-
-
- -
-
- -
${LabelUserLibraryHelp}
-
-
-

${LabelSupportedMediaTypes}

-
- - - -
-
-
-
- -
${LabelMaxStreamingBitrateHelp}
-
-
- -
${LabelMusicStreamingTranscodingBitrateHelp}
-
-
- - -
${OptionIgnoreTranscodeByteRangeRequestsHelp}
-
-
-
-

${HeaderIdentificationCriteriaHelp}

-
- -
${LabelIdentificationFieldHelp}
-
-
- -
${LabelIdentificationFieldHelp}
-
-
- -
${LabelIdentificationFieldHelp}
-
-
- -
${LabelIdentificationFieldHelp}
-
-
- -
${LabelIdentificationFieldHelp}
-
-
- -
${LabelIdentificationFieldHelp}
-
-
- -
${LabelIdentificationFieldHelp}
-
-
- -
${LabelIdentificationFieldHelp}
-
-
- -
${LabelIdentificationFieldHelp}
-
-
-

${HeaderHttpHeaders}

- -
-
-
-
-
-
-
-
- -
${OptionPlainStorageFoldersHelp}
-
-
- -
${OptionPlainVideoItemsHelp}
-
-
-
-
-
-
- -
${LabelEmbedAlbumArtDidlHelp}
-
-
- -
${LabelEnableSingleImageInDidlLimitHelp}
-
-
- -
${LabelAlbumArtHelp}
-
-
- -
${LabelAlbumArtMaxResHelp}
-
-
- -
${LabelAlbumArtMaxResHelp}
-
-
- -
${LabelIconMaxResHelp}
-
-
- -
${LabelIconMaxResHelp}
-
-
-
-
-
-

${HeaderProfileServerSettingsHelp}

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
${LabelProtocolInfoHelp}
-
-
- -
${LabelXDlnaCapHelp}
-
-
- -
${LabelXDlnaDocHelp}
-
-
- -
${LabelSonyAggregationFlagsHelp}
-
-
-
-
-
-

${HeaderSubtitleProfilesHelp}

- -
-
-
-
-
-
-
-

${HeaderXmlDocumentAttributes}

- -
-
-
${XmlDocumentAttributeListHelp}
-
-
-
-
-
-

${HeaderDirectPlayProfileHelp}

- -
-
-
-
-

${HeaderTranscodingProfileHelp}

- -
-
-
-
-

${HeaderContainerProfileHelp}

- -
-
-
-
-

${HeaderCodecProfileHelp}

- -
-
-
-
-

${HeaderResponseProfileHelp}

- -
-
-
-
-
- - -
-
-
-
-
-
-
-

${HeaderDirectPlayProfile}

-
-
-
- -
-
- -
${LabelProfileContainersHelp}
-
-
-
- -
${LabelProfileCodecsHelp}
-
-
-
-
- -
${LabelProfileCodecsHelp}
-
-
-

- - -

-
-
-
-
-
-
-

${HeaderTranscodingProfile}

-
-
-
- - - - -
-
- - -

- - -

-
-
-
-
-
-
-

${HeaderContainerProfile}

-
-
-

${HeaderContainerProfileHelp}

-
-
- -
-
- -
${LabelProfileContainersHelp}
-
-
- -

- - -

-
-
-
-
-
-
-

${HeaderCodecProfile}

-
-
-

${HeaderCodecProfileHelp}

-
- -
-
- -
${LabelProfileCodecsHelp}
-
-

- - -

-
-
-
-
-
-
-

${HeaderResponseProfile}

-
-
-
- -
-
- -
${LabelProfileContainersHelp}
-
-
-
- -
${LabelProfileCodecsHelp}
-
-
-
-
- -
${LabelProfileCodecsHelp}
-
-
-

- - -

-
-
-
-
-
-
-

${HeaderIdentificationHeader}

-
-
-
- -
-
- -
-
- -
-

- - -

-
-
-
-
-
-
-

${HeaderXmlDocumentAttribute}

-
-
-
- -
-
- -
-

- - -

-
-
-
-
-
-
-

${HeaderSubtitleProfile}

-
-
-
- -
${LabelSubtitleFormatHelp}
-
-
- -
-
- -
-

- - -

-
-
-
-
diff --git a/src/controllers/dashboard/dlna/profile.js b/src/controllers/dashboard/dlna/profile.js deleted file mode 100644 index 0f92a3200c..0000000000 --- a/src/controllers/dashboard/dlna/profile.js +++ /dev/null @@ -1,830 +0,0 @@ -import escapeHtml from 'escape-html'; -import 'jquery'; -import loading from '../../../components/loading/loading'; -import globalize from '../../../scripts/globalize'; -import '../../../elements/emby-select/emby-select'; -import '../../../elements/emby-button/emby-button'; -import '../../../elements/emby-input/emby-input'; -import '../../../elements/emby-checkbox/emby-checkbox'; -import '../../../components/listview/listview.scss'; -import Dashboard from '../../../utils/dashboard'; -import toast from '../../../components/toast/toast'; -import { getParameterByName } from '../../../utils/url.ts'; - -function loadProfile(page) { - loading.show(); - const promise1 = getProfile(); - const promise2 = ApiClient.getUsers(); - Promise.all([promise1, promise2]).then(function (responses) { - currentProfile = responses[0]; - renderProfile(page, currentProfile, responses[1]); - loading.hide(); - }); -} - -function getProfile() { - const id = getParameterByName('id'); - const url = id ? 'Dlna/Profiles/' + id : 'Dlna/Profiles/Default'; - return ApiClient.getJSON(ApiClient.getUrl(url)); -} - -function renderProfile(page, profile, users) { - $('#txtName', page).val(profile.Name); - $('.chkMediaType', page).each(function () { - this.checked = (profile.SupportedMediaTypes || '').split(',').indexOf(this.getAttribute('data-value')) != -1; - }); - $('#chkEnableAlbumArtInDidl', page).prop('checked', profile.EnableAlbumArtInDidl); - $('#chkEnableSingleImageLimit', page).prop('checked', profile.EnableSingleAlbumArtLimit); - renderXmlDocumentAttributes(page, profile.XmlRootAttributes || []); - const idInfo = profile.Identification || {}; - renderIdentificationHeaders(page, idInfo.Headers || []); - renderSubtitleProfiles(page, profile.SubtitleProfiles || []); - $('#txtInfoFriendlyName', page).val(profile.FriendlyName || ''); - $('#txtInfoModelName', page).val(profile.ModelName || ''); - $('#txtInfoModelNumber', page).val(profile.ModelNumber || ''); - $('#txtInfoModelDescription', page).val(profile.ModelDescription || ''); - $('#txtInfoModelUrl', page).val(profile.ModelUrl || ''); - $('#txtInfoManufacturer', page).val(profile.Manufacturer || ''); - $('#txtInfoManufacturerUrl', page).val(profile.ManufacturerUrl || ''); - $('#txtInfoSerialNumber', page).val(profile.SerialNumber || ''); - $('#txtIdFriendlyName', page).val(idInfo.FriendlyName || ''); - $('#txtIdModelName', page).val(idInfo.ModelName || ''); - $('#txtIdModelNumber', page).val(idInfo.ModelNumber || ''); - $('#txtIdModelDescription', page).val(idInfo.ModelDescription || ''); - $('#txtIdModelUrl', page).val(idInfo.ModelUrl || ''); - $('#txtIdManufacturer', page).val(idInfo.Manufacturer || ''); - $('#txtIdManufacturerUrl', page).val(idInfo.ManufacturerUrl || ''); - $('#txtIdSerialNumber', page).val(idInfo.SerialNumber || ''); - $('#txtIdDeviceDescription', page).val(idInfo.DeviceDescription || ''); - $('#txtAlbumArtPn', page).val(profile.AlbumArtPn || ''); - $('#txtAlbumArtMaxWidth', page).val(profile.MaxAlbumArtWidth || ''); - $('#txtAlbumArtMaxHeight', page).val(profile.MaxAlbumArtHeight || ''); - $('#txtIconMaxWidth', page).val(profile.MaxIconWidth || ''); - $('#txtIconMaxHeight', page).val(profile.MaxIconHeight || ''); - $('#chkIgnoreTranscodeByteRangeRequests', page).prop('checked', profile.IgnoreTranscodeByteRangeRequests); - $('#txtMaxAllowedBitrate', page).val(profile.MaxStreamingBitrate || ''); - $('#txtMusicStreamingTranscodingBitrate', page).val(profile.MusicStreamingTranscodingBitrate || ''); - $('#chkRequiresPlainFolders', page).prop('checked', profile.RequiresPlainFolders); - $('#chkRequiresPlainVideoItems', page).prop('checked', profile.RequiresPlainVideoItems); - $('#txtProtocolInfo', page).val(profile.ProtocolInfo || ''); - $('#txtXDlnaCap', page).val(profile.XDlnaCap || ''); - $('#txtXDlnaDoc', page).val(profile.XDlnaDoc || ''); - $('#txtSonyAggregationFlags', page).val(profile.SonyAggregationFlags || ''); - profile.DirectPlayProfiles = profile.DirectPlayProfiles || []; - profile.TranscodingProfiles = profile.TranscodingProfiles || []; - profile.ContainerProfiles = profile.ContainerProfiles || []; - profile.CodecProfiles = profile.CodecProfiles || []; - profile.ResponseProfiles = profile.ResponseProfiles || []; - const usersHtml = '' + users.map(function (u) { - return ''; - }).join(''); - $('#selectUser', page).html(usersHtml).val(profile.UserId || ''); - renderSubProfiles(page, profile); -} - -function renderIdentificationHeaders(page, headers) { - let index = 0; - const html = '
' + headers.map(function (h) { - let li = '
'; - li += ''; - li += '
'; - li += '

' + escapeHtml(h.Name + ': ' + (h.Value || '')) + '

'; - li += '
' + escapeHtml(h.Match || '') + '
'; - li += '
'; - li += ''; - li += '
'; - index++; - return li; - }).join('') + '
'; - const elem = $('.httpHeaderIdentificationList', page).html(html).trigger('create'); - $('.btnDeleteIdentificationHeader', elem).on('click', function () { - const itemIndex = parseInt(this.getAttribute('data-index'), 10); - currentProfile.Identification.Headers.splice(itemIndex, 1); - renderIdentificationHeaders(page, currentProfile.Identification.Headers); - }); -} - -function openPopup(elem) { - elem.classList.remove('hide'); -} - -function closePopup(elem) { - elem.classList.add('hide'); -} - -function editIdentificationHeader(page, header) { - isSubProfileNew = header == null; - header = header || {}; - currentSubProfile = header; - const popup = $('#identificationHeaderPopup', page); - $('#txtIdentificationHeaderName', popup).val(header.Name || ''); - $('#txtIdentificationHeaderValue', popup).val(header.Value || ''); - $('#selectMatchType', popup).val(header.Match || 'Equals'); - openPopup(popup[0]); -} - -function saveIdentificationHeader(page) { - currentSubProfile.Name = $('#txtIdentificationHeaderName', page).val(); - currentSubProfile.Value = $('#txtIdentificationHeaderValue', page).val(); - currentSubProfile.Match = $('#selectMatchType', page).val(); - - if (isSubProfileNew) { - currentProfile.Identification = currentProfile.Identification || {}; - currentProfile.Identification.Headers = currentProfile.Identification.Headers || []; - currentProfile.Identification.Headers.push(currentSubProfile); - } - - renderIdentificationHeaders(page, currentProfile.Identification.Headers); - currentSubProfile = null; - closePopup($('#identificationHeaderPopup', page)[0]); -} - -function renderXmlDocumentAttributes(page, attribute) { - const html = '
' + attribute.map(function (h) { - let li = '
'; - li += ''; - li += '
'; - li += '

' + escapeHtml(h.Name + ' = ' + (h.Value || '')) + '

'; - li += '
'; - li += ''; - li += '
'; - return li; - }).join('') + '
'; - const elem = $('.xmlDocumentAttributeList', page).html(html).trigger('create'); - $('.btnDeleteXmlAttribute', elem).on('click', function () { - const itemIndex = parseInt(this.getAttribute('data-index'), 10); - currentProfile.XmlRootAttributes.splice(itemIndex, 1); - renderXmlDocumentAttributes(page, currentProfile.XmlRootAttributes); - }); -} - -function editXmlDocumentAttribute(page, attribute) { - isSubProfileNew = attribute == null; - attribute = attribute || {}; - currentSubProfile = attribute; - const popup = $('#xmlAttributePopup', page); - $('#txtXmlAttributeName', popup).val(attribute.Name || ''); - $('#txtXmlAttributeValue', popup).val(attribute.Value || ''); - openPopup(popup[0]); -} - -function saveXmlDocumentAttribute(page) { - currentSubProfile.Name = $('#txtXmlAttributeName', page).val(); - currentSubProfile.Value = $('#txtXmlAttributeValue', page).val(); - - if (isSubProfileNew) { - currentProfile.XmlRootAttributes.push(currentSubProfile); - } - - renderXmlDocumentAttributes(page, currentProfile.XmlRootAttributes); - currentSubProfile = null; - closePopup($('#xmlAttributePopup', page)[0]); -} - -function renderSubtitleProfiles(page, profiles) { - let index = 0; - const html = '
' + profiles.map(function (h) { - let li = '
'; - li += ''; - li += '
'; - li += '

' + escapeHtml(h.Format || '') + '

'; - li += '
'; - li += ''; - li += '
'; - index++; - return li; - }).join('') + '
'; - const elem = $('.subtitleProfileList', page).html(html).trigger('create'); - $('.btnDeleteProfile', elem).on('click', function () { - const itemIndex = parseInt(this.getAttribute('data-index'), 10); - currentProfile.SubtitleProfiles.splice(itemIndex, 1); - renderSubtitleProfiles(page, currentProfile.SubtitleProfiles); - }); - $('.lnkEditSubProfile', elem).on('click', function () { - const itemIndex = parseInt(this.getAttribute('data-index'), 10); - editSubtitleProfile(page, currentProfile.SubtitleProfiles[itemIndex]); - }); -} - -function editSubtitleProfile(page, profile) { - isSubProfileNew = profile == null; - profile = profile || {}; - currentSubProfile = profile; - const popup = $('#subtitleProfilePopup', page); - $('#txtSubtitleProfileFormat', popup).val(profile.Format || ''); - $('#selectSubtitleProfileMethod', popup).val(profile.Method || ''); - $('#selectSubtitleProfileDidlMode', popup).val(profile.DidlMode || ''); - openPopup(popup[0]); -} - -function saveSubtitleProfile(page) { - currentSubProfile.Format = $('#txtSubtitleProfileFormat', page).val(); - currentSubProfile.Method = $('#selectSubtitleProfileMethod', page).val(); - currentSubProfile.DidlMode = $('#selectSubtitleProfileDidlMode', page).val(); - - if (isSubProfileNew) { - currentProfile.SubtitleProfiles.push(currentSubProfile); - } - - renderSubtitleProfiles(page, currentProfile.SubtitleProfiles); - currentSubProfile = null; - closePopup($('#subtitleProfilePopup', page)[0]); -} - -function renderSubProfiles(page, profile) { - renderDirectPlayProfiles(page, profile.DirectPlayProfiles); - renderTranscodingProfiles(page, profile.TranscodingProfiles); - renderContainerProfiles(page, profile.ContainerProfiles); - renderCodecProfiles(page, profile.CodecProfiles); - renderResponseProfiles(page, profile.ResponseProfiles); -} - -function saveDirectPlayProfile(page) { - currentSubProfile.Type = $('#selectDirectPlayProfileType', page).val(); - currentSubProfile.Container = $('#txtDirectPlayContainer', page).val(); - currentSubProfile.AudioCodec = $('#txtDirectPlayAudioCodec', page).val(); - currentSubProfile.VideoCodec = $('#txtDirectPlayVideoCodec', page).val(); - - if (isSubProfileNew) { - currentProfile.DirectPlayProfiles.push(currentSubProfile); - } - - renderSubProfiles(page, currentProfile); - currentSubProfile = null; - closePopup($('#popupEditDirectPlayProfile', page)[0]); -} - -function renderDirectPlayProfiles(page, profiles) { - let html = ''; - html += ''; - const elem = $('.directPlayProfiles', page).html(html).trigger('create'); - $('.btnDeleteProfile', elem).on('click', function () { - const index = this.getAttribute('data-profileindex'); - deleteDirectPlayProfile(page, index); - }); - $('.lnkEditSubProfile', elem).on('click', function () { - const index = parseInt(this.getAttribute('data-profileindex'), 10); - editDirectPlayProfile(page, currentProfile.DirectPlayProfiles[index]); - }); -} - -function deleteDirectPlayProfile(page, index) { - currentProfile.DirectPlayProfiles.splice(index, 1); - renderDirectPlayProfiles(page, currentProfile.DirectPlayProfiles); -} - -function editDirectPlayProfile(page, directPlayProfile) { - isSubProfileNew = directPlayProfile == null; - directPlayProfile = directPlayProfile || {}; - currentSubProfile = directPlayProfile; - const popup = $('#popupEditDirectPlayProfile', page); - $('#selectDirectPlayProfileType', popup).val(directPlayProfile.Type || 'Video').trigger('change'); - $('#txtDirectPlayContainer', popup).val(directPlayProfile.Container || ''); - $('#txtDirectPlayAudioCodec', popup).val(directPlayProfile.AudioCodec || ''); - $('#txtDirectPlayVideoCodec', popup).val(directPlayProfile.VideoCodec || ''); - openPopup(popup[0]); -} - -function renderTranscodingProfiles(page, profiles) { - let html = ''; - html += ''; - const elem = $('.transcodingProfiles', page).html(html).trigger('create'); - $('.btnDeleteProfile', elem).on('click', function () { - const index = this.getAttribute('data-profileindex'); - deleteTranscodingProfile(page, index); - }); - $('.lnkEditSubProfile', elem).on('click', function () { - const index = parseInt(this.getAttribute('data-profileindex'), 10); - editTranscodingProfile(page, currentProfile.TranscodingProfiles[index]); - }); -} - -function editTranscodingProfile(page, transcodingProfile) { - isSubProfileNew = transcodingProfile == null; - transcodingProfile = transcodingProfile || {}; - currentSubProfile = transcodingProfile; - const popup = $('#transcodingProfilePopup', page); - $('#selectTranscodingProfileType', popup).val(transcodingProfile.Type || 'Video').trigger('change'); - $('#txtTranscodingContainer', popup).val(transcodingProfile.Container || ''); - $('#txtTranscodingAudioCodec', popup).val(transcodingProfile.AudioCodec || ''); - $('#txtTranscodingVideoCodec', popup).val(transcodingProfile.VideoCodec || ''); - $('#selectTranscodingProtocol', popup).val(transcodingProfile.Protocol || 'Http'); - $('#chkEnableMpegtsM2TsMode', popup).prop('checked', transcodingProfile.EnableMpegtsM2TsMode || false); - $('#chkEstimateContentLength', popup).prop('checked', transcodingProfile.EstimateContentLength || false); - $('#chkReportByteRangeRequests', popup).prop('checked', transcodingProfile.TranscodeSeekInfo == 'Bytes'); - $('.radioTabButton:first', popup).trigger('click'); - openPopup(popup[0]); -} - -function deleteTranscodingProfile(page, index) { - currentProfile.TranscodingProfiles.splice(index, 1); - renderTranscodingProfiles(page, currentProfile.TranscodingProfiles); -} - -function saveTranscodingProfile(page) { - currentSubProfile.Type = $('#selectTranscodingProfileType', page).val(); - currentSubProfile.Container = $('#txtTranscodingContainer', page).val(); - currentSubProfile.AudioCodec = $('#txtTranscodingAudioCodec', page).val(); - currentSubProfile.VideoCodec = $('#txtTranscodingVideoCodec', page).val(); - currentSubProfile.Protocol = $('#selectTranscodingProtocol', page).val(); - currentSubProfile.Context = 'Streaming'; - currentSubProfile.EnableMpegtsM2TsMode = $('#chkEnableMpegtsM2TsMode', page).is(':checked'); - currentSubProfile.EstimateContentLength = $('#chkEstimateContentLength', page).is(':checked'); - currentSubProfile.TranscodeSeekInfo = $('#chkReportByteRangeRequests', page).is(':checked') ? 'Bytes' : 'Auto'; - - if (isSubProfileNew) { - currentProfile.TranscodingProfiles.push(currentSubProfile); - } - - renderSubProfiles(page, currentProfile); - currentSubProfile = null; - closePopup($('#transcodingProfilePopup', page)[0]); -} - -function renderContainerProfiles(page, profiles) { - let html = ''; - html += ''; - const elem = $('.containerProfiles', page).html(html).trigger('create'); - $('.btnDeleteProfile', elem).on('click', function () { - const index = this.getAttribute('data-profileindex'); - deleteContainerProfile(page, index); - }); - $('.lnkEditSubProfile', elem).on('click', function () { - const index = parseInt(this.getAttribute('data-profileindex'), 10); - editContainerProfile(page, currentProfile.ContainerProfiles[index]); - }); -} - -function deleteContainerProfile(page, index) { - currentProfile.ContainerProfiles.splice(index, 1); - renderContainerProfiles(page, currentProfile.ContainerProfiles); -} - -function editContainerProfile(page, containerProfile) { - isSubProfileNew = containerProfile == null; - containerProfile = containerProfile || {}; - currentSubProfile = containerProfile; - const popup = $('#containerProfilePopup', page); - $('#selectContainerProfileType', popup).val(containerProfile.Type || 'Video').trigger('change'); - $('#txtContainerProfileContainer', popup).val(containerProfile.Container || ''); - $('.radioTabButton:first', popup).trigger('click'); - openPopup(popup[0]); -} - -function saveContainerProfile(page) { - currentSubProfile.Type = $('#selectContainerProfileType', page).val(); - currentSubProfile.Container = $('#txtContainerProfileContainer', page).val(); - - if (isSubProfileNew) { - currentProfile.ContainerProfiles.push(currentSubProfile); - } - - renderSubProfiles(page, currentProfile); - currentSubProfile = null; - closePopup($('#containerProfilePopup', page)[0]); -} - -function renderCodecProfiles(page, profiles) { - let html = ''; - html += ''; - const elem = $('.codecProfiles', page).html(html).trigger('create'); - $('.btnDeleteProfile', elem).on('click', function () { - const index = this.getAttribute('data-profileindex'); - deleteCodecProfile(page, index); - }); - $('.lnkEditSubProfile', elem).on('click', function () { - const index = parseInt(this.getAttribute('data-profileindex'), 10); - editCodecProfile(page, currentProfile.CodecProfiles[index]); - }); -} - -function deleteCodecProfile(page, index) { - currentProfile.CodecProfiles.splice(index, 1); - renderCodecProfiles(page, currentProfile.CodecProfiles); -} - -function editCodecProfile(page, codecProfile) { - isSubProfileNew = codecProfile == null; - codecProfile = codecProfile || {}; - currentSubProfile = codecProfile; - const popup = $('#codecProfilePopup', page); - $('#selectCodecProfileType', popup).val(codecProfile.Type || 'Video').trigger('change'); - $('#txtCodecProfileCodec', popup).val(codecProfile.Codec || ''); - $('.radioTabButton:first', popup).trigger('click'); - openPopup(popup[0]); -} - -function saveCodecProfile(page) { - currentSubProfile.Type = $('#selectCodecProfileType', page).val(); - currentSubProfile.Codec = $('#txtCodecProfileCodec', page).val(); - - if (isSubProfileNew) { - currentProfile.CodecProfiles.push(currentSubProfile); - } - - renderSubProfiles(page, currentProfile); - currentSubProfile = null; - closePopup($('#codecProfilePopup', page)[0]); -} - -function renderResponseProfiles(page, profiles) { - let html = ''; - html += ''; - const elem = $('.mediaProfiles', page).html(html).trigger('create'); - $('.btnDeleteProfile', elem).on('click', function () { - const index = this.getAttribute('data-profileindex'); - deleteResponseProfile(page, index); - }); - $('.lnkEditSubProfile', elem).on('click', function () { - const index = parseInt(this.getAttribute('data-profileindex'), 10); - editResponseProfile(page, currentProfile.ResponseProfiles[index]); - }); -} - -function deleteResponseProfile(page, index) { - currentProfile.ResponseProfiles.splice(index, 1); - renderResponseProfiles(page, currentProfile.ResponseProfiles); -} - -function editResponseProfile(page, responseProfile) { - isSubProfileNew = responseProfile == null; - responseProfile = responseProfile || {}; - currentSubProfile = responseProfile; - const popup = $('#responseProfilePopup', page); - $('#selectResponseProfileType', popup).val(responseProfile.Type || 'Video').trigger('change'); - $('#txtResponseProfileContainer', popup).val(responseProfile.Container || ''); - $('#txtResponseProfileAudioCodec', popup).val(responseProfile.AudioCodec || ''); - $('#txtResponseProfileVideoCodec', popup).val(responseProfile.VideoCodec || ''); - $('.radioTabButton:first', popup).trigger('click'); - openPopup(popup[0]); -} - -function saveResponseProfile(page) { - currentSubProfile.Type = $('#selectResponseProfileType', page).val(); - currentSubProfile.Container = $('#txtResponseProfileContainer', page).val(); - currentSubProfile.AudioCodec = $('#txtResponseProfileAudioCodec', page).val(); - currentSubProfile.VideoCodec = $('#txtResponseProfileVideoCodec', page).val(); - - if (isSubProfileNew) { - currentProfile.ResponseProfiles.push(currentSubProfile); - } - - renderSubProfiles(page, currentProfile); - currentSubProfile = null; - closePopup($('#responseProfilePopup', page)[0]); -} - -function saveProfile(page, profile) { - updateProfile(page, profile); - const id = getParameterByName('id'); - - if (id) { - ApiClient.ajax({ - type: 'POST', - url: ApiClient.getUrl('Dlna/Profiles/' + id), - data: JSON.stringify(profile), - contentType: 'application/json' - }).then(function () { - toast(globalize.translate('SettingsSaved')); - }, Dashboard.processErrorResponse); - } else { - ApiClient.ajax({ - type: 'POST', - url: ApiClient.getUrl('Dlna/Profiles'), - data: JSON.stringify(profile), - contentType: 'application/json' - }).then(function () { - Dashboard.navigate('dashboard/dlna/profiles'); - }, Dashboard.processErrorResponse); - } - - loading.hide(); -} - -function updateProfile(page, profile) { - profile.Name = $('#txtName', page).val(); - profile.EnableAlbumArtInDidl = $('#chkEnableAlbumArtInDidl', page).is(':checked'); - profile.EnableSingleAlbumArtLimit = $('#chkEnableSingleImageLimit', page).is(':checked'); - profile.SupportedMediaTypes = $('.chkMediaType:checked', page).get().map(function (c) { - return c.getAttribute('data-value'); - }).join(','); - profile.Identification = profile.Identification || {}; - profile.FriendlyName = $('#txtInfoFriendlyName', page).val(); - profile.ModelName = $('#txtInfoModelName', page).val(); - profile.ModelNumber = $('#txtInfoModelNumber', page).val(); - profile.ModelDescription = $('#txtInfoModelDescription', page).val(); - profile.ModelUrl = $('#txtInfoModelUrl', page).val(); - profile.Manufacturer = $('#txtInfoManufacturer', page).val(); - profile.ManufacturerUrl = $('#txtInfoManufacturerUrl', page).val(); - profile.SerialNumber = $('#txtInfoSerialNumber', page).val(); - profile.Identification.FriendlyName = $('#txtIdFriendlyName', page).val(); - profile.Identification.ModelName = $('#txtIdModelName', page).val(); - profile.Identification.ModelNumber = $('#txtIdModelNumber', page).val(); - profile.Identification.ModelDescription = $('#txtIdModelDescription', page).val(); - profile.Identification.ModelUrl = $('#txtIdModelUrl', page).val(); - profile.Identification.Manufacturer = $('#txtIdManufacturer', page).val(); - profile.Identification.ManufacturerUrl = $('#txtIdManufacturerUrl', page).val(); - profile.Identification.SerialNumber = $('#txtIdSerialNumber', page).val(); - profile.Identification.DeviceDescription = $('#txtIdDeviceDescription', page).val(); - profile.AlbumArtPn = $('#txtAlbumArtPn', page).val(); - profile.MaxAlbumArtWidth = $('#txtAlbumArtMaxWidth', page).val(); - profile.MaxAlbumArtHeight = $('#txtAlbumArtMaxHeight', page).val(); - profile.MaxIconWidth = $('#txtIconMaxWidth', page).val(); - profile.MaxIconHeight = $('#txtIconMaxHeight', page).val(); - profile.RequiresPlainFolders = $('#chkRequiresPlainFolders', page).is(':checked'); - profile.RequiresPlainVideoItems = $('#chkRequiresPlainVideoItems', page).is(':checked'); - profile.IgnoreTranscodeByteRangeRequests = $('#chkIgnoreTranscodeByteRangeRequests', page).is(':checked'); - profile.MaxStreamingBitrate = $('#txtMaxAllowedBitrate', page).val(); - profile.MusicStreamingTranscodingBitrate = $('#txtMusicStreamingTranscodingBitrate', page).val(); - profile.ProtocolInfo = $('#txtProtocolInfo', page).val(); - profile.XDlnaCap = $('#txtXDlnaCap', page).val(); - profile.XDlnaDoc = $('#txtXDlnaDoc', page).val(); - profile.SonyAggregationFlags = $('#txtSonyAggregationFlags', page).val(); - profile.UserId = $('#selectUser', page).val(); -} - -let currentProfile; -let currentSubProfile; -let isSubProfileNew; -const allText = globalize.translate('All'); - -$(document).on('pageinit', '#dlnaProfilePage', function () { - const page = this; - $('.radioTabButton', page).on('click', function () { - $(this).siblings().removeClass('ui-btn-active'); - $(this).addClass('ui-btn-active'); - const value = this.tagName == 'A' ? this.getAttribute('data-value') : this.value; - const elem = $('.' + value, page); - elem.siblings('.tabContent').hide(); - elem.show(); - }); - $('#selectDirectPlayProfileType', page).on('change', function () { - if (this.value == 'Video') { - $('#fldDirectPlayVideoCodec', page).show(); - } else { - $('#fldDirectPlayVideoCodec', page).hide(); - } - - if (this.value == 'Photo') { - $('#fldDirectPlayAudioCodec', page).hide(); - } else { - $('#fldDirectPlayAudioCodec', page).show(); - } - }); - $('#selectTranscodingProfileType', page).on('change', function () { - if (this.value == 'Video') { - $('#fldTranscodingVideoCodec', page).show(); - $('#fldTranscodingProtocol', page).show(); - $('#fldEnableMpegtsM2TsMode', page).show(); - } else { - $('#fldTranscodingVideoCodec', page).hide(); - $('#fldTranscodingProtocol', page).hide(); - $('#fldEnableMpegtsM2TsMode', page).hide(); - } - - if (this.value == 'Photo') { - $('#fldTranscodingAudioCodec', page).hide(); - $('#fldEstimateContentLength', page).hide(); - $('#fldReportByteRangeRequests', page).hide(); - } else { - $('#fldTranscodingAudioCodec', page).show(); - $('#fldEstimateContentLength', page).show(); - $('#fldReportByteRangeRequests', page).show(); - } - }); - $('#selectResponseProfileType', page).on('change', function () { - if (this.value == 'Video') { - $('#fldResponseProfileVideoCodec', page).show(); - } else { - $('#fldResponseProfileVideoCodec', page).hide(); - } - - if (this.value == 'Photo') { - $('#fldResponseProfileAudioCodec', page).hide(); - } else { - $('#fldResponseProfileAudioCodec', page).show(); - } - }); - $('.btnAddDirectPlayProfile', page).on('click', function () { - editDirectPlayProfile(page); - }); - $('.btnAddTranscodingProfile', page).on('click', function () { - editTranscodingProfile(page); - }); - $('.btnAddContainerProfile', page).on('click', function () { - editContainerProfile(page); - }); - $('.btnAddCodecProfile', page).on('click', function () { - editCodecProfile(page); - }); - $('.btnAddResponseProfile', page).on('click', function () { - editResponseProfile(page); - }); - $('.btnAddIdentificationHttpHeader', page).on('click', function () { - editIdentificationHeader(page); - }); - $('.btnAddXmlDocumentAttribute', page).on('click', function () { - editXmlDocumentAttribute(page); - }); - $('.btnAddSubtitleProfile', page).on('click', function () { - editSubtitleProfile(page); - }); - $('.dlnaProfileForm').off('submit', DlnaProfilePage.onSubmit).on('submit', DlnaProfilePage.onSubmit); - $('.editDirectPlayProfileForm').off('submit', DlnaProfilePage.onDirectPlayFormSubmit).on('submit', DlnaProfilePage.onDirectPlayFormSubmit); - $('.transcodingProfileForm').off('submit', DlnaProfilePage.onTranscodingProfileFormSubmit).on('submit', DlnaProfilePage.onTranscodingProfileFormSubmit); - $('.containerProfileForm').off('submit', DlnaProfilePage.onContainerProfileFormSubmit).on('submit', DlnaProfilePage.onContainerProfileFormSubmit); - $('.codecProfileForm').off('submit', DlnaProfilePage.onCodecProfileFormSubmit).on('submit', DlnaProfilePage.onCodecProfileFormSubmit); - $('.editResponseProfileForm').off('submit', DlnaProfilePage.onResponseProfileFormSubmit).on('submit', DlnaProfilePage.onResponseProfileFormSubmit); - $('.identificationHeaderForm').off('submit', DlnaProfilePage.onIdentificationHeaderFormSubmit).on('submit', DlnaProfilePage.onIdentificationHeaderFormSubmit); - $('.xmlAttributeForm').off('submit', DlnaProfilePage.onXmlAttributeFormSubmit).on('submit', DlnaProfilePage.onXmlAttributeFormSubmit); - $('.subtitleProfileForm').off('submit', DlnaProfilePage.onSubtitleProfileFormSubmit).on('submit', DlnaProfilePage.onSubtitleProfileFormSubmit); -}).on('pageshow', '#dlnaProfilePage', function () { - const page = this; - $('#radioInfo', page).trigger('click'); - loadProfile(page); -}); -window.DlnaProfilePage = { - onSubmit: function () { - loading.show(); - saveProfile($(this).parents('.page'), currentProfile); - return false; - }, - onDirectPlayFormSubmit: function () { - saveDirectPlayProfile($(this).parents('.page')); - return false; - }, - onTranscodingProfileFormSubmit: function () { - saveTranscodingProfile($(this).parents('.page')); - return false; - }, - onContainerProfileFormSubmit: function () { - saveContainerProfile($(this).parents('.page')); - return false; - }, - onCodecProfileFormSubmit: function () { - saveCodecProfile($(this).parents('.page')); - return false; - }, - onResponseProfileFormSubmit: function () { - saveResponseProfile($(this).parents('.page')); - return false; - }, - onIdentificationHeaderFormSubmit: function () { - saveIdentificationHeader($(this).parents('.page')); - return false; - }, - onXmlAttributeFormSubmit: function () { - saveXmlDocumentAttribute($(this).parents('.page')); - return false; - }, - onSubtitleProfileFormSubmit: function () { - saveSubtitleProfile($(this).parents('.page')); - return false; - } -}; - diff --git a/src/controllers/dashboard/dlna/profiles.html b/src/controllers/dashboard/dlna/profiles.html deleted file mode 100644 index f1696632c9..0000000000 --- a/src/controllers/dashboard/dlna/profiles.html +++ /dev/null @@ -1,32 +0,0 @@ -
- -
-
- -
- -
-
-

${HeaderCustomDlnaProfiles}

- - - -
- -

${CustomDlnaProfilesHelp}

-
-
- - -
-
-

${HeaderSystemDlnaProfiles}

-
- -

${SystemDlnaProfilesHelp}

-
-
-
-
-
-
diff --git a/src/controllers/dashboard/dlna/profiles.js b/src/controllers/dashboard/dlna/profiles.js deleted file mode 100644 index f69a0c6bf0..0000000000 --- a/src/controllers/dashboard/dlna/profiles.js +++ /dev/null @@ -1,93 +0,0 @@ -import escapeHtml from 'escape-html'; -import 'jquery'; -import globalize from '../../../scripts/globalize'; -import loading from '../../../components/loading/loading'; -import libraryMenu from '../../../scripts/libraryMenu'; -import '../../../components/listview/listview.scss'; -import '../../../elements/emby-button/emby-button'; -import confirm from '../../../components/confirm/confirm'; - -function loadProfiles(page) { - loading.show(); - ApiClient.getJSON(ApiClient.getUrl('Dlna/ProfileInfos')).then(function (result) { - renderUserProfiles(page, result); - renderSystemProfiles(page, result); - loading.hide(); - }); -} - -function renderUserProfiles(page, profiles) { - renderProfiles(page, page.querySelector('.customProfiles'), profiles.filter(function (p) { - return p.Type == 'User'; - })); -} - -function renderSystemProfiles(page, profiles) { - renderProfiles(page, page.querySelector('.systemProfiles'), profiles.filter(function (p) { - return p.Type == 'System'; - })); -} - -function renderProfiles(page, element, profiles) { - let html = ''; - - if (profiles.length) { - html += '
'; - } - - for (let i = 0, length = profiles.length; i < length; i++) { - const profile = profiles[i]; - html += '
'; - html += ''; - html += ''; - - if (profile.Type == 'User') { - html += ''; - } - - html += '
'; - } - - if (profiles.length) { - html += '
'; - } - - element.innerHTML = html; - $('.btnDeleteProfile', element).on('click', function () { - const id = this.getAttribute('data-profileid'); - deleteProfile(page, id); - }); -} - -function deleteProfile(page, id) { - confirm(globalize.translate('MessageConfirmProfileDeletion'), globalize.translate('HeaderConfirmProfileDeletion')).then(function () { - loading.show(); - ApiClient.ajax({ - type: 'DELETE', - url: ApiClient.getUrl('Dlna/Profiles/' + id) - }).then(function () { - loading.hide(); - loadProfiles(page); - }); - }); -} - -function getTabs() { - return [{ - href: '#/dashboard/dlna', - name: globalize.translate('Settings') - }, { - href: '#/dashboard/dlna/profiles', - name: globalize.translate('TabProfiles') - }]; -} - -$(document).on('pageshow', '#dlnaProfilesPage', function () { - libraryMenu.setTabs('dlna', 1, getTabs); - loadProfiles(this); -}); - diff --git a/src/controllers/dashboard/dlna/settings.html b/src/controllers/dashboard/dlna/settings.html deleted file mode 100644 index 4bf5ffc81c..0000000000 --- a/src/controllers/dashboard/dlna/settings.html +++ /dev/null @@ -1,69 +0,0 @@ -
- -
-
- -
- -
-
-

${Settings}

- ${Help} -
-
- -
- -
${LabelEnableDlnaPlayToHelp}
-
- -
- -
${LabelEnableDlnaDebugLoggingHelp}
-
- -
- -
${LabelEnableDlnaClientDiscoveryIntervalHelp}
-
- -
- -
${LabelEnableDlnaServerHelp}
-
- -
- -
${LabelEnableBlastAliveMessagesHelp}
-
- -
- -
${LabelBlastMessageIntervalHelp}
-
-
- -
${LabelDefaultUserHelp}
-
-
- -
-
- -
-
-
diff --git a/src/controllers/dashboard/dlna/settings.js b/src/controllers/dashboard/dlna/settings.js deleted file mode 100644 index d12b6744af..0000000000 --- a/src/controllers/dashboard/dlna/settings.js +++ /dev/null @@ -1,60 +0,0 @@ -import escapeHtml from 'escape-html'; -import 'jquery'; -import loading from '../../../components/loading/loading'; -import libraryMenu from '../../../scripts/libraryMenu'; -import globalize from '../../../scripts/globalize'; -import Dashboard from '../../../utils/dashboard'; - -function loadPage(page, config, users) { - page.querySelector('#chkEnablePlayTo').checked = config.EnablePlayTo; - page.querySelector('#chkEnableDlnaDebugLogging').checked = config.EnableDebugLog; - $('#txtClientDiscoveryInterval', page).val(config.ClientDiscoveryIntervalSeconds); - $('#chkEnableServer', page).prop('checked', config.EnableServer); - $('#chkBlastAliveMessages', page).prop('checked', config.BlastAliveMessages); - $('#txtBlastInterval', page).val(config.BlastAliveMessageIntervalSeconds); - const usersHtml = users.map(function (u) { - return ''; - }).join(''); - $('#selectUser', page).html(usersHtml).val(config.DefaultUserId || ''); - loading.hide(); -} - -function onSubmit() { - loading.show(); - const form = this; - ApiClient.getNamedConfiguration('dlna').then(function (config) { - config.EnablePlayTo = form.querySelector('#chkEnablePlayTo').checked; - config.EnableDebugLog = form.querySelector('#chkEnableDlnaDebugLogging').checked; - config.ClientDiscoveryIntervalSeconds = $('#txtClientDiscoveryInterval', form).val(); - config.EnableServer = $('#chkEnableServer', form).is(':checked'); - config.BlastAliveMessages = $('#chkBlastAliveMessages', form).is(':checked'); - config.BlastAliveMessageIntervalSeconds = $('#txtBlastInterval', form).val(); - config.DefaultUserId = $('#selectUser', form).val(); - ApiClient.updateNamedConfiguration('dlna', config).then(Dashboard.processServerConfigurationUpdateResult); - }); - return false; -} - -function getTabs() { - return [{ - href: '#/dashboard/dlna', - name: globalize.translate('Settings') - }, { - href: '#/dashboard/dlna/profiles', - name: globalize.translate('TabProfiles') - }]; -} - -$(document).on('pageinit', '#dlnaSettingsPage', function () { - $('.dlnaSettingsForm').off('submit', onSubmit).on('submit', onSubmit); -}).on('pageshow', '#dlnaSettingsPage', function () { - libraryMenu.setTabs('dlna', 0, getTabs); - loading.show(); - const page = this; - const promise1 = ApiClient.getNamedConfiguration('dlna'); - const promise2 = ApiClient.getUsers(); - Promise.all([promise1, promise2]).then(function (responses) { - loadPage(page, responses[0], responses[1]); - }); -}); - diff --git a/src/strings/en-us.json b/src/strings/en-us.json index c7a6fe5edf..bde44f6886 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -165,7 +165,6 @@ "CopyStreamURLSuccess": "URL copied successfully.", "CriticRating": "Critics rating", "Cursive": "Cursive", - "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.", "DailyAt": "Daily at {0}", "Data": "Data", "DateAdded": "Date added", @@ -208,6 +207,7 @@ "DisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons", "DisplayMissingEpisodesWithinSeasonsHelp": "This must also be enabled for TV libraries in the server configuration.", "DisplayModeHelp": "Select the layout style you want for the interface.", + "DlnaMovedMessage": "The DLNA functionality has moved to a plugin.", "DoNotRecord": "Do not record", "Down": "Down", "Download": "Download", @@ -338,21 +338,15 @@ "HeaderCastAndCrew": "Cast & Crew", "HeaderChannelAccess": "Channel Access", "HeaderChapterImages": "Chapter Images", - "HeaderCodecProfile": "Codec Profile", - "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct playback.", "HeaderConfigureRemoteAccess": "Set up Remote Access", "HeaderConfirmPluginInstallation": "Confirm Plugin Installation", "HeaderConfirmRepositoryInstallation": "Confirm Plugin Repository Installation", - "HeaderConfirmProfileDeletion": "Confirm Profile Deletion", "HeaderConfirmRevokeApiKey": "Revoke API Key", "HeaderConnectionFailure": "Connection Failure", "HeaderConnectToServer": "Connect to Server", - "HeaderContainerProfile": "Container Profile", - "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct playback.", "HeaderContinueListening": "Continue Listening", "HeaderContinueWatching": "Continue Watching", "HeaderContinueReading": "Continue Reading", - "HeaderCustomDlnaProfiles": "Custom Profiles", "HeaderDateIssued": "Date Issued", "HeaderDefaultRecordingSettings": "Default Recording Settings", "HeaderDeleteDevice": "Delete Device", @@ -365,8 +359,6 @@ "HeaderDeveloperInfo": "Developer Info", "HeaderDeviceAccess": "Device Access", "HeaderDevices": "Devices", - "HeaderDirectPlayProfile": "Direct Playback Profile", - "HeaderDirectPlayProfileHelp": "Add direct playback profiles to indicate which formats the device can handle natively.", "HeaderDownloadSync": "Download & Sync", "HeaderDummyChapter": "Chapter Images", "HeaderDVR": "DVR", @@ -383,14 +375,9 @@ "HeaderFrequentlyPlayed": "Frequently Played", "HeaderGuestCast": "Guest Stars", "HeaderGuideProviders": "TV Guide Data Providers", - "HeaderHttpHeaders": "HTTP Headers", "HeaderHttpsSettings": "HTTPS Settings", - "HeaderIdentification": "Identification", - "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.", - "HeaderIdentificationHeader": "Identification Header", "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.", "HeaderImageOptions": "Image Options", - "HeaderImageSettings": "Image Settings", "HeaderInstall": "Install", "HeaderInstantMix": "Instant Mix", "HeaderKeepRecording": "Keep Recording", @@ -439,8 +426,6 @@ "HeaderPluginInstallation": "Plugin Installation", "HeaderPortRanges": "Firewall and Proxy Settings", "HeaderPreferredMetadataLanguage": "Preferred Metadata Language", - "HeaderProfileInformation": "Profile Information", - "HeaderProfileServerSettingsHelp": "These values control how the server will present itself to clients.", "HeaderRecentlyPlayed": "Recently Played", "HeaderRecordingMetadataSaving": "Recording Metadata", "HeaderRecordingOptions": "Recording Options", @@ -449,8 +434,6 @@ "HeaderRemoteControl": "Remote Control", "HeaderRemoveMediaFolder": "Remove Media Folder", "HeaderRemoveMediaLocation": "Remove Media Location", - "HeaderResponseProfile": "Response Profile", - "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.", "HeaderRevisionHistory": "Revision History", "HeaderRunningTasks": "Running Tasks", "HeaderScenes": "Scenes", @@ -468,7 +451,6 @@ "HeaderSeriesOptions": "Series Options", "HeaderSeriesStatus": "Series Status", "HeaderServerAddressSettings": "Server Address Settings", - "HeaderServerSettings": "Server Settings", "HeaderSetupLibrary": "Setup your media libraries", "HeaderSortBy": "Sort By", "HeaderSortOrder": "Sort Order", @@ -478,20 +460,14 @@ "HeaderStopRecording": "Stop Recording", "HeaderSubtitleAppearance": "Subtitle Appearance", "HeaderSubtitleDownloads": "Subtitle Downloads", - "HeaderSubtitleProfile": "Subtitle Profile", - "HeaderSubtitleProfiles": "Subtitle Profiles", - "HeaderSubtitleProfilesHelp": "Subtitle profiles describe the subtitle formats supported by the device.", "HeaderSyncPlayEnabled": "SyncPlay enabled", "HeaderSyncPlaySelectGroup": "Join a group", "HeaderSyncPlaySettings": "SyncPlay Settings", "HeaderSyncPlayPlaybackSettings": "Playback", "HeaderSyncPlayTimeSyncSettings": "Time sync", - "HeaderSystemDlnaProfiles": "System Profiles", "HeaderTaskTriggers": "Task Triggers", "HeaderThisUserIsCurrentlyDisabled": "This user is currently disabled", "HeaderTracks": "Tracks", - "HeaderTranscodingProfile": "Transcoding Profile", - "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.", "HeaderTunerDevices": "Tuner Devices", "HeaderTuners": "Tuners", "HeaderTypeImageFetchers": "Image fetchers ({0})", @@ -506,9 +482,6 @@ "HeaderVideos": "Videos", "HeaderVideoType": "Video Type", "HeaderVideoTypes": "Video Types", - "HeaderXmlDocumentAttribute": "XML Document Attribute", - "HeaderXmlDocumentAttributes": "XML Document Attributes", - "HeaderXmlSettings": "XML Settings", "HeaderYears": "Years", "Help": "Help", "Hide": "Hide", @@ -541,12 +514,7 @@ "LabelAirsBeforeSeason": "Airs before season", "LabelAirTime": "Air time", "LabelAlbum": "Album", - "LabelAlbumArtHelp": "PN used for album art, within the 'dlna:profileID' attribute on 'upnp:albumArtURI'. Some devices require a specific value, regardless of the size of the image.", "LabelAlbumArtists": "Album artists", - "LabelAlbumArtMaxHeight": "Album art max height", - "LabelAlbumArtMaxResHelp": "Maximum resolution of album art exposed via the 'upnp:albumArtURI' property.", - "LabelAlbumArtMaxWidth": "Album art max width", - "LabelAlbumArtPN": "Album art PN", "LabelAlbumGain": "Album Gain", "LabelAllowedRemoteAddresses": "Remote IP address filter", "LabelAllowedRemoteAddressesMode": "Remote IP address filter mode", @@ -618,12 +586,8 @@ "LabelDay": "Day of week", "LabelDeathDate": "Death date", "LabelDefaultScreen": "Default screen", - "LabelDefaultUser": "Default user", - "LabelDefaultUserHelp": "Determine which user library should be displayed on connected devices. This can be overridden for each device using profiles.", "LabelDeinterlaceMethod": "Deinterlacing method", "LabelDeveloper": "Developer", - "LabelDeviceDescription": "Device description", - "LabelDidlMode": "DIDL mode", "LabelDisableCustomCss": "Disable custom CSS code for theming/branding provided from the server.", "LabelDiscNumber": "Disc number", "LabelDisplayLanguage": "Display language", @@ -645,22 +609,10 @@ "LabelChapterImageResolution": "Resolution", "LabelChapterImageResolutionHelp": "The resolution of the extracted chapter images. Changing this will have no effect on existing dummy chapters.", "LabelDynamicExternalId": "{0} Id", - "LabelEmbedAlbumArtDidl": "Embed album art in DIDL", - "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for getting the album art. Others may fail to play with this option enabled.", "LabelEnableAudioVbr": "Enable VBR audio encoding", "LabelEnableAudioVbrHelp": "Variable bitrate offers better quality to average bitrate ratio, but in some rare cases may cause buffering and compatibility issues.", "LabelEnableAutomaticPortMap": "Enable automatic port mapping", "LabelEnableAutomaticPortMapHelp": "Automatically forward public ports on your router to local ports on your server via UPnP. This may not work with some router models or network configurations. Changes will not apply until after a server restart.", - "LabelEnableBlastAliveMessages": "Blast alive messages", - "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.", - "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval", - "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determine the duration in seconds between two SSDP searches.", - "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging", - "LabelEnableDlnaDebugLoggingHelp": "Create large log files and should only be used as needed for troubleshooting purposes.", - "LabelEnableDlnaPlayTo": "Enable 'Play To' DLNA feature", - "LabelEnableDlnaPlayToHelp": "Detect devices within your network and offer the ability to control them remotely.", - "LabelEnableDlnaServer": "Enable DLNA server", - "LabelEnableDlnaServerHelp": "Allow UPnP devices on your network to browse and play content.", "LabelEnableHardwareDecodingFor": "Enable hardware decoding for", "LabelEnableHttps": "Enable HTTPS", "LabelEnableHttpsHelp": "Listen on the configured HTTPS port. A valid certificate must also be supplied for this to take effect.", @@ -672,8 +624,6 @@ "LabelEnableLUFSScanHelp": "Clients can normalize audio playback to get equal loudness across tracks. This will make library scans longer and take more resources.", "LabelEnableRealtimeMonitor": "Enable real time monitoring", "LabelEnableRealtimeMonitorHelp": "Changes to files will be processed immediately on supported file systems.", - "LabelEnableSingleImageInDidlLimit": "Limit to single embedded image", - "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within DIDL.", "LabelEncoderPreset": "Encoding preset", "LabelEndDate": "End date", "LabelEpisodeNumber": "Episode number", @@ -702,10 +652,6 @@ "LabelHomeScreenSectionValue": "Home screen section {0}", "LabelHttpsPort": "Local HTTPS port number", "LabelHttpsPortHelp": "The TCP port number for the HTTPS server.", - "LabelIconMaxHeight": "Icon maximum height", - "LabelIconMaxResHelp": "Maximum resolution of icons exposed via the 'upnp:icon' property.", - "LabelIconMaxWidth": "Icon maximum width", - "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.", "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.", "LabelImageType": "Image type", "LabelImportOnlyFavoriteChannels": "Restrict to channels marked as favorite", @@ -741,9 +687,6 @@ "LabelLoginDisclaimer": "Login disclaimer", "LabelLoginDisclaimerHelp": "A message that will be displayed at the bottom of the login page.", "LabelLogs": "Logs", - "LabelManufacturer": "Manufacturer", - "LabelManufacturerUrl": "Manufacturer URL", - "LabelMatchType": "Match type", "LabelMaxAudiobookResume": "Audiobook remaining minutes to resume", "LabelMaxAudiobookResumeHelp": "Titles are assumed fully played if stopped when the remaining duration is less than this value.", "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item", @@ -753,8 +696,6 @@ "LabelMaxParentalRating": "Maximum allowed parental rating", "LabelMaxResumePercentage": "Maximum resume percentage", "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time.", - "LabelMaxStreamingBitrate": "Maximum streaming quality", - "LabelMaxStreamingBitrateHelp": "Specify a maximum bitrate when streaming.", "LabelMessageText": "Message text", "LabelMessageTitle": "Message title", "LabelMetadata": "Metadata", @@ -766,7 +707,6 @@ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.", "LabelMetadataSavers": "Metadata savers", "LabelMetadataSaversHelp": "Pick the file formats to use when saving your metadata.", - "LabelMethod": "Method", "LabelMinAudiobookResume": "Minimum Audiobook resume in minutes", "LabelMinAudiobookResumeHelp": "Titles are assumed unplayed if stopped before this time.", "LabelMinBackdropDownloadWidth": "Minimum backdrop download width", @@ -774,16 +714,10 @@ "LabelMinResumeDurationHelp": "The shortest video length in seconds that will save playback location and let you resume.", "LabelMinResumePercentage": "Minimum resume percentage", "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time.", - "LabelModelDescription": "Model description", - "LabelModelName": "Model name", - "LabelModelNumber": "Model number", - "LabelModelUrl": "Model URL", "LabelMovieCategories": "Movie categories", "LabelMoviePrefix": "Movie prefix", "LabelMoviePrefixHelp": "If a prefix is applied to movie titles, enter it here so the server can handle it properly.", "LabelMovieRecordingPath": "Movie recording path", - "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate", - "LabelMusicStreamingTranscodingBitrateHelp": "Specify a maximum bitrate when streaming music.", "LabelName": "Name", "LabelNewName": "New name", "LabelNewPassword": "New password", @@ -823,15 +757,8 @@ "LabelPostProcessorArgumentsHelp": "Use {path} as the path to the recording file.", "LabelPreferredDisplayLanguage": "Preferred display language", "LabelPreferredSubtitleLanguage": "Preferred subtitle language", - "LabelProfileAudioCodecs": "Audio codecs", - "LabelProfileCodecs": "Codecs", - "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.", "LabelProfileContainer": "Container", - "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.", - "LabelProfileVideoCodecs": "Video codecs", "LabelProtocol": "Protocol", - "LabelProtocolInfo": "Protocol info", - "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.", "LabelPublicHttpPort": "Public HTTP port number", "LabelPublicHttpPortHelp": "The public port number that should be mapped to the local HTTP port.", "LabelPublicHttpsPort": "Public HTTPS port number", @@ -862,7 +789,6 @@ "LabelSelectFolderGroups": "Automatically group content from the following folders into views such as 'Movies', 'Music' and 'TV'", "LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.", "LabelSelectVersionToInstall": "Select version to install", - "LabelSerialNumber": "Serial number", "LabelSeriesRecordingPath": "Series recording path", "LabelServerHost": "Host", "LabelServerHostHelp": "192.168.1.100:8096 or https://myserver.com", @@ -879,8 +805,6 @@ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery and decrease the likelihood of video transcoding.", "LabelSlowResponseEnabled": "Log a warning message if the server was slow to answer", "LabelSlowResponseTime": "Time in ms after which a response is considered slow", - "LabelSonyAggregationFlags": "Sony aggregation flags", - "LabelSonyAggregationFlagsHelp": "Determine the content of the 'aggregationFlags' element in the 'urn:schemas-sonycom:av' namespace.", "LabelSortBy": "Sort by", "LabelSortName": "Sort name", "LabelSortOrder": "Sort order", @@ -895,10 +819,8 @@ "LabelStopWhenPossible": "Stop when possible", "LabelStreamType": "Stream type", "LabelSubtitleDownloaders": "Subtitle downloaders", - "LabelSubtitleFormatHelp": "Example: srt", "LabelSubtitlePlaybackMode": "Subtitle mode", "LabelSubtitleVerticalPosition": "Vertical position", - "LabelSupportedMediaTypes": "Supported Media Types", "LabelSyncPlayAccess": "SyncPlay access", "LabelSyncPlayAccessCreateAndJoinGroups": "Allow user to create and join groups", "LabelSyncPlayAccessJoinGroups": "Allow user to join groups", @@ -973,8 +895,6 @@ "LabelUnstable": "Unstable", "LabelUser": "User", "LabelUserAgent": "User agent", - "LabelUserLibrary": "User library", - "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.", "LabelUserLoginAttemptsBeforeLockout": "Failed login tries before user is locked out", "LabelUserMaxActiveSessions": "Maximum number of simultaneous user sessions", "LabelUsername": "Username", @@ -990,10 +910,6 @@ "LabelVideoResolution": "Video resolution", "LabelWeb": "Web", "LabelWebVersion": "Web version", - "LabelXDlnaCap": "Device Capability ID", - "LabelXDlnaCapHelp": "Determine the content of the 'X_DLNACAP' element in the 'urn:schemas-dlna-org:device-1-0' namespace.", - "LabelXDlnaDoc": "Device Class ID", - "LabelXDlnaDocHelp": "Determine the content of the 'X_DLNADOC' element in the 'urn:schemas-dlna-org:device-1-0' namespace.", "LabelYear": "Year", "LabelYoureDone": "You're Done!", "LabelZipCode": "Zip Code", @@ -1070,7 +986,6 @@ "MessageConfirmAppExit": "Do you want to exit?", "MessageConfirmDeleteGuideProvider": "Are you sure you wish to delete this guide provider?", "MessageConfirmDeleteTunerDevice": "Are you sure you wish to delete this device?", - "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?", "MessageConfirmRecordingCancellation": "Cancel recording?", "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?", "MessageConfirmRestart": "Are you sure you wish to restart Jellyfin?", @@ -1215,7 +1130,6 @@ "OptionAutomaticallyGroupSeries": "Automatically merge series that are spread across multiple folders", "OptionAutomaticallyGroupSeriesHelp": "Series that are spread across multiple folders within this library will be automatically merged into a single series.", "OptionBluray": "BD", - "OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)", "OptionCommunityRating": "Community Rating", "OptionCriticRating": "Critics Rating", "OptionDaily": "Daily", @@ -1230,28 +1144,19 @@ "OptionDisplayFolderView": "Display a folder view to show plain media folders", "OptionDisplayFolderViewHelp": "Display folders alongside your other media libraries. This can be useful if you'd like to have a plain folder view.", "OptionDvd": "DVD", - "OptionEmbedSubtitles": "Embed within container", "OptionEnableAccessFromAllDevices": "Enable access from all devices", "OptionEnableAccessToAllChannels": "Enable access to all channels", "OptionEnableAccessToAllLibraries": "Enable access to all libraries", "OptionEnableExternalContentInSuggestions": "Enable external content in suggestions", "OptionEnableExternalContentInSuggestionsHelp": "Allow internet trailers and live TV programs to be included within suggested content.", "OptionEnableForAllTuners": "Enable for all tuner devices", - "OptionEnableM2tsMode": "Enable M2TS mode", - "OptionEnableM2tsModeHelp": "Enable M2TS mode when encoding to MPEG-TS.", - "OptionEquals": "Equals", - "OptionEstimateContentLength": "Estimate content length when transcoding", "OptionEveryday": "Every day", - "OptionExternallyDownloaded": "External download", "OptionExtractChapterImage": "Enable chapter image extraction", "OptionForceRemoteSourceTranscoding": "Force transcoding of remote media sources such as Live TV", "OptionHasThemeSong": "Theme Song", "OptionHasThemeVideo": "Theme Video", "OptionHideUser": "Hide this user from login screens", "OptionHideUserFromLoginHelp": "Useful for private or hidden administrator accounts. The user will need to sign in manually by entering their username and password.", - "OptionHlsSegmentedSubtitles": "HLS segmented subtitles", - "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests", - "OptionIgnoreTranscodeByteRangeRequestsHelp": "These requests will be honored but will ignore the byte range header.", "OptionImdbRating": "IMDb Rating", "OptionIsHD": "HD", "OptionIsSD": "SD", @@ -1264,27 +1169,16 @@ "OptionNew": "New…", "OptionOnInterval": "On an interval", "OptionParentalRating": "Parental Rating", - "OptionPlainStorageFolders": "Display all folders as plain storage folders", - "OptionPlainStorageFoldersHelp": "All folders are represented in DIDL as 'object.container.storageFolder' instead of a more specific type, such as 'object.container.person.musicArtist'.", - "OptionPlainVideoItems": "Display all videos as plain video items", - "OptionPlainVideoItemsHelp": "All videos are represented in DIDL as 'object.item.videoItem' instead of a more specific type, such as 'object.item.videoItem.movie'.", "OptionPlayCount": "Play Count", "OptionPremiereDate": "Premiere Date", - "OptionProtocolHls": "HTTP Live Streaming (HLS)", - "OptionProtocolHttp": "HTTP", "OptionRandom": "Random", - "OptionRegex": "Regex", "OptionReleaseDate": "Release Date", - "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding", - "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.", "OptionRequirePerfectSubtitleMatch": "Only download subtitles that are a perfect match for video files", "OptionRequirePerfectSubtitleMatchHelp": "Requiring a perfect match will filter subtitles to include only those that have been tested and verified with your exact video file. Unchecking this will increase the likelihood of subtitles being downloaded, but will increase the chances of mistimed or incorrect subtitle text.", - "OptionResElement": "'res' element", "OptionResumable": "Resumable", "OptionSaveMetadataAsHidden": "Save metadata and images as hidden files", "OptionSaveMetadataAsHiddenHelp": "Changing this will apply to new metadata saved going forward. Existing metadata files will be updated the next time they are saved by the server.", "OptionSpecialEpisode": "Specials", - "OptionSubstring": "Substring", "OptionTrackName": "Track Name", "OptionTvdbRating": "TheTVDB Rating", "OptionUnairedEpisode": "Unaired Episodes", @@ -1501,14 +1395,10 @@ "Sunday": "Sunday", "SyncPlayAccessHelp": "The SyncPlay feature enables to sync playback with other devices. Select the level of access this user has to the SyncPlay.", "SyncPlayGroupDefaultTitle": "{0}'s group", - "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.", "TabAccess": "Access", "TabAdvanced": "Advanced", "TabCatalog": "Catalog", - "TabCodecs": "Codecs", - "TabContainers": "Containers", "TabDashboard": "Dashboard", - "TabDirectPlay": "Direct Playback", "TabLatest": "Recently Added", "TabLogs": "Logs", "TabMusic": "Music", @@ -1519,9 +1409,7 @@ "TabOther": "Other", "TabParentalControl": "Parental Control", "TabPlugins": "Plugins", - "TabProfiles": "Profiles", "TabRepositories": "Repositories", - "TabResponses": "Responses", "TabScheduledTasks": "Scheduled Tasks", "TabServer": "Server", "TabStreaming": "Streaming", @@ -1578,10 +1466,6 @@ "UserMenu": "User Menu", "UserProfilesIntro": "Jellyfin includes support for user profiles with granular display settings, play state, and parental controls.", "ValueAlbumCount": "{0} albums", - "ValueAudioCodec": "Audio Codec: {0}", - "ValueCodec": "Codec: {0}", - "ValueConditions": "Conditions: {0}", - "ValueContainer": "Container: {0}", "ValueDiscNumber": "Disc {0}", "ValueEpisodeCount": "{0} episodes", "ValueMinutes": "{0} min", @@ -1599,7 +1483,6 @@ "ValueSpecialEpisodeName": "Special - {0}", "ValueTimeLimitMultiHour": "Time limit: {0} hours", "ValueTimeLimitSingleHour": "Time limit: 1 hour", - "ValueVideoCodec": "Video Codec: {0}", "Vertical": "Vertical", "Video": "Video", "VideoAudio": "Video Audio", @@ -1615,7 +1498,6 @@ "WriteAccessRequired": "Jellyfin requires write access to this folder. Please ensure write access and try again.", "Writer": "Writer", "Writers": "Writers", - "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every XML response.", "XmlTvKidsCategoriesHelp": "Programs with these categories will be displayed as programs for children. Separate multiple with '|'.", "XmlTvMovieCategoriesHelp": "Programs with these categories will be displayed as movies. Separate multiple with '|'.", "XmlTvNewsCategoriesHelp": "Programs with these categories will be displayed as news programs. Separate multiple with '|'.", From ec1f016d5b2a1e92b09047b742888a9a7eadaa84 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Mon, 4 Mar 2024 13:49:29 -0500 Subject: [PATCH 104/118] Update notifications page ui --- src/apps/dashboard/routes/notifications.tsx | 38 ++++++++++----------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/apps/dashboard/routes/notifications.tsx b/src/apps/dashboard/routes/notifications.tsx index 6f673c753f..7642ee033b 100644 --- a/src/apps/dashboard/routes/notifications.tsx +++ b/src/apps/dashboard/routes/notifications.tsx @@ -1,23 +1,13 @@ +import Alert from '@mui/material/Alert/Alert'; +import Box from '@mui/material/Box/Box'; +import Button from '@mui/material/Button/Button'; import React from 'react'; +import { Link } from 'react-router-dom'; import Page from 'components/Page'; import globalize from 'scripts/globalize'; -const PluginLink = () => ( -
+
+ +
${ChannelHeightHelp}
+
diff --git a/src/strings/en-us.json b/src/strings/en-us.json index bde44f6886..c2af890818 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -134,6 +134,7 @@ "Categories": "Categories", "ChangingMetadataImageSettingsNewContent": "Changes to metadata or artwork downloading settings will only apply to new content added to your library. To apply the changes to existing titles, you'll need to refresh their metadata manually.", "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", + "ChannelHeightHelp": "Set height of video received on this channel. 720 or greater will mark this channel as HD.", "ChannelNameOnly": "Channel {0} only", "ChannelNumber": "Channel number", "Channels": "Channels", @@ -648,6 +649,7 @@ "LabelHardwareAccelerationType": "Hardware acceleration", "LabelHardwareAccelerationTypeHelp": "Hardware acceleration requires additional configuration.", "LabelHardwareEncoding": "Hardware encoding", + "LabelHeight": "Height", "LabelHomeNetworkQuality": "Home network quality", "LabelHomeScreenSectionValue": "Home screen section {0}", "LabelHttpsPort": "Local HTTPS port number", From 420ff05d916cb07fed41adcaf799cb7baa396e54 Mon Sep 17 00:00:00 2001 From: SenorSmartyPants Date: Thu, 30 Mar 2023 13:43:49 -0500 Subject: [PATCH 107/118] Add dropdown with common broadcast video heights --- src/components/metadataEditor/metadataEditor.js | 4 ++-- .../metadataEditor/metadataEditor.template.html | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/metadataEditor/metadataEditor.js b/src/components/metadataEditor/metadataEditor.js index 8dbb103355..c3c50688fc 100644 --- a/src/components/metadataEditor/metadataEditor.js +++ b/src/components/metadataEditor/metadataEditor.js @@ -153,7 +153,7 @@ function onSubmit(e) { DateCreated: getDateValue(form, '#txtDateAdded', 'DateCreated'), EndDate: getDateValue(form, '#txtEndDate', 'EndDate'), ProductionYear: form.querySelector('#txtProductionYear').value, - Height: form.querySelector('#txtHeight').value, + Height: form.querySelector('#selectHeight').value, AspectRatio: form.querySelector('#txtOriginalAspectRatio').value, Video3DFormat: form.querySelector('#select3dFormat').value, @@ -835,7 +835,7 @@ function fillItemInfo(context, item, parentalRatingOptions) { const placeofBirth = item.ProductionLocations?.length ? item.ProductionLocations[0] : ''; context.querySelector('#txtPlaceOfBirth').value = placeofBirth; - context.querySelector('#txtHeight').value = item.Height || ''; + context.querySelector('#selectHeight').value = item.Height || ''; context.querySelector('#txtOriginalAspectRatio').value = item.AspectRatio || ''; diff --git a/src/components/metadataEditor/metadataEditor.template.html b/src/components/metadataEditor/metadataEditor.template.html index f56acb73f1..7f7acd7e3d 100644 --- a/src/components/metadataEditor/metadataEditor.template.html +++ b/src/components/metadataEditor/metadataEditor.template.html @@ -142,8 +142,15 @@
-
- +
+
${ChannelHeightHelp}
From 8443b5d6db5e3836bfc2b7a231962428cd072b44 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Tue, 5 Mar 2024 02:31:53 -0500 Subject: [PATCH 108/118] Update channel resolution setting text --- .../metadataEditor/metadataEditor.template.html | 13 ++++++------- src/strings/en-us.json | 7 +++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/metadataEditor/metadataEditor.template.html b/src/components/metadataEditor/metadataEditor.template.html index 7f7acd7e3d..6c01c2fc07 100644 --- a/src/components/metadataEditor/metadataEditor.template.html +++ b/src/components/metadataEditor/metadataEditor.template.html @@ -143,15 +143,14 @@
- - - - - - + + + + + -
${ChannelHeightHelp}
diff --git a/src/strings/en-us.json b/src/strings/en-us.json index c2af890818..7bc81572d4 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -134,7 +134,11 @@ "Categories": "Categories", "ChangingMetadataImageSettingsNewContent": "Changes to metadata or artwork downloading settings will only apply to new content added to your library. To apply the changes to existing titles, you'll need to refresh their metadata manually.", "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.", - "ChannelHeightHelp": "Set height of video received on this channel. 720 or greater will mark this channel as HD.", + "ChannelResolutionSD": "SD", + "ChannelResolutionSDPAL": "SD (PAL)", + "ChannelResolutionHD": "HD", + "ChannelResolutionFullHD": "Full HD", + "ChannelResolutionUHD4K": "UHD (4K)", "ChannelNameOnly": "Channel {0} only", "ChannelNumber": "Channel number", "Channels": "Channels", @@ -649,7 +653,6 @@ "LabelHardwareAccelerationType": "Hardware acceleration", "LabelHardwareAccelerationTypeHelp": "Hardware acceleration requires additional configuration.", "LabelHardwareEncoding": "Hardware encoding", - "LabelHeight": "Height", "LabelHomeNetworkQuality": "Home network quality", "LabelHomeScreenSectionValue": "Home screen section {0}", "LabelHttpsPort": "Local HTTPS port number", From 2e85cb9e33917a3251c40bbd5496b382dc071f9c Mon Sep 17 00:00:00 2001 From: Kityn Date: Tue, 5 Mar 2024 07:29:23 +0000 Subject: [PATCH 109/118] Translated using Weblate (Polish) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/pl/ --- src/strings/pl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/pl.json b/src/strings/pl.json index b0436984d0..4c80c3f4a9 100644 --- a/src/strings/pl.json +++ b/src/strings/pl.json @@ -1786,5 +1786,6 @@ "LabelBuildVersion": "Wersja kompilacji", "LabelServerVersion": "Wersja serwera", "LabelWebVersion": "Wersja sieciowa", - "ButtonEditUser": "Edytuj użytkownika" + "ButtonEditUser": "Edytuj użytkownika", + "DlnaMovedMessage": "Funkcjonalność DLNA została przeniesiona do wtyczki." } From 1d38aa120888cc9199646ceecea880adcae017d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Mar=C3=B3y?= Date: Mon, 19 Feb 2024 10:22:02 +0000 Subject: [PATCH 110/118] Lower web0s version needed for audiotracks support --- src/scripts/browserDeviceProfile.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index 51097a475b..b69ff1dd3d 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -394,8 +394,7 @@ export function canPlaySecondaryAudio(videoTestElement) { && !browser.firefox // It seems to work on Tizen 5.5+ (2020, Chrome 69+). See https://developer.tizen.org/forums/web-application-development/video-tag-not-work-audiotracks && (browser.tizenVersion >= 5.5 || !browser.tizen) - // Assume webOS 5+ (2020, Chrome 68+) supports secondary audio like Tizen 5.5+ - && (browser.web0sVersion >= 5.0 || !browser.web0sVersion); + && (browser.web0sVersion >= 4.0 || !browser.web0sVersion); } export default function (options) { From b62c045868583dd7f9dae5c4d9acc237b76b3c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Mar=C3=B3y?= Date: Mon, 19 Feb 2024 10:22:34 +0000 Subject: [PATCH 111/118] Update CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index daec591172..f30c32b359 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -79,6 +79,7 @@ - [Kevin Tan (Valius)](https://github.com/valius) - [Rasmus Krämer](https://github.com/rasmuslos) - [ntarelix](https://github.com/ntarelix) +- [András Maróy](https://github.com/andrasmaroy) ## Emby Contributors From ed758c6320a31ca955e833cdd6cb4a66c682315a Mon Sep 17 00:00:00 2001 From: foXaCe Date: Tue, 5 Mar 2024 18:50:53 +0000 Subject: [PATCH 112/118] Translated using Weblate (French) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/fr/ --- src/strings/fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/strings/fr.json b/src/strings/fr.json index 8ec284a83c..71a68765ec 100644 --- a/src/strings/fr.json +++ b/src/strings/fr.json @@ -1785,5 +1785,7 @@ "HeaderAllRecordings": "Tous les enregistrements", "LabelBuildVersion": "Numéro de build", "LabelServerVersion": "Version du serveur", - "LabelWebVersion": "Version web" + "LabelWebVersion": "Version web", + "ButtonEditUser": "Modifier l'utilisateur", + "DlnaMovedMessage": "La fonctionnalité DLNA a été déplacée vers un plugin." } From 045c950ce6438c5e16d5d2a1d8b1ea3ef88fefef Mon Sep 17 00:00:00 2001 From: Adrian Sandu Date: Wed, 14 Feb 2024 14:22:13 +0200 Subject: [PATCH 113/118] Make the server field ignore the trailing slash. Useful on the tizen build, if a trailing slash is added the error message is not helping. --- src/controllers/session/addServer/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/session/addServer/index.js b/src/controllers/session/addServer/index.js index be339ca978..47ebfc6af6 100644 --- a/src/controllers/session/addServer/index.js +++ b/src/controllers/session/addServer/index.js @@ -36,7 +36,7 @@ function handleConnectionResult(page, result) { function submitServer(page) { loading.show(); - const host = page.querySelector('#txtServerHost').value; + const host = page.querySelector('#txtServerHost').value.replace(/\/+$/, ''); ServerConnections.connectToAddress(host, { enableAutoLogin: appSettings.enableAutoLogin() }).then(function(result) { From 53705680e22920e3f53515a1a5777861ffccf9ba Mon Sep 17 00:00:00 2001 From: Gurmeet Athwal Date: Wed, 6 Mar 2024 14:22:53 +0000 Subject: [PATCH 114/118] Translated using Weblate (Hindi) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/hi/ --- src/strings/hi-in.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/strings/hi-in.json b/src/strings/hi-in.json index 7901b4c5ee..247d7fcb0c 100644 --- a/src/strings/hi-in.json +++ b/src/strings/hi-in.json @@ -56,7 +56,7 @@ "UnsupportedPlayback": "Jellyfin DRM द्वारा संरक्षित सामग्री को डिक्रिप्ट नहीं कर सकता है, लेकिन सभी सामग्री की परवाह किए बिना, संरक्षित शीर्षकों सहित प्रयास किया जाएगा। एन्क्रिप्शन या अन्य असमर्थित सुविधाओं जैसे इंटरेक्टिव शीर्षक के कारण कुछ फाइलें पूरी तरह से काली दिखाई दे सकती हैं।", "BoxRear": "बॉक्स (पीछे)", "Box": "बॉक्स", - "Books": "पुस्तकों", + "Books": "पुस्तकें", "BookLibraryHelp": "ऑडियो और पाठ्य पुस्तकें समर्थित हैं। {0} पुस्तक नामकरण गाइड {1} की समीक्षा करें।", "Blacklist": "काला सूची में डालना", "BirthPlaceValue": "जन्म स्थान: {0}", @@ -72,7 +72,7 @@ "AskAdminToCreateLibrary": "लाइब्रेरी बनाने के लिए किसी व्यवस्थापक से पूछें।", "Ascending": "आरोही", "AsManyAsPossible": "जितने अधिक संभव हों", - "Artists": "कलाकारों", + "Artists": "कलाकार", "Artist": "कलाकार", "Art": "कला", "AroundTime": "लगभग {0}", @@ -102,7 +102,7 @@ "Folders": "फ़ोल्डरें", "Favorites": "पसंदीदा", "Default": "प्राथमिक", - "Collections": "संग्रहों", + "Collections": "संग्रह", "Channels": "चैनल", "Movies": "फ़िल्म", "ButtonActivate": "सक्रिय", From 9d03410edb12f9d4800aca2c1f5ad30b77176074 Mon Sep 17 00:00:00 2001 From: stanol Date: Wed, 6 Mar 2024 13:09:13 +0000 Subject: [PATCH 115/118] Translated using Weblate (Ukrainian) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/uk/ --- src/strings/uk.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/uk.json b/src/strings/uk.json index 241873c27a..98b18ecf63 100644 --- a/src/strings/uk.json +++ b/src/strings/uk.json @@ -1783,5 +1783,6 @@ "LabelBuildVersion": "Версія збірки", "LabelServerVersion": "Версія сервера", "LabelWebVersion": "Версія вебу", - "ButtonEditUser": "Редагувати користувача" + "ButtonEditUser": "Редагувати користувача", + "DlnaMovedMessage": "Функціональність DLNA перенесено у плагін." } From 276a51767255af506ff29c5bb9c7342bd805bd2c Mon Sep 17 00:00:00 2001 From: Gurmeet Athwal Date: Wed, 6 Mar 2024 14:50:06 +0000 Subject: [PATCH 116/118] Translated using Weblate (Hindi) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/hi/ --- src/strings/hi-in.json | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/strings/hi-in.json b/src/strings/hi-in.json index 247d7fcb0c..d4fff81e4e 100644 --- a/src/strings/hi-in.json +++ b/src/strings/hi-in.json @@ -80,10 +80,10 @@ "AnyLanguage": "कोई भी भाषा", "AlwaysPlaySubtitlesHelp": "भाषा की वरीयता से मेल खाने वाले उपशीर्षक ऑडियो भाषा की परवाह किए बिना लोड किए जाएंगे।", "AlwaysPlaySubtitles": "हमेशा खेलो", - "AllowedRemoteAddressesHelp": "कोमा ने नेटवर्क के लिए आईपी पते या आईपी / नेटमास्क प्रविष्टियों की सूची को अलग कर दिया है जिन्हें दूरस्थ रूप से कनेक्ट करने की अनुमति दी जाएगी। यदि खाली छोड़ दिया जाता है, तो सभी दूरस्थ पते की अनुमति दी जाएगी।", + "AllowedRemoteAddressesHelp": "नेटवर्क के लिए आईपी पतों आईपी/नेटमास्क एंट्रीज़ की कॉमा विभाजित सूची जो रिमोट रूप से कनेक्ट करने की अनुमति देगा। यदि खाली छोड़ा गया है, तो सभी रिमोट पतों को अनुमति दी जाएगी।", "AllowRemoteAccessHelp": "अनियंत्रित होने पर, सभी दूरस्थ कनेक्शन अवरुद्ध हो जाएंगे।", "AllowRemoteAccess": "इस सर्वर को असमीप संपर्क की अनुमति दें", - "AllowFfmpegThrottlingHelp": "जब एक ट्रांसकोड या रीमूक्स वर्तमान प्लेबैक स्थिति से काफी आगे हो जाता है, तो प्रक्रिया को रोकें ताकि यह कम संसाधनों का उपभोग करेगा। अक्सर मांग किए बिना देखने पर यह सबसे उपयोगी है। यदि आप प्लेबैक समस्याओं का अनुभव करते हैं तो इसे बंद कर दें।", + "AllowFfmpegThrottlingHelp": "जब कोई ट्रांसकोड या रीमक्स वर्तमान प्लेबैक स्थिति से काफी आगे निकल जाता है, तो प्रक्रिया को रोक दें ताकि यह कम संसाधनों का उपभोग करे। अक्सर बिना खोजे देखते समय यह सबसे उपयोगी होता है। यदि आप प्लेबैक समस्याओं का अनुभव करते हैं तो इसे बंद कर दें।", "AllowFfmpegThrottling": "थ्रोटल ट्रांसकोड", "AllowOnTheFlySubtitleExtractionHelp": "वीडियो ट्रांसकोडिंग को रोकने में मदद करने के लिए एंबेडेड सबटाइटल वीडियो से निकाले जा सकते हैं और सादे पाठ में ग्राहकों तक पहुंचाए जाते हैं। कुछ प्रणालियों पर यह एक लंबा समय ले सकता है और निष्कर्षण प्रक्रिया के दौरान वीडियो प्लेबैक को स्टाल करने का कारण बन सकता है। जब वे क्लाइंट डिवाइस द्वारा मूल रूप से समर्थित नहीं होते हैं, तो वीडियो ट्रांसकोडिंग के साथ जले हुए एम्बेडेड उपशीर्षक को अक्षम करें।", "AlbumArtist": "एल्बम कलाकार", @@ -96,10 +96,10 @@ "BurnSubtitlesHelp": "निर्धारित करता है कि वीडियो ट्रांसकोडिंग करते समय सर्वर को उपशीर्षक बर्न-इन करना चाहिए। इससे बचने से प्रदर्शन में बहुत सुधार होगा। छवि आधारित उपशीर्षक (VOBSUB, PGS, SUB, IDX, …) एवं ASS अथवा SSA जैसे उपशीर्षक बर्न-इन करने के लिए ऑटो का चयन करें।", "ButtonRemove": "हटाना", "ButtonOpen": "खोलो", - "HeaderContinueWatching": "देखते रहिए", + "HeaderContinueWatching": "देखना जारी रखें", "HeaderAlbumArtists": "एल्बम कलाकार", - "Genres": "शैली", - "Folders": "फ़ोल्डरें", + "Genres": "शैलियां", + "Folders": "फ़ोल्डर", "Favorites": "पसंदीदा", "Default": "प्राथमिक", "Collections": "संग्रह", @@ -151,9 +151,11 @@ "Shows": "शो", "ValueSpecialEpisodeName": "विशेष - {0}", "Sync": "समाकलयति", - "AllowCollectionManagement": "इस यूजर को कलेक्शन परिवर्तन करने की अनुमति दें", + "AllowCollectionManagement": "इस यूजर को संग्रह प्रबंधित करने की अनुमति दें", "AllowSegmentDeletion": "खंड हटाएँ", "AllowSegmentDeletionHelp": "क्लाइंट को भेजे जाने के बाद पुराने सेगमेंट हटा दें। यह संपूर्ण ट्रांसकोड की गई फ़ाइल को डिस्क पर स्टोर करने से रोकता है। केवल थ्रॉटलिंग सक्षम होने पर ही काम करेगा। यदि आप प्लेबैक समस्याओं का अनुभव करते हैं तो इसे बंद कर दें।", "LabelThrottleDelaySeconds": "थ्रॉटर बाद", - "LabelSegmentKeepSeconds": "सेगमेंट रखने का समय" + "LabelSegmentKeepSeconds": "सेगमेंट रखने का समय", + "LabelThrottleDelaySecondsHelp": "सेकंड में समय जिसके बाद ट्रांसकोडर को थ्रॉटल कर दिया जाएगा। क्लाइंट के लिए स्वस्थ बफ़र बनाए रखने के लिए पर्याप्त बड़ा होना चाहिए। केवल तभी काम करता है जब थ्रॉटलिंग सक्रिय हो।", + "LabelSegmentKeepSecondsHelp": "किन खंडों को अधिलेखित करने से पहले रखा जाना चाहिए, इसका समय सेकंड में। \"थ्रोटल आफ्टर\" से बड़ा होना चाहिए। केवल तभी काम करता है जब खंड हटाना सक्रिय हो।" } From e13baa00c043a1fda16a0e1568bb9314d06e6128 Mon Sep 17 00:00:00 2001 From: Bas Date: Wed, 6 Mar 2024 21:16:02 +0000 Subject: [PATCH 117/118] Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/nl/ --- src/strings/nl.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/strings/nl.json b/src/strings/nl.json index 5c5757bddb..b4b2a46fb0 100644 --- a/src/strings/nl.json +++ b/src/strings/nl.json @@ -1784,5 +1784,7 @@ "HeaderAllRecordings": "Alle opnamen", "LabelBuildVersion": "Buildversie", "LabelServerVersion": "Serverversie", - "LabelWebVersion": "Webversie" + "LabelWebVersion": "Webversie", + "ButtonEditUser": "Gebruiker bewerken", + "DlnaMovedMessage": "De DLNA-functionaliteit is verplaatst naar een plug-in." } From 06c3602bd0585fcbc98c859db254ae4831531989 Mon Sep 17 00:00:00 2001 From: Appoxo Date: Wed, 6 Mar 2024 22:44:21 +0000 Subject: [PATCH 118/118] Translated using Weblate (German) Translation: Jellyfin/Jellyfin Web Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-web/de/ --- src/strings/de.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/strings/de.json b/src/strings/de.json index 3d125d9048..40cecfc975 100644 --- a/src/strings/de.json +++ b/src/strings/de.json @@ -1786,5 +1786,6 @@ "LabelBuildVersion": "Build-Version", "LabelServerVersion": "Server-Version", "LabelWebVersion": "Web-Version", - "ButtonEditUser": "Editiere Benutzer" + "ButtonEditUser": "Editiere Benutzer", + "DlnaMovedMessage": "Die DLNA-Funktion wurde in ein Plugin verschoben." }