diff --git a/api/src/unraid-api/graph/resolvers/customization/customization.service.spec.ts b/api/src/unraid-api/graph/resolvers/customization/customization.service.spec.ts index feae194caf..b719b0e60c 100644 --- a/api/src/unraid-api/graph/resolvers/customization/customization.service.spec.ts +++ b/api/src/unraid-api/graph/resolvers/customization/customization.service.spec.ts @@ -3,6 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import * as fs from 'fs/promises'; import * as path from 'path'; +import type { Mock } from 'vitest'; import { plainToInstance } from 'class-transformer'; import * as ini from 'ini'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; @@ -1182,4 +1183,58 @@ describe('CustomizationService - updateCfgFile', () => { writeError ); }); + + describe('getTheme', () => { + const mockDynamix = getters.dynamix as unknown as Mock; + const baseDisplay = { + theme: 'white', + banner: '', + showBannerGradient: 'no', + background: '123456', + headerdescription: 'yes', + headermetacolor: '789abc', + header: 'abcdef', + }; + + const setDisplay = (overrides: Partial) => { + mockDynamix.mockReturnValue({ + display: { + ...baseDisplay, + ...overrides, + }, + }); + }; + + it('reports showBannerImage when banner is "image"', async () => { + setDisplay({ banner: 'image' }); + + const theme = await service.getTheme(); + + expect(theme.showBannerImage).toBe(true); + }); + + it('reports showBannerImage when banner is "yes"', async () => { + setDisplay({ banner: 'yes' }); + + const theme = await service.getTheme(); + + expect(theme.showBannerImage).toBe(true); + }); + + it('disables showBannerImage when banner is empty', async () => { + setDisplay({ banner: '' }); + + const theme = await service.getTheme(); + + expect(theme.showBannerImage).toBe(false); + }); + + it('mirrors showBannerGradient flag from display settings', async () => { + setDisplay({ banner: 'image', showBannerGradient: 'yes' }); + expect((await service.getTheme()).showBannerGradient).toBe(true); + + setDisplay({ banner: 'image', showBannerGradient: 'no' }); + expect((await service.getTheme()).showBannerGradient).toBe(false); + }); + }); }); diff --git a/api/src/unraid-api/graph/resolvers/customization/customization.service.ts b/api/src/unraid-api/graph/resolvers/customization/customization.service.ts index be008c42a4..5b27356e81 100644 --- a/api/src/unraid-api/graph/resolvers/customization/customization.service.ts +++ b/api/src/unraid-api/graph/resolvers/customization/customization.service.ts @@ -458,7 +458,7 @@ export class CustomizationService implements OnModuleInit { return { name, - showBannerImage: banner === 'yes', + showBannerImage: banner === 'image' || banner === 'yes', showBannerGradient: bannerGradient === 'yes', headerBackgroundColor: this.addHashtoHexField(bgColor), headerPrimaryTextColor: this.addHashtoHexField(textColor), diff --git a/web/src/assets/main.css b/web/src/assets/main.css index a4221aec12..dea0c1086f 100644 --- a/web/src/assets/main.css +++ b/web/src/assets/main.css @@ -156,3 +156,42 @@ iframe#progressFrame { background-color: var(--background-color); color-scheme: light; } + +/* Header banner compatibility tweaks */ +#header.image { + background-position: center center; + background-repeat: no-repeat; + background-size: cover; +} + +.has-banner-gradient #header.image { + position: relative; + overflow: hidden; +} + +.has-banner-gradient #header.image::before { + content: ''; + position: absolute; + inset: 0; + pointer-events: none; + background-repeat: no-repeat; + background-position: left center, right center; + background-size: min(30%, 320px) 100%, min(30%, 320px) 100%; + background-image: + linear-gradient( + 90deg, + var(--color-header-gradient-end, rgba(0, 0, 0, 0.7)) 0%, + var(--color-header-gradient-start, rgba(0, 0, 0, 0)) 100% + ), + linear-gradient( + 270deg, + var(--color-header-gradient-end, rgba(0, 0, 0, 0.7)) 0%, + var(--color-header-gradient-start, rgba(0, 0, 0, 0)) 100% + ); + z-index: 0; +} + +.has-banner-gradient #header.image > * { + position: relative; + z-index: 1; +} diff --git a/web/src/components/UserProfile.standalone.vue b/web/src/components/UserProfile.standalone.vue index 711d3bc0e4..609ab906cd 100644 --- a/web/src/components/UserProfile.standalone.vue +++ b/web/src/components/UserProfile.standalone.vue @@ -94,11 +94,11 @@ onMounted(() => {