diff --git a/frontend/src/app/components/fees-box/fees-box.component.ts b/frontend/src/app/components/fees-box/fees-box.component.ts index a1c8e7698..b0686ab2e 100644 --- a/frontend/src/app/components/fees-box/fees-box.component.ts +++ b/frontend/src/app/components/fees-box/fees-box.component.ts @@ -44,10 +44,13 @@ export class FeesBoxComponent implements OnInit, OnDestroy { ); this.themeSubscription = this.themeService.themeChanged$.subscribe(() => { this.setFeeGradient(); - }) + }); } setFeeGradient() { + if (!this.fees || !this.themeService.mempoolFeeColors) { + return; + } let feeLevelIndex = feeLevels.slice().reverse().findIndex((feeLvl) => this.fees.minimumFee >= feeLvl); feeLevelIndex = feeLevelIndex >= 0 ? feeLevels.length - feeLevelIndex : feeLevelIndex; const startColor = '#' + (this.themeService.mempoolFeeColors[feeLevelIndex - 1] || this.themeService.mempoolFeeColors[this.themeService.mempoolFeeColors.length - 1]); diff --git a/frontend/src/app/services/theme.service.ts b/frontend/src/app/services/theme.service.ts index 6ed9c1027..2453acf05 100644 --- a/frontend/src/app/services/theme.service.ts +++ b/frontend/src/app/services/theme.service.ts @@ -8,7 +8,7 @@ import { StateService } from '@app/services/state.service'; providedIn: 'root' }) export class ThemeService { - style: HTMLLinkElement; + style: HTMLLinkElement | null = null; theme: string = 'default'; themeChanged$: Subject = new Subject(); mempoolFeeColors: string[] = defaultMempoolFeeColors; @@ -17,20 +17,32 @@ export class ThemeService { private storageService: StorageService, private stateService: StateService, ) { - const theme = this.stateService.env.customize?.theme || this.storageService.getValue('theme-preference') || 'default'; + let theme = this.stateService.env.customize?.theme || this.storageService.getValue('theme-preference') || 'default'; + // theme preference must be a valid known public theme + if (!this.stateService.env.customize?.theme && !['default', 'contrast', 'softsimon'].includes(theme)) { + theme = 'default'; + this.storageService.setValue('theme-preference', 'default'); + } this.apply(theme); } - apply(theme) { + apply(theme: string): void { + if (this.theme === theme) { + return; + } + this.theme = theme; if (theme !== 'default') { - theme === 'contrast' || theme === 'bukele' ? this.mempoolFeeColors = contrastMempoolFeeColors : this.mempoolFeeColors = defaultMempoolFeeColors; + this.mempoolFeeColors = (theme === 'contrast' || theme === 'bukele') ? contrastMempoolFeeColors : defaultMempoolFeeColors; try { if (!this.style) { this.style = document.createElement('link'); this.style.rel = 'stylesheet'; this.style.href = `${theme}.css`; - document.head.appendChild(this.style); + this.style.onerror = (): void => { // something went wrong (eg the css resource does not exist, revert to default) + this.apply('default'); + }; + document.head.appendChild(this.style); // load the css now } else { this.style.href = `${theme}.css`; }