commit 58d9383c772b84550b6a335dc32500cca9f27e22 Author: sandro Date: Tue Mar 17 10:58:04 2026 +0100 Initialer Commit diff --git a/assets/img/banner-dark.png b/assets/img/banner-dark.png new file mode 100755 index 0000000..f678d25 Binary files /dev/null and b/assets/img/banner-dark.png differ diff --git a/assets/img/banner-light.png b/assets/img/banner-light.png new file mode 100755 index 0000000..f678d25 Binary files /dev/null and b/assets/img/banner-light.png differ diff --git a/assets/img/icon-transparent.png b/assets/img/icon-transparent.png new file mode 100755 index 0000000..a51276b Binary files /dev/null and b/assets/img/icon-transparent.png differ diff --git a/assets/splash/ipad_splash.png b/assets/splash/ipad_splash.png new file mode 100755 index 0000000..808fdaa Binary files /dev/null and b/assets/splash/ipad_splash.png differ diff --git a/assets/splash/ipad_splash_l.png b/assets/splash/ipad_splash_l.png new file mode 100755 index 0000000..9007bef Binary files /dev/null and b/assets/splash/ipad_splash_l.png differ diff --git a/assets/splash/ipadpro1_splash.png b/assets/splash/ipadpro1_splash.png new file mode 100755 index 0000000..53f7a86 Binary files /dev/null and b/assets/splash/ipadpro1_splash.png differ diff --git a/assets/splash/ipadpro1_splash_l.png b/assets/splash/ipadpro1_splash_l.png new file mode 100755 index 0000000..2c1e52f Binary files /dev/null and b/assets/splash/ipadpro1_splash_l.png differ diff --git a/assets/splash/ipadpro2_splash.png b/assets/splash/ipadpro2_splash.png new file mode 100755 index 0000000..763db47 Binary files /dev/null and b/assets/splash/ipadpro2_splash.png differ diff --git a/assets/splash/ipadpro2_splash_l.png b/assets/splash/ipadpro2_splash_l.png new file mode 100755 index 0000000..7fd8d89 Binary files /dev/null and b/assets/splash/ipadpro2_splash_l.png differ diff --git a/assets/splash/ipadpro3_splash.png b/assets/splash/ipadpro3_splash.png new file mode 100755 index 0000000..c5d0366 Binary files /dev/null and b/assets/splash/ipadpro3_splash.png differ diff --git a/assets/splash/ipadpro3_splash_l.png b/assets/splash/ipadpro3_splash_l.png new file mode 100755 index 0000000..3ece9d1 Binary files /dev/null and b/assets/splash/ipadpro3_splash_l.png differ diff --git a/assets/splash/iphone5_splash.png b/assets/splash/iphone5_splash.png new file mode 100755 index 0000000..a022d7a Binary files /dev/null and b/assets/splash/iphone5_splash.png differ diff --git a/assets/splash/iphone5_splash_l.png b/assets/splash/iphone5_splash_l.png new file mode 100755 index 0000000..44ff556 Binary files /dev/null and b/assets/splash/iphone5_splash_l.png differ diff --git a/assets/splash/iphone6_splash.png b/assets/splash/iphone6_splash.png new file mode 100755 index 0000000..633bc51 Binary files /dev/null and b/assets/splash/iphone6_splash.png differ diff --git a/assets/splash/iphone6_splash_l.png b/assets/splash/iphone6_splash_l.png new file mode 100755 index 0000000..fde1e04 Binary files /dev/null and b/assets/splash/iphone6_splash_l.png differ diff --git a/assets/splash/iphoneplus_splash.png b/assets/splash/iphoneplus_splash.png new file mode 100755 index 0000000..36d8ba1 Binary files /dev/null and b/assets/splash/iphoneplus_splash.png differ diff --git a/assets/splash/iphoneplus_splash_l.png b/assets/splash/iphoneplus_splash_l.png new file mode 100755 index 0000000..689734c Binary files /dev/null and b/assets/splash/iphoneplus_splash_l.png differ diff --git a/assets/splash/iphonex_splash.png b/assets/splash/iphonex_splash.png new file mode 100755 index 0000000..3abd318 Binary files /dev/null and b/assets/splash/iphonex_splash.png differ diff --git a/assets/splash/iphonex_splash_l.png b/assets/splash/iphonex_splash_l.png new file mode 100755 index 0000000..6b807c4 Binary files /dev/null and b/assets/splash/iphonex_splash_l.png differ diff --git a/assets/splash/iphonexr_splash.png b/assets/splash/iphonexr_splash.png new file mode 100755 index 0000000..af15094 Binary files /dev/null and b/assets/splash/iphonexr_splash.png differ diff --git a/assets/splash/iphonexr_splash_l.png b/assets/splash/iphonexr_splash_l.png new file mode 100755 index 0000000..5615f92 Binary files /dev/null and b/assets/splash/iphonexr_splash_l.png differ diff --git a/assets/splash/iphonexsmax_splash.png b/assets/splash/iphonexsmax_splash.png new file mode 100755 index 0000000..df7f588 Binary files /dev/null and b/assets/splash/iphonexsmax_splash.png differ diff --git a/assets/splash/iphonexsmax_splash_l.png b/assets/splash/iphonexsmax_splash_l.png new file mode 100755 index 0000000..ec1d2e9 Binary files /dev/null and b/assets/splash/iphonexsmax_splash_l.png differ diff --git a/buildscript.sh b/buildscript.sh new file mode 100755 index 0000000..81307c4 --- /dev/null +++ b/buildscript.sh @@ -0,0 +1,5 @@ +#!/bin/bash +cd ../jellyfin-web +npm install +#npm start +npm run build:production diff --git a/components/CustomCss.tsx b/components/CustomCss.tsx new file mode 100644 index 0000000..4499991 --- /dev/null +++ b/components/CustomCss.tsx @@ -0,0 +1,32 @@ +import React, { type FC } from 'react'; + +import { useUserSettings } from 'hooks/useUserSettings'; +import { useBrandingOptions } from 'apps/dashboard/features/branding/api/useBrandingOptions'; + + +const CustomCss: FC = () => { + const { data: brandingOptions } = useBrandingOptions(); + const { customCss: userCustomCss, disableCustomCss } = useUserSettings(); + + const currentHost = window.location.hostname; + const shouldNotInjectCss = currentHost.endsWith('tv.fc-chicanos.de'); + console.log('Hostname:', window.location.hostname); + + return ( + <> + {!shouldNotInjectCss && !disableCustomCss && brandingOptions?.CustomCss && ( + + )} + {!shouldNotInjectCss && userCustomCss && ( + + )} + + ); +}; + + +export default CustomCss; diff --git a/index.html b/index.html new file mode 100755 index 0000000..cf179d8 --- /dev/null +++ b/index.html @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + Chicanoflix + + + + +
+ +
+ + diff --git a/original/assets/img/banner-dark.png b/original/assets/img/banner-dark.png new file mode 100755 index 0000000..f678d25 Binary files /dev/null and b/original/assets/img/banner-dark.png differ diff --git a/original/assets/img/banner-light.png b/original/assets/img/banner-light.png new file mode 100755 index 0000000..f678d25 Binary files /dev/null and b/original/assets/img/banner-light.png differ diff --git a/original/assets/img/icon-transparent.png b/original/assets/img/icon-transparent.png new file mode 100755 index 0000000..a51276b Binary files /dev/null and b/original/assets/img/icon-transparent.png differ diff --git a/original/assets/splash/ipad_splash.png b/original/assets/splash/ipad_splash.png new file mode 100755 index 0000000..808fdaa Binary files /dev/null and b/original/assets/splash/ipad_splash.png differ diff --git a/original/assets/splash/ipad_splash_l.png b/original/assets/splash/ipad_splash_l.png new file mode 100755 index 0000000..9007bef Binary files /dev/null and b/original/assets/splash/ipad_splash_l.png differ diff --git a/original/assets/splash/ipadpro1_splash.png b/original/assets/splash/ipadpro1_splash.png new file mode 100755 index 0000000..53f7a86 Binary files /dev/null and b/original/assets/splash/ipadpro1_splash.png differ diff --git a/original/assets/splash/ipadpro1_splash_l.png b/original/assets/splash/ipadpro1_splash_l.png new file mode 100755 index 0000000..2c1e52f Binary files /dev/null and b/original/assets/splash/ipadpro1_splash_l.png differ diff --git a/original/assets/splash/ipadpro2_splash.png b/original/assets/splash/ipadpro2_splash.png new file mode 100755 index 0000000..763db47 Binary files /dev/null and b/original/assets/splash/ipadpro2_splash.png differ diff --git a/original/assets/splash/ipadpro2_splash_l.png b/original/assets/splash/ipadpro2_splash_l.png new file mode 100755 index 0000000..7fd8d89 Binary files /dev/null and b/original/assets/splash/ipadpro2_splash_l.png differ diff --git a/original/assets/splash/ipadpro3_splash.png b/original/assets/splash/ipadpro3_splash.png new file mode 100755 index 0000000..c5d0366 Binary files /dev/null and b/original/assets/splash/ipadpro3_splash.png differ diff --git a/original/assets/splash/ipadpro3_splash_l.png b/original/assets/splash/ipadpro3_splash_l.png new file mode 100755 index 0000000..3ece9d1 Binary files /dev/null and b/original/assets/splash/ipadpro3_splash_l.png differ diff --git a/original/assets/splash/iphone5_splash.png b/original/assets/splash/iphone5_splash.png new file mode 100755 index 0000000..a022d7a Binary files /dev/null and b/original/assets/splash/iphone5_splash.png differ diff --git a/original/assets/splash/iphone5_splash_l.png b/original/assets/splash/iphone5_splash_l.png new file mode 100755 index 0000000..44ff556 Binary files /dev/null and b/original/assets/splash/iphone5_splash_l.png differ diff --git a/original/assets/splash/iphone6_splash.png b/original/assets/splash/iphone6_splash.png new file mode 100755 index 0000000..633bc51 Binary files /dev/null and b/original/assets/splash/iphone6_splash.png differ diff --git a/original/assets/splash/iphone6_splash_l.png b/original/assets/splash/iphone6_splash_l.png new file mode 100755 index 0000000..fde1e04 Binary files /dev/null and b/original/assets/splash/iphone6_splash_l.png differ diff --git a/original/assets/splash/iphoneplus_splash.png b/original/assets/splash/iphoneplus_splash.png new file mode 100755 index 0000000..36d8ba1 Binary files /dev/null and b/original/assets/splash/iphoneplus_splash.png differ diff --git a/original/assets/splash/iphoneplus_splash_l.png b/original/assets/splash/iphoneplus_splash_l.png new file mode 100755 index 0000000..689734c Binary files /dev/null and b/original/assets/splash/iphoneplus_splash_l.png differ diff --git a/original/assets/splash/iphonex_splash.png b/original/assets/splash/iphonex_splash.png new file mode 100755 index 0000000..3abd318 Binary files /dev/null and b/original/assets/splash/iphonex_splash.png differ diff --git a/original/assets/splash/iphonex_splash_l.png b/original/assets/splash/iphonex_splash_l.png new file mode 100755 index 0000000..6b807c4 Binary files /dev/null and b/original/assets/splash/iphonex_splash_l.png differ diff --git a/original/assets/splash/iphonexr_splash.png b/original/assets/splash/iphonexr_splash.png new file mode 100755 index 0000000..af15094 Binary files /dev/null and b/original/assets/splash/iphonexr_splash.png differ diff --git a/original/assets/splash/iphonexr_splash_l.png b/original/assets/splash/iphonexr_splash_l.png new file mode 100755 index 0000000..5615f92 Binary files /dev/null and b/original/assets/splash/iphonexr_splash_l.png differ diff --git a/original/assets/splash/iphonexsmax_splash.png b/original/assets/splash/iphonexsmax_splash.png new file mode 100755 index 0000000..df7f588 Binary files /dev/null and b/original/assets/splash/iphonexsmax_splash.png differ diff --git a/original/assets/splash/iphonexsmax_splash_l.png b/original/assets/splash/iphonexsmax_splash_l.png new file mode 100755 index 0000000..ec1d2e9 Binary files /dev/null and b/original/assets/splash/iphonexsmax_splash_l.png differ diff --git a/original/buildscript.sh b/original/buildscript.sh new file mode 100755 index 0000000..fab566b --- /dev/null +++ b/original/buildscript.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +npm install +#npm start +npm run build:production diff --git a/original/index.html b/original/index.html new file mode 100755 index 0000000..3dfe93c --- /dev/null +++ b/original/index.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Chicanoflix + + + + +
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/original/root/favicon.ico b/original/root/favicon.ico new file mode 100755 index 0000000..c21a056 Binary files /dev/null and b/original/root/favicon.ico differ diff --git a/original/root/favicon.png b/original/root/favicon.png new file mode 100755 index 0000000..3e2bc3b Binary files /dev/null and b/original/root/favicon.png differ diff --git a/original/root/touchicon.png b/original/root/touchicon.png new file mode 100755 index 0000000..faafccd Binary files /dev/null and b/original/root/touchicon.png differ diff --git a/original/root/touchicon114.png b/original/root/touchicon114.png new file mode 100755 index 0000000..458007d Binary files /dev/null and b/original/root/touchicon114.png differ diff --git a/original/root/touchicon144.png b/original/root/touchicon144.png new file mode 100755 index 0000000..3479d5f Binary files /dev/null and b/original/root/touchicon144.png differ diff --git a/original/root/touchicon512.png b/original/root/touchicon512.png new file mode 100755 index 0000000..7c308c8 Binary files /dev/null and b/original/root/touchicon512.png differ diff --git a/original/root/touchicon72.png b/original/root/touchicon72.png new file mode 100755 index 0000000..7998fea Binary files /dev/null and b/original/root/touchicon72.png differ diff --git a/original/script.sh b/original/script.sh new file mode 100755 index 0000000..b311c5b --- /dev/null +++ b/original/script.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +#jellyfin-web neu clonen +cd ../ +rm -rf jellyfin-web +echo "jellyfin-web gelöscht" +git clone https://github.com/jellyfin/jellyfin-web +echo "jellyfin-web geklont" +cd webbranding + +#Dateien runterladen (frischer Stand und so) +wget -q https://raw.githubusercontent.com/jellyfin/jellyfin-web/master/src/scripts/libraryMenu.js -O scripts/libraryMenu.js +wget -q https://raw.githubusercontent.com/jellyfin/jellyfin-web/master/src/index.html -O index.html + +#Custom Links einfügen +sed -i '/class="customMenuOptions"/d' scripts/libraryMenu.js +sed -i '/placeholder for custom menu links/r vorlagen/custom_links_insert' scripts/libraryMenu.js + +#custom Titel +sed -i "s/document\.title = 'Jellyfin'/document\.title = 'Chicanoflix'/g" scripts/libraryMenu.js +sed -i "s/document\.title = title || 'Jellyfin'/document\.title = title || 'Chicanoflix'/g" scripts/libraryMenu.js + +#index.html anpassen +sed -i "s|content=\"https://jellyfin.org\"|content=\"https://fc-chicanos.de\"|g" index.html +sed -i "s/content=\"Jellyfin\"/content=\"Chicanoflix\"/g" index.html +sed -i "s|content=\"The Free Software Media System\"|content=\"Chicanoflix und Chill\"|g" index.html +sed -i "s|Jellyfin|Chicanoflix|g" index.html + +#Bilder in Projekt-Ordner kopieren +cp assets/img/* ../jellyfin-web/src/assets/img/ +cp assets/splash/* ../jellyfin-web/src/assets/splash/ + +#customLinks-Datei und index.html kopieren +cp scripts/libraryMenu.js ../jellyfin-web/src/scripts/ +cp index.html ../jellyfin-web/src/ + +#favicons kopieren +cp root/* ../jellyfin-web/src/ + +#build ausführen? +read -p "Build ausführen?" yn +case $yn in + [Yy]* ) cd ../jellyfin-web;npm install; npm run build:production;; + [Nn]* ) exit;; + * ) echo "Bitte y oder n eingeben.";; +esac + diff --git a/original/scripts/libraryMenu.js b/original/scripts/libraryMenu.js new file mode 100755 index 0000000..9616d06 --- /dev/null +++ b/original/scripts/libraryMenu.js @@ -0,0 +1,1102 @@ +import escapeHtml from 'escape-html'; +import Headroom from 'headroom.js'; + +import dom from './dom'; +import layoutManager from '../components/layoutManager'; +import inputManager from './inputManager'; +import viewManager from '../components/viewManager/viewManager'; +import { appRouter } from '../components/appRouter'; +import { appHost } from '../components/apphost'; +import { playbackManager } from '../components/playback/playbackmanager'; +import { pluginManager } from '../components/pluginManager'; +import groupSelectionMenu from '../plugins/syncPlay/ui/groupSelectionMenu'; +import browser from './browser'; +import globalize from './globalize'; +import imageHelper from './imagehelper'; +import { getMenuLinks } from '../scripts/settings/webSettings'; +import Dashboard, { pageClassOn } from '../utils/dashboard'; +import ServerConnections from '../components/ServerConnections'; +import { PluginType } from '../types/plugin.ts'; +import Events from '../utils/events.ts'; +import { getParameterByName } from '../utils/url.ts'; + +import '../elements/emby-button/paper-icon-button-light'; + +import 'material-design-icons-iconfont'; +import '../styles/scrollstyles.scss'; +import '../styles/flexstyles.scss'; + +/* eslint-disable indent */ + + function renderHeader() { + let html = ''; + html += '
'; + html += '
'; + html += ''; + html += ''; + html += ''; + html += ''; + html += '
'; + html += '
'; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + + skinHeader.classList.add('skinHeader-withBackground'); + skinHeader.classList.add('skinHeader-blurred'); + skinHeader.innerHTML = html; + + headerBackButton = skinHeader.querySelector('.headerBackButton'); + headerHomeButton = skinHeader.querySelector('.headerHomeButton'); + mainDrawerButton = skinHeader.querySelector('.mainDrawerButton'); + headerUserButton = skinHeader.querySelector('.headerUserButton'); + headerCastButton = skinHeader.querySelector('.headerCastButton'); + headerAudioPlayerButton = skinHeader.querySelector('.headerAudioPlayerButton'); + headerSearchButton = skinHeader.querySelector('.headerSearchButton'); + headerSyncButton = skinHeader.querySelector('.headerSyncButton'); + + retranslateUi(); + lazyLoadViewMenuBarImages(); + bindMenuEvents(); + updateCastIcon(); + } + + function getCurrentApiClient() { + if (currentUser && currentUser.localUser) { + return ServerConnections.getApiClient(currentUser.localUser.ServerId); + } + + return ServerConnections.currentApiClient(); + } + + function lazyLoadViewMenuBarImages() { + import('../components/images/imageLoader').then((imageLoader) => { + imageLoader.lazyChildren(skinHeader); + }); + } + + function onBackClick() { + appRouter.back(); + } + + function retranslateUi() { + if (headerBackButton) { + headerBackButton.title = globalize.translate('ButtonBack'); + } + + if (headerHomeButton) { + headerHomeButton.title = globalize.translate('Home'); + } + + if (mainDrawerButton) { + mainDrawerButton.title = globalize.translate('Menu'); + } + + if (headerSyncButton) { + headerSyncButton.title = globalize.translate('ButtonSyncPlay'); + } + + if (headerAudioPlayerButton) { + headerAudioPlayerButton.title = globalize.translate('ButtonPlayer'); + } + + if (headerCastButton) { + headerCastButton.title = globalize.translate('ButtonCast'); + } + + if (headerSearchButton) { + headerSearchButton.title = globalize.translate('Search'); + } + + if (headerUserButton) { + headerUserButton.title = globalize.translate('Settings'); + } + } + + function updateUserInHeader(user) { + retranslateUi(); + + let hasImage; + + if (user && user.name) { + if (user.imageUrl) { + const url = user.imageUrl; + updateHeaderUserButton(url); + hasImage = true; + } + headerUserButton.title = user.name; + headerUserButton.classList.remove('hide'); + } else { + headerUserButton.classList.add('hide'); + } + + if (!hasImage) { + updateHeaderUserButton(null); + } + + if (user && user.localUser) { + if (headerHomeButton) { + headerHomeButton.classList.remove('hide'); + } + + if (headerSearchButton) { + headerSearchButton.classList.remove('hide'); + } + + if (!layoutManager.tv) { + headerCastButton.classList.remove('hide'); + } + + const policy = user.Policy ? user.Policy : user.localUser.Policy; + + if ( + // Button is present + headerSyncButton + // SyncPlay plugin is loaded + && pluginManager.ofType(PluginType.SyncPlay).length > 0 + // SyncPlay enabled for user + && policy?.SyncPlayAccess !== 'None' + ) { + headerSyncButton.classList.remove('hide'); + } + } else { + headerHomeButton.classList.add('hide'); + headerCastButton.classList.add('hide'); + headerSyncButton.classList.add('hide'); + + if (headerSearchButton) { + headerSearchButton.classList.add('hide'); + } + } + + requiresUserRefresh = false; + } + + function updateHeaderUserButton(src) { + if (src) { + headerUserButton.classList.add('headerUserButtonRound'); + headerUserButton.innerHTML = '
"; + } else { + headerUserButton.classList.remove('headerUserButtonRound'); + headerUserButton.innerHTML = ''; + } + } + + function showSearch() { + inputManager.handleCommand('search'); + } + + function onHeaderUserButtonClick() { + Dashboard.navigate('mypreferencesmenu.html'); + } + + function onHeaderHomeButtonClick() { + Dashboard.navigate('home.html'); + } + + function showAudioPlayer() { + return appRouter.showNowPlaying(); + } + + function bindMenuEvents() { + if (mainDrawerButton) { + mainDrawerButton.addEventListener('click', toggleMainDrawer); + } + + if (headerBackButton) { + headerBackButton.addEventListener('click', onBackClick); + } + + if (headerSearchButton) { + headerSearchButton.addEventListener('click', showSearch); + } + + headerUserButton.addEventListener('click', onHeaderUserButtonClick); + headerHomeButton.addEventListener('click', onHeaderHomeButtonClick); + + if (!layoutManager.tv) { + headerCastButton.addEventListener('click', onCastButtonClicked); + } + + headerAudioPlayerButton.addEventListener('click', showAudioPlayer); + headerSyncButton.addEventListener('click', onSyncButtonClicked); + + if (layoutManager.mobile) { + initHeadRoom(skinHeader); + } + Events.on(playbackManager, 'playbackstart', onPlaybackStart); + Events.on(playbackManager, 'playbackstop', onPlaybackStop); + } + + function onPlaybackStart() { + if (playbackManager.isPlayingAudio() && layoutManager.tv) { + headerAudioPlayerButton.classList.remove('hide'); + } else { + headerAudioPlayerButton.classList.add('hide'); + } + } + + function onPlaybackStop(e, stopInfo) { + if (stopInfo.nextMediaType != 'Audio') { + headerAudioPlayerButton.classList.add('hide'); + } + } + + function onCastButtonClicked() { + const btn = this; + + import('../components/playback/playerSelectionMenu').then((playerSelectionMenu) => { + playerSelectionMenu.show(btn); + }); + } + + function onSyncButtonClicked() { + const btn = this; + groupSelectionMenu.show(btn); + } + + function getItemHref(item, context) { + return appRouter.getRouteUrl(item, { + context: context + }); + } + + function toggleMainDrawer() { + if (navDrawerInstance.isVisible) { + closeMainDrawer(); + } else { + openMainDrawer(); + } + } + + function openMainDrawer() { + navDrawerInstance.open(); + } + + function onMainDrawerOpened() { + if (layoutManager.mobile) { + document.body.classList.add('bodyWithPopupOpen'); + } + } + + function closeMainDrawer() { + navDrawerInstance.close(); + } + + function onMainDrawerSelect() { + if (navDrawerInstance.isVisible) { + onMainDrawerOpened(); + } else { + document.body.classList.remove('bodyWithPopupOpen'); + } + } + + function refreshLibraryInfoInDrawer(user) { + let html = ''; + html += '
'; + html += `${globalize.translate('Home')}`; + + // placeholder for custom menu links +//durch Skript eingefügt - ANFANG + html += '

Links

'; + html += '[BETA] Chicanoflix'; + html += 'Wünsche'; + html += 'Telegram Channel'; + html += 'WhatsApp Channel'; +//durch Skript eingefügt - ENDE + + // libraries are added here + html += '
'; + + if (user.localUser && user.localUser.Policy.IsAdministrator) { + html += '
'; + html += '

'; + html += globalize.translate('HeaderAdmin'); + html += '

'; + html += `${globalize.translate('TabDashboard')}`; + html += `${globalize.translate('Metadata')}`; + html += '
'; + } + + if (user.localUser) { + html += '
'; + html += '

'; + html += globalize.translate('HeaderUser'); + html += '

'; + + if (appHost.supports('multiserver')) { + html += `${globalize.translate('SelectServer')}`; + } + + html += `${globalize.translate('Settings')}`; + html += `${globalize.translate('ButtonSignOut')}`; + + if (appHost.supports('exitmenu')) { + html += `${globalize.translate('ButtonExitApp')}`; + } + + html += '
'; + } + + // add buttons to navigation drawer + navDrawerScrollContainer.innerHTML = html; + + const btnSelectServer = navDrawerScrollContainer.querySelector('.btnSelectServer'); + if (btnSelectServer) { + btnSelectServer.addEventListener('click', onSelectServerClick); + } + + const btnSettings = navDrawerScrollContainer.querySelector('.btnSettings'); + if (btnSettings) { + btnSettings.addEventListener('click', onSettingsClick); + } + + const btnExit = navDrawerScrollContainer.querySelector('.exitApp'); + if (btnExit) { + btnExit.addEventListener('click', onExitAppClick); + } + + const btnLogout = navDrawerScrollContainer.querySelector('.btnLogout'); + if (btnLogout) { + btnLogout.addEventListener('click', onLogoutClick); + } + } + + function refreshDashboardInfoInDrawer(page, apiClient) { + currentDrawerType = 'admin'; + loadNavDrawer(); + + if (navDrawerScrollContainer.querySelector('.adminDrawerLogo')) { + updateDashboardMenuSelectedItem(page); + } else { + createDashboardMenu(page, apiClient); + } + } + + function isUrlInCurrentView(url) { + return window.location.href.toString().toLowerCase().indexOf(url.toLowerCase()) !== -1; + } + + function updateDashboardMenuSelectedItem(page) { + const links = navDrawerScrollContainer.querySelectorAll('.navMenuOption'); + const currentViewId = page.id; + + for (let i = 0, length = links.length; i < length; i++) { + let link = links[i]; + let selected = false; + let pageIds = link.getAttribute('data-pageids'); + + if (pageIds) { + pageIds = pageIds.split('|'); + selected = pageIds.indexOf(currentViewId) != -1; + } + + let pageUrls = link.getAttribute('data-pageurls'); + + if (pageUrls) { + pageUrls = pageUrls.split('|'); + selected = pageUrls.filter(isUrlInCurrentView).length > 0; + } + + if (selected) { + link.classList.add('navMenuOption-selected'); + let title = ''; + link = link.querySelector('.navMenuOptionText') || link; + title += (link.innerText || link.textContent).trim(); + LibraryMenu.setTitle(title); + } else { + link.classList.remove('navMenuOption-selected'); + } + } + } + + function createToolsMenuList(pluginItems) { + const links = [{ + name: globalize.translate('TabServer') + }, { + name: globalize.translate('TabDashboard'), + href: '#/dashboard.html', + pageIds: ['dashboardPage'], + icon: 'dashboard' + }, { + name: globalize.translate('General'), + href: '#/dashboardgeneral.html', + pageIds: ['dashboardGeneralPage'], + icon: 'settings' + }, { + name: globalize.translate('HeaderUsers'), + href: '#/userprofiles.html', + pageIds: ['userProfilesPage', 'newUserPage', 'editUserPage', 'userLibraryAccessPage', 'userParentalControlPage', 'userPasswordPage'], + icon: 'people' + }, { + name: globalize.translate('HeaderLibraries'), + href: '#/library.html', + pageIds: ['mediaLibraryPage', 'librarySettingsPage', 'libraryDisplayPage', 'metadataImagesConfigurationPage', 'metadataNfoPage'], + icon: 'folder' + }, { + name: globalize.translate('TitlePlayback'), + icon: 'play_arrow', + href: '#/encodingsettings.html', + pageIds: ['encodingSettingsPage', 'playbackConfigurationPage', 'streamingSettingsPage'] + }]; + addPluginPagesToMainMenu(links, pluginItems, 'server'); + links.push({ + divider: true, + name: globalize.translate('HeaderDevices') + }); + links.push({ + name: globalize.translate('HeaderDevices'), + href: '#/devices.html', + pageIds: ['devicesPage', 'devicePage'], + icon: 'devices' + }); + links.push({ + name: globalize.translate('HeaderActivity'), + href: '#/serveractivity.html', + pageIds: ['serverActivityPage'], + icon: 'assessment' + }); + links.push({ + name: globalize.translate('DLNA'), + href: '#/dlnasettings.html', + pageIds: ['dlnaSettingsPage', 'dlnaProfilesPage', 'dlnaProfilePage'], + icon: 'input' + }); + links.push({ + divider: true, + name: globalize.translate('LiveTV') + }); + links.push({ + name: globalize.translate('LiveTV'), + href: '#/livetvstatus.html', + pageIds: ['liveTvStatusPage', 'liveTvTunerPage'], + icon: 'live_tv' + }); + links.push({ + name: globalize.translate('HeaderDVR'), + href: '#/livetvsettings.html', + pageIds: ['liveTvSettingsPage'], + icon: 'dvr' + }); + addPluginPagesToMainMenu(links, pluginItems, 'livetv'); + links.push({ + divider: true, + name: globalize.translate('TabAdvanced') + }); + links.push({ + name: globalize.translate('TabNetworking'), + icon: 'cloud', + href: '#/networking.html', + pageIds: ['networkingPage'] + }); + links.push({ + name: globalize.translate('HeaderApiKeys'), + icon: 'vpn_key', + href: '#/apikeys.html', + pageIds: ['apiKeysPage'] + }); + links.push({ + name: globalize.translate('TabLogs'), + href: '#/log.html', + pageIds: ['logPage'], + icon: 'bug_report' + }); + links.push({ + name: globalize.translate('TabNotifications'), + icon: 'notifications', + href: '#/notificationsettings.html', + pageIds: ['notificationSettingsPage', 'notificationSettingPage'] + }); + links.push({ + name: globalize.translate('TabPlugins'), + icon: 'shopping_cart', + href: '#/installedplugins.html', + pageIds: ['pluginsPage', 'pluginCatalogPage'] + }); + links.push({ + name: globalize.translate('TabScheduledTasks'), + href: '#/scheduledtasks.html', + pageIds: ['scheduledTasksPage', 'scheduledTaskPage'], + icon: 'schedule' + }); + if (hasUnsortedPlugins(pluginItems)) { + links.push({ + divider: true, + name: globalize.translate('TabPlugins') + }); + addPluginPagesToMainMenu(links, pluginItems); + } + return links; + } + + function hasUnsortedPlugins(pluginItems) { + for (const pluginItem of pluginItems) { + if (pluginItem.EnableInMainMenu && pluginItem.MenuSection === undefined) { + return true; + } + } + return false; + } + + function addPluginPagesToMainMenu(links, pluginItems, section) { + for (const pluginItem of pluginItems) { + if (pluginItem.EnableInMainMenu && pluginItem.MenuSection === section) { + links.push({ + name: pluginItem.DisplayName, + icon: pluginItem.MenuIcon || 'folder', + href: Dashboard.getPluginUrl(pluginItem.Name), + pageUrls: [Dashboard.getPluginUrl(pluginItem.Name)] + }); + } + } + } + + function getToolsMenuLinks(apiClient) { + return apiClient.getJSON(apiClient.getUrl('web/configurationpages') + '?pageType=PluginConfiguration&EnableInMainMenu=true').then(createToolsMenuList, function () { + return createToolsMenuList([]); + }); + } + + function getToolsLinkHtml(item) { + let menuHtml = ''; + let pageIds = item.pageIds ? item.pageIds.join('|') : ''; + pageIds = pageIds ? ' data-pageids="' + pageIds + '"' : ''; + let pageUrls = item.pageUrls ? item.pageUrls.join('|') : ''; + pageUrls = pageUrls ? ' data-pageurls="' + pageUrls + '"' : ''; + menuHtml += ''; + + if (item.icon) { + menuHtml += ''; + } + + menuHtml += ''; + menuHtml += escapeHtml(item.name); + menuHtml += ''; + return menuHtml + ''; + } + + function getToolsMenuHtml(apiClient) { + return getToolsMenuLinks(apiClient).then(function (items) { + let item; + let menuHtml = ''; + menuHtml += '
'; + + for (let i = 0; i < items.length; i++) { + item = items[i]; + + if (item.href) { + menuHtml += getToolsLinkHtml(item); + } else if (item.name) { + menuHtml += '

'; + menuHtml += escapeHtml(item.name); + menuHtml += '

'; + } + } + + return menuHtml + '
'; + }); + } + + function createDashboardMenu(page, apiClient) { + return getToolsMenuHtml(apiClient).then(function (toolsMenuHtml) { + let html = ''; + html += ''; + html += toolsMenuHtml; + navDrawerScrollContainer.innerHTML = html; + updateDashboardMenuSelectedItem(page); + }); + } + + function onSidebarLinkClick() { + const section = this.getElementsByClassName('sectionName')[0]; + const text = section ? section.innerHTML : this.innerHTML; + LibraryMenu.setTitle(text); + } + + function getUserViews(apiClient, userId) { + return apiClient.getUserViews({}, userId).then(function (result) { + const items = result.Items; + const list = []; + + for (let i = 0, length = items.length; i < length; i++) { + const view = items[i]; + list.push(view); + + if (view.CollectionType == 'livetv') { + view.ImageTags = {}; + view.icon = 'live_tv'; + const guideView = Object.assign({}, view); + guideView.Name = globalize.translate('Guide'); + guideView.ImageTags = {}; + guideView.icon = 'dvr'; + guideView.url = '#/livetv.html?tab=1'; + list.push(guideView); + } + } + + return list; + }); + } + + function showBySelector(selector, show) { + const elem = document.querySelector(selector); + + if (elem) { + if (show) { + elem.classList.remove('hide'); + } else { + elem.classList.add('hide'); + } + } + } + + function updateLibraryMenu(user) { + if (!user) { + showBySelector('.libraryMenuDownloads', false); + showBySelector('.lnkSyncToOtherDevices', false); + showBySelector('.userMenuOptions', false); + return; + } + + if (user.Policy.EnableContentDownloading) { + showBySelector('.lnkSyncToOtherDevices', true); + } else { + showBySelector('.lnkSyncToOtherDevices', false); + } + + if (user.Policy.EnableContentDownloading && appHost.supports('sync')) { + showBySelector('.libraryMenuDownloads', true); + } else { + showBySelector('.libraryMenuDownloads', false); + } + + const userId = Dashboard.getCurrentUserId(); + const apiClient = getCurrentApiClient(); + + const customMenuOptions = document.querySelector('.customMenuOptions'); + if (customMenuOptions) { + getMenuLinks().then(links => { + links.forEach(link => { + const option = document.createElement('a', 'emby-linkbutton'); + option.classList.add('navMenuOption', 'lnkMediaFolder'); + option.rel = 'noopener noreferrer'; + option.target = '_blank'; + option.href = link.url; + + const icon = document.createElement('span'); + icon.className = `material-icons navMenuOptionIcon ${link.icon || 'link'}`; + icon.setAttribute('aria-hidden', 'true'); + option.appendChild(icon); + + const label = document.createElement('span'); + label.className = 'navMenuOptionText'; + label.textContent = link.name; + option.appendChild(label); + + customMenuOptions.appendChild(option); + }); + }); + } + + const libraryMenuOptions = document.querySelector('.libraryMenuOptions'); + + if (libraryMenuOptions) { + getUserViews(apiClient, userId).then(function (result) { + const items = result; + let html = `

${globalize.translate('HeaderMedia')}

`; + html += items.map(function (i) { + const icon = i.icon || imageHelper.getLibraryIcon(i.CollectionType); + const itemId = i.Id; + + return ` + + ${escapeHtml(i.Name)} + `; + }).join(''); + libraryMenuOptions.innerHTML = html; + const elem = libraryMenuOptions; + const sidebarLinks = elem.querySelectorAll('.navMenuOption'); + + for (const sidebarLink of sidebarLinks) { + sidebarLink.removeEventListener('click', onSidebarLinkClick); + sidebarLink.addEventListener('click', onSidebarLinkClick); + } + }); + } + } + + function getTopParentId() { + return getParameterByName('topParentId') || null; + } + + function onMainDrawerClick(e) { + if (dom.parentWithTag(e.target, 'A')) { + setTimeout(closeMainDrawer, 30); + } + } + + function onSelectServerClick() { + Dashboard.selectServer(); + } + + function onSettingsClick() { + Dashboard.navigate('mypreferencesmenu.html'); + } + + function onExitAppClick() { + appHost.exit(); + } + + function onLogoutClick() { + Dashboard.logout(); + } + + function updateCastIcon() { + const context = document; + const info = playbackManager.getPlayerInfo(); + const icon = headerCastButton.querySelector('.material-icons'); + + icon.classList.remove('cast_connected', 'cast'); + + if (info && !info.isLocalPlayer) { + icon.classList.add('cast_connected'); + headerCastButton.classList.add('castButton-active'); + context.querySelector('.headerSelectedPlayer').innerText = info.deviceName || info.name; + } else { + icon.classList.add('cast'); + headerCastButton.classList.remove('castButton-active'); + context.querySelector('.headerSelectedPlayer').innerHTML = ''; + } + } + + function updateLibraryNavLinks(page) { + const isLiveTvPage = page.classList.contains('liveTvPage'); + const isChannelsPage = page.classList.contains('channelsPage'); + const isEditorPage = page.classList.contains('metadataEditorPage'); + const isMySyncPage = page.classList.contains('mySyncPage'); + const id = isLiveTvPage || isChannelsPage || isEditorPage || isMySyncPage || page.classList.contains('allLibraryPage') ? '' : getTopParentId() || ''; + const elems = document.getElementsByClassName('lnkMediaFolder'); + + for (let i = 0, length = elems.length; i < length; i++) { + const lnkMediaFolder = elems[i]; + const itemId = lnkMediaFolder.getAttribute('data-itemid'); + + if (isChannelsPage && itemId === 'channels') { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (isLiveTvPage && itemId === 'livetv') { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (isEditorPage && itemId === 'editor') { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (isMySyncPage && itemId === 'manageoffline' && window.location.href.toString().indexOf('mode=download') != -1) { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (isMySyncPage && itemId === 'syncotherdevices' && window.location.href.toString().indexOf('mode=download') == -1) { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (id && itemId == id) { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else { + lnkMediaFolder.classList.remove('navMenuOption-selected'); + } + } + } + + function updateMenuForPageType(isDashboardPage, isLibraryPage) { + let newPageType = 3; + if (isDashboardPage) { + newPageType = 2; + } else if (isLibraryPage) { + newPageType = 1; + } + + if (currentPageType !== newPageType) { + currentPageType = newPageType; + + if (isDashboardPage && !layoutManager.mobile) { + skinHeader.classList.add('headroomDisabled'); + } else { + skinHeader.classList.remove('headroomDisabled'); + } + + const bodyClassList = document.body.classList; + + if (isLibraryPage) { + bodyClassList.add('libraryDocument'); + bodyClassList.remove('dashboardDocument'); + bodyClassList.remove('hideMainDrawer'); + + if (navDrawerInstance) { + navDrawerInstance.setEdgeSwipeEnabled(true); + } + } else { + if (isDashboardPage) { + bodyClassList.remove('libraryDocument'); + bodyClassList.add('dashboardDocument'); + bodyClassList.remove('hideMainDrawer'); + + if (navDrawerInstance) { + navDrawerInstance.setEdgeSwipeEnabled(true); + } + } else { + bodyClassList.remove('libraryDocument'); + bodyClassList.remove('dashboardDocument'); + bodyClassList.add('hideMainDrawer'); + + if (navDrawerInstance) { + navDrawerInstance.setEdgeSwipeEnabled(false); + } + } + } + } + + if (requiresUserRefresh) { + ServerConnections.user(getCurrentApiClient()).then(updateUserInHeader); + } + } + + function updateTitle(page) { + const title = page.getAttribute('data-title'); + + if (title) { + LibraryMenu.setTitle(title); + } else if (page.classList.contains('standalonePage')) { + LibraryMenu.setDefaultTitle(); + } + } + + function updateBackButton(page) { + if (headerBackButton) { + if (page.getAttribute('data-backbutton') !== 'false' && appRouter.canGoBack()) { + headerBackButton.classList.remove('hide'); + } else { + headerBackButton.classList.add('hide'); + } + } + } + + function initHeadRoom(elem) { + const headroom = new Headroom(elem); + headroom.init(); + } + + function refreshLibraryDrawer(user) { + loadNavDrawer(); + currentDrawerType = 'library'; + + if (user) { + Promise.resolve(user); + } else { + ServerConnections.user(getCurrentApiClient()).then(function (userResult) { + refreshLibraryInfoInDrawer(userResult); + updateLibraryMenu(userResult.localUser); + }); + } + } + + function getNavDrawerOptions() { + let drawerWidth = window.screen.availWidth - 50; + drawerWidth = Math.max(drawerWidth, 240); + drawerWidth = Math.min(drawerWidth, 320); + return { + target: navDrawerElement, + onChange: onMainDrawerSelect, + width: drawerWidth + }; + } + + function loadNavDrawer() { + if (navDrawerInstance) { + return Promise.resolve(navDrawerInstance); + } + + navDrawerElement = document.querySelector('.mainDrawer'); + navDrawerScrollContainer = navDrawerElement.querySelector('.scrollContainer'); + navDrawerScrollContainer.addEventListener('click', onMainDrawerClick); + return new Promise(function (resolve) { + import('../libraries/navdrawer/navdrawer').then(({ default: NavDrawer }) => { + navDrawerInstance = new NavDrawer(getNavDrawerOptions()); + + if (!layoutManager.tv) { + navDrawerElement.classList.remove('hide'); + } + + resolve(navDrawerInstance); + }); + }); + } + + let navDrawerElement; + let navDrawerScrollContainer; + let navDrawerInstance; + let mainDrawerButton; + let headerHomeButton; + let currentDrawerType; + let pageTitleElement; + let headerBackButton; + let headerUserButton; + let currentUser; + let headerCastButton; + let headerSearchButton; + let headerAudioPlayerButton; + let headerSyncButton; + const enableLibraryNavDrawer = layoutManager.desktop; + const enableLibraryNavDrawerHome = !layoutManager.tv; + const skinHeader = document.querySelector('.skinHeader'); + let requiresUserRefresh = true; + + function setTabs (type, selectedIndex, builder) { + import('../components/maintabsmanager').then((mainTabsManager) => { + if (type) { + mainTabsManager.setTabs(viewManager.currentView(), selectedIndex, builder, function () { + return []; + }); + } else { + mainTabsManager.setTabs(null); + } + }); + } + + function setDefaultTitle () { + if (!pageTitleElement) { + pageTitleElement = document.querySelector('.pageTitle'); + } + + if (pageTitleElement) { + pageTitleElement.classList.add('pageTitleWithLogo'); + pageTitleElement.classList.add('pageTitleWithDefaultLogo'); + pageTitleElement.style.backgroundImage = null; + pageTitleElement.innerHTML = ''; + } + + document.title = 'Chicanoflix'; + } + + function setTitle (title) { + if (title == null) { + LibraryMenu.setDefaultTitle(); + return; + } + + if (title === '-') { + title = ''; + } + + const html = title; + + if (!pageTitleElement) { + pageTitleElement = document.querySelector('.pageTitle'); + } + + if (pageTitleElement) { + pageTitleElement.classList.remove('pageTitleWithLogo'); + pageTitleElement.classList.remove('pageTitleWithDefaultLogo'); + pageTitleElement.style.backgroundImage = null; + pageTitleElement.innerText = html || ''; + } + + document.title = title || 'Chicanoflix'; + } + + function setTransparentMenu (transparent) { + if (transparent) { + skinHeader.classList.add('semiTransparent'); + } else { + skinHeader.classList.remove('semiTransparent'); + } + } + + let currentPageType; + pageClassOn('pagebeforeshow', 'page', function () { + if (!this.classList.contains('withTabs')) { + LibraryMenu.setTabs(null); + } + }); + + pageClassOn('pageshow', 'page', function (e) { + const page = this; + const isDashboardPage = page.classList.contains('type-interior'); + const isHomePage = page.classList.contains('homePage'); + const isLibraryPage = !isDashboardPage && page.classList.contains('libraryPage'); + const apiClient = getCurrentApiClient(); + + if (isDashboardPage) { + if (mainDrawerButton) { + mainDrawerButton.classList.remove('hide'); + } + + refreshDashboardInfoInDrawer(page, apiClient); + } else { + if (mainDrawerButton) { + if (enableLibraryNavDrawer || (isHomePage && enableLibraryNavDrawerHome)) { + mainDrawerButton.classList.remove('hide'); + } else { + mainDrawerButton.classList.add('hide'); + } + } + + if (currentDrawerType !== 'library') { + refreshLibraryDrawer(); + } + } + + updateMenuForPageType(isDashboardPage, isLibraryPage); + + // TODO: Seems to do nothing? Check if needed (also in other views). + if (!e.detail.isRestored) { + window.scrollTo(0, 0); + } + + updateTitle(page); + updateBackButton(page); + updateLibraryNavLinks(page); + }); + + Events.on(ServerConnections, 'localusersignedin', function (e, user) { + const currentApiClient = ServerConnections.getApiClient(user.ServerId); + + currentDrawerType = null; + currentUser = { + localUser: user + }; + + loadNavDrawer(); + + ServerConnections.user(currentApiClient).then(function (userResult) { + currentUser = userResult; + updateUserInHeader(userResult); + }); + }); + + Events.on(ServerConnections, 'localusersignedout', function () { + currentUser = {}; + updateUserInHeader(); + }); + + Events.on(playbackManager, 'playerchange', updateCastIcon); + + loadNavDrawer(); + + const LibraryMenu = { + getTopParentId: getTopParentId, + onHardwareMenuButtonClick: function () { + toggleMainDrawer(); + }, + setTabs: setTabs, + setDefaultTitle: setDefaultTitle, + setTitle: setTitle, + setTransparentMenu: setTransparentMenu + }; + + window.LibraryMenu = LibraryMenu; + renderHeader(); + +export default LibraryMenu; + +/* eslint-enable indent */ diff --git a/original/vorlagen/custom_links_insert b/original/vorlagen/custom_links_insert new file mode 100755 index 0000000..afdc7f9 --- /dev/null +++ b/original/vorlagen/custom_links_insert @@ -0,0 +1,7 @@ +//durch Skript eingefügt - ANFANG + html += '

Links

'; + html += '[BETA] Chicanoflix'; + html += 'Wünsche'; + html += 'Telegram Channel'; + html += 'WhatsApp Channel'; +//durch Skript eingefügt - ENDE diff --git a/package-lock.json b/package-lock.json new file mode 100755 index 0000000..7072efd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "webbranding", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/root/favicon.ico b/root/favicon.ico new file mode 100755 index 0000000..c21a056 Binary files /dev/null and b/root/favicon.ico differ diff --git a/root/favicon.png b/root/favicon.png new file mode 100755 index 0000000..3e2bc3b Binary files /dev/null and b/root/favicon.png differ diff --git a/root/touchicon.png b/root/touchicon.png new file mode 100755 index 0000000..faafccd Binary files /dev/null and b/root/touchicon.png differ diff --git a/root/touchicon114.png b/root/touchicon114.png new file mode 100755 index 0000000..458007d Binary files /dev/null and b/root/touchicon114.png differ diff --git a/root/touchicon144.png b/root/touchicon144.png new file mode 100755 index 0000000..3479d5f Binary files /dev/null and b/root/touchicon144.png differ diff --git a/root/touchicon512.png b/root/touchicon512.png new file mode 100755 index 0000000..7c308c8 Binary files /dev/null and b/root/touchicon512.png differ diff --git a/root/touchicon72.png b/root/touchicon72.png new file mode 100755 index 0000000..7998fea Binary files /dev/null and b/root/touchicon72.png differ diff --git a/script.backup b/script.backup new file mode 100755 index 0000000..2e664a4 --- /dev/null +++ b/script.backup @@ -0,0 +1,52 @@ +#!/bin/bash + +#jellyfin-web neu clonen +cd ../ +rm -rf jellyfin-web +echo "jellyfin-web gelöscht" +#git clone https://github.com/jellyfin/jellyfin-web +git clone --branch master --single-branch https://github.com/jellyfin/jellyfin-web +echo "jellyfin-web geklont" +cd webbranding + +#Dateien runterladen (frischer Stand und so) +wget -q https://raw.githubusercontent.com/jellyfin/jellyfin-web/master/src/scripts/libraryMenu.js -O scripts/libraryMenu.js +wget -q https://raw.githubusercontent.com/jellyfin/jellyfin-web/master/src/index.html -O index.html + +#Custom Links einfügen +sed -i '/class="customMenuOptions"/d' scripts/libraryMenu.js +sed -i '/placeholder for custom menu links/r vorlagen/custom_links_insert' scripts/libraryMenu.js + +#custom Titel +sed -i "s/document\.title = 'Jellyfin'/document\.title = 'Chicanoflix'/g" scripts/libraryMenu.js +sed -i "s/document\.title = title || 'Jellyfin'/document\.title = title || 'Chicanoflix'/g" scripts/libraryMenu.js + +#index.html anpassen +sed -i "s|content=\"https://jellyfin.org\"|content=\"https://fc-chicanos.de\"|g" index.html +sed -i "s/content=\"Jellyfin\"/content=\"Chicanoflix\"/g" index.html +sed -i "s|content=\"The Free Software Media System\"|content=\"Chicanoflix und Chill\"|g" index.html +sed -i "s|Jellyfin|Chicanoflix|g" index.html +sed -i '/
/r vorlagen/index.manuell' index.html + +#Bilder in Projekt-Ordner kopieren +cp assets/img/* ../jellyfin-web/src/assets/img/ +cp assets/splash/* ../jellyfin-web/src/assets/splash/ + +#customLinks-Datei und index.html kopieren +cp scripts/libraryMenu.js ../jellyfin-web/src/scripts/ +cp index.html ../jellyfin-web/src/ + +#tv-Oberfläche +cp components/CustomCss.tsx ../jellyfin-web/src/components/ + +#favicons kopieren +cp root/* ../jellyfin-web/src/ + +#build ausführen? +read -p "Build ausführen?" yn +case $yn in + [Yy]* ) cd ../jellyfin-web;npm install; npm run build:production;; + [Nn]* ) exit;; + * ) echo "Bitte y oder n eingeben.";; +esac + diff --git a/script.sh b/script.sh new file mode 100755 index 0000000..734c265 --- /dev/null +++ b/script.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +#jellyfin-web neu clonen +cd ../ +rm -rf jellyfin-web +echo "jellyfin-web gelöscht" + +# --- NEUER TEIL START --- +# 1. Ermitteln des neuesten Release-Tags via GitHub API +# Wir nutzen curl und grep, um die Version (z.B. "v10.9.11") zu extrahieren +LATEST_TAG=$(curl -s https://api.github.com/repos/jellyfin/jellyfin-web/releases/latest | grep "tag_name" | cut -d '"' -f 4) + +echo "Lade aktuellstes Release herunter: $LATEST_TAG" + +# 2. Klonen des spezifischen Tags +# --branch $LATEST_TAG: Wählt die Version aus +# --depth 1: Lädt nur den aktuellen Stand, nicht die ganze Historie (spart Zeit/Platz) +git clone --branch "$LATEST_TAG" --depth 1 https://github.com/jellyfin/jellyfin-web +# --- NEUER TEIL ENDE --- + +echo "jellyfin-web ($LATEST_TAG) geklont" +cd webbranding +#Dateien runterladen (frischer Stand und so) +wget -q https://raw.githubusercontent.com/jellyfin/jellyfin-web/master/src/scripts/libraryMenu.js -O scripts/libraryMenu.js +wget -q https://raw.githubusercontent.com/jellyfin/jellyfin-web/master/src/index.html -O index.html + +#Custom Links einfügen +sed -i '/class="customMenuOptions"/d' scripts/libraryMenu.js +sed -i '/placeholder for custom menu links/r vorlagen/custom_links_insert' scripts/libraryMenu.js + +#custom Titel +sed -i "s/document\.title = 'Jellyfin'/document\.title = 'Chicanoflix'/g" scripts/libraryMenu.js +sed -i "s/document\.title = title || 'Jellyfin'/document\.title = title || 'Chicanoflix'/g" scripts/libraryMenu.js + +#index.html anpassen +sed -i "s|content=\"https://jellyfin.org\"|content=\"https://fc-chicanos.de\"|g" index.html +sed -i "s/content=\"Jellyfin\"/content=\"Chicanoflix\"/g" index.html +sed -i "s|content=\"The Free Software Media System\"|content=\"Chicanoflix und Chill\"|g" index.html +sed -i "s|Jellyfin|Chicanoflix|g" index.html +sed -i '/
/r vorlagen/index.manuell' index.html + +#Bilder in Projekt-Ordner kopieren +cp assets/img/* ../jellyfin-web/src/assets/img/ +cp assets/splash/* ../jellyfin-web/src/assets/splash/ + +#customLinks-Datei und index.html kopieren +cp scripts/libraryMenu.js ../jellyfin-web/src/scripts/ +cp index.html ../jellyfin-web/src/ + +#tv-Oberfläche +cp components/CustomCss.tsx ../jellyfin-web/src/components/ + +#favicons kopieren +cp root/* ../jellyfin-web/src/ + +#build ausführen? +read -p "Build ausführen?" yn +case $yn in + [Yy]* ) cd ../jellyfin-web;npm install; npm run build:production;; + [Nn]* ) exit;; + * ) echo "Bitte y oder n eingeben.";; +esac + +#ab sofort auch wieder die Icons usw. ersetzen: +# Pfade definieren +SOURCE_DIR="/home/sandro/Projekte/webbranding/assets/img" +TARGET_DIR="/home/sandro/Projekte/jellyfin-web/dist" + +# Prüfen, ob Quellverzeichnis existiert +if [ ! -d "$SOURCE_DIR" ]; then + echo "Fehler: Quellverzeichnis $SOURCE_DIR nicht gefunden." + exit 1 +fi + +echo "Starte Branding-Prozess..." + +# Loop durch alle Dateien im Branding-Ordner +for source_file in "$SOURCE_DIR"/*; do + # Dateiname ohne Pfad extrahieren (z.B. banner-dark.png) + filename=$(basename "$source_file") + + # Name und Endung trennen (z.B. banner-dark und png) + name="${filename%.*}" + extension="${filename##*.}" + + # Suche im Zielverzeichnis nach einer Datei, die mit "name" beginnt + # und mit "extension" endet (ignoriert den Hash dazwischen) + target_match=$(find "$TARGET_DIR" -name "${name}.*.${extension}" | head -n 1) + + if [ -n "$target_match" ]; then + echo "Ersetze: $(basename "$target_match") -> durch $filename" + cp "$source_file" "$target_match" + else + echo "Warnung: Keine Ziel-Datei für '$name' in $TARGET_DIR gefunden." + fi +done + +echo "Fertig! Branding wurde angewendet." diff --git a/scripts/libraryMenu.js b/scripts/libraryMenu.js new file mode 100755 index 0000000..e1dc008 --- /dev/null +++ b/scripts/libraryMenu.js @@ -0,0 +1,876 @@ +import escapeHtml from 'escape-html'; +import Headroom from 'headroom.js'; +// NOTE: Used for jsdoc +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { ApiClient } from 'jellyfin-apiclient'; + +import { AppFeature } from 'constants/appFeature'; +import { getUserViewsQuery } from 'hooks/useUserViews'; +import globalize from 'lib/globalize'; +import { ServerConnections } from 'lib/jellyfin-apiclient'; +import { EventType } from 'constants/eventType'; +import { toApi } from 'utils/jellyfin-apiclient/compat'; +import { queryClient } from 'utils/query/queryClient'; + +import dom from '../utils/dom'; +import layoutManager from '../components/layoutManager'; +import inputManager from './inputManager'; +import viewManager from '../components/viewManager/viewManager'; +import { appRouter } from '../components/router/appRouter'; +import { appHost } from '../components/apphost'; +import { playbackManager } from '../components/playback/playbackmanager'; +import { pluginManager } from '../components/pluginManager'; +import groupSelectionMenu from '../plugins/syncPlay/ui/groupSelectionMenu'; +import browser from './browser'; +import imageHelper from '../utils/image'; +import { getMenuLinks } from '../scripts/settings/webSettings'; +import Dashboard, { pageClassOn } from '../utils/dashboard'; +import { PluginType } from '../types/plugin.ts'; +import Events from '../utils/events.ts'; +import { getParameterByName } from '../utils/url.ts'; +import datetime from '../scripts/datetime'; + +import '../elements/emby-button/paper-icon-button-light'; + +import 'material-design-icons-iconfont'; +import '../styles/scrollstyles.scss'; +import '../styles/flexstyles.scss'; + +function renderHeader() { + let html = ''; + html += '
'; + html += '
'; + html += ''; + html += ''; + html += ''; + html += ''; + html += '
'; + html += '
'; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + + skinHeader.classList.add('skinHeader-withBackground'); + skinHeader.classList.add('skinHeader-blurred'); + skinHeader.innerHTML = html; + + Events.trigger(document, EventType.HEADER_RENDERED); + + headerBackButton = skinHeader.querySelector('.headerBackButton'); + headerHomeButton = skinHeader.querySelector('.headerHomeButton'); + mainDrawerButton = skinHeader.querySelector('.mainDrawerButton'); + headerUserButton = skinHeader.querySelector('.headerUserButton'); + headerCastButton = skinHeader.querySelector('.headerCastButton'); + headerAudioPlayerButton = skinHeader.querySelector('.headerAudioPlayerButton'); + headerSearchButton = skinHeader.querySelector('.headerSearchButton'); + headerSyncButton = skinHeader.querySelector('.headerSyncButton'); + currentTimeText = skinHeader.querySelector('.currentTimeText'); + + retranslateUi(); + lazyLoadViewMenuBarImages(); + bindMenuEvents(); + updateCastIcon(); + updateClock(); +} + +function getCurrentApiClient() { + if (currentUser?.localUser) { + return ServerConnections.getApiClient(currentUser.localUser.ServerId); + } + + return ServerConnections.currentApiClient(); +} + +function lazyLoadViewMenuBarImages() { + import('../components/images/imageLoader').then((imageLoader) => { + imageLoader.lazyChildren(skinHeader); + }); +} + +function onBackClick() { + appRouter.back(); +} + +function retranslateUi() { + if (headerBackButton) { + headerBackButton.title = globalize.translate('ButtonBack'); + } + + if (headerHomeButton) { + headerHomeButton.title = globalize.translate('Home'); + } + + if (mainDrawerButton) { + mainDrawerButton.title = globalize.translate('Menu'); + } + + if (headerSyncButton) { + headerSyncButton.title = globalize.translate('ButtonSyncPlay'); + } + + if (headerAudioPlayerButton) { + headerAudioPlayerButton.title = globalize.translate('ButtonPlayer'); + } + + if (headerCastButton) { + headerCastButton.title = globalize.translate('ButtonCast'); + } + + if (headerSearchButton) { + headerSearchButton.title = globalize.translate('Search'); + } + + if (headerUserButton) { + headerUserButton.title = globalize.translate('Settings'); + } +} + +function updateUserInHeader(user) { + retranslateUi(); + + let hasImage; + + if (user?.name) { + if (user.imageUrl) { + const url = user.imageUrl; + updateHeaderUserButton(url); + hasImage = true; + } + headerUserButton.title = user.name; + headerUserButton.classList.remove('hide'); + } else { + headerUserButton.classList.add('hide'); + } + + if (!hasImage) { + updateHeaderUserButton(null); + } + + if (user?.localUser) { + if (headerHomeButton) { + headerHomeButton.classList.remove('hide'); + } + + if (headerSearchButton) { + headerSearchButton.classList.remove('hide'); + } + + if (!layoutManager.tv) { + headerCastButton.classList.remove('hide'); + } + + const policy = user.Policy ? user.Policy : user.localUser.Policy; + + if ( + // Button is present + headerSyncButton + // SyncPlay plugin is loaded + && pluginManager.ofType(PluginType.SyncPlay).length > 0 + // SyncPlay enabled for user + && policy?.SyncPlayAccess !== 'None' + ) { + headerSyncButton.classList.remove('hide'); + } + } else { + headerHomeButton.classList.add('hide'); + headerCastButton.classList.add('hide'); + headerSyncButton.classList.add('hide'); + + if (headerSearchButton) { + headerSearchButton.classList.add('hide'); + } + } + + requiresUserRefresh = false; +} + +function updateHeaderUserButton(src) { + if (src) { + headerUserButton.classList.add('headerUserButtonRound'); + headerUserButton.innerHTML = '
"; + } else { + headerUserButton.classList.remove('headerUserButtonRound'); + headerUserButton.innerHTML = ''; + } +} + +function updateClock() { + if (layoutManager.tv) { + currentTimeText.classList.remove('hide'); + setInterval(function() { + currentTimeText.innerText = datetime.getDisplayTime(new Date()); + }, 1000); + } else { + currentTimeText.classList.add('hide'); + } +} + +function showSearch() { + inputManager.handleCommand('search'); +} + +function onHeaderUserButtonClick() { + Dashboard.navigate('mypreferencesmenu'); +} + +function onHeaderHomeButtonClick() { + Dashboard.navigate('home'); +} + +function showAudioPlayer() { + return appRouter.showNowPlaying(); +} + +function bindMenuEvents() { + if (mainDrawerButton) { + mainDrawerButton.addEventListener('click', toggleMainDrawer); + } + + if (headerBackButton) { + headerBackButton.addEventListener('click', onBackClick); + } + + if (headerSearchButton) { + headerSearchButton.addEventListener('click', showSearch); + } + + headerUserButton.addEventListener('click', onHeaderUserButtonClick); + headerHomeButton.addEventListener('click', onHeaderHomeButtonClick); + + if (!layoutManager.tv) { + headerCastButton.addEventListener('click', onCastButtonClicked); + } + + headerAudioPlayerButton.addEventListener('click', showAudioPlayer); + headerSyncButton.addEventListener('click', onSyncButtonClicked); + + if (layoutManager.mobile) { + initHeadRoom(skinHeader); + } + Events.on(playbackManager, 'playbackstart', onPlaybackStart); + Events.on(playbackManager, 'playbackstop', onPlaybackStop); +} + +function onPlaybackStart() { + if (playbackManager.isPlayingAudio() && layoutManager.tv) { + headerAudioPlayerButton.classList.remove('hide'); + } else { + headerAudioPlayerButton.classList.add('hide'); + } +} + +function onPlaybackStop(e, stopInfo) { + if (stopInfo.nextMediaType != 'Audio') { + headerAudioPlayerButton.classList.add('hide'); + } +} + +function onCastButtonClicked() { + const btn = this; + + import('../components/playback/playerSelectionMenu').then((playerSelectionMenu) => { + playerSelectionMenu.show(btn); + }); +} + +function onSyncButtonClicked() { + const btn = this; + groupSelectionMenu.show(btn); +} + +function getItemHref(item, context) { + return appRouter.getRouteUrl(item, { + context: context + }); +} + +function toggleMainDrawer() { + if (navDrawerInstance.isVisible) { + closeMainDrawer(); + } else { + openMainDrawer(); + } +} + +function openMainDrawer() { + navDrawerInstance.open(); +} + +function onMainDrawerOpened() { + if (layoutManager.mobile) { + document.body.classList.add('bodyWithPopupOpen'); + } +} + +function closeMainDrawer() { + navDrawerInstance.close(); +} + +function onMainDrawerSelect() { + if (navDrawerInstance.isVisible) { + onMainDrawerOpened(); + } else { + document.body.classList.remove('bodyWithPopupOpen'); + } +} + +function refreshLibraryInfoInDrawer(user) { + let html = ''; + html += '
'; + html += `${globalize.translate('Home')}`; + + // placeholder for custom menu links +//durch Skript eingefügt - ANFANG + html += '

Links

'; + html += '[BETA] Chicanoflix'; + html += 'Wünsche'; + html += 'Telegram Channel'; +//durch Skript eingefügt - ENDE + + // libraries are added here + html += '
'; + + if (user.localUser?.Policy.IsAdministrator) { + html += '
'; + html += '

'; + html += globalize.translate('HeaderAdmin'); + html += '

'; + html += `${globalize.translate('TabDashboard')}`; + html += `${globalize.translate('MetadataManager')}`; + html += '
'; + } + + if (user.localUser) { + html += '
'; + html += '

'; + html += globalize.translate('HeaderUser'); + html += '

'; + + if (appHost.supports(AppFeature.MultiServer)) { + html += `${globalize.translate('SelectServer')}`; + } + + html += `${globalize.translate('Settings')}`; + html += `${globalize.translate('ButtonSignOut')}`; + + if (appHost.supports(AppFeature.ExitMenu)) { + html += `${globalize.translate('ButtonExitApp')}`; + } + + html += '
'; + } + + // add buttons to navigation drawer + navDrawerScrollContainer.innerHTML = html; + + const btnSelectServer = navDrawerScrollContainer.querySelector('.btnSelectServer'); + if (btnSelectServer) { + btnSelectServer.addEventListener('click', onSelectServerClick); + } + + const btnSettings = navDrawerScrollContainer.querySelector('.btnSettings'); + if (btnSettings) { + btnSettings.addEventListener('click', onSettingsClick); + } + + const btnExit = navDrawerScrollContainer.querySelector('.exitApp'); + if (btnExit) { + btnExit.addEventListener('click', onExitAppClick); + } + + const btnLogout = navDrawerScrollContainer.querySelector('.btnLogout'); + if (btnLogout) { + btnLogout.addEventListener('click', onLogoutClick); + } +} + +function onSidebarLinkClick() { + const section = this.getElementsByClassName('sectionName')[0]; + const text = section ? section.innerHTML : this.innerHTML; + LibraryMenu.setTitle(text); +} + +function getUserViews(apiClient, userId) { + return queryClient + .fetchQuery(getUserViewsQuery(toApi(apiClient), userId)) + .then(function (result) { + const items = result.Items; + const list = []; + + for (let i = 0, length = items.length; i < length; i++) { + const view = items[i]; + list.push(view); + + if (view.CollectionType == 'livetv') { + view.icon = 'live_tv'; + const guideView = Object.assign({}, view); + guideView.Name = globalize.translate('Guide'); + guideView.ImageTags = {}; + guideView.icon = 'dvr'; + guideView.url = '#/livetv?tab=1'; + list.push(guideView); + } + } + + return list; + }); +} + +function showBySelector(selector, show) { + const elem = document.querySelector(selector); + + if (elem) { + if (show) { + elem.classList.remove('hide'); + } else { + elem.classList.add('hide'); + } + } +} + +function updateLibraryMenu(user) { + if (!user) { + showBySelector('.userMenuOptions', false); + return; + } + + const userId = Dashboard.getCurrentUserId(); + const apiClient = getCurrentApiClient(); + + const customMenuOptions = document.querySelector('.customMenuOptions'); + if (customMenuOptions) { + getMenuLinks().then(links => { + links.forEach(link => { + const option = document.createElement('a', 'emby-linkbutton'); + option.classList.add('navMenuOption', 'lnkMediaFolder'); + option.rel = 'noopener noreferrer'; + option.target = '_blank'; + option.href = link.url; + + const icon = document.createElement('span'); + icon.className = `material-icons navMenuOptionIcon ${link.icon || 'link'}`; + icon.setAttribute('aria-hidden', 'true'); + option.appendChild(icon); + + const label = document.createElement('span'); + label.className = 'navMenuOptionText'; + label.textContent = link.name; + option.appendChild(label); + + customMenuOptions.appendChild(option); + }); + }); + } + + const libraryMenuOptions = document.querySelector('.libraryMenuOptions'); + + if (libraryMenuOptions) { + getUserViews(apiClient, userId).then(function (result) { + const items = result; + let html = `

${globalize.translate('HeaderMedia')}

`; + html += items.map(function (i) { + const icon = i.icon || imageHelper.getLibraryIcon(i.CollectionType); + const itemId = i.Id; + + return ` + + ${escapeHtml(i.Name)} + `; + }).join(''); + libraryMenuOptions.innerHTML = html; + const elem = libraryMenuOptions; + const sidebarLinks = elem.querySelectorAll('.navMenuOption'); + + for (const sidebarLink of sidebarLinks) { + sidebarLink.removeEventListener('click', onSidebarLinkClick); + sidebarLink.addEventListener('click', onSidebarLinkClick); + } + }); + } +} + +function getTopParentId() { + return getParameterByName('topParentId') || null; +} + +function onMainDrawerClick(e) { + if (dom.parentWithTag(e.target, 'A')) { + setTimeout(closeMainDrawer, 30); + } +} + +function onSelectServerClick() { + Dashboard.selectServer(); +} + +function onSettingsClick() { + Dashboard.navigate('mypreferencesmenu'); +} + +function onExitAppClick() { + appHost.exit(); +} + +function onLogoutClick() { + Dashboard.logout(); +} + +function updateCastIcon() { + const context = document; + const info = playbackManager.getPlayerInfo(); + const icon = headerCastButton.querySelector('.material-icons'); + + icon.classList.remove('cast_connected', 'cast'); + + if (info && !info.isLocalPlayer) { + icon.classList.add('cast_connected'); + headerCastButton.classList.add('castButton-active'); + context.querySelector('.headerSelectedPlayer').innerText = info.deviceName || info.name; + } else { + icon.classList.add('cast'); + headerCastButton.classList.remove('castButton-active'); + context.querySelector('.headerSelectedPlayer').innerHTML = ''; + } +} + +function updateLibraryNavLinks(page) { + const isLiveTvPage = page.classList.contains('liveTvPage'); + const isChannelsPage = page.classList.contains('channelsPage'); + const isEditorPage = page.classList.contains('metadataEditorPage'); + const isMySyncPage = page.classList.contains('mySyncPage'); + const id = isLiveTvPage || isChannelsPage || isEditorPage || isMySyncPage || page.classList.contains('allLibraryPage') ? '' : getTopParentId() || ''; + const elems = document.getElementsByClassName('lnkMediaFolder'); + + for (let i = 0, length = elems.length; i < length; i++) { + const lnkMediaFolder = elems[i]; + const itemId = lnkMediaFolder.getAttribute('data-itemid'); + + if (isChannelsPage && itemId === 'channels') { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (isLiveTvPage && itemId === 'livetv') { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (isEditorPage && itemId === 'editor') { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (isMySyncPage && itemId === 'manageoffline' && window.location.href.toString().indexOf('mode=download') != -1) { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (isMySyncPage && itemId === 'syncotherdevices' && window.location.href.toString().indexOf('mode=download') == -1) { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else if (id && itemId == id) { + lnkMediaFolder.classList.add('navMenuOption-selected'); + } else { + lnkMediaFolder.classList.remove('navMenuOption-selected'); + } + } +} + +function updateMenuForPageType(isDashboardPage, isLibraryPage) { + let newPageType = 3; + if (isDashboardPage) { + newPageType = 2; + } else if (isLibraryPage) { + newPageType = 1; + } + + if (currentPageType !== newPageType) { + currentPageType = newPageType; + + if (isDashboardPage && !layoutManager.mobile) { + skinHeader.classList.add('headroomDisabled'); + } else { + skinHeader.classList.remove('headroomDisabled'); + } + + const bodyClassList = document.body.classList; + + if (isLibraryPage) { + bodyClassList.add('libraryDocument'); + bodyClassList.remove('hideMainDrawer'); + + if (navDrawerInstance) { + navDrawerInstance.setEdgeSwipeEnabled(true); + } + } else if (isDashboardPage) { + bodyClassList.remove('libraryDocument'); + bodyClassList.remove('hideMainDrawer'); + + if (navDrawerInstance) { + navDrawerInstance.setEdgeSwipeEnabled(true); + } + } else { + bodyClassList.remove('libraryDocument'); + bodyClassList.add('hideMainDrawer'); + + if (navDrawerInstance) { + navDrawerInstance.setEdgeSwipeEnabled(false); + } + } + } + + if (requiresUserRefresh) { + ServerConnections.user(getCurrentApiClient()).then(updateUserInHeader); + } +} + +function updateTitle(page) { + const title = page.getAttribute('data-title'); + + if (title) { + LibraryMenu.setTitle(title); + } else if (page.classList.contains('standalonePage')) { + LibraryMenu.setDefaultTitle(); + } +} + +function updateBackButton(page) { + if (headerBackButton) { + if (page.getAttribute('data-backbutton') !== 'false' && appRouter.canGoBack()) { + headerBackButton.classList.remove('hide'); + } else { + headerBackButton.classList.add('hide'); + } + } +} + +function initHeadRoom(elem) { + const headroom = new Headroom(elem); + headroom.init(); +} + +function refreshLibraryDrawer(user) { + loadNavDrawer(); + currentDrawerType = 'library'; + + if (user) { + Promise.resolve(user); + } else { + ServerConnections.user(getCurrentApiClient()).then(function (userResult) { + refreshLibraryInfoInDrawer(userResult); + updateLibraryMenu(userResult.localUser); + }); + } +} + +function getNavDrawerOptions() { + let drawerWidth = window.screen.availWidth - 50; + drawerWidth = Math.max(drawerWidth, 240); + drawerWidth = Math.min(drawerWidth, 320); + return { + target: navDrawerElement, + onChange: onMainDrawerSelect, + width: drawerWidth + }; +} + +function loadNavDrawer() { + if (navDrawerInstance) { + return Promise.resolve(navDrawerInstance); + } + + navDrawerElement = document.querySelector('.mainDrawer'); + navDrawerScrollContainer = navDrawerElement.querySelector('.scrollContainer'); + navDrawerScrollContainer.addEventListener('click', onMainDrawerClick); + return new Promise(function (resolve) { + import('../lib/navdrawer/navdrawer').then(({ default: NavDrawer }) => { + navDrawerInstance = new NavDrawer(getNavDrawerOptions()); + + if (!layoutManager.tv) { + navDrawerElement.classList.remove('hide'); + } + + resolve(navDrawerInstance); + }); + }); +} + +let navDrawerElement; +let navDrawerScrollContainer; +let navDrawerInstance; +let mainDrawerButton; +let headerHomeButton; +let currentDrawerType; +let documentTitle = 'Jellyfin'; +let pageTitleElement; +let headerBackButton; +let headerUserButton; +let currentUser; +let headerCastButton; +let headerSearchButton; +let headerAudioPlayerButton; +let headerSyncButton; +let currentTimeText; +const enableLibraryNavDrawer = layoutManager.desktop; +const enableLibraryNavDrawerHome = !layoutManager.tv; +const skinHeader = document.querySelector('.skinHeader'); +let requiresUserRefresh = true; + +function setTabs (type, selectedIndex, builder) { + Events.trigger(document, EventType.SET_TABS, type ? [ type, selectedIndex, builder()] : []); + + import('../components/maintabsmanager').then((mainTabsManager) => { + if (type) { + mainTabsManager.setTabs(viewManager.currentView(), selectedIndex, builder, function () { + return []; + }); + } else { + mainTabsManager.setTabs(null); + } + }); +} + +/** + * Fetch the server name and update the document title. + * @param {ApiClient} [_apiClient] The current api client. + */ +const fetchServerName = (_apiClient) => { + _apiClient + ?.getPublicSystemInfo() + .then(({ ServerName }) => { + documentTitle = ServerName || documentTitle; + document.title = documentTitle; + }) + .catch(err => { + console.error('[LibraryMenu] failed to fetch system info', err); + }); +}; + +function setDefaultTitle () { + if (!pageTitleElement) { + pageTitleElement = document.querySelector('.pageTitle'); + } + + if (pageTitleElement) { + pageTitleElement.classList.add('pageTitleWithLogo'); + pageTitleElement.classList.add('pageTitleWithDefaultLogo'); + pageTitleElement.style.backgroundImage = null; + pageTitleElement.innerHTML = ''; + } + + document.title = documentTitle; +} + +function setTitle (title) { + if (title == null) { + LibraryMenu.setDefaultTitle(); + return; + } + + if (title === '-') { + title = ''; + } + + const html = title; + + if (!pageTitleElement) { + pageTitleElement = document.querySelector('.pageTitle'); + } + + if (pageTitleElement) { + pageTitleElement.classList.remove('pageTitleWithLogo'); + pageTitleElement.classList.remove('pageTitleWithDefaultLogo'); + pageTitleElement.style.backgroundImage = null; + pageTitleElement.innerText = html || ''; + } + + document.title = title || documentTitle; +} + +function setTransparentMenu (transparent) { + if (transparent) { + skinHeader.classList.add('semiTransparent'); + } else { + skinHeader.classList.remove('semiTransparent'); + } +} + +let currentPageType; +pageClassOn('pagebeforeshow', 'page', function () { + if (!this.classList.contains('withTabs')) { + LibraryMenu.setTabs(null); + } +}); + +pageClassOn('pageshow', 'page', function (e) { + const page = this; + const isDashboardPage = page.classList.contains('type-interior'); + const isHomePage = page.classList.contains('homePage'); + const isLibraryPage = !isDashboardPage && page.classList.contains('libraryPage'); + + if (!isDashboardPage) { + if (mainDrawerButton) { + if (enableLibraryNavDrawer || (isHomePage && enableLibraryNavDrawerHome)) { + mainDrawerButton.classList.remove('hide'); + } else { + mainDrawerButton.classList.add('hide'); + } + } + + if (currentDrawerType !== 'library') { + refreshLibraryDrawer(); + } + } + + updateMenuForPageType(isDashboardPage, isLibraryPage); + + // TODO: Seems to do nothing? Check if needed (also in other views). + if (!e.detail.isRestored) { + window.scrollTo(0, 0); + } + + updateTitle(page); + updateBackButton(page); + updateLibraryNavLinks(page); +}); + +Events.on(ServerConnections, 'apiclientcreated', (e, newApiClient) => { + fetchServerName(newApiClient); +}); + +Events.on(ServerConnections, 'localusersignedin', function (e, user) { + const currentApiClient = ServerConnections.getApiClient(user.ServerId); + + currentDrawerType = null; + currentUser = { + localUser: user + }; + + loadNavDrawer(); + + ServerConnections.user(currentApiClient).then(function (userResult) { + currentUser = userResult; + updateUserInHeader(userResult); + }); +}); + +Events.on(ServerConnections, 'localusersignedout', function () { + currentUser = {}; + updateUserInHeader(); +}); + +Events.on(playbackManager, 'playerchange', updateCastIcon); + +fetchServerName(getCurrentApiClient()); +loadNavDrawer(); + +const LibraryMenu = { + getTopParentId, + onHardwareMenuButtonClick: function () { + toggleMainDrawer(); + }, + setTabs, + setDefaultTitle, + setTitle, + setTransparentMenu +}; + +window.LibraryMenu = LibraryMenu; +renderHeader(); + +export default LibraryMenu; diff --git a/vorlagen/custom_links_insert b/vorlagen/custom_links_insert new file mode 100755 index 0000000..3cf9179 --- /dev/null +++ b/vorlagen/custom_links_insert @@ -0,0 +1,6 @@ +//durch Skript eingefügt - ANFANG + html += '

Links

'; + html += '[BETA] Chicanoflix'; + html += 'Wünsche'; + html += 'Telegram Channel'; +//durch Skript eingefügt - ENDE diff --git a/vorlagen/index.manuell b/vorlagen/index.manuell new file mode 100755 index 0000000..2f0738e --- /dev/null +++ b/vorlagen/index.manuell @@ -0,0 +1,23 @@ + + + +