From 52d0a46c709dbf9b18a3ef75cc957eb64b111cc6 Mon Sep 17 00:00:00 2001 From: Zakhar Timoshenko Date: Sat, 14 Oct 2023 20:26:56 +0300 Subject: [PATCH] Dev section --- .vitepress/config/en.ts | 66 +++++------ .vitepress/config/hooks/generateOgImages.ts | 4 +- .vitepress/config/shortcodes.ts | 4 + .vitepress/theme/components/HomeHero.vue | 9 ++ .../theme/components/OgImageTemplate.vue | 1 + website/contribute/index.md | 31 ----- website/dev/contribute/index.md | 110 ++++++++++++++++++ website/dev/parsers-library/index.md | 59 ++++++++++ website/dev/sync-server/index.md | 53 +++++++++ website/index.md | 6 +- website/manuals/guides/synchronization.md | 37 +++++- 11 files changed, 310 insertions(+), 70 deletions(-) delete mode 100644 website/contribute/index.md create mode 100644 website/dev/contribute/index.md create mode 100644 website/dev/parsers-library/index.md create mode 100644 website/dev/sync-server/index.md diff --git a/.vitepress/config/en.ts b/.vitepress/config/en.ts index facd545..b9614bb 100644 --- a/.vitepress/config/en.ts +++ b/.vitepress/config/en.ts @@ -88,10 +88,6 @@ function defaultSidebar(): DefaultTheme.SidebarItem[] { text: "Changelogs", link: "/changelogs/", }, - { - text: "Contribute", - link: "/contribute/", - }, ], }, { @@ -111,26 +107,26 @@ function defaultSidebar(): DefaultTheme.SidebarItem[] { text: "Sources", link: "/manuals/faq/explore/sources" }, - { + /* { text: "Local storage", link: "/manuals/faq/explore/local-storage", - }, - { + }, */ + /* { text: "Bookmarks", link: "/manuals/faq/explore/bookmarks", }, { text: "Random", link: "/manuals/faq/explore/random", - }, + }, */ { text: "Downloads", link: "/manuals/faq/explore/downloads", }, - { + /* { text: "Suggestions", link: "/manuals/faq/explore/suggestions", - }, + }, */ ], }, { @@ -172,27 +168,29 @@ function defaultSidebar(): DefaultTheme.SidebarItem[] { { text: "Backups", link: "/manuals/guides/backups" }, { text: "Tracking", link: "/manuals/guides/tracking" }, { text: "Categories", link: "/manuals/guides/categories" }, - { - text: "Local storage", - link: "/manuals/guides/local-storage/", - collapsed: true, - items: [ - { - text: "Advanced editing", - link: "/manuals/guides/local-source/advanced", - }, - ], - }, - { - text: "Reader settings", - link: "/manuals/guides/reader-settings", - }, { text: "Synchronization", link: "/manuals/guides/synchronization" } ], }, + { + text: "For developers", + items: [ + { + text: "Contribute", + link: "/dev/contribute/", + }, + { + text: "Parsers library", + link: "/dev/parsers-library/", + }, + { + text: "Synchronization server", + link: "/dev/sync-server/", + }, + ] + } ] } @@ -213,19 +211,19 @@ function getNav(): DefaultTheme.NavItem[] { ], }, { - text: "Manual", + text: "User manual", link: "/manuals/guides/getting-started", activeMatch: "/manuals/", }, - /* { - text: "News", - link: "/news/", - activeMatch: "/news/", + { + text: "Desktop app", + link: "/desktop/", + activeMatch: "/desktop/", }, { - text: "Account", - link: "/account/", - activeMatch: "/account/" - } */ + text: "News", + link: "/news/", + activeMatch: "/news/" + } ] } \ No newline at end of file diff --git a/.vitepress/config/hooks/generateOgImages.ts b/.vitepress/config/hooks/generateOgImages.ts index 3767c4f..d6a6469 100644 --- a/.vitepress/config/hooks/generateOgImages.ts +++ b/.vitepress/config/hooks/generateOgImages.ts @@ -64,7 +64,9 @@ function getDir(url: string) { return "News" } else if (url.startsWith("/sandbox/")) { return "Sandbox" - } else if (url !== "/manuals/faq/" && url !== "/manuals/guides/" && url !== "/news/" && url !== "/sandbox/") { + } else if (url.startsWith("/dev/")) { + return "Dev" + } else if (url !== "/manuals/faq/" && url !== "/manuals/guides/" && url !== "/news/" && url !== "/sandbox/" && url !== "/dev/") { return "Other" } diff --git a/.vitepress/config/shortcodes.ts b/.vitepress/config/shortcodes.ts index ca79d3b..125dec3 100644 --- a/.vitepress/config/shortcodes.ts +++ b/.vitepress/config/shortcodes.ts @@ -57,6 +57,10 @@ const navigationMappings: Record = { "checking": { name: "Check for new chapters", icon: iconMappings.feed, dependsOn: "main_settings" }, "services": { name: "Services", icon: iconMappings.services, dependsOn: "main_settings" }, "about": { name: "About", icon: iconMappings.about, dependsOn: "main_settings" }, + + // Sync + "sync_settings": { name: "Synchronization settings", dependsOn: "services" }, + "server_address": { name: "Server address", dependsOn: "sync_settings" } } function generateNavigationHtml(navKey: string) { diff --git a/.vitepress/theme/components/HomeHero.vue b/.vitepress/theme/components/HomeHero.vue index eaea1b5..71249f3 100644 --- a/.vitepress/theme/components/HomeHero.vue +++ b/.vitepress/theme/components/HomeHero.vue @@ -47,6 +47,9 @@ defineProps<{ section { padding: 42px 32px; + background: var(--vp-c-bg-soft); + border-radius: var(--vp-border-radius); + margin: 48px 96px; } #hero { @@ -113,6 +116,9 @@ html:not(.dark) .accent, } @media (max-width: 768px) { + section { + margin: 24px; + } .tagline { font-size: 48px; letter-spacing: -0.5px; @@ -120,6 +126,9 @@ html:not(.dark) .accent, } @media (max-width: 576px) { + section { + margin: 24px; + } #hero { padding: 56px 32px; } diff --git a/.vitepress/theme/components/OgImageTemplate.vue b/.vitepress/theme/components/OgImageTemplate.vue index 04f5fe1..2995add 100644 --- a/.vitepress/theme/components/OgImageTemplate.vue +++ b/.vitepress/theme/components/OgImageTemplate.vue @@ -26,6 +26,7 @@ defineProps<{ title: string; description?: string; dir?: string }>() + diff --git a/website/contribute/index.md b/website/contribute/index.md deleted file mode 100644 index d9c3415..0000000 --- a/website/contribute/index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Contribute -description: Find out how to help translate or build the app and parsers. -lastUpdated: false -editLink: false -prev: false -next: false ---- - -# Contribute -Find out how to help translate or build the app and parsers. - -## Code -Know how to code and want to improve something or you generally want to support the creation of the app? - -[![KotatsuApp/Kotatsu - GitHub](https://gh-card.dev/repos/KotatsuApp/Kotatsu.svg)](https://github.com/KotatsuApp/Kotatsu) - -[![KotatsuApp/kotatsu-parsers - GitHub](https://gh-card.dev/repos/KotatsuApp/kotatsu-parsers.svg)](https://github.com/KotatsuApp/kotatsu-parsers) - -[![KotatsuApp/website - GitHub](https://gh-card.dev/repos/KotatsuApp/website.svg)](https://github.com/KotatsuApp/website) - -## Translation -![Graph of Weblate Translations](https://hosted.weblate.org/widgets/kotatsu/-/strings/open-graph.png) - -Want to help translate the app to your language? You can easily help by utilizing a service we use called **Weblate**. - -### Helpful links -* [Translators guide](https://docs.weblate.org/en/latest/user/translating.html) -* [Secondary languages](https://docs.weblate.org/en/latest/user/profile.html#secondary-languages) -* [Subscriptions](https://docs.weblate.org/en/latest/user/profile.html#subscriptions) -* [Glossary](https://docs.weblate.org/en/latest/user/translating.html#glossary) \ No newline at end of file diff --git a/website/dev/contribute/index.md b/website/dev/contribute/index.md new file mode 100644 index 0000000..f079257 --- /dev/null +++ b/website/dev/contribute/index.md @@ -0,0 +1,110 @@ +--- +title: Contribute +description: Find out how to help translate or build the app and parsers. +--- + +# Contribute +Find out how to help translate or build the app and parsers. + +## App contribution guidelines +- If you want to fix bug or implement a new feature, that already mention in the [issues](https://github.com/KotatsuApp/Kotatsu/issues), please, assign this issue to you and/or comment about it. +- Whether you have to implement new feature, please, open an issue or discussion regarding it to ensure it will be accepted. +- Translations have to be managed using the [Weblate](https://hosted.weblate.org/engage/kotatsu/) platform. +- In case you want to add a new manga source, refer to the [parsers repository](https://github.com/KotatsuApp/kotatsu-parsers). + +Refactoring or some dev-faces improvements are also might be accepted, however please stick to the following principles: +- Performance matters. In the case of choosing between source code beauty and performance, performance should be a priority. +- Please, do not modify readme and other information files (except for typos). +- Avoid adding new dependencies unless required. APK size is important. + +## Parsers contribution guidelines +The following is guide for creating a Kotatsu parsers. Thanks for taking the time to contribute! + +### Prerequisites +Before you start, please note that the ability to use following technologies is **required**. + +- Basic [Android development](https://developer.android.com/) +- [Kotlin](https://kotlinlang.org/) +- Web scraping ([JSoup](https://jsoup.org/)) or JSON API + +#### Tools + +- [Android Studio](https://developer.android.com/studio) +- [IntelliJ IDEA](https://www.jetbrains.com/idea/) (Community edition is enough) +- Android device (or emulator) + +Kotatsu parsers is not a part of Android application, but you can easily develop and test it directly inside an Android +application project and relocate it to the library project when done. + +#### Before you start + +First, take a look at `kotatsu-parsers` project structure. Each parser is a single class that +extends `MangaParser` class and have a `MangaSourceParser` annotation. +Also pay attention on extensions in `util` package. For example, extensions from `Jsoup` file +should be used instead of existing JSoup functions because they have better nullability support +and improved error messages. + +### Writing your parser + +So, you want to create a parser, that will provide access to manga from a website. +First, you should explore a website for API availability. +If it does not contain any documentation about +API, [explore network requests](https://firefox-source-docs.mozilla.org/devtools-user/): +some websites use ajax. + +- [Example](https://github.com/KotatsuApp/kotatsu-parsers/blob/master/src/main/kotlin/org/koitharu/kotatsu/parsers/site/ru/DesuMeParser.kt) + of Json API usage. +- [Example](https://github.com/KotatsuApp/kotatsu-parsers/blob/master/src/main/kotlin/org/koitharu/kotatsu/parsers/site/be/AnibelParser.kt) + of GraphQL API usage +- [Example](https://github.com/KotatsuApp/kotatsu-parsers/blob/master/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/MangaTownParser.kt) + of pure HTML parsing. + +If website is based on some engine it is rationally to use common base class for this one (for example, Madara wordress +theme +and the `MadaraParser` class) + +#### Parser class skeleton + +Parser class must have exactly one primary constructor parameter of type `MangaLoaderContext` and have an +`MangaSourceParser` annotation that provides internal name, title and language of a manga source. + +All functions in `MangaParser` class are documented. Pay attention to some peculiarities: + +- Never hardcode domain. Specify default domain in `configKeyDomain` field and obtain an actual one using `getDomain()`. +- All ids must be unique and domain-independent. Use `generateUid` functions with relative url or some internal id which + is unique across the manga source. +- `sortOrders` set should not be empty. If your source is not support sorting, specify one most relevance value. +- If you cannot obtain direct links to pages images inside `getPages` method, it is ok to use an intermediate url + as `Page.url` and fetch a direct link at `getPageUrl` function. +- You can use _asserts_ to check some optional fields. For example. `Manga.author` field is not required, but if your + source provide such information, add `assert(it != null)`. This will not have any effect on production but help to + find issues during unit testing. +- If your source website (or it's api) uses pages for pagination instead of offset you should extend `PagedMangaParser` + instead of `MangaParser`. +- Your parser may also implement the `Interceptor` interface for additional manipulation of all network requests and/or + responses, including image loading. + +### Development process + +During the development it is recommended (but not necessary) to write it directly +in the Kotatsu android application project. You can use `core.parser.DummyParser` class as a sandbox. `Dummy` manga +source is available in debug Kotatsu build. + +Once parser is ready you can relocate your code into `kotatsu-parsers` library project in a `site` package and create a +Pull Request. + +#### Testing + +It is recommended to run unit tests before submitting a PR. + +- Temporary modify the `MangaSources` annotation class: specify your parser(s) name(s) and change mode to `EnumSource.Mode.INCLUDE` +- Run the `MangaParserTest` +```bash +gradlew :test --tests "org.koitharu.kotatsu.parsers.MangaParserTest" +``` +- Optionally, you can run the `generateTestsReport` gradle task to get a pretty readable html report from test results. + +### Help + +If you need a help or have some questions, ask a community in our [Telegram chat](https://t.me/kotatsuapp) +or [Discord server](https://discord.gg/NNJ5RgVBC5). \ No newline at end of file diff --git a/website/dev/parsers-library/index.md b/website/dev/parsers-library/index.md new file mode 100644 index 0000000..e56c1a3 --- /dev/null +++ b/website/dev/parsers-library/index.md @@ -0,0 +1,59 @@ +--- +title: Parsers library +description: Instructions for using the Kotatsu parser library. +--- + +# Kotatsu parsers +This library provides manga sources. + +## Usage +Add it to your root `build.gradle` at the end of repositories: + +```groovy{4} +allprojects { + repositories { + ... + maven { url 'https://jitpack.io' } // [!code focus] + } +} +``` +Add the dependency + +:::tip For Java/Kotlin project: +```groovy +dependencies { + implementation("com.github.KotatsuApp:kotatsu-parsers:$parsers_version") +} +``` +::: + +:::tip For Android project: +```groovy +dependencies { + implementation("com.github.KotatsuApp:kotatsu-parsers:$parsers_version") { + exclude group: 'org.json', module: 'json' + } +} +``` +::: + +Versions are available on [JitPack](https://jitpack.io/#KotatsuApp/kotatsu-parsers) + +:::tip Usage in code +```kotlin +val parser = mangaLoaderContext.newParserInstance(MangaSource.MANGADEX) +``` +::: + +`mangaLoaderContext` is an implementation of the `MangaLoaderContext` class. + +See examples +of [Android](https://github.com/KotatsuApp/Kotatsu/blob/devel/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt) +and [Non-Android](https://github.com/KotatsuApp/kotatsu-dl/blob/master/src/main/kotlin/org/koitharu/kotatsu_dl/env/MangaLoaderContextImpl.kt) implementation. + +Note that the `MangaSource.LOCAL` and `MangaSource.DUMMY` parsers cannot be instantiated. + +## DMCA disclaimer + +The developers of this application have no affiliation with the content available in the app. It is collected from +sources freely available through any web browser. \ No newline at end of file diff --git a/website/dev/sync-server/index.md b/website/dev/sync-server/index.md new file mode 100644 index 0000000..f31d0eb --- /dev/null +++ b/website/dev/sync-server/index.md @@ -0,0 +1,53 @@ +--- +title: Synchronization server +description: Instructions for installing the synchronization server. +--- + +# Synchronization server +Instructions for installing the synchronization server. + +## Installation + +### Docker +Build image container: + +```bash +docker build github.com/KotatsuApp/kotatsu-syncserver.git -t kotatsuapp/syncserver +``` + +Run container: + +```bash +docker run -d -p 8081:8080 \ +-e DATABASE_HOST=your_db_host \ +-e DATABASE_USER=your_db_user \ +-e DATABASE_PASSWORD=your_db_password \ +-e DATABASE_NAME=your_db_name \ +-e DATABASE_PORT=your_db_port \ +-e JWT_SECRET=your_secret \ +--restart always \ +--name kotatsu-sync kotatsuapp/syncserver +``` + +### Systemd +Requirements: +- JDK 11+ +- Gradle 7.0+ + +Commands: + +```bash +git clone https://github.com/KotatsuApp/kotatsu-syncserver.git +cd kotatsu-syncserver && ./gradlew shadowJar +``` + +Then edit file `kotatsu-sync.service`, change `replaceme` fields with your values and specify the `kotatsu-syncserver-0.0.1.jar` file location (it can be found in `build/libs` directory after buliding) + +```bash +cp kotatsu-sync.service /etc/systemd/system +systemctl enable kotatsu-sync +systemctl daemon-reload +systemctl start kotatsu-sync +``` + +For any questions, please, contact us in [Telegram group](https://t.me/kotatsuapp) or write an issue, thanks. \ No newline at end of file diff --git a/website/index.md b/website/index.md index 035bbce..02d6841 100644 --- a/website/index.md +++ b/website/index.md @@ -8,11 +8,11 @@ main: tagline: A simple and convenient open source manga reader from and for the community, where you can find and read your favorite manga easier than ever. actions: - theme: brand - text: Get started - link: /manuals/guides/getting-started - - theme: alt text: Download link: /download/ + - theme: alt + text: Manuals + link: /manuals/guides/getting-started features: - icon: title: Huge count of sources diff --git a/website/manuals/guides/synchronization.md b/website/manuals/guides/synchronization.md index bd0ebe8..4feaf09 100644 --- a/website/manuals/guides/synchronization.md +++ b/website/manuals/guides/synchronization.md @@ -1,4 +1,39 @@ --- title: Synchronization description: Allows you to continue reading on your device from where you left off on another device. ---- \ No newline at end of file +--- + +# Synchronization +Allows you to continue reading on your device from where you left off on another device. + +List of official servers: + +| Domain | IP:Port | Location | +| ---------------- | ------------------ | ---------------- | +| sync.kotatsu.app | 86.57.183.214:8081 | Belarus | +| - | 86.57.183.214:1337 | Belarus (Mirror) | + +## What is synchronization? +Synchronization is needed to store your collection of favorites, history and categories and have remote access to them. On a synchronized device, you can restore your manga collection in real time without loss. It also supports working across multiple devices. It is convenient for those who use several devices. + +## How does synchronization work? + - An account is created and configured in the application where it will store data; + - Synchronization starts. The data selected by the user is saved on the service and stored there under protection; + - Another device connects and syncs with the service; + - The uploaded data appears on the device connected to the account. + +## What data can be synchronized? + - Favorites (with categories); + - History. + +## How do I sync my data? +Go to