diff --git a/package.json b/package.json index 6ad740b..7e987ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chytanka", - "version": "0.13.54", + "version": "0.13.56", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/src/app/app.module.ts b/src/app/app.module.ts index ed72431..89d5952 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,5 +1,5 @@ -import { NgModule, isDevMode, provideZoneChangeDetection } from '@angular/core'; -import { BrowserModule, provideClientHydration, withEventReplay, withHttpTransferCacheOptions } from '@angular/platform-browser'; +import { NgModule, isDevMode } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -11,6 +11,7 @@ import { SharedModule } from './shared/shared.module'; import { registerLocaleData } from '@angular/common'; import localeUk from "@angular/common/locales/uk"; import { parserProviders } from './link-parser/data-access/parser.providers'; +import { languageConfigProvider } from './shared/data-access/lang.provider'; registerLocaleData(localeUk) @@ -23,20 +24,13 @@ registerLocaleData(localeUk) AppRoutingModule, ServiceWorkerModule.register('ngsw-worker.js', { enabled: !isDevMode(), - // Register the ServiceWorker as soon as the application is stable - // or after 30 seconds (whichever comes first). registrationStrategy: 'registerWhenStable:30000' }), SharedModule], providers: [ - // provideZoneChangeDetection({ eventCoalescing: true }), - // provideClientHydration(withEventReplay(), - // withHttpTransferCacheOptions({ - // includePostRequests: false, - // }) - // ), + languageConfigProvider, provideHttpClient(withFetch()), - ...parserProviders + ...parserProviders, ] }) export class AppModule { } diff --git a/src/app/link-parser/data-access/link-parser-settings.service.ts b/src/app/link-parser/data-access/link-parser-settings.service.ts index cc33fec..1908af3 100644 --- a/src/app/link-parser/data-access/link-parser-settings.service.ts +++ b/src/app/link-parser/data-access/link-parser-settings.service.ts @@ -1,5 +1,6 @@ import { isPlatformBrowser } from '@angular/common'; import { Injectable, PLATFORM_ID, WritableSignal, computed, inject, signal } from '@angular/core'; +import { ToggleBarOption } from '../../shared/ui/toggle-bar'; export const DISPLAY_MODES = ['softmode', 'truemode']; const NAME_DISPLAY_MODE = 'displayMode'; @@ -36,6 +37,11 @@ export class LinkParserSettingsService { displayMode!: WritableSignal; + displayModeOptions: ToggleBarOption[] = [ + { value: 'true', emoji: '👑', label: 'trueMode' }, + { value: 'soft', emoji: '🧸', label: 'softMode' } + ] + initDisplayMode() { if (!isPlatformBrowser(this.platformId)) return; diff --git a/src/app/link-parser/link-parser/link-parser.component.ts b/src/app/link-parser/link-parser/link-parser.component.ts index 6c72842..30719f7 100644 --- a/src/app/link-parser/link-parser/link-parser.component.ts +++ b/src/app/link-parser/link-parser/link-parser.component.ts @@ -1,9 +1,8 @@ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, effect, inject } from '@angular/core'; import { LangService } from '../../shared/data-access/lang.service'; 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 { take } from 'rxjs'; import { FileService } from '../../file/data-access/file.service'; @Component({ @@ -30,14 +29,11 @@ export class LinkParserComponent { public setts = inject(LinkParserSettingsService) public file = inject(FileService) - constructor() { } - - ngOnInit() { - this.initMeta() - this.lang.langChanged$.pipe(take(1)).subscribe(() => { + constructor() { + effect(() => { this.initMeta() }); - } + } initMeta() { this.meta.setOg() diff --git a/src/app/link-parser/ui/settings/settings.component.html b/src/app/link-parser/ui/settings/settings.component.html index 6a06aec..ea504ab 100644 --- a/src/app/link-parser/ui/settings/settings.component.html +++ b/src/app/link-parser/ui/settings/settings.component.html @@ -1,11 +1,11 @@
- 🛠️ Base + 🛠️ {{lang.ph().baseSettings}}
-

+

🈚 {{lang.ph().language}} - {{lang.ph().getByKey(getLangValue(lang.lang()).hintPhraceKey)}} + {{lang.ph().getByKey(getLangValue(lang.lang()).label)}}

{{lang.ph().settingLangDesc}}

@@ -15,7 +15,7 @@ @if(vibro.enabled()){
-

+

@if(vibro.vibrationOn()) { ON @@ -34,7 +34,7 @@

-

+

@if(setts.autoPasteLink()) { ON @@ -50,28 +50,23 @@ id="autoPasteLink">

-
-
-

- 🖥️ Display Mode +

+
+

+ 🖥️ {{lang.ph().displayMode}} {{setts.displayMode() | titlecase}}

-
- - -
-
+

{{lang.ph().displayModeDesc}}

+
+
+ +
-

+

@if(setts.seasonalTheme()) { ON @@ -89,11 +84,11 @@

- 🗐 Files + 🗐 {{lang.ph().fileSettings}}
-

+

@if(fileSetts.saveFileToHistory()) { ON @@ -112,7 +107,7 @@ @if(fileSetts.saveFileToHistory()){

-

+

@if(fileSetts.copyFileToHistory()) { ON @@ -131,7 +126,7 @@ @if(fileSetts.copyFileToHistory()){

-

+

{{fileSetts.storageLimit()}}

@@ -142,7 +137,7 @@
-

+

{{fileSetts.retentionTime()}}

diff --git a/src/app/link-parser/ui/settings/settings.component.scss b/src/app/link-parser/ui/settings/settings.component.scss index 0eece6b..1793c90 100644 --- a/src/app/link-parser/ui/settings/settings.component.scss +++ b/src/app/link-parser/ui/settings/settings.component.scss @@ -86,14 +86,14 @@ fieldset { } -@supports (corner-shape: squircle) -{ +@supports (corner-shape: squircle) { section { input[type=checkbox] { - corner-shape: squircle; - border-radius: 1ch; - } + corner-shape: squircle; + border-radius: 1ch; + } } + fieldset { corner-shape: squircle; border-radius: calc(var(--r) * 2); @@ -110,4 +110,10 @@ input[type=number] { grid-template-columns: repeat(auto-fit, minmax(8ch, 1fr)); gap: 1ch; margin-top: 1ch; +} + +.setting-title { + display: flex; + justify-content: space-between; + align-items: center; } \ No newline at end of file diff --git a/src/app/link-parser/ui/settings/settings.component.ts b/src/app/link-parser/ui/settings/settings.component.ts index 4dc6719..2b0450c 100644 --- a/src/app/link-parser/ui/settings/settings.component.ts +++ b/src/app/link-parser/ui/settings/settings.component.ts @@ -1,8 +1,9 @@ -import { Component, WritableSignal, effect, inject, input, signal } from '@angular/core'; +import { Component, inject} from '@angular/core'; import { LinkParserSettingsService } from '../../data-access/link-parser-settings.service'; 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'; @Component({ selector: 'app-settings', @@ -18,20 +19,16 @@ export class SettingsComponent { getLangValue(lang: string) { - return this.lang.langOpt.filter((opt: any) => opt.code == lang)[0] + return this.lang.options.filter((opt: ToggleBarOption) => opt.value == lang)[0] } setAutoPasteLink(e: Event) { this.setts.setAutoPasteLink((e.target as HTMLInputElement).checked) - this.vibro.vibrateForSettings(this.setts.autoPasteLink()) - } setSeasonalTheme(e: Event) { this.setts.setSeasonalTheme((e.target as HTMLInputElement).checked) - // - } setSaveFileToHistory(e: Event) { diff --git a/src/app/shared/data-access/lang.provider.ts b/src/app/shared/data-access/lang.provider.ts new file mode 100644 index 0000000..3c178b5 --- /dev/null +++ b/src/app/shared/data-access/lang.provider.ts @@ -0,0 +1,16 @@ +import { LANGUAGE_CONFIG } from "./lang.token"; + +export const languageConfigProvider = { + provide: LANGUAGE_CONFIG, + useValue: { + options: [ + { label: "english", value: "en", emoji: "🇬🇧" }, + { label: "ukrainian", value: "uk", emoji: "🇺🇦" } + ], + defaultLang: "en", + manifests: new Map([ + ['en', "manifest.webmanifest"], + ['uk', "manifest-uk.webmanifest"] + ]) + } +}; \ No newline at end of file diff --git a/src/app/shared/data-access/lang.service.ts b/src/app/shared/data-access/lang.service.ts index 34ecd48..dfb35ec 100644 --- a/src/app/shared/data-access/lang.service.ts +++ b/src/app/shared/data-access/lang.service.ts @@ -1,78 +1,61 @@ -import { ChangeDetectorRef, Injectable, PLATFORM_ID, WritableSignal, inject, signal } from '@angular/core'; +import { Injectable, PLATFORM_ID, WritableSignal, inject, signal } from '@angular/core'; import { Phrases } from '../utils/phrases'; -import { Observable, Subject, map, of } from 'rxjs'; +import { Observable, map } from 'rxjs'; import { HttpClient } from '@angular/common/http'; -import { ViewModeOption } from '../../viewer/services/viewer.service'; import { DOCUMENT, isPlatformBrowser } from '@angular/common'; import { VibrationService } from './vibration.service'; +import { LANGUAGE_CONFIG } from './lang.token'; -const LANG_OPTIONS: ViewModeOption[] = [ - { dir: "rtl", mode: "pages", hintPhraceKey: "english", code: "en", emoji: "🇬🇧" }, - { dir: "ltr", mode: "pages", hintPhraceKey: "ukrainian", code: "uk", emoji: "🇺🇦" } -] - -const DEFAULT_LANG = 'en' const LANG_STORAGE_NAME = 'lang' - @Injectable({ providedIn: 'root' }) export class LangService { - public readonly manifests = new Map([ - ['en', "manifest.webmanifest"], - ['uk', "manifest-uk.webmanifest"] - ]); - - private langChanged = new Subject(); - langChanged$ = this.langChanged.asObservable(); - - langOpt = LANG_OPTIONS - platformId = inject(PLATFORM_ID) private readonly document = inject(DOCUMENT); - vibro = inject(VibrationService) - - - lang: WritableSignal = signal( - (!isPlatformBrowser(this.platformId)) ? DEFAULT_LANG : + private readonly vibro = inject(VibrationService) - localStorage?.getItem(LANG_STORAGE_NAME) ?? DEFAULT_LANG) - ; - linkManifestElement: WritableSignal = signal(this.document.querySelector('link[rel="manifest"]')) + private readonly _platformId = inject(PLATFORM_ID); + private readonly _config = inject(LANGUAGE_CONFIG); + private _lang = signal('en'); + private _linkManifestElement = signal(this.document.querySelector('link[rel="manifest"]')) - ph: WritableSignal = signal(new Phrases()); + public readonly manifests = this._config.manifests; + public readonly options = this._config.options; + public readonly defaultLang = this._config.defaultLang; + public readonly lang = this._lang.asReadonly(); + public readonly ph = signal(new Phrases()); getTemplate: (phrase: string, value: string) => string = Phrases.getTemplate; - constructor(private http: HttpClient) { } + constructor(private http: HttpClient) { + const lang = this._initLang(); + this._lang.set(lang); + } setLang(lang: string) { - this.lang.set(lang) + this._lang.set(lang) this.document.documentElement.lang = lang this.updateTranslate(); - // this.langChanged.next(); - if (!isPlatformBrowser(this.platformId)) return; + if (!isPlatformBrowser(this._platformId)) return; localStorage.setItem(LANG_STORAGE_NAME, lang) - this.vibro.vibrateLangToggle(this.lang()) + this.vibro.vibrateLangToggle(this._lang()) } updateManifest() { - this.linkManifestElement()?.setAttribute('href', this.manifests.get(this.lang()) ?? 'manifest.webmanifest'); + this._linkManifestElement()?.setAttribute('href', this.manifests.get(this._lang()) ?? 'manifest.webmanifest'); } updateTranslate() { - if (this.lang() == 'en') { + if (this._lang() == 'en') { this.ph.set(new Phrases()); - this.langChanged.next(); return; } - this.getTranslate(this.lang()).subscribe(data => { + this.getTranslate(this._lang()).subscribe(data => { this.ph.set(data) - this.langChanged.next(); - }) } @@ -94,4 +77,10 @@ export class LangService { }) ) } + + private _initLang(): string { + return (!isPlatformBrowser(this._platformId)) ? this.defaultLang : + + localStorage?.getItem(LANG_STORAGE_NAME) ?? this.defaultLang; + } } diff --git a/src/app/shared/data-access/lang.token.ts b/src/app/shared/data-access/lang.token.ts new file mode 100644 index 0000000..9da2bdc --- /dev/null +++ b/src/app/shared/data-access/lang.token.ts @@ -0,0 +1,17 @@ +import { InjectionToken } from '@angular/core'; + +export interface LanguageOption { + label: string; + value: string; + emoji: string; +} + +export interface LanguageConfig { + options: LanguageOption[]; + defaultLang: string; + manifests: Map; +} + +export const LANGUAGE_CONFIG = new InjectionToken( + 'LANGUAGE_CONFIG' +); \ No newline at end of file diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 62ccd91..1504bb7 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -30,8 +30,9 @@ import { DropZoneComponent } from './ui/drop-zone/drop-zone.component'; import { SourceCopyrightComponent } from './ui/source-copyright/source-copyright.component'; import { SourceCopyrightLogoComponent } from './ui/source-copyright-logo/source-copyright-logo.component'; import { SloganComponent } from './ui/slogan/slogan.component'; +import { ToggleBarComponent } from './ui/toggle-bar/toggle-bar.component'; -const components = [GamepadCursorComponent, TruncatePipe, TextEmbracerComponent, OverlayComponent, ViewModeBarComponent, MadeInUkraineComponent, DialogComponent, LangToggleComponent, TitleCardComponent, LoadingComponent, SeparatorComponent, FileChangeComponent, ChytankaLogoWithTagsComponent, FileSizePipe, VibrateHapticDirective, SircleBlurComponent, DropZoneComponent, SourceCopyrightComponent, SourceCopyrightLogoComponent, SloganComponent, NsfwWarningComponent, ImgMetaDirective, NewTabDirective, PagesIndicatorComponent, WarmFilterComponent, WarmControlComponent] +const components = [GamepadCursorComponent, TruncatePipe, TextEmbracerComponent, OverlayComponent, ViewModeBarComponent, MadeInUkraineComponent, DialogComponent, LangToggleComponent, TitleCardComponent, LoadingComponent, SeparatorComponent, FileChangeComponent, ChytankaLogoWithTagsComponent, FileSizePipe, VibrateHapticDirective, SircleBlurComponent, DropZoneComponent, SourceCopyrightComponent, SourceCopyrightLogoComponent, SloganComponent, NsfwWarningComponent, ImgMetaDirective, NewTabDirective, PagesIndicatorComponent, WarmFilterComponent, WarmControlComponent, ToggleBarComponent] @NgModule({ declarations: [...components], diff --git a/src/app/shared/ui/lang-toggle/lang-toggle.component.html b/src/app/shared/ui/lang-toggle/lang-toggle.component.html index c996a76..f4cbb1d 100644 --- a/src/app/shared/ui/lang-toggle/lang-toggle.component.html +++ b/src/app/shared/ui/lang-toggle/lang-toggle.component.html @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/app/shared/ui/lang-toggle/lang-toggle.component.ts b/src/app/shared/ui/lang-toggle/lang-toggle.component.ts index 7a34556..0181636 100644 --- a/src/app/shared/ui/lang-toggle/lang-toggle.component.ts +++ b/src/app/shared/ui/lang-toggle/lang-toggle.component.ts @@ -1,7 +1,6 @@ import { ChangeDetectionStrategy, Component, WritableSignal, inject, signal } from '@angular/core'; import { LangService } from '../../data-access/lang.service'; - - +import { ToggleBarOption } from '../toggle-bar'; @Component({ selector: 'app-lang-toggle', @@ -15,5 +14,10 @@ export class LangToggleComponent { seed: WritableSignal = signal((Math.ceil(Math.random() * 1000)).toString()) - optLangValue = () => this.lang.langOpt.filter((opt: any) => opt.code == this.lang.lang())[0] + optLangValue = () => this.lang.options.filter((opt: ToggleBarOption) => opt.value == this.lang.lang())[0] + + protected onLangChange(lang: string) { + this.lang.setLang(lang); + this.lang.updateManifest() + } } diff --git a/src/app/shared/ui/toggle-bar/index.ts b/src/app/shared/ui/toggle-bar/index.ts new file mode 100644 index 0000000..cd9c15d --- /dev/null +++ b/src/app/shared/ui/toggle-bar/index.ts @@ -0,0 +1,2 @@ +export * from './toggle-bar.component'; +export * from './toggle-bar.model'; \ No newline at end of file diff --git a/src/app/shared/ui/toggle-bar/toggle-bar.component.html b/src/app/shared/ui/toggle-bar/toggle-bar.component.html new file mode 100644 index 0000000..9cbdc19 --- /dev/null +++ b/src/app/shared/ui/toggle-bar/toggle-bar.component.html @@ -0,0 +1,12 @@ +@for(option of options(); track option.emoji) { +
+ + + + +
+} \ No newline at end of file diff --git a/src/app/shared/ui/toggle-bar/toggle-bar.component.scss b/src/app/shared/ui/toggle-bar/toggle-bar.component.scss new file mode 100644 index 0000000..d626cc5 --- /dev/null +++ b/src/app/shared/ui/toggle-bar/toggle-bar.component.scss @@ -0,0 +1,53 @@ +:host { + display: flex; + gap: 1ch; + + --size-3: 1ch; + --size-1: 1ch; + --radius-2: .5ch; + --surface-2: hsl(203.44 8% 16%); + --surface-1: #ffd60a; + --link: #166496; + + @media (prefers-color-scheme: light) { + --surface-2: hsl(203.44 8% 96%); + --link: #88a8c8 + } + + >div { + display: grid; + align-items: center; + grid-auto-flow: column; + grid-template-columns: auto 1fr; + + >* { + grid-area: 1/1; + } + + >label { + cursor: pointer; + text-shadow: 0 0 0.25ch #0008; + } + + >input { + appearance: none; + background: none; + border: none; + inline-size: 100%; + block-size: 100%; + margin: 0; + padding: 0; + + &:checked~label { + background-color: var(--surface-avarage); + color: var(--surface-1); + transform: translate(2px, 2px); + box-shadow: unset; + } + + &:not(:checked):is(:focus-within, :hover)~label { + color: var(--link); + } + } + } +} \ No newline at end of file diff --git a/src/app/shared/ui/toggle-bar/toggle-bar.component.ts b/src/app/shared/ui/toggle-bar/toggle-bar.component.ts new file mode 100644 index 0000000..acf7053 --- /dev/null +++ b/src/app/shared/ui/toggle-bar/toggle-bar.component.ts @@ -0,0 +1,25 @@ +import { Component, input, output } from '@angular/core'; +import { LangService } from '../../data-access'; +import { ToggleBarOption } from './toggle-bar.model'; + +@Component({ + selector: 'app-toggle-bar', + standalone: false, + + templateUrl: './toggle-bar.component.html', + styleUrl: './toggle-bar.component.scss' +}) +export class ToggleBarComponent { + options = input.required[]>(); + value = input.required(); + seed = input('seed'); + + valueChange = output(); + + onChange(value: T) { + this.valueChange.emit(value) + } + + constructor(public lang: LangService) { + } +} diff --git a/src/app/shared/ui/toggle-bar/toggle-bar.model.ts b/src/app/shared/ui/toggle-bar/toggle-bar.model.ts new file mode 100644 index 0000000..13fb607 --- /dev/null +++ b/src/app/shared/ui/toggle-bar/toggle-bar.model.ts @@ -0,0 +1,5 @@ +export interface ToggleBarOption { + value: T; + emoji: string; + label: string; +} \ No newline at end of file diff --git a/src/app/shared/utils/phrases.ts b/src/app/shared/utils/phrases.ts index 5f097f0..5249654 100644 --- a/src/app/shared/utils/phrases.ts +++ b/src/app/shared/utils/phrases.ts @@ -19,7 +19,7 @@ export class Phrases { scrollDown: string = "Scroll down"; nightlight: string = "Nightlight"; nsfwWarnTitle: string = "⚠️🔞 NSFW Content" - nsfwWarnText: string = "2The following content may be Not Safe For Work. Viewer discretion is advised." + nsfwWarnText: string = "2The following content may be Not Safe For Work. Viewer discretion is advised." nsfwLabelAgree: string = "Ready for the wild side!" nsfwLabelDisagree: string = "I'll pass, let's keep it safe." ukrainian: string = "Українська" @@ -70,6 +70,12 @@ export class Phrases { noPagesFound = "No pages found" noPagesFoundDesc = "This episode might only have videos or text" episodeEnd = "End of episode" + displayMode = "Display Mode" + displayModeDesc = "True mode is good for OLED/E-ink screens. Soft mode is good for everyone else." + trueMode = "True mode" + softMode = "Soft mode" + baseSettings = "Base settings" + fileSettings = "File settings" getByKey = (key: string) => (Object.keys(this).includes(key)) ? this[key as keyof Phrases] : null; static getTemplate(phrase: string, value: string) { diff --git a/src/app/viewer/viewer/components/viewer-header/viewer-header.component.ts b/src/app/viewer/viewer/components/viewer-header/viewer-header.component.ts index 0037c08..27347da 100644 --- a/src/app/viewer/viewer/components/viewer-header/viewer-header.component.ts +++ b/src/app/viewer/viewer/components/viewer-header/viewer-header.component.ts @@ -5,7 +5,6 @@ import { PlaylistItem } from '../../../../playlist/data-access/playlist.service' import { LangService } from '../../../../shared/data-access/lang.service'; import { DialogComponent } from '../../../../shared/ui/dialog/dialog.component'; import { EmbedHalperService } from '../../../../shared/data-access/embed-halper.service'; -import { parseTags, resolveViewMode } from '../../../../shared/utils'; import { isPlatformBrowser } from '@angular/common'; import { GamepadService } from '../../../../shared/data-access/gamepad.service'; import { GamepadButton } from '../../../../shared/models'; @@ -76,31 +75,11 @@ export class ViewerHeaderComponent { // #region ⚙️ Lifecycle / Effects constructor() { effect(() => { - // const episode = this.episode(); - // if (!episode) return; - // const tags = this.parseTagsFromTitle(episode.title); - // this.applyEpisodeTitleTags(tags); - if (this.gamepad.buttons()[GamepadButton.Share]?.pressed) this.showShare(); }) } //#endregion - // #region 🏷️ Episode Tags Logic - // parseTagsFromTitle = (title: string): Set => parseTags(title); - - // applyEpisodeTitleTags(tags: Set): void { - // const code = resolveViewMode(tags); - - // if (code) - // this.viewer.setViewModeOptionByCode(code); - - // if (tags.has('nsfw')) { - // this.episode().nsfw = true; - // } - // } - //#endregion - // #region 🧭 Actions (UI) showShare = () => this.shareDialogComponent.showDialog(); showDownload = () => this.dlDialogComponent.showDialog(); diff --git a/src/assets/langs/uk.json b/src/assets/langs/uk.json index 43e396a..d4e0185 100644 --- a/src/assets/langs/uk.json +++ b/src/assets/langs/uk.json @@ -66,5 +66,11 @@ "readlist": "Список для читання", "noPagesFound": "Сторінок не знайдено", "noPagesFoundDesc": "Цей епізод певно містить лише відео або текст", - "episodeEnd": "Кінець епізоду" + "episodeEnd": "Кінець епізоду", + "displayMode": "Режим відображення", + "displayModeDesc": "True mode підходить для OLED/E-ink екранів. Soft mode підходить для всіх інших.", + "trueMode": "True mode", + "softMode": "Soft mode", + "baseSettings": "Основні налаштування", + "fileSettings": "Налаштування файлів" } \ No newline at end of file diff --git a/src/environments/environment.development.ts b/src/environments/environment.development.ts index bd8427b..ae33c1d 100644 --- a/src/environments/environment.development.ts +++ b/src/environments/environment.development.ts @@ -1,7 +1,7 @@ const PROXY = `http://192.168.10.107:3003/api?url=` export const environment = { - version: "0.13.54-2026.4.8", + version: "0.13.56-2026.4.9", prod: false, proxy: PROXY, blankaryoHost: `https://blankary.com/page/`, diff --git a/src/environments/environment.ts b/src/environments/environment.ts index f439285..c3bbb2f 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -1,7 +1,7 @@ const PROXY = `https://proxy.chytanka.ink/api?url=` export const environment = { - version: "0.13.54-2026.4.8", + version: "0.13.56-2026.4.9", prod: true, proxy: PROXY, blankaryoHost: `https://blankary.com/page/`,