Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/app/core/services/display-mode.service.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { Injectable, inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { DISPLAY_MODES, LinkParserSettingsService } from '../../link-parser/data-access/link-parser-settings.service';
import { LinkParserSettingsService } from '../../link-parser/data-access/link-parser-settings.service';
import { DISPLAY_MODES, ThemeService } from '../../shared/data-access/theme.service';

@Injectable({ providedIn: 'root' })
export class DisplayModeService {
private doc = inject(DOCUMENT);
private setts = inject(LinkParserSettingsService);
private theme = inject(ThemeService)

update() {
if (this.setts.displayMode == undefined) return;
if (this.theme.displayMode == undefined) return;

for (const mode of DISPLAY_MODES) {
this.doc.documentElement.classList.remove(mode);
}

this.doc.documentElement.classList.add(this.setts.displayMode() + 'mode');
this.doc.documentElement.classList.add(this.theme.displayMode() + 'mode');
}
}
2 changes: 1 addition & 1 deletion src/app/file/data-access/file-history.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class FileHistoryService {

private createDatabase() {
this.db = new Dexie(HISTORY_DB_NAME);
this.db.version(1).stores({
this.db.version(2).stores({
filehistory: '++id,sha256,pages,size,title,format,page,cover,arrayBuffer,created,updated'
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/history/data-access/history.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class HistoryService {
private createDatabase() {

this.db = new Dexie(HISTORY_DB_NAME);
this.db.version(1).stores({
this.db.version(2).stores({
history: '++id,site,post_id,title,cover,episode,pages,page,created,updated'
});
}
Expand Down
77 changes: 6 additions & 71 deletions src/app/link-parser/data-access/link-parser-settings.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { isPlatformBrowser } from '@angular/common';
import { Injectable, PLATFORM_ID, WritableSignal, computed, inject, signal } from '@angular/core';
import { ToggleBarOption } from '../../shared/ui/toggle-bar';
import { isPlatformServer } from '@angular/common';
import { Injectable, PLATFORM_ID, WritableSignal, inject, signal } from '@angular/core';

export const DISPLAY_MODES = ['softmode', 'truemode'];
const NAME_DISPLAY_MODE = 'displayMode';
const NAME_AUTO_PASTE_LINK = 'autoPasteLink';
const NAME_SEASONAL_THEME = 'seasonalTheme';

@Injectable({
providedIn: 'root'
Expand All @@ -17,80 +13,19 @@ export class LinkParserSettingsService {

constructor() {
this.initAutoPasteLink()
this.initSeasonalTheme()
this.initDisplayMode()
}

initAutoPasteLink() {
if (!isPlatformBrowser(this.platformId)) return;
if (isPlatformServer(this.platformId)) return;

const n = Boolean(localStorage.getItem('autoPasteLink') == 'true');
const n = Boolean(localStorage.getItem(NAME_AUTO_PASTE_LINK) == 'true');
this.autoPasteLink = signal(n);
}

setAutoPasteLink(n: boolean) {
if (!isPlatformBrowser(this.platformId)) return;
if (isPlatformServer(this.platformId)) return;

this.autoPasteLink.set(n);
localStorage.setItem('autoPasteLink', n.toString())
localStorage.setItem(NAME_AUTO_PASTE_LINK, n.toString())
}

displayMode!: WritableSignal<string>;

displayModeOptions: ToggleBarOption<string>[] = [
{ value: 'true', emoji: '👑', label: 'trueMode' },
{ value: 'soft', emoji: '🧸', label: 'softMode' }
]

initDisplayMode() {
if (!isPlatformBrowser(this.platformId)) return;

const n = localStorage.getItem(NAME_DISPLAY_MODE) === null ? 'soft' : localStorage.getItem(NAME_DISPLAY_MODE) as string;
this.displayMode = signal(n);
this.setDisplayMode(n);
}

setDisplayMode(n: string) {
if (!isPlatformBrowser(this.platformId)) return;

this.displayMode.update(v => n);
localStorage.setItem(NAME_DISPLAY_MODE, n)
}

/**
*
*/
seasonalTheme: WritableSignal<boolean> = signal(false);

initSeasonalTheme() {
if (!isPlatformBrowser(this.platformId)) return;

const n = localStorage.getItem('seasonalTheme') === null ? true : Boolean(localStorage.getItem('seasonalTheme') == 'true');
this.seasonalTheme.set(n);
this.setSeasonalTheme(n);
}

setSeasonalTheme(n: boolean) {
if (!isPlatformBrowser(this.platformId)) return;

this.seasonalTheme.set(n);
localStorage.setItem('seasonalTheme', n.toString())
}

getSeasonalTheme(): string {
const now = new Date();
const month = now.getMonth(); // 0-11
const day = now.getDate();

if (month === 5) return 'pride'; // June
if (month === 9 && day > 15) return 'halloween'; // second half of Oct
if (month === 11 || (month === 0 && day < 10)) return 'newyear';
if (month === 1 && day <= 15) return 'valentine';
return 'default';
}

theme = computed(() => {
if (!this.seasonalTheme) return '';
return this.seasonalTheme() ? this.getSeasonalTheme() : ''
})
}
2 changes: 1 addition & 1 deletion src/app/link-parser/link-parser/link-parser.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
</main>

<aside>
<app-chytanka-logo-with-tags [ngClass]="setts.theme()" [fileTags]="file.supportFiles()" [siteTags]="parser.supportSites()" />
<app-chytanka-logo-with-tags [ngClass]="theme.theme()" [fileTags]="file.supportFiles()" [siteTags]="parser.supportSites()" />
</aside>

@defer (on immediate) {
Expand Down
4 changes: 3 additions & 1 deletion src/app/link-parser/link-parser/link-parser.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { MetaTagsService } from '../../shared/data-access/meta-tags.service';
import { LinkParserService } from '../data-access/link-parser.service';
import { LinkParserSettingsService } from '../data-access/link-parser-settings.service';
import { FileService } from '../../file/data-access/file.service';
import { ThemeService } from '../../shared/data-access/theme.service';

@Component({
selector: 'app-link-parser',
Expand All @@ -19,7 +20,7 @@ import { FileService } from '../../file/data-access/file.service';
standalone: false,
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'[class]': 'this.setts.theme()'
'[class]': 'this.theme.theme()'
}
})
export class LinkParserComponent {
Expand All @@ -28,6 +29,7 @@ export class LinkParserComponent {
public parser: LinkParserService = inject(LinkParserService)
public setts = inject(LinkParserSettingsService)
public file = inject(FileService)
protected theme = inject(ThemeService);

constructor() {
effect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</div>
}
<h1 class="logo-text">
<app-text-embracer [ngClass]="linkInit.setts.theme()" [text]="ph.shortTitle" />
<app-text-embracer [ngClass]="theme.theme()" [text]="ph.shortTitle" />
</h1>
@if (online) {
<form (submit)="navFacade.goToParsedLink()">
Expand Down
2 changes: 2 additions & 0 deletions src/app/link-parser/ui/parser-form/parser-form.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { LangService } from '../../../shared/data-access/lang.service';
import { FileNetFacade, LinkInitFacade, LinkParserFacade, NavigationFacade } from './facades';
import { ThemeService } from '../../../shared/data-access/theme.service';

@Component({
selector: 'app-parser-form',
Expand All @@ -15,6 +16,7 @@ export class ParserFormComponent {
protected navFacade = inject(NavigationFacade);
protected fileNetFacade = inject(FileNetFacade);
protected linkInit = inject(LinkInitFacade);
protected theme = inject(ThemeService);

ngOnInit() {
this.linkFacade.setLink('');
Expand Down
12 changes: 6 additions & 6 deletions src/app/link-parser/ui/settings/settings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,21 @@
<div>
<p class="setting-title">
<span class="label">🖥️ {{lang.ph().displayMode}}</span>
<small>{{setts.displayMode() | titlecase}}</small>
<small>{{theme.displayMode() | titlecase}}</small>
</p>
<p><small>{{lang.ph().displayModeDesc}}</small></p>
</div>
<div>
<app-toggle-bar [options]="setts.displayModeOptions" [value]="setts.displayMode()"
(valueChange)="setts.setDisplayMode($event)" />
<app-toggle-bar [options]="theme.displayModeOptions" [value]="theme.displayMode()"
(valueChange)="theme.setDisplayMode($event)" />
</div>
</section>

<section [class]="!setts.seasonalTheme()? 'inactive': ''">
<section [class]="!theme.seasonalTheme()? 'inactive': ''">
<div>
<p class="setting-title">
<label class="label" for="seasonalTheme">🎨 {{lang.ph().seasonalTheme}}</label>
@if(setts.seasonalTheme()) {
@if(theme.seasonalTheme()) {
<small class="on">ON</small>
} @else {
<small class="off">OFF</small>
Expand All @@ -78,7 +78,7 @@
<small>{{lang.ph().seasonalThemeDesc}}</small>
</p>
</div>
<input type="checkbox" [vibrateHaptic]="10" [checked]="setts.seasonalTheme()" (input)="setSeasonalTheme($event)"
<input type="checkbox" [vibrateHaptic]="10" [checked]="theme.seasonalTheme()" (input)="setSeasonalTheme($event)"
id="seasonalTheme">
</section>
</fieldset>
Expand Down
4 changes: 3 additions & 1 deletion src/app/link-parser/ui/settings/settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { LangService } from '../../../shared/data-access/lang.service';
import { FileSettingsService } from '../../../file/data-access/file-settings.service';
import { VibrationService } from '../../../shared/data-access/vibration.service';
import { ToggleBarOption } from '../../../shared/ui/toggle-bar';
import { ThemeService } from '../../../shared/data-access/theme.service';

@Component({
selector: 'app-settings',
Expand All @@ -16,6 +17,7 @@ export class SettingsComponent {
lang = inject(LangService)
fileSetts = inject(FileSettingsService)
vibro = inject(VibrationService)
theme = inject(ThemeService)


getLangValue(lang: string) {
Expand All @@ -28,7 +30,7 @@ export class SettingsComponent {
}

setSeasonalTheme(e: Event) {
this.setts.setSeasonalTheme((e.target as HTMLInputElement).checked)
this.theme.setSeasonalTheme((e.target as HTMLInputElement).checked)
}

setSaveFileToHistory(e: Event) {
Expand Down
99 changes: 99 additions & 0 deletions src/app/shared/data-access/theme.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { computed, inject, Injectable, PLATFORM_ID, signal, WritableSignal } from '@angular/core';
import { ToggleBarOption } from '../ui/toggle-bar';
import { DOCUMENT, isPlatformServer } from '@angular/common';

export const DISPLAY_MODES = ['softmode', 'truemode'];
const NAME_DISPLAY_MODE = 'displayMode';
const NAME_SEASONAL_THEME = 'seasonalTheme';

@Injectable({
providedIn: 'root'
})
export class ThemeService {
private readonly document = inject(DOCUMENT);
private platformId = inject(PLATFORM_ID)

constructor() {
this.initDisplayMode()
this.initSeasonalTheme()
}

//#region Display Mode

displayMode!: WritableSignal<string>;
private _lightMetaElement = signal(this.document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: light)"]') as HTMLMetaElement);
private _darkMetaElement = signal(this.document.querySelector('meta[name="theme-color"][media="(prefers-color-scheme: dark)"]') as HTMLMetaElement);

readonly displayModeOptions: ToggleBarOption<string>[] = [
{ value: 'true', emoji: '👑', label: 'trueMode' },
{ value: 'soft', emoji: '🧸', label: 'softMode' }
]

readonly displayModeMetaThemeColors: Record<string, { light: string, dark: string }> = {
'soft': { light: '#166496', dark: '#002741' },
'true': { light: '#ffffff', dark: '#000000' }
}

private initDisplayMode() {
if (isPlatformServer(this.platformId)) return;

const n = localStorage.getItem(NAME_DISPLAY_MODE) === null ? 'soft' : localStorage.getItem(NAME_DISPLAY_MODE) as string;
this.displayMode = signal(n);
this.setDisplayMode(n);
}

private setMetaThemeColors(mode: string) {
const colors = this.displayModeMetaThemeColors[mode];
if (!colors) return;

if (this._lightMetaElement()) this._lightMetaElement()!.content = colors.light;
if (this._darkMetaElement()) this._darkMetaElement()!.content = colors.dark;
}

setDisplayMode(n: string) {
if (isPlatformServer(this.platformId)) return;

this.displayMode.update(v => n);
localStorage.setItem(NAME_DISPLAY_MODE, n)

this.setMetaThemeColors(n);
}

//#endregion

//#region Seasonal Theme
seasonalTheme: WritableSignal<boolean> = signal(false);

private initSeasonalTheme() {
if (isPlatformServer(this.platformId)) return;

const n = localStorage.getItem(NAME_SEASONAL_THEME) === null ? true : Boolean(localStorage.getItem(NAME_SEASONAL_THEME) == 'true');
this.seasonalTheme.set(n);
this.setSeasonalTheme(n);
}

setSeasonalTheme(n: boolean) {
if (isPlatformServer(this.platformId)) return;

this.seasonalTheme.set(n);
localStorage.setItem(NAME_SEASONAL_THEME, n.toString())
}

getSeasonalTheme(): string {
const now = new Date();
const month = now.getMonth(); // 0-11
const day = now.getDate();

if (month === 5) return 'pride'; // June
if (month === 9 && day > 15) return 'halloween'; // second half of Oct
if (month === 11 || (month === 0 && day < 10)) return 'newyear';
if (month === 1 && day <= 15) return 'valentine';
return 'default';
}

theme = computed(() => {
if (!this.seasonalTheme) return '';
return this.seasonalTheme() ? this.getSeasonalTheme() : ''
})
//#endregion
}
6 changes: 4 additions & 2 deletions src/app/shared/ui/slogan/slogan.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, computed, inject, signal } from '@angular/core';
import { LinkParserSettingsService } from '../../../link-parser/data-access/link-parser-settings.service';
import { LangService } from '../../data-access';
import { ThemeService } from '../../data-access/theme.service';

@Component({
selector: 'slogan',
Expand All @@ -11,6 +12,7 @@ import { LangService } from '../../data-access';
})
export class SloganComponent {
private setts = inject(LinkParserSettingsService)
private theme = inject(ThemeService)
private lang = inject(LangService);

private seasonalTheme = signal(new Map<string, { class: string, phrase: string, emoji: string }>([
Expand All @@ -27,9 +29,9 @@ export class SloganComponent {
emoji: '🌻'
};

if (!this.setts.seasonalTheme()) return defaultSlogan;
if (!this.theme.seasonalTheme()) return defaultSlogan;

const theme = this.seasonalTheme().get(this.setts.theme());
const theme = this.seasonalTheme().get(this.theme.theme());

if (!theme) return defaultSlogan;

Expand Down
Loading
Loading