From e1e4b1996ff42ffe24f5a28a82ea92536d6a220c Mon Sep 17 00:00:00 2001 From: Andrii Rodzyk Date: Wed, 21 Feb 2024 18:18:14 +0200 Subject: [PATCH 1/2] fix: Reddit image media type --- src/app/reddit/data-access/reddit.service.ts | 9 +++++++-- src/app/shared/ui/viewer/viewer.component.html | 2 +- src/app/shared/ui/viewer/viewer.component.scss | 11 +++++++++++ src/app/shared/ui/viewer/viewer.component.ts | 1 + 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/app/reddit/data-access/reddit.service.ts b/src/app/reddit/data-access/reddit.service.ts index 204d802..8509ada 100644 --- a/src/app/reddit/data-access/reddit.service.ts +++ b/src/app/reddit/data-access/reddit.service.ts @@ -18,16 +18,21 @@ export class RedditService { map(data: any): CompositionEpisode { + const media_metadata = data[0].data.children[0].data.media_metadata + const imgs = data[0]?.data.children[0]?.data?.gallery_data?.items - ?? Object.keys(data[0].data.children[0].data.media_metadata).map(i => { return { media_id: i } }); + ?? Object.keys(media_metadata).map(i => { return { media_id: i } }); const post = data[0].data.children[0].data; const res: CompositionEpisode = { title: post.title, nsfw: post.thumbnail == "nsfw" || post.over_18, images: imgs.map((i: any): any => { + const ext = (media_metadata[i.media_id]?.m).replace('image/', ''); return { - src: `https://i.redd.it/${i.media_id}.jpg`, + src: `https://i.redd.it/${i.media_id}.${ext ?? 'jpg'}`, + height: (media_metadata[i.media_id]?.s).y, + width: (media_metadata[i.media_id]?.s).x, } }) diff --git a/src/app/shared/ui/viewer/viewer.component.html b/src/app/shared/ui/viewer/viewer.component.html index 9c30631..b886135 100644 --- a/src/app/shared/ui/viewer/viewer.component.html +++ b/src/app/shared/ui/viewer/viewer.component.html @@ -60,7 +60,7 @@

- 🏠 |{{episode?.title}} + 🏠 {{separator}}{{episode?.title}} diff --git a/src/app/shared/ui/viewer/viewer.component.scss b/src/app/shared/ui/viewer/viewer.component.scss index 7f45849..3560ce7 100644 --- a/src/app/shared/ui/viewer/viewer.component.scss +++ b/src/app/shared/ui/viewer/viewer.component.scss @@ -110,4 +110,15 @@ display: block; justify-self: end; opacity: .8; } +} + +span.title { + text-shadow: 0 0 0.25ch black; + font-weight: bold; + color: white; +} + +span.separator { + user-select: none; + opacity: .5; } \ No newline at end of file diff --git a/src/app/shared/ui/viewer/viewer.component.ts b/src/app/shared/ui/viewer/viewer.component.ts index 05f2fcf..d542dba 100644 --- a/src/app/shared/ui/viewer/viewer.component.ts +++ b/src/app/shared/ui/viewer/viewer.component.ts @@ -15,6 +15,7 @@ import { LangService } from '../../data-access/lang.service'; changeDetection: ChangeDetectionStrategy.OnPush }) export class ViewerComponent { + readonly separator: string = '│' showNsfw: WritableSignal = signal(false); @Input() episode: CompositionEpisode | undefined = undefined; From 853fd5ccc157b340caec7a4d9a942c9d565ba748 Mon Sep 17 00:00:00 2001 From: Andrii Rodzyk Date: Sat, 24 Feb 2024 02:02:05 +0200 Subject: [PATCH 2/2] feat: faq --- .../ui/common-read/common-read.component.scss | 39 ------- src/app/link-parser/link-parser.module.ts | 4 +- .../link-parser/link-parser.component.html | 40 +++++-- .../link-parser/link-parser.component.scss | 108 +++++++++++++++++- .../link-parser/link-parser.component.ts | 98 +++++++++++++--- src/app/link-parser/ui/faq/faq.component.html | 77 +++++++++++++ src/app/link-parser/ui/faq/faq.component.scss | 62 ++++++++++ src/app/link-parser/ui/faq/faq.component.ts | 13 +++ .../data-access/dom-manipulation.service.ts | 6 + src/app/shared/data-access/lang.service.ts | 11 +- src/app/shared/shared.module.ts | 6 +- .../made-in-ukraine.component.ts | 26 +++++ src/app/shared/utils/phrases.ts | 20 +++- src/assets/langs/uk.json | 16 ++- src/index.html | 1 - src/styles.scss | 78 ++++++++++++- 16 files changed, 519 insertions(+), 86 deletions(-) create mode 100644 src/app/link-parser/ui/faq/faq.component.html create mode 100644 src/app/link-parser/ui/faq/faq.component.scss create mode 100644 src/app/link-parser/ui/faq/faq.component.ts create mode 100644 src/app/shared/ui/made-in-ukraine/made-in-ukraine.component.ts diff --git a/src/app/common/common-read/ui/common-read/common-read.component.scss b/src/app/common/common-read/ui/common-read/common-read.component.scss index 8df5eb6..843eb73 100644 --- a/src/app/common/common-read/ui/common-read/common-read.component.scss +++ b/src/app/common/common-read/ui/common-read/common-read.component.scss @@ -33,43 +33,4 @@ place-items: center; gap: 1.5ch; } -} - -.button { - --q: 1; - - user-select: none; - border: 0; - font: inherit; - color: inherit; - padding-inline: calc(var(--q) * 1ch); - padding-block: calc(var(--q) * 1ch); - border-radius: .5ch; - cursor: pointer; - background: hsl(203.44 8% 16%); - transition: all .25s ; - text-wrap: balance; - -webkit-tap-highlight-color: transparent; - box-shadow: 0 .1ch .2ch #0004; - - &.mediun { - --q: 1.5 - } - - &.large { - --q: 2 - } - - &.primary { - background: #166496; - } - - &:hover { - background-color: #166496; - color: #ffd60a; - } - - &:active { - background-color: rgba(0, 15, 30, 1); - } } \ No newline at end of file diff --git a/src/app/link-parser/link-parser.module.ts b/src/app/link-parser/link-parser.module.ts index b68d35a..2031004 100644 --- a/src/app/link-parser/link-parser.module.ts +++ b/src/app/link-parser/link-parser.module.ts @@ -5,11 +5,13 @@ import { LinkParserRoutingModule } from './link-parser-routing.module'; import { LinkParserComponent } from './link-parser/link-parser.component'; import { SharedModule } from '../shared/shared.module'; import { FormsModule } from '@angular/forms'; +import { FaqComponent } from './ui/faq/faq.component'; @NgModule({ declarations: [ - LinkParserComponent + LinkParserComponent, + FaqComponent ], imports: [ CommonModule, 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 e9e174f..3bfaaae 100644 --- a/src/app/link-parser/link-parser/link-parser.component.html +++ b/src/app/link-parser/link-parser/link-parser.component.html @@ -8,7 +8,7 @@
{{lang.phrases.slogan}} @if (linkParams()) { - + {{lang.phrases.letsgo}} {{linkParams()?.site}} {{'/'+linkParams()?.id | truncate}} @@ -21,6 +21,7 @@
@defer{ + @@ -28,14 +29,31 @@ @defer{ {{lang.phrases.shortTitle}}, © 2024 - - Github - - - Reddit - - - Blue Sky - + + @for (item of social; track $index) { + + + + } + + -} \ No newline at end of file +} + + +
+
+

🙋‍♂️ {{lang.ph().faq}}

+
+
+ @defer{ } +
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/src/app/link-parser/link-parser/link-parser.component.scss b/src/app/link-parser/link-parser/link-parser.component.scss index a2722ed..535a5fd 100644 --- a/src/app/link-parser/link-parser/link-parser.component.scss +++ b/src/app/link-parser/link-parser/link-parser.component.scss @@ -61,12 +61,12 @@ input[type=url]::placeholder { } } -a { - padding: 1ch; - font-size: smaller; - color: inherit; - text-decoration: none; -} +// a { +// padding: 1ch; +// font-size: smaller; +// color: inherit; +// text-decoration: none; +// } .site-name { text-transform: uppercase; @@ -109,4 +109,100 @@ app-overlay { &::before { content: unset; } +} + +made-in-ukraine { + margin-left: auto; + +} + + +dialog { + --r: 1ch; + --b: 2px; + padding: 0; + max-width: min(calc(100vw - 4ch), 60ch); + max-height: calc(100dvh - 4ch); + border-radius: var(--r); + border: var(--b) solid #166496; + background-color: rgb(0, 15, 30); + color: inherit; + + &::before { + content: 'esc'; + position: fixed; + left: 2ch; + top: 2ch; + display: inline-grid; + place-content: center; + background-color: rgba(0, 39, 65, 1); + border: 1px solid #166496; + height: 3.5ch; + padding: 1ch .75ch; + font-size: smaller; + border-radius: .5ch; + margin: 0 .25ch; + font-family: monospace; + font-weight: bold; + line-height: 1ch; + box-shadow: 0 .35ch #166496; + color: #ffd60a; + opacity: .5; + } + + &::backdrop { + backdrop-filter: blur(.5ch) brightness(.32); + } + + .dialog-wrapper { + display: grid; + max-height: 100%; + grid-template: auto 1fr auto / 1fr; + } + + header, + footer { + background-color: rgb(0, 39, 65); + padding: 1ch 2ch; + } + + header { + border-top-left-radius: calc(var(--r) - var(--b)); + border-top-right-radius: calc(var(--r) - var(--b)); + + h2, + h4 { + margin: 0; + } + } + + footer { + border-bottom-left-radius: calc(var(--r) - var(--b)); + border-bottom-right-radius: calc(var(--r) - var(--b)); + } + + section { + padding: 2ch; + overflow: auto; + } + + &[open] { + display: flex; + } +} + + +:host { + transition: scale .1s ease-in-out; +} + +:host:has(dialog[open]) { + scale: .99; + overflow: hidden; +} + +:host:has(input[type=url]:focus) { + app-overlay { + opacity: 0; + } } \ No newline at end of file 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 786a265..843d500 100644 --- a/src/app/link-parser/link-parser/link-parser.component.ts +++ b/src/app/link-parser/link-parser/link-parser.component.ts @@ -1,10 +1,11 @@ -import { Component, Signal, WritableSignal, computed, signal } from '@angular/core'; +import { Component, ElementRef, HostListener, Signal, ViewChild, WritableSignal, computed, effect, inject, signal } from '@angular/core'; import { LinkParserService } from '../data-access/link-parser.service'; import { ImgurLinkParser, JsonLinkParser, MangadexLinkParser, RedditLinkParser, TelegraphLinkParser } from '../utils'; -import { ActivatedRoute , Router} from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { LangService } from '../../shared/data-access/lang.service'; -import { ViewModeOption } from '../../shared/data-access'; +import { DomManipulationService, ViewModeOption } from '../../shared/data-access'; import { Base64 } from '../../shared/utils'; +import { Title } from '@angular/platform-browser'; const LANG_OPTIONS: ViewModeOption[] = [ { dir: "rtl", mode: "pages", hintPhraceKey: "english", code: "en", emoji: "🇬🇧" }, @@ -19,6 +20,10 @@ const LANG_OPTIONS: ViewModeOption[] = [ ] }) export class LinkParserComponent { + private title: Title = inject(Title); + private router: Router = inject(Router); + private route: ActivatedRoute = inject(ActivatedRoute); + private dm: DomManipulationService = inject(DomManipulationService) link: WritableSignal = signal(''); linkParams: Signal = computed(() => this.parser.parse(this.link())); @@ -32,12 +37,14 @@ export class LinkParserComponent { langOpt = LANG_OPTIONS - optLangValue = () => this.langOpt.filter((opt: any)=>opt.code == this.lang.lang())[0] + optLangValue = () => this.langOpt.filter((opt: any) => opt.code == this.lang.lang())[0] - constructor(private route: ActivatedRoute, private router: Router, public parser: LinkParserService, public lang: LangService) { + constructor(public parser: LinkParserService, public lang: LangService) { this.initParser(); - // console.log( this.); - + + effect(() => { + this.initTitle() + }) } initParser() { @@ -55,13 +62,7 @@ export class LinkParserComponent { } ngOnInit() { - const url: string | null = this.route.snapshot.queryParamMap.get('url'); - - if (url) { - this.link.set(url ?? '') - } else { - this.initFromclipboard(); - } + this.initUrl() } async initFromclipboard() { @@ -69,19 +70,84 @@ export class LinkParserComponent { const text = await navigator.clipboard?.readText() this.link.set(text ?? '') } catch (error) { - + } if (!this.linkParams()) { this.link.set('') } } + initTitle() { + this.title.setTitle(this.lang.ph().title) + } + + initUrl() { + const url: string | null = this.route.snapshot.queryParamMap.get('url'); + + if (url) { + this.link.set(url ?? '') + } else { + this.initFromclipboard(); + } + } onSubmit() { - if(!this.linkParams) return; + if (!this.linkParams) return; const link = `/${this.linkParams().site}/${this.linkParams64().id}` this.router.navigateByUrl(link); } + @ViewChild('dialog', { static: true }) dialogRef!: ElementRef; + dialogElement: WritableSignal = signal(document.createElement('dialog')); + + + ngAfterViewInit() { + this.dialogElement.set(this.dialogRef.nativeElement); + } + + async showHelp() { + this.dialogElement().showModal() + // const mutate = () => { + // this.dialogElement().showModal() + // } + + // this.dm.startViewTransition(mutate) + } + + async closeDialog(event: Event) { + if (event.target instanceof HTMLDialogElement) { + const mutate = () => (event.target as HTMLDialogElement).close(); + + this.dm.startViewTransition(mutate) + } + + } + + @HostListener('window:keydown', ["$event"]) + helpHotKey(event: KeyboardEvent) { + if (event.key === 'F1') { + event.preventDefault() + this.showHelp() + } + } + + social: any[] = [ + { + alt: "Github", + link: "//github.com/chytanka", + logoSrc: "/assets/logos/github-logo.svg" + }, + { + alt: "Reddit", + link: "//www.reddit.com/r/chytanka", + logoSrc: "/assets/logos/reddit-logo.svg" + }, + { + alt: "Blue Sky", + link: "//bsky.app/profile/chytanka.github.io", + logoSrc: "/assets/logos/bsky-logo.svg" + } + ] + } diff --git a/src/app/link-parser/ui/faq/faq.component.html b/src/app/link-parser/ui/faq/faq.component.html new file mode 100644 index 0000000..c9b22e1 --- /dev/null +++ b/src/app/link-parser/ui/faq/faq.component.html @@ -0,0 +1,77 @@ +
+ 🤔 {{lang.ph().whatIsChytanka}} +

{{lang.ph().description}}

+
+ +
+ 📖 {{lang.ph().howToUseChytanka}} +

+
+ +
+ 🌐 {{lang.ph().whatLinks}} +
+
MangaDexImgur
+
+
    +
  • imgur.com/a/{id}
  • +
  • imgur.com/gallery/{id}
  • +
  • imgur.com/t/manga/{id}
  • +
  • imgur.com/t/webtoon/{id}
  • +
  • imgur.com/t/comics/{id}
  • +
+
+
MangaDexTelegra.ph
+
+
    +
  • telegra.ph/{id}
  • +
+
+ +
MangaDexReddit
+
+
    +
  • reddit.com/r/{id}/whatever
  • +
  • reddit.com/u/{id}/whatever
  • +
+
+ +
MangaDexMangaDex
+
+
    +
  • mangadex.org/{id}
  • +
+
+
+

{{lang.ph().whereIdIs}}

+ +
+ + +
+ 📄 {{lang.ph().canIPasteJsonLink}} +

+
+ +
+ 📝 {{lang.ph().whatJsonModel}} +
{
+"title": "Title of the episode",
+"nsfw": false,
+"images": [
+  {
+    "src": "full-link-to-image-1"
+  },
+  {
+    "src": "full-link-to-image-2"
+  },
+  {
+    "src": "full-link-to-image-n"
+  }
+]
+}
+
\ No newline at end of file diff --git a/src/app/link-parser/ui/faq/faq.component.scss b/src/app/link-parser/ui/faq/faq.component.scss new file mode 100644 index 0000000..372eb68 --- /dev/null +++ b/src/app/link-parser/ui/faq/faq.component.scss @@ -0,0 +1,62 @@ +details { + padding: 1.5ch 2ch; + border-radius: .5ch; + border: 1px solid rgb(0, 40, 64); + margin-bottom: 2ch; + transition: all .25s ease-in-out; + + summary { + cursor: pointer; + font-weight: bold; + transition: color .25s cubic-bezier(0.45, 0.05, 0.55, 0.95); + } + + &[open] { + border-color: #166496; + + summary { + color: #ffd60a; + border-bottom: 1px solid #fff2; + padding-bottom: 1ch; + } + } + +} + +dl { + margin: 1rem 0; + padding: 0; + + dt { + align-items: center; + display: flex; + gap: 1ch; + + img { + max-width: 2ch; + height: auto; + max-height: 2ch; + } + } + + dd { + margin: 0 0 1rem; + } +} + +ul { + margin: 0; + padding: 0; + + li { + list-style: square; + list-style-position: inside; + padding-left: 1ch; + + &::marker { + text-combine-upright: all; + content: '\2228 \a0'; + color: #fff5; + } + } +} \ No newline at end of file diff --git a/src/app/link-parser/ui/faq/faq.component.ts b/src/app/link-parser/ui/faq/faq.component.ts new file mode 100644 index 0000000..2589b79 --- /dev/null +++ b/src/app/link-parser/ui/faq/faq.component.ts @@ -0,0 +1,13 @@ +import { Component, inject } from '@angular/core'; +import { LangService } from '../../../shared/data-access/lang.service'; + +@Component({ + selector: 'app-faq', + templateUrl: './faq.component.html', + styleUrl: './faq.component.scss' +}) +export class FaqComponent { + public lang = inject(LangService) + + gistLinkHref: string = `Github Gist` +} diff --git a/src/app/shared/data-access/dom-manipulation.service.ts b/src/app/shared/data-access/dom-manipulation.service.ts index feaaacf..63a980c 100644 --- a/src/app/shared/data-access/dom-manipulation.service.ts +++ b/src/app/shared/data-access/dom-manipulation.service.ts @@ -34,4 +34,10 @@ export class DomManipulationService { behavior: "smooth", }); } + + async startViewTransition(fn: Function) { + ((document as any).startViewTransition) + ? await (document as any).startViewTransition(fn) + : fn(); + } } diff --git a/src/app/shared/data-access/lang.service.ts b/src/app/shared/data-access/lang.service.ts index c7ea0fc..9690133 100644 --- a/src/app/shared/data-access/lang.service.ts +++ b/src/app/shared/data-access/lang.service.ts @@ -23,6 +23,10 @@ export class LangService { phrases: Phrases = new Phrases(); + ph: WritableSignal = signal(new Phrases()); + + getTemplate: (phrase: string, value: string) => string = Phrases.getTemplate; + constructor(private http: HttpClient) { } setLang(lang: string) { @@ -37,10 +41,15 @@ export class LangService { } updateTranslate() { - if (this.lang() == 'en') { this.phrases = new Phrases(); return; } + if (this.lang() == 'en') { + this.phrases = new Phrases(); + this.ph.set(new Phrases()); + return; + } this.getTranslate(this.lang()).subscribe(data =>{ this.phrases = data + this.ph.set(data) }) } diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 9927238..1ec78ec 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -11,6 +11,7 @@ import { ViewModeBarComponent } from './ui/view-mode-bar/view-mode-bar.component import { WarmControlComponent } from './ui/warm-control/warm-control.component'; import { PagesIndicatorComponent } from './ui/pages-indicator/pages-indicator.component'; import { NsfwWarningComponent } from './ui/nsfw-warning/nsfw-warning.component'; +import { MadeInUkraineComponent } from './ui/made-in-ukraine/made-in-ukraine.component'; @@ -24,13 +25,14 @@ import { NsfwWarningComponent } from './ui/nsfw-warning/nsfw-warning.component'; ViewModeBarComponent, WarmControlComponent, PagesIndicatorComponent, - NsfwWarningComponent + NsfwWarningComponent, + MadeInUkraineComponent ], imports: [ CommonModule, FormsModule, RouterModule ], - exports: [TruncatePipe, TextEmbracerComponent, ViewerComponent, OverlayComponent, ViewModeBarComponent] + exports: [TruncatePipe, TextEmbracerComponent, ViewerComponent, OverlayComponent, ViewModeBarComponent, MadeInUkraineComponent] }) export class SharedModule { } diff --git a/src/app/shared/ui/made-in-ukraine/made-in-ukraine.component.ts b/src/app/shared/ui/made-in-ukraine/made-in-ukraine.component.ts new file mode 100644 index 0000000..cc63712 --- /dev/null +++ b/src/app/shared/ui/made-in-ukraine/made-in-ukraine.component.ts @@ -0,0 +1,26 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'made-in-ukraine', + template: `Made in + Ukraine`, + styles: [` + :host { + font-weight: bold; + font-size: x-small; + font-family: 'Courier New', Courier, monospace; + display: grid; + text-transform: uppercase; + opacity: .4; + transition: opacity .25s ease-in-out; + + &:hover { + opacity: 1; + cursor: none; + } + } + `] +}) +export class MadeInUkraineComponent { + +} diff --git a/src/app/shared/utils/phrases.ts b/src/app/shared/utils/phrases.ts index 3df3a57..6a4148a 100644 --- a/src/app/shared/utils/phrases.ts +++ b/src/app/shared/utils/phrases.ts @@ -20,12 +20,22 @@ export class Phrases { ukrainian: string = "Українська" english: string = "English" tryAgain: string = "Try again" + description: string = "Chytanka is a PWA designed for comfortable manga and comic reading. The minimalist design and the night mode feature make reading easy and comfortable." + ok: string = "OK" + help = "Help" + faq = "F.A.Q" + whatIsChytanka = "What is Chytanka?" + howToUseChytanka = "How to use Chytanka?" + whatLinks = "What links does Chytanka support?" + canIPasteJsonLink = "Can I paste a link to a JSON file?" + whatJsonModel = "What should the JSON file model be?" + yesYouCanPasteJsonLink = "Yes, you can, for example, to {value} or to your website." + howToUseChytankaAnswer = "🔗 Just paste the link to the episode into the input field.
🔳 If the link is supported, a button will appear,
🖱️ click it,
📖 and read easily and comfortably! 🛋️" + whereIdIs = ", where {id} is the unique identifier of the post." - getByKey(key: string) { - const keys = Object.keys(this); - - if (keys.includes(key)) return this[key as keyof Phrases] + getByKey = (key: string) => (Object.keys(this).includes(key)) ? this[key as keyof Phrases] : null; - return null; + static getTemplate(phrase: string, value: string) { + return phrase.replace("{value}", value) } } \ No newline at end of file diff --git a/src/assets/langs/uk.json b/src/assets/langs/uk.json index 38512de..b91038a 100644 --- a/src/assets/langs/uk.json +++ b/src/assets/langs/uk.json @@ -15,7 +15,19 @@ "nightlight": "Нічник", "nsfwWarnTitle": "⚠️🔞 Чутливий вміст", "nsfwWarnText": "Наступний вміст може бути чутливим. Рекомендується переглядати його на власний розсуд.", - "nsfwLabelAgree":"Я готовий!", + "nsfwLabelAgree": "Я готовий!", "nsfwLabelDisagree": "Пас, безпека перш за все!", - "tryAgain": "Спробувати ще раз" + "tryAgain": "Спробувати ще раз", + "description": "Читанка це прогресивний веб-застосунок для комфортного читання манґи та коміксів. Мінімалістичний дизайн та функція нічного режиму роблять читання легким та комфортним.", + "ok": "Гаразд", + "help": "Допомога", + "faq": "ЧаПи", + "whatIsChytanka": "Що таке Читанка?", + "howToUseChytanka": "Як користуватися Читанкою?", + "whatLinks": "Які посилання підтримує Читанка?", + "canIPasteJsonLink": "Чи можна вставити посилання на JSON-файл?", + "whatJsonModel": "Якою має бути модель JSON файлу?", + "yesYouCanPasteJsonLink": "Так, можна, наприклад, на {value} або на власний сайт.", + "howToUseChytankaAnswer" : "🔗 Просто встав посилання на епізод у поле введення.
🔳Якщо посилання підтримується, з'явиться кнопка,
🖱️ натисни її,
📖 і читай легко та зручно 🛋️.", + "whereIdIs": ", де {id} — унікальний ідентифікатор допису." } \ No newline at end of file diff --git a/src/index.html b/src/index.html index 2fbf137..701f38b 100644 --- a/src/index.html +++ b/src/index.html @@ -38,7 +38,6 @@ } - diff --git a/src/styles.scss b/src/styles.scss index 09913c8..7c2a540 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,9 +1,9 @@ @import url('https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@1,500&family=Rampart+One&display=swap'); -html { +:root { --surface: hsl(203.44 8% 16%); --text: hsl(200 5% 80%); - + color-scheme: light dark; background-color: var(--surface); color: var(--text); block-size: 100%; @@ -24,4 +24,78 @@ body { box-sizing: border-box; scrollbar-width: thin; scrollbar-color: var(--text) var(--surface); +} + +.button { + --q: 1; + + user-select: none; + border: 0; + font: inherit; + color: inherit; + padding-inline: calc(var(--q) * 1ch); + padding-block: calc(var(--q) * 1ch); + border-radius: .5ch; + cursor: pointer; + background: hsl(203.44 8% 16%); + transition: all .25s; + text-wrap: balance; + -webkit-tap-highlight-color: transparent; + box-shadow: 0 .1ch .2ch #0004; + + &.small { + --q: 0.5 + } + + &.mediun { + --q: 1.5 + } + + &.large { + --q: 2 + } + + &.tshadow { + text-shadow: 0 0 0.25ch #000a; + } + + &.empty { + background: transparent; + } + + &.primary { + background: #166496; + color: white; + } + + + &:hover { + background-color: #166496; + color: #ffd60a; + } + + &:active { + background-color: rgba(0, 15, 30, 1); + } + + &.full { + width: 100%; + } +} + +a { + color: #4081b1; + text-decoration: none; + transition: all .25s ease-in-out; + + &:hover { + color: #ffd60a; + } +} + +a[target="_blank"]:after { + content: " \2197"; + font-size: 0.8em; + opacity: .8; + vertical-align: super; } \ No newline at end of file