mempool/frontend/src/app/services/theme.service.ts

108 lines
3.1 KiB
TypeScript
Raw Normal View History

2023-01-02 12:26:10 -06:00
import { Injectable } from '@angular/core';
import { audit, Subject } from 'rxjs';
import { Color } from '../components/block-overview-graph/sprite-types';
import { defaultMempoolFeeColors, contrastMempoolFeeColors } from '../app.constants';
import { StorageService } from './storage.service';
const defaultAuditColors = {
censored: hexToColor('f344df'),
missing: darken(desaturate(hexToColor('f344df'), 0.3), 0.7),
added: hexToColor('0099ff'),
selected: darken(desaturate(hexToColor('0099ff'), 0.3), 0.7),
};
const contrastAuditColors = {
censored: hexToColor('ffa8ff'),
missing: darken(desaturate(hexToColor('ffa8ff'), 0.3), 0.7),
added: hexToColor('00bb98'),
selected: darken(desaturate(hexToColor('00bb98'), 0.3), 0.7),
};
@Injectable({
providedIn: 'root'
})
export class ThemeService {
style: HTMLLinkElement;
theme: string = 'default';
themeChanged$: Subject<string> = new Subject();
mempoolFeeColors: string[] = defaultMempoolFeeColors;
/* block visualization colors */
defaultHoverColor: Color;
feeColors: Color[];
auditFeeColors: Color[];
auditColors: { [category: string]: Color } = defaultAuditColors;
constructor(
private storageService: StorageService,
) {
const theme = this.storageService.getValue('theme-preference') || 'default';
this.apply(theme);
}
apply(theme) {
this.theme = theme;
if (theme !== 'default') {
if (theme === 'contrast') {
this.mempoolFeeColors = contrastMempoolFeeColors;
this.auditColors = contrastAuditColors;
}
2023-01-03 05:24:14 -06:00
try {
if (!this.style) {
this.style = document.createElement('link');
this.style.rel = 'stylesheet';
this.style.href = `${theme}.css`;
document.head.appendChild(this.style);
} else {
this.style.href = `${theme}.css`;
}
} catch (err) {
console.log('failed to apply theme stylesheet: ', err);
2023-01-02 12:26:10 -06:00
}
} else {
this.mempoolFeeColors = defaultMempoolFeeColors;
this.auditColors = defaultAuditColors;
if (this.style) {
this.style.remove();
this.style = null;
}
}
this.updateFeeColors();
this.storageService.setValue('theme-preference', theme);
this.themeChanged$.next(this.theme);
}
updateFeeColors() {
this.defaultHoverColor = hexToColor('1bd8f4');
this.feeColors = this.mempoolFeeColors.map(hexToColor);
this.auditFeeColors = this.feeColors.map((color) => darken(desaturate(color, 0.3), 0.9));
}
}
export function hexToColor(hex: string): Color {
return {
r: parseInt(hex.slice(0, 2), 16) / 255,
g: parseInt(hex.slice(2, 4), 16) / 255,
b: parseInt(hex.slice(4, 6), 16) / 255,
a: 1
};
}
export function desaturate(color: Color, amount: number): Color {
const gray = (color.r + color.g + color.b) / 6;
return {
r: color.r + ((gray - color.r) * amount),
g: color.g + ((gray - color.g) * amount),
b: color.b + ((gray - color.b) * amount),
a: color.a,
};
}
export function darken(color: Color, amount: number): Color {
return {
r: color.r * amount,
g: color.g * amount,
b: color.b * amount,
a: color.a,
}
}