diff --git a/package-lock.json b/package-lock.json index 761e22009..b33d3b7ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@fontsource/noto-sans-tc": "5.2.5", "@jellyfin/libass-wasm": "4.2.3", "@jellyfin/sdk": "0.0.0-unstable.202504100501", + "@jellyfin/ux-web": "1.0.0", "@mui/icons-material": "6.4.10", "@mui/material": "6.4.10", "@mui/x-date-pickers": "7.28.2", @@ -4097,6 +4098,11 @@ "axios": "^1.3.4" } }, + "node_modules/@jellyfin/ux-web": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jellyfin/ux-web/-/ux-web-1.0.0.tgz", + "integrity": "sha512-3uBl/CMkWBsL2aD5xmg5qEQcN57ZJE/d5JktbwxXgWPrfa9A6KltivvcEltY4zVyT6btGgLy7sKmtFyu6gQ7dw==" + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -24604,9 +24610,9 @@ } }, "node_modules/tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "devOptional": true }, "node_modules/tunnel-agent": { @@ -28558,6 +28564,11 @@ "integrity": "sha512-Qpmn8+TQz//EJjkhcXmhq5cytcIsQhxRQz943udlKoRXbz9UdnnMq/VUngMg+F+FHbDM1TTpb3h1Ki3tCH/HFw==", "requires": {} }, + "@jellyfin/ux-web": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jellyfin/ux-web/-/ux-web-1.0.0.tgz", + "integrity": "sha512-3uBl/CMkWBsL2aD5xmg5qEQcN57ZJE/d5JktbwxXgWPrfa9A6KltivvcEltY4zVyT6btGgLy7sKmtFyu6gQ7dw==" + }, "@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -42679,9 +42690,9 @@ } }, "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "devOptional": true }, "tunnel-agent": { diff --git a/package.json b/package.json index 6863ada04..78335b2f2 100644 --- a/package.json +++ b/package.json @@ -85,6 +85,7 @@ "@fontsource/noto-sans-tc": "5.2.5", "@jellyfin/libass-wasm": "4.2.3", "@jellyfin/sdk": "0.0.0-unstable.202504100501", + "@jellyfin/ux-web": "1.0.0", "@mui/icons-material": "6.4.10", "@mui/material": "6.4.10", "@mui/x-date-pickers": "7.28.2", diff --git a/src/apps/experimental/components/drawers/DrawerHeaderLink.tsx b/src/apps/experimental/components/drawers/DrawerHeaderLink.tsx index 7f9b14206..f60a87fef 100644 --- a/src/apps/experimental/components/drawers/DrawerHeaderLink.tsx +++ b/src/apps/experimental/components/drawers/DrawerHeaderLink.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { useSystemInfo } from 'hooks/useSystemInfo'; import ListItemLink from 'components/ListItemLink'; -import appIcon from 'assets/img/icon-transparent.png'; +import appIcon from '@jellyfin/ux-web/icon-transparent.png'; const DrawerHeaderLink = () => { const { data: systemInfo } = useSystemInfo(); diff --git a/src/assets/img/banner-dark.png b/src/assets/img/banner-dark.png deleted file mode 100644 index 7189aac21..000000000 Binary files a/src/assets/img/banner-dark.png and /dev/null differ diff --git a/src/assets/img/banner-light.png b/src/assets/img/banner-light.png deleted file mode 100644 index 769801160..000000000 Binary files a/src/assets/img/banner-light.png and /dev/null differ diff --git a/src/assets/img/icon-transparent.png b/src/assets/img/icon-transparent.png deleted file mode 100644 index 76ef75baf..000000000 Binary files a/src/assets/img/icon-transparent.png and /dev/null differ diff --git a/src/favicon.ico b/src/favicon.ico deleted file mode 100644 index a127e27d4..000000000 Binary files a/src/favicon.ico and /dev/null differ diff --git a/src/favicon.png b/src/favicon.png deleted file mode 100644 index 7300170d9..000000000 Binary files a/src/favicon.png and /dev/null differ diff --git a/src/index.html b/src/index.html index 550cec1ec..fca71a44a 100644 --- a/src/index.html +++ b/src/index.html @@ -15,9 +15,9 @@ - - - + + + Jellyfin @@ -80,37 +80,6 @@ [dir="rtl"] .mainDrawerHandle { left: 0; } - - @keyframes fadein { - from { - opacity: 0; - } - - to { - opacity: 1; - } - } - - .splashLogo { - animation: fadein 0.5s; - width: 30%; - height: 30%; - background-image: url(assets/img/icon-transparent.png); - background-position: center center; - background-repeat: no-repeat; - background-size: contain; - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - @media screen - and (min-device-width: 992px) { - .splashLogo { - background-image: url(assets/img/banner-light.png); - } - } diff --git a/src/manifest.json b/src/manifest.json index 1e8f9dd71..144f32840 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -10,22 +10,22 @@ "icons": [ { "sizes": "72x72", - "src": "touchicon72.png", + "src": "favicons/touchicon72.png", "type": "image/png" }, { "sizes": "114x114", - "src": "touchicon114.png", + "src": "favicons/touchicon114.png", "type": "image/png" }, { "sizes": "144x144", - "src": "touchicon144.png", + "src": "favicons/touchicon144.png", "type": "image/png" }, { "sizes": "512x512", - "src": "touchicon512.png", + "src": "favicons/touchicon512.png", "type": "image/png" } ] diff --git a/src/plugins/logoScreensaver/plugin.js b/src/plugins/logoScreensaver/plugin.js index 06d643d77..37535d0ff 100644 --- a/src/plugins/logoScreensaver/plugin.js +++ b/src/plugins/logoScreensaver/plugin.js @@ -1,3 +1,5 @@ +import icon from '@jellyfin/ux-web/icon-transparent.png'; + import { PluginType } from '../../types/plugin.ts'; import { randomInt } from '../../utils/number.ts'; @@ -133,7 +135,7 @@ export default function () { elem.classList.add('logoScreenSaver'); document.body.appendChild(elem); - elem.innerHTML = ''; + elem.innerHTML = ``; } stopInterval(); diff --git a/src/styles/site.scss b/src/styles/site.scss index 429305b7d..3cb2d1fe7 100644 --- a/src/styles/site.scss +++ b/src/styles/site.scss @@ -4,6 +4,37 @@ height: 100%; } +@keyframes fadein { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.splashLogo { + animation: fadein 0.5s; + width: 30%; + height: 30%; + background-image: url(@jellyfin/ux-web/icon-transparent.png); + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +@media screen + and (min-device-width: 992px) { + .splashLogo { + background-image: url(@jellyfin/ux-web/banner-light.png); + } +} + html { @include fullpage; line-height: 1.35; diff --git a/src/themes/appletv/theme.scss b/src/themes/appletv/theme.scss index bee10ed5f..71cbabcd9 100644 --- a/src/themes/appletv/theme.scss +++ b/src/themes/appletv/theme.scss @@ -35,11 +35,11 @@ html { } .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/banner-dark.png); + background-image: url(@jellyfin/ux-web/banner-dark.png); } .layout-tv .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/icon-transparent.png); + background-image: url(@jellyfin/ux-web/icon-transparent.png); } html { diff --git a/src/themes/blueradiance/theme.scss b/src/themes/blueradiance/theme.scss index aabfaba6b..c6d0d7c68 100644 --- a/src/themes/blueradiance/theme.scss +++ b/src/themes/blueradiance/theme.scss @@ -35,11 +35,11 @@ html { } .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/banner-light.png); + background-image: url(@jellyfin/ux-web/banner-light.png); } .layout-tv .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/icon-transparent.png); + background-image: url(@jellyfin/ux-web/icon-transparent.png); } .dialog, diff --git a/src/themes/dark/theme.scss b/src/themes/dark/theme.scss index f7447c4c8..f055a4cfc 100644 --- a/src/themes/dark/theme.scss +++ b/src/themes/dark/theme.scss @@ -34,11 +34,11 @@ html { } .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/banner-light.png); + background-image: url(@jellyfin/ux-web/banner-light.png); } .layout-tv .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/icon-transparent.png); + background-image: url(@jellyfin/ux-web/icon-transparent.png); } .backgroundContainer, diff --git a/src/themes/light/theme.scss b/src/themes/light/theme.scss index feedf23a1..f0235dc97 100644 --- a/src/themes/light/theme.scss +++ b/src/themes/light/theme.scss @@ -44,11 +44,11 @@ html { } .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/banner-light.png); + background-image: url(@jellyfin/ux-web/banner-light.png); } .layout-tv .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/icon-transparent.png); + background-image: url(@jellyfin/ux-web/icon-transparent.png); } .backgroundContainer, diff --git a/src/themes/purplehaze/theme.scss b/src/themes/purplehaze/theme.scss index 87e4f7cc3..5e47b2353 100644 --- a/src/themes/purplehaze/theme.scss +++ b/src/themes/purplehaze/theme.scss @@ -31,11 +31,11 @@ html { } .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/banner-light.png); + background-image: url(@jellyfin/ux-web/banner-light.png); } .layout-tv .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/icon-transparent.png); + background-image: url(@jellyfin/ux-web/icon-transparent.png); } .dialog, diff --git a/src/themes/wmc/theme.scss b/src/themes/wmc/theme.scss index 5d62369a8..2749ca1cf 100644 --- a/src/themes/wmc/theme.scss +++ b/src/themes/wmc/theme.scss @@ -41,11 +41,11 @@ html { } .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/banner-light.png); + background-image: url(@jellyfin/ux-web/banner-light.png); } .layout-tv .pageTitleWithDefaultLogo { - background-image: url(../../assets/img/icon-transparent.png); + background-image: url(@jellyfin/ux-web/icon-transparent.png); } .backgroundContainer, diff --git a/src/touchicon.png b/src/touchicon.png deleted file mode 100644 index 8ad4ee0af..000000000 Binary files a/src/touchicon.png and /dev/null differ diff --git a/src/touchicon114.png b/src/touchicon114.png deleted file mode 100644 index 1a04cfa87..000000000 Binary files a/src/touchicon114.png and /dev/null differ diff --git a/src/touchicon144.png b/src/touchicon144.png deleted file mode 100644 index 87081ec3f..000000000 Binary files a/src/touchicon144.png and /dev/null differ diff --git a/src/touchicon512.png b/src/touchicon512.png deleted file mode 100644 index a253b46e1..000000000 Binary files a/src/touchicon512.png and /dev/null differ diff --git a/src/touchicon72.png b/src/touchicon72.png deleted file mode 100644 index dfefc075f..000000000 Binary files a/src/touchicon72.png and /dev/null differ diff --git a/webpack.common.js b/webpack.common.js index b66f0b761..4fa50976f 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -80,35 +80,24 @@ const config = { new CopyPlugin({ patterns: [ { - from: 'assets/**', - globOptions: { - dot: true, - ignore: ['**/css/*'] - } + from: 'assets', + to: 'assets' }, + 'config.json', + 'robots.txt', { - from: '*.*', - globOptions: { - dot: true, - ignore: [ - '**.js', - '**.jsx', - '**.html', - '**.ts', - '**.tsx' - ] - } - } + from: 'touchicon*.png', + context: path.resolve(__dirname, 'node_modules/@jellyfin/ux-web/favicons'), + to: 'favicons' + }, + ...Assets.map(asset => { + return { + from: path.resolve(__dirname, `node_modules/${asset}`), + to: 'libraries' + }; + }) ] }), - new CopyPlugin({ - patterns: Assets.map(asset => { - return { - from: path.resolve(__dirname, `./node_modules/${asset}`), - to: path.resolve(__dirname, './dist/libraries') - }; - }) - }), // The libarchive.js worker-bundle is copied manually. // If it is automatically bundled, escheck will fail since it uses import.meta.url. new IgnorePlugin({ @@ -139,7 +128,7 @@ const config = { if (pathData.filename.startsWith('assets/') || pathData.filename.startsWith('themes/')) { return '[path][base][query]'; } - return '[hash][ext][query]'; + return '[name].[hash][ext][query]'; }, path: path.resolve(__dirname, 'dist'), publicPath: '' @@ -359,7 +348,7 @@ const config = { ] }, { - test: /\.(png|jpg|gif|svg)$/i, + test: /\.(ico|png|jpg|gif|svg)$/i, type: 'asset/resource' }, {