diff --git a/package.json b/package.json index 26e5d1d..a8231ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chytanka", - "version": "0.13.48", + "version": "0.13.50", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/scripts/list-tree.js b/scripts/list-tree.js new file mode 100644 index 0000000..876e447 --- /dev/null +++ b/scripts/list-tree.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const path = require('path'); + +function printTree(dir, prefix = '') { + const entries = fs.readdirSync(dir, { withFileTypes: true }); + const lastIndex = entries.length - 1; + + entries.forEach((entry, index) => { + const isLast = index === lastIndex; + const pointer = isLast ? '└─' : '├─'; + console.log(`${prefix}${pointer} ${entry.name}`); + + if (entry.isDirectory()) { + const newPrefix = prefix + (isLast ? ' ' : '│ '); + printTree(path.join(dir, entry.name), newPrefix); + } + }); +} + +const appDir = path.join(__dirname, '../src/app'); +console.log(appDir); +printTree(appDir); \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000..3c55ff9 --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,4 @@ + +
+
+@defer{} \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index dd5bd4c..a14f837 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,167 +1,29 @@ -import { Component, HostListener, PLATFORM_ID, effect, inject } from '@angular/core'; -import { LangService } from './shared/data-access/lang.service'; +import { Component, effect, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { DOCUMENT, isPlatformBrowser, isPlatformServer } from '@angular/common'; -import { environment } from '../environments/environment'; -import { DISPLAY_MODES, LinkParserSettingsService } from './link-parser/data-access/link-parser-settings.service'; -import { GamepadService } from './shared/data-access/gamepad.service'; -import { GamepadButton } from './shared/models'; -import { deadzone } from './shared/utils'; -import { DomManipulationService } from './shared/data-access'; - -const SCALE_GAP = 64; +import { LanguageFacadeService, GamepadFacadeService } from './core/facades'; +import { DisplayModeService, ConsoleWelcomeService, ViewportService } from './core/services'; @Component({ selector: 'chtnk-root', - template: `
@defer{}`, + templateUrl: 'app.component.html', styles: [``], - standalone: false + standalone: false, + host: { + '(window:resize)': 'this.viewport.updateScaleDiff()' + } }) export class AppComponent { - private readonly document = inject(DOCUMENT); - platformId = inject(PLATFORM_ID) - setts = inject(LinkParserSettingsService) - gamepad = inject(GamepadService); - dom = inject(DomManipulationService); - - constructor(public lang: LangService, private route: ActivatedRoute) { - this.lang.updateManifest() - this.lang.updateTranslate() - - this.handleLanguageQueryParams(); - - this.displayWelcomeMessage(); - - effect(() => { - // Update display mode based on settings - this.updateDisplayMode(); - // Handle gamepad input - this.handleGamepadInput(); - }); - } - - private handleLanguageQueryParams() { - this.route.pathFromRoot[0].queryParams.subscribe(async (q) => { - const l = q['lang']; - - if (l) { - this.lang.setLang(l); - } - - if (l && this.lang.manifests.has(l)) { - this.lang.updateManifest(); - } - }); - } - - private displayWelcomeMessage() { - if (isPlatformBrowser(this.platformId) && window.console && environment.prod) { - const msg = `What are you looking for here? The plot twist is in the next volume!`; - console.log(`%c${msg}`, "background-color: #166496; color: #ffd60a; font-size: 4rem; font-family: monospace; padding: 8px 16px"); - } - } - - private handleGamepadInput() { - // Move cursor based on left gamepad stick input - this.cursorMove(this.gamepad.leftStick()); - this.showCursor(this.gamepad.leftStick()); - this.scrollByStick(this.gamepad.rightStick()); - - // Imitate click if the Cross/A button is pressed - if (this.gamepad.buttons()[GamepadButton.Cross]?.pressed) - this.imitateClick({ x: this.gamepad.x(), y: this.gamepad.y() }); - - // Imitate Escape key press if the Circle/B button is pressed - if (this.gamepad.buttons()[GamepadButton.Circle]?.pressed) - this.imitateEscape(); - } - - private showCursor(coords: { x: number, y: number }) { - const { x, y } = coords; - - if (Math.abs(x) > 0.01 || Math.abs(y) > 0.01) { - this.gamepad.showCursor(); - } - } - - private imitateEscape() { - const event = new KeyboardEvent('keydown', { - key: 'Escape', - code: 'Escape', - keyCode: 27, - which: 27, - bubbles: true - }); - - document.dispatchEvent(event); - } - - private imitateClick(coords: { x: number, y: number }) { - const { x, y } = coords; - const el = document.elementFromPoint(x - window.scrollX, y - window.scrollY) as HTMLElement; - if (el) { - el.focus(); - el.click(); - } - } - - private cursorMove(coords: { x: number, y: number }) { - if (isPlatformServer(this.platformId)) return; - - const { x, y } = coords; - const speed = 16; - const halfCursor = 8; - this.gamepad.x.update(v => { - const result = v + x * speed; - return Math.max(halfCursor, Math.min(this.document.documentElement.scrollWidth - halfCursor, result)); - }); - this.gamepad.y.update(v => { - const result = v + y * speed; - return Math.max(halfCursor, Math.min(this.document.documentElement.scrollHeight - halfCursor, result)); - }); - this.dom.updateHover(this.gamepad.x() - window.scrollX, this.gamepad.y() - window.scrollY); - } - - private scrollByStick(coords: { x: number, y: number }) { - if (isPlatformServer(this.platformId)) return; - - const { x, y } = coords; - const target = this.document.elementFromPoint(this.gamepad.x(), this.gamepad.y()) as HTMLElement; - const scrollContainer = this.dom.getScrollableParent(target); - const scrollSpeed = 20 + Math.abs(y) * 60; - const scrollX = deadzone(x) * scrollSpeed; - const scrollY = deadzone(y) * scrollSpeed; - - if (!scrollContainer || (scrollX === 0 && scrollY === 0)) return; - - scrollContainer.scrollBy({ - left: scrollX, - top: scrollY, - }); - } - - ngOnInit() { - this.initScaleDifference(); - this.updateDisplayMode(); - } - - updateDisplayMode() { - if (this.setts.displayMode != undefined) { - for (const mode of DISPLAY_MODES) { - this.document.documentElement.classList.remove(mode); - } - this.document.documentElement.classList.add(this.setts.displayMode() + 'mode'); - } - } - - @HostListener('window:resize') - initScaleDifference() { - const w = this.document.documentElement.clientWidth; - const h = this.document.documentElement.clientHeight; - const scalex = 1 - ((w - SCALE_GAP) / w) - const scaley = 1 - ((h - SCALE_GAP) / h) - - this.document.documentElement.style.setProperty('--scale-diff-x', scalex.toString()) - this.document.documentElement.style.setProperty('--scale-diff-y', scaley.toString()) + private route = inject(ActivatedRoute); + private lang = inject(LanguageFacadeService); + private display = inject(DisplayModeService); + private welcome = inject(ConsoleWelcomeService); + protected viewport = inject(ViewportService); + protected gamepad = inject(GamepadFacadeService); + + constructor() { + this.lang.init(this.route); + this.welcome.show(); + + effect(() => this.display.update()); } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 28b854f..03325ab 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -28,12 +28,12 @@ registerLocaleData(localeUk) }), SharedModule], providers: [ - provideZoneChangeDetection({ eventCoalescing: true }), - provideClientHydration(withEventReplay(), - withHttpTransferCacheOptions({ - includePostRequests: false, - }) - ), + // provideZoneChangeDetection({ eventCoalescing: true }), + // provideClientHydration(withEventReplay(), + // withHttpTransferCacheOptions({ + // includePostRequests: false, + // }) + // ), provideHttpClient(withFetch()) ] }) diff --git a/src/app/core/facades/gamepad-facade.service.ts b/src/app/core/facades/gamepad-facade.service.ts new file mode 100644 index 0000000..7e171a8 --- /dev/null +++ b/src/app/core/facades/gamepad-facade.service.ts @@ -0,0 +1,41 @@ +import { effect, inject, Injectable, PLATFORM_ID } from '@angular/core'; +import { isPlatformServer } from '@angular/common'; +import { GamepadService } from '../../shared/data-access'; +import { GamepadButton } from '../../shared/models'; +import { ActionService, CursorService, ScrollService } from '../services'; + +@Injectable({ + providedIn: 'root' +}) +export class GamepadFacadeService { + private platformId = inject(PLATFORM_ID); + gamepad = inject(GamepadService); + private cursor = inject(CursorService); + private scroll = inject(ScrollService); + private actions = inject(ActionService); + + constructor() { + effect(() => this.handle()); + } + + private handle() { + if (isPlatformServer(this.platformId)) return; + + const left = this.gamepad.leftStick(); + const right = this.gamepad.rightStick(); + const buttons = this.gamepad.buttons(); + + this.cursor.move(left); + this.cursor.showIfNeeded(left); + + this.scroll.scroll(right, this.gamepad.x(), this.gamepad.y()); + + if (buttons[GamepadButton.Cross]?.pressed) { + this.actions.click(this.gamepad.x(), this.gamepad.y()); + } + + if (buttons[GamepadButton.Circle]?.pressed) { + this.actions.escape(); + } + } +} diff --git a/src/app/core/facades/index.ts b/src/app/core/facades/index.ts new file mode 100644 index 0000000..a7915cd --- /dev/null +++ b/src/app/core/facades/index.ts @@ -0,0 +1,2 @@ +export * from './gamepad-facade.service'; +export * from './language-facade.service'; \ No newline at end of file diff --git a/src/app/core/facades/language-facade.service.ts b/src/app/core/facades/language-facade.service.ts new file mode 100644 index 0000000..75fc322 --- /dev/null +++ b/src/app/core/facades/language-facade.service.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { LangService } from '../../shared/data-access'; + +@Injectable({ + providedIn: 'root' +}) +export class LanguageFacadeService { + constructor(private lang: LangService) { } + + init(route: ActivatedRoute) { + this.lang.updateManifest(); + this.lang.updateTranslate(); + + route.queryParams.subscribe(q => { + const l = q['lang']; + + if (l) this.lang.setLang(l); + if (l && this.lang.manifests.has(l)) { + this.lang.updateManifest(); + } + }); + } +} diff --git a/src/app/core/services/action.service.ts b/src/app/core/services/action.service.ts new file mode 100644 index 0000000..0c4839e --- /dev/null +++ b/src/app/core/services/action.service.ts @@ -0,0 +1,28 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ providedIn: 'root' }) +export class ActionService { + click(x: number, y: number) { + const el = document.elementFromPoint( + x - window.scrollX, + y - window.scrollY + ) as HTMLElement; + + if (el) { + el.focus(); + el.click(); + } + } + + escape() { + document.dispatchEvent( + new KeyboardEvent('keydown', { + key: 'Escape', + code: 'Escape', + keyCode: 27, + which: 27, + bubbles: true, + }) + ); + } +} \ No newline at end of file diff --git a/src/app/core/services/console-welcome.service.ts b/src/app/core/services/console-welcome.service.ts new file mode 100644 index 0000000..c9560cd --- /dev/null +++ b/src/app/core/services/console-welcome.service.ts @@ -0,0 +1,27 @@ +import { Injectable, inject, PLATFORM_ID } from '@angular/core'; +import { isPlatformBrowser } from '@angular/common'; +import { environment } from '../../../environments/environment'; + +@Injectable({ providedIn: 'root' }) +export class ConsoleWelcomeService { + private platformId = inject(PLATFORM_ID); + + show() { + if (!isPlatformBrowser(this.platformId)) return; + if (!environment.prod) return; + if (!window?.console) return; + + const msg = `What are you looking for here? The plot twist is in the next volume!`; + + console.log( + `%c${msg}`, + ` + background-color: #166496; + color: #ffd60a; + font-size: 4rem; + font-family: monospace; + padding: 8px 16px; + ` + ); + } +} \ No newline at end of file diff --git a/src/app/core/services/cursor.service.ts b/src/app/core/services/cursor.service.ts new file mode 100644 index 0000000..314881b --- /dev/null +++ b/src/app/core/services/cursor.service.ts @@ -0,0 +1,31 @@ +import { Injectable, inject } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { DomManipulationService, GamepadService } from '../../shared/data-access'; + +const SPEED = 16; +const HALF = 8; + +@Injectable({ providedIn: 'root' }) +export class CursorService { + private doc = inject(DOCUMENT); + private gamepad = inject(GamepadService); + private dom = inject(DomManipulationService); + + move({ x, y }: { x: number; y: number }) { + this.gamepad.x.update(v => { + const result = v + x * SPEED; + return Math.max(HALF, Math.min(this.doc.documentElement.scrollWidth - HALF, result)); + }); + this.gamepad.y.update(v => { + const result = v + y * SPEED; + return Math.max(HALF, Math.min(this.doc.documentElement.scrollHeight - HALF, result)); + }); + this.dom.updateHover(this.gamepad.x() - window.scrollX, this.gamepad.y() - window.scrollY); + } + + showIfNeeded({ x, y }: { x: number; y: number }) { + if (Math.abs(x) > 0.01 || Math.abs(y) > 0.01) { + this.gamepad.showCursor(); + } + } +} \ No newline at end of file diff --git a/src/app/core/services/display-mode.service.ts b/src/app/core/services/display-mode.service.ts new file mode 100644 index 0000000..adfd71c --- /dev/null +++ b/src/app/core/services/display-mode.service.ts @@ -0,0 +1,19 @@ +import { Injectable, inject } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { DISPLAY_MODES, LinkParserSettingsService } from '../../link-parser/data-access/link-parser-settings.service'; + +@Injectable({ providedIn: 'root' }) +export class DisplayModeService { + private doc = inject(DOCUMENT); + private setts = inject(LinkParserSettingsService); + + update() { + if (this.setts.displayMode == undefined) return; + + for (const mode of DISPLAY_MODES) { + this.doc.documentElement.classList.remove(mode); + } + + this.doc.documentElement.classList.add(this.setts.displayMode() + 'mode'); + } +} \ No newline at end of file diff --git a/src/app/core/services/index.ts b/src/app/core/services/index.ts new file mode 100644 index 0000000..6629348 --- /dev/null +++ b/src/app/core/services/index.ts @@ -0,0 +1,6 @@ +export * from './action.service'; +export * from './console-welcome.service'; +export * from './cursor.service'; +export * from './display-mode.service'; +export * from './scroll.service'; +export * from './viewport.service'; \ No newline at end of file diff --git a/src/app/core/services/scroll.service.ts b/src/app/core/services/scroll.service.ts new file mode 100644 index 0000000..559bb5c --- /dev/null +++ b/src/app/core/services/scroll.service.ts @@ -0,0 +1,28 @@ +import { Injectable, PLATFORM_ID, inject } from '@angular/core'; +import { DOCUMENT, isPlatformServer } from '@angular/common'; +import { DomManipulationService } from '../../shared/data-access'; +import { deadzone } from '../../shared/utils'; + +@Injectable({ providedIn: 'root' }) +export class ScrollService { + private platformId = inject(PLATFORM_ID) + + private doc = inject(DOCUMENT); + private dom = inject(DomManipulationService); + + scroll(coords: { x: number; y: number }, cx: number, cy: number) { + if(isPlatformServer(this.platformId)) return; + + const target = this.doc.elementFromPoint(cx, cy) as HTMLElement; + const container = this.dom.getScrollableParent(target); + + const speed = 20 + Math.abs(coords.y) * 60; + + const dx = deadzone(coords.x) * speed; + const dy = deadzone(coords.y) * speed; + + if (!container || (!dx && !dy)) return; + + container.scrollBy({ left: dx, top: dy }); + } +} \ No newline at end of file diff --git a/src/app/core/services/viewport.service.ts b/src/app/core/services/viewport.service.ts new file mode 100644 index 0000000..eb255ad --- /dev/null +++ b/src/app/core/services/viewport.service.ts @@ -0,0 +1,20 @@ +import { Injectable, inject } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; + +const GAP = 64; + +@Injectable({ providedIn: 'root' }) +export class ViewportService { + private doc = inject(DOCUMENT); + + updateScaleDiff() { + const w = this.doc.documentElement.clientWidth; + const h = this.doc.documentElement.clientHeight; + + const sx = 1 - (w - GAP) / w; + const sy = 1 - (h - GAP) / h; + + this.doc.documentElement.style.setProperty('--scale-diff-x', sx.toString()); + this.doc.documentElement.style.setProperty('--scale-diff-y', sy.toString()); + } +} \ No newline at end of file diff --git a/src/app/file/data-access/file.service.ts b/src/app/file/data-access/file.service.ts index 336a0f9..2dcfd4a 100644 --- a/src/app/file/data-access/file.service.ts +++ b/src/app/file/data-access/file.service.ts @@ -1,12 +1,19 @@ -import { effect, inject, Injectable, signal, WritableSignal } from '@angular/core'; +import { computed, effect, inject, Injectable, signal, WritableSignal } from '@angular/core'; import { FILE_PATH } from '../../app-routing.module'; import { Router } from '@angular/router'; +import { BrowserService } from '../../shared/data-access'; @Injectable({ providedIn: 'root' }) export class FileService { router = inject(Router); + browser = inject(BrowserService); + + osAcceptSupport = signal(["Windows", "Android", "Linux"].includes(this.browser.brouserInfo().os)); + supportFiles = signal([".zip", ".cbz", ".pdf", ".mobi"]) + + access = computed(() => this.osAcceptSupport()?this.supportFiles():[]); private _file: WritableSignal = signal(null); diff --git a/src/app/link-parser/data-access/link-parser.service.ts b/src/app/link-parser/data-access/link-parser.service.ts index 913a647..776b823 100644 --- a/src/app/link-parser/data-access/link-parser.service.ts +++ b/src/app/link-parser/data-access/link-parser.service.ts @@ -5,9 +5,6 @@ import { LinkParseResult, LinkParser } from '../utils'; providedIn: 'root' }) export class LinkParserService { - - supportFiles = signal([".zip", ".cbz", ".pdf", ".mobi"]) - supportSites = signal([ "Imgur", "Telegra.ph", diff --git a/src/app/link-parser/link-parser/link-parser.component.html b/src/app/link-parser/link-parser/link-parser.component.html index e1f42ac..c92121b 100644 --- a/src/app/link-parser/link-parser/link-parser.component.html +++ b/src/app/link-parser/link-parser/link-parser.component.html @@ -3,7 +3,7 @@ @defer (on immediate) { 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 d2486e8..9c3cfb3 100644 --- a/src/app/link-parser/link-parser/link-parser.component.ts +++ b/src/app/link-parser/link-parser/link-parser.component.ts @@ -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 { take } from 'rxjs'; +import { FileService } from '../../file/data-access/file.service'; @Component({ selector: 'app-link-parser', @@ -28,6 +29,7 @@ export class LinkParserComponent { private lang: LangService = inject(LangService) public parser: LinkParserService = inject(LinkParserService) public setts = inject(LinkParserSettingsService) + public file = inject(FileService) constructor() { } diff --git a/src/app/link-parser/ui/parser-form/parser-form.component.html b/src/app/link-parser/ui/parser-form/parser-form.component.html index 7c61aee..fa4fffe 100644 --- a/src/app/link-parser/ui/parser-form/parser-form.component.html +++ b/src/app/link-parser/ui/parser-form/parser-form.component.html @@ -1,43 +1,43 @@ +@let ph = lang.ph(); @let online = net.online(); -@let openFileLabel = (online) ? '📃 '+lang.ph().orOpenFile: '📃 '+lang.ph().openFile; +@let openFileLabel = (online) ? '📃 '+ph.orOpenFile: '📃 '+ph.openFile;
@if (online === false ) {
- 🚫 No internet connection + 🚫 {{ph.noInternet}}
} -

+

+ +

@if (online) {
+ autofocus [placeholder]="'🔗 '+ph.enterLink" (input)="inputLink($event)" [value]="link()">
} - +

@if (setts.seasonalTheme != undefined && setts.seasonalTheme()) { - @switch (setts.theme()) { - @case ('pride') { {{lang.ph().sloganPride}} 🏳️‍🌈} - @case ('halloween') { {{lang.ph().sloganHalloween}} 🕷️} - @case ('newyear') { {{lang.ph().sloganNewYear}} 🎇} - @case ('valentine') { {{lang.ph().sloganValentine}} ❤️📖} + @let theme = seasonalTheme().get(setts.theme()); + @if(theme) { + {{ph.getByKey(theme.phrase)}} {{theme?.emoji}} } } @else { - {{lang.ph().slogan}} + {{ph.slogan}} }

@if (linkParams()) { - {{lang.ph().letsgo}} + {{ph.letsgo}} {{linkParams()?.id | truncate}} diff --git a/src/app/link-parser/ui/parser-form/parser-form.component.ts b/src/app/link-parser/ui/parser-form/parser-form.component.ts index 9a9a1e1..cad0761 100644 --- a/src/app/link-parser/ui/parser-form/parser-form.component.ts +++ b/src/app/link-parser/ui/parser-form/parser-form.component.ts @@ -7,6 +7,7 @@ import { LinkParserService } from '../../data-access/link-parser.service'; import { ImgurLinkParser, MangadexLinkParser, TelegraphLinkParser, RedditLinkParser, ZenkoLinkParser, NhentaiLinkParser, YandereParser, PixivLinkParser, JsonLinkParser } from '../../utils'; import { ImgchestLinkParser } from '../../utils/imgchest-link-parser'; import { NetworkService, BrowserService } from '../../../shared/data-access/'; +import { FileService } from '../../../file/data-access/file.service'; @Component({ selector: 'app-parser-form', @@ -18,6 +19,7 @@ import { NetworkService, BrowserService } from '../../../shared/data-access/'; export class ParserFormComponent { private router: Router = inject(Router); private route: ActivatedRoute = inject(ActivatedRoute); + file = inject(FileService); setts = inject(LinkParserSettingsService) net = inject(NetworkService); browser = inject(BrowserService); @@ -117,4 +119,12 @@ export class ParserFormComponent { // blankary: '//blankary.com/favicon.ico', read: 'data:image/svg+xml,🗯️' } + + seasonalTheme = signal(new Map([ + ["pride", { class: 'slogan-rainbow', phrase: "sloganPride", emoji: '🏳️‍🌈' }], + ["halloween", { class: 'slogan-halloween', phrase: 'sloganHalloween', emoji: '🕷️' }], + ["newyear", { class: 'slogan-newyear', phrase: 'sloganNewYear', emoji: '🎇' }], + ["valentine", { class: 'slogan-valentine', phrase: 'sloganValentine', emoji: '❤️📖' }] + ])); + } diff --git a/src/app/shared/ui/chytanka-logo-with-tags/chytanka-logo-with-tags.component.scss b/src/app/shared/ui/chytanka-logo-with-tags/chytanka-logo-with-tags.component.scss index 91baecf..98b2203 100644 --- a/src/app/shared/ui/chytanka-logo-with-tags/chytanka-logo-with-tags.component.scss +++ b/src/app/shared/ui/chytanka-logo-with-tags/chytanka-logo-with-tags.component.scss @@ -75,6 +75,9 @@ ul { align-items: anchor-center; align-self: start; justify-content: center; + margin: 0; + padding: 0; + width: 100%; } .tag { diff --git a/src/app/shared/ui/text-embracer/text-embracer.component.ts b/src/app/shared/ui/text-embracer/text-embracer.component.ts index 3d65f73..68f6d53 100644 --- a/src/app/shared/ui/text-embracer/text-embracer.component.ts +++ b/src/app/shared/ui/text-embracer/text-embracer.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Signal, computed, input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core'; @Component({ selector: 'app-text-embracer', @@ -8,13 +8,6 @@ import { ChangeDetectionStrategy, Component, Signal, computed, input } from '@an standalone: false }) export class TextEmbracerComponent { - text = input('') - - public letters: Signal = computed(() => this.split(this.text())); - - split(text: string) { - return Array.from(text); - } - + protected letters = computed(() => Array.from(this.text())); } diff --git a/src/app/shared/ui/viewer/components/viewer-header/viewer-header.component.html b/src/app/shared/ui/viewer/components/viewer-header/viewer-header.component.html index 222661d..640ce55 100644 --- a/src/app/shared/ui/viewer/components/viewer-header/viewer-header.component.html +++ b/src/app/shared/ui/viewer/components/viewer-header/viewer-header.component.html @@ -2,7 +2,7 @@ @if(!embedHelper.isEmbedded()){ 🏠 - + } @else { diff --git a/src/app/shared/ui/viewer/components/viewer-header/viewer-header.component.ts b/src/app/shared/ui/viewer/components/viewer-header/viewer-header.component.ts index c48bf43..a8a3582 100644 --- a/src/app/shared/ui/viewer/components/viewer-header/viewer-header.component.ts +++ b/src/app/shared/ui/viewer/components/viewer-header/viewer-header.component.ts @@ -9,6 +9,7 @@ import { parseTags, resolveViewMode } from '../../../../utils'; import { isPlatformBrowser } from '@angular/common'; import { GamepadService } from '../../../../data-access/gamepad.service'; import { GamepadButton } from '../../../../models'; +import { FileService } from '../../../../../file/data-access/file.service'; @Component({ selector: 'app-viewer-header', @@ -24,6 +25,7 @@ export class ViewerHeaderComponent { domMan = inject(DomManipulationService) viewer = inject(ViewerService) lang = inject(LangService) + file = inject(FileService); embedHelper = inject(EmbedHalperService); gamepad = inject(GamepadService); // #endregion diff --git a/src/app/shared/utils/phrases.ts b/src/app/shared/utils/phrases.ts index fadfe08..0c4dcb0 100644 --- a/src/app/shared/utils/phrases.ts +++ b/src/app/shared/utils/phrases.ts @@ -65,6 +65,7 @@ export class Phrases { ch = "Ch" sitesHistory = "Sites history" filesHistory = "Files history" + noInternet = "No internet connection" getByKey = (key: string) => (Object.keys(this).includes(key)) ? this[key as keyof Phrases] : null; static getTemplate(phrase: string, value: string) { diff --git a/src/assets/langs/uk.json b/src/assets/langs/uk.json index fa1fe47..7695fd1 100644 --- a/src/assets/langs/uk.json +++ b/src/assets/langs/uk.json @@ -61,5 +61,6 @@ "vol": "Том", "ch": "Розд", "sitesHistory": "Історія сайтів", - "filesHistory": "Історія файлів" + "filesHistory": "Історія файлів", + "noInternet": "Немає підключення до інтернету" } \ No newline at end of file diff --git a/src/environments/environment.development.ts b/src/environments/environment.development.ts index 4713780..d01f5bb 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.48-2026.3.24", + version: "0.13.50-2026.3.26", prod: false, proxy: PROXY, blankaryoHost: `https://blankary.com/page/`, diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 25ea463..da9c301 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.48-2026.3.24", + version: "0.13.50-2026.3.26", prod: true, proxy: PROXY, blankaryoHost: `https://blankary.com/page/`,