43
.github/ISSUE_TEMPLATE/01_report_issue.yml
vendored
43
.github/ISSUE_TEMPLATE/01_report_issue.yml
vendored
@@ -3,26 +3,6 @@ description: Report a source issue in Tachiyomi
|
|||||||
labels: [Bug]
|
labels: [Bug]
|
||||||
body:
|
body:
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: source
|
|
||||||
attributes:
|
|
||||||
label: Source information
|
|
||||||
description: |
|
|
||||||
You can find the extension name and version in **Browse → Extensions**.
|
|
||||||
placeholder: |
|
|
||||||
Example: "Mangahere 1.3.18"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: language
|
|
||||||
attributes:
|
|
||||||
label: Source language
|
|
||||||
placeholder: |
|
|
||||||
Example: "English"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: reproduce-steps
|
id: reproduce-steps
|
||||||
attributes:
|
attributes:
|
||||||
@@ -59,14 +39,25 @@ body:
|
|||||||
- type: input
|
- type: input
|
||||||
id: tachiyomi-version
|
id: tachiyomi-version
|
||||||
attributes:
|
attributes:
|
||||||
label: Tachiyomi version
|
label: Mihon/Komikku version
|
||||||
description: |
|
description: |
|
||||||
You can find your Tachiyomi version in **More → About**.
|
You can find your Mihon/Komikku version in **More → About**.
|
||||||
placeholder: |
|
placeholder: |
|
||||||
Example: "0.14.7"
|
Example: "0.14.7"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: kavita-version
|
||||||
|
attributes:
|
||||||
|
label: Kavita version
|
||||||
|
description: |
|
||||||
|
You can find your Kavita version in **Settings → System**.
|
||||||
|
placeholder: |
|
||||||
|
Example: "0.8.7.2"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
- type: input
|
- type: input
|
||||||
id: android-version
|
id: android-version
|
||||||
attributes:
|
attributes:
|
||||||
@@ -95,13 +86,11 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I have written a short but informative title.
|
- label: I have written a short but informative title.
|
||||||
required: true
|
required: true
|
||||||
- label: I have updated the app to version **[0.14.7](https://github.com/tachiyomiorg/tachiyomi/releases/latest)**.
|
- label: I have updated Mihon/Komikku to last version.
|
||||||
required: true
|
required: true
|
||||||
- label: I have updated all installed extensions.
|
- label: I have updated the extension to last version.
|
||||||
required: true
|
required: true
|
||||||
- label: I have tried the [troubleshooting guide](https://tachiyomi.org/help/guides/troubleshooting/).
|
- label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/mihonapp/mihon/issues/new/choose).
|
||||||
required: true
|
|
||||||
- label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/tachiyomiorg/tachiyomi/issues/new/choose).
|
|
||||||
required: true
|
required: true
|
||||||
- label: I will fill out all of the requested information in this form.
|
- label: I will fill out all of the requested information in this form.
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -3,26 +3,6 @@ description: Suggest a feature to improve an existing source
|
|||||||
labels: [Feature request]
|
labels: [Feature request]
|
||||||
body:
|
body:
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: source
|
|
||||||
attributes:
|
|
||||||
label: Source name
|
|
||||||
description: |
|
|
||||||
You can find the extension name in **Browse → Extensions**.
|
|
||||||
placeholder: |
|
|
||||||
Example: "Mangahere"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: language
|
|
||||||
attributes:
|
|
||||||
label: Source language
|
|
||||||
placeholder: |
|
|
||||||
Example: "English"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: feature-description
|
id: feature-description
|
||||||
attributes:
|
attributes:
|
||||||
@@ -51,9 +31,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I have written a short but informative title.
|
- label: I have written a short but informative title.
|
||||||
required: true
|
required: true
|
||||||
- label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/tachiyomiorg/tachiyomi/issues/new/choose).
|
- label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/mihonapp/mihon/issues/new/choose).
|
||||||
required: true
|
|
||||||
- label: I have updated the app to version **[0.14.7](https://github.com/tachiyomiorg/tachiyomi/releases/latest)**.
|
|
||||||
required: true
|
required: true
|
||||||
- label: I will fill out all of the requested information in this form.
|
- label: I will fill out all of the requested information in this form.
|
||||||
required: true
|
required: true
|
||||||
59
.github/ISSUE_TEMPLATE/02_request_source.yml
vendored
59
.github/ISSUE_TEMPLATE/02_request_source.yml
vendored
@@ -1,59 +0,0 @@
|
|||||||
name: 🌐 Source request
|
|
||||||
description: Suggest a new source for Tachiyomi
|
|
||||||
labels: [Source request]
|
|
||||||
body:
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: name
|
|
||||||
attributes:
|
|
||||||
label: Source name
|
|
||||||
placeholder: |
|
|
||||||
Example: "Not Real Scans"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: link
|
|
||||||
attributes:
|
|
||||||
label: Source link
|
|
||||||
placeholder: |
|
|
||||||
Example: "https://notrealscans.org"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: language
|
|
||||||
attributes:
|
|
||||||
label: Source language
|
|
||||||
placeholder: |
|
|
||||||
Example: "English"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: other-details
|
|
||||||
attributes:
|
|
||||||
label: Other details
|
|
||||||
placeholder: |
|
|
||||||
Additional details and attachments.
|
|
||||||
Example:
|
|
||||||
"18+/NSFW = yes"
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: acknowledgements
|
|
||||||
attributes:
|
|
||||||
label: Acknowledgements
|
|
||||||
description: Your issue will be closed if you haven't done these steps.
|
|
||||||
options:
|
|
||||||
- label: I have checked that the extension does not already exist on the [website extensions list](https://tachiyomi.org/extensions/) or the app.
|
|
||||||
required: true
|
|
||||||
- label: I have checked that the extension is not on [the removed sources list](https://github.com/tachiyomiorg/tachiyomi-extensions/blob/master/REMOVED_SOURCES.md).
|
|
||||||
required: true
|
|
||||||
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue.
|
|
||||||
required: true
|
|
||||||
- label: I have checked that the extension does not already exist by searching the [GitHub repository](https://github.com/tachiyomiorg/tachiyomi-extensions/) and verified it does not appear in the code base.
|
|
||||||
required:
|
|
||||||
- label: I have written a meaningful title with the source name.
|
|
||||||
required: true
|
|
||||||
- label: I will fill out all of the requested information in this form.
|
|
||||||
required: true
|
|
||||||
57
.github/ISSUE_TEMPLATE/03_report_url_change.yml
vendored
57
.github/ISSUE_TEMPLATE/03_report_url_change.yml
vendored
@@ -1,57 +0,0 @@
|
|||||||
name: 🔗 URL change report
|
|
||||||
description: Report URL change of an existing source
|
|
||||||
labels: [Bug,Domain changed]
|
|
||||||
body:
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: source
|
|
||||||
attributes:
|
|
||||||
label: Source information
|
|
||||||
description: |
|
|
||||||
You can find the extension name and version in **Browse → Extensions**.
|
|
||||||
placeholder: |
|
|
||||||
Example: "NotRealScans 1.3.1"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: language
|
|
||||||
attributes:
|
|
||||||
label: Source language
|
|
||||||
placeholder: |
|
|
||||||
Example: "English"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: link
|
|
||||||
attributes:
|
|
||||||
label: Source new URL
|
|
||||||
placeholder: |
|
|
||||||
Example: "https://notrealscans.org"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: other-details
|
|
||||||
attributes:
|
|
||||||
label: Other details
|
|
||||||
placeholder: |
|
|
||||||
Additional details and attachments.
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: acknowledgements
|
|
||||||
attributes:
|
|
||||||
label: Acknowledgements
|
|
||||||
description: Your issue will be closed if you haven't done these steps.
|
|
||||||
options:
|
|
||||||
- label: I have updated all installed extensions.
|
|
||||||
required: true
|
|
||||||
- label: I have opened WebView and checked that the source URL is not updated yet.
|
|
||||||
required: true
|
|
||||||
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue.
|
|
||||||
required: true
|
|
||||||
- label: I have written a short but informative title.
|
|
||||||
required: true
|
|
||||||
- label: I will fill out all of the requested information in this form.
|
|
||||||
required: true
|
|
||||||
@@ -31,11 +31,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I have written a short but informative title.
|
- label: I have written a short but informative title.
|
||||||
required: true
|
required: true
|
||||||
- label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/tachiyomiorg/tachiyomi/issues/new/choose).
|
- label: If this is an issue with the app itself, I should be opening an issue in the [app repository](https://github.com/mihonapp/mihon/issues/new/choose).
|
||||||
required: true
|
|
||||||
- label: I have updated the app to version **[0.14.7](https://github.com/tachiyomiorg/tachiyomi/releases/latest)**.
|
|
||||||
required: true
|
|
||||||
- label: I have updated all installed extensions.
|
|
||||||
required: true
|
required: true
|
||||||
- label: I will fill out all of the requested information in this form.
|
- label: I will fill out all of the requested information in this form.
|
||||||
required: true
|
required: true
|
||||||
63
.github/ISSUE_TEMPLATE/04_report_dead_source.yml
vendored
63
.github/ISSUE_TEMPLATE/04_report_dead_source.yml
vendored
@@ -1,63 +0,0 @@
|
|||||||
name: ❌ Dead source report
|
|
||||||
description: Source is down and website is closed
|
|
||||||
labels: [Source is down]
|
|
||||||
body:
|
|
||||||
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
### Notice
|
|
||||||
If you have a lot of dead sources to report, please go back and submit a single meta request.
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: source
|
|
||||||
attributes:
|
|
||||||
label: Source name
|
|
||||||
description: |
|
|
||||||
You can find the extension name in **Browse → Extensions**.
|
|
||||||
placeholder: |
|
|
||||||
Example: "NotRealScans"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: language
|
|
||||||
attributes:
|
|
||||||
label: Source language
|
|
||||||
placeholder: |
|
|
||||||
Example: "English"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: link
|
|
||||||
attributes:
|
|
||||||
label: Source link
|
|
||||||
placeholder: |
|
|
||||||
Example: "https://notrealscans.org"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: other-details
|
|
||||||
attributes:
|
|
||||||
label: Other details
|
|
||||||
placeholder: |
|
|
||||||
Additional details and attachments.
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: acknowledgements
|
|
||||||
attributes:
|
|
||||||
label: Acknowledgements
|
|
||||||
description: Your issue will be closed if you haven't done these steps.
|
|
||||||
options:
|
|
||||||
- label: I have updated all installed extensions.
|
|
||||||
required: true
|
|
||||||
- label: I have opened WebView and checked that the source website is down.
|
|
||||||
required: true
|
|
||||||
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue.
|
|
||||||
required: true
|
|
||||||
- label: I have written a meaningful title with the source name.
|
|
||||||
required: true
|
|
||||||
- label: I will fill out all of the requested information in this form.
|
|
||||||
required: true
|
|
||||||
33
.github/ISSUE_TEMPLATE/07_request_removal.yml
vendored
33
.github/ISSUE_TEMPLATE/07_request_removal.yml
vendored
@@ -1,33 +0,0 @@
|
|||||||
name: 🗑 Source removal request
|
|
||||||
description: Scanlators can request their site to be removed
|
|
||||||
labels: [Meta request]
|
|
||||||
body:
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: link
|
|
||||||
attributes:
|
|
||||||
label: Source link
|
|
||||||
placeholder: |
|
|
||||||
Example: "https://notrealscans.org"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: other-details
|
|
||||||
attributes:
|
|
||||||
label: Other details
|
|
||||||
placeholder: |
|
|
||||||
Additional details and attachments.
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: requirements
|
|
||||||
attributes:
|
|
||||||
label: Requirements
|
|
||||||
description: Your request will be denied if you don't meet these requirements.
|
|
||||||
options:
|
|
||||||
- label: I've added a `TXT` DNS record for my domain with the value `tachiyomi-verification`
|
|
||||||
required: true
|
|
||||||
- label: Site only hosts content scanlated by the group and not stolen from other scanlators or official releases (i.e., not an aggregator site)
|
|
||||||
required: true
|
|
||||||
- label: Site is not infested with user-hostile features (e.g., invasive or malicious ads)
|
|
||||||
required: true
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* Add or remove modules to load as needed for local development here.
|
* Add or remove modules to load as needed for local development here.
|
||||||
*/
|
*/
|
||||||
loadAllIndividualExtensions()
|
loadAllIndividualExtensions()
|
||||||
// loadIndividualExtension("all", "mangadex")
|
loadIndividualExtension("all", "kavita")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ===================================== COMMON CONFIGURATION ======================================
|
* ===================================== COMMON CONFIGURATION ======================================
|
||||||
|
|||||||
@@ -1,32 +1,107 @@
|
|||||||
login_errors_failed_login=Login failed. Something went wrong
|
# ================ #
|
||||||
login_errors_header_token_empty="Error: The JSON Web Token is empty.\nTry opening the extension first."
|
# Authentication #
|
||||||
login_errors_invalid_url=Invalid URL:
|
# ================ #
|
||||||
login_errors_parse_tokendto=There was an error parsing the auth token
|
login_errors_failed_login=Authentication failed.\nPlease check your credentials
|
||||||
pref_customsource_title=Displayed name for source
|
login_errors_header_token_empty=Authorization token missing\nPlease open the extension first to generate a token
|
||||||
pref_group_tags_title=Group Tags (fork must support grouping)
|
login_errors_invalid_url=Invalid server URL:
|
||||||
pref_group_tags_summary_on=Will prefix tags with their type
|
login_errors_parse_tokendto=Failed to process authentication token
|
||||||
pref_group_tags_summary_off=List all tags together
|
http_errors_401=Authentication expired\nPlease log in again
|
||||||
pref_last_volume_cover_title=Keep cover updated
|
http_errors_500=Server error occurred
|
||||||
pref_last_volume_cover_summary_off=Keep current cover
|
|
||||||
pref_last_volume_cover_summary_on=Use the last volume cover when updating
|
# ============== #
|
||||||
pref_show_epub_title=Show EPUB (EPUB can't be read in Mihon)
|
# Preferences #
|
||||||
pref_show_epub_summary_off=Hide EPUB titles in browsing
|
# ============== #
|
||||||
pref_show_epub_summary_on=Show EPUB titles in browsing
|
pref_customsource_title=Source Display Name
|
||||||
|
pref_edit_customsource_summary=Customize how this Kavita instance appears in your library\nExample: "Home Server" or "Cloud Instance"
|
||||||
|
|
||||||
|
pref_group_tags_title=Tag Grouping (fork must support grouping)
|
||||||
|
pref_group_tags_summary_on=Show tags with category prefixes
|
||||||
|
pref_group_tags_summary_off=Display tags as flat list
|
||||||
|
|
||||||
|
pref_last_volume_cover_title=Keep Cover Updated
|
||||||
|
pref_last_volume_cover_summary_off=Keep series cover
|
||||||
|
pref_last_volume_cover_summary_on=Always show current Volume/Issue cover on refresh
|
||||||
|
|
||||||
|
pref_show_epub_title=EPUB Visibility
|
||||||
|
pref_show_epub_summary_off=Hide EPUB entries
|
||||||
|
pref_show_epub_summary_on=Show EPUB entries (unreadable in Mihon)
|
||||||
|
|
||||||
pref_rd_date_title=Reading List: Display Release Date
|
pref_rd_date_title=Reading List: Display Release Date
|
||||||
pref_rd_date_summary_off=Do not display the release date
|
pref_rd_date_summary_off=Hide publication dates
|
||||||
pref_rd_date_summary_on=Display the release date | !! Once you toggle it on, if you toggle it off again, it will stays as N/A !!
|
pref_rd_date_summary_on=Show publication dates\nNote: Once you toggle it on, if you toggle it off again, it will stays as N/A.
|
||||||
pref_reset_title=Reset All Settings
|
|
||||||
pref_reset_summary=Clear all preferences for this Kavita instance (Only affect the selected instance)
|
pref_reset_title=Reset Settings
|
||||||
pref_edit_customsource_summary=Here you can change this source name.\nYou can write a descriptive name to identify this OPDS URL.
|
pref_reset_summary=Clear all preferences for this Kavita instance
|
||||||
pref_filters_summary=Show these filters in the filter list
|
|
||||||
pref_filters_title=Default filters shown
|
pref_filters_title=Default Filters
|
||||||
pref_opds_badformed_url=Incorrect OPDS address. Please copy it from User settings \u2192 3rd party apps \u2192 OPDS URL
|
pref_filters_summary=Select which filters appear by default
|
||||||
pref_opds_duplicated_source_url=The URL is configured in a different source ->
|
|
||||||
pref_opds_must_setup_address=You must set up the address to communicate with Kavita
|
# ============== #
|
||||||
pref_opds_summary=The OPDS URL copied from User Settings. This should include address and end with the API key.
|
# OPDS Setup #
|
||||||
restartapp_settings=Restart Mihon to apply new setting.
|
# ============== #
|
||||||
version_exceptions_chapters_parse=Unhandled exception parsing chapters. Send your logs to the Kavita devs.
|
pref_opds_must_setup_address=OPDS URL required for connection
|
||||||
check_version=Ensure you have the newest version of the extension and Kavita. (0.7.8 or newer.)\nIf the issue persists, report it to the Kavita developers with the accompanying logs.
|
pref_opds_badformed_url=Invalid OPDS address\nCopy from: User Settings > API Key / OPDS > OPDS URL (settings#clients)
|
||||||
version_exceptions_smart_filter=Could not decode SmartFilter. Ensure you are using Kavita version 0.7.11 or later.
|
pref_opds_duplicated_source_url=URL already used in another source:
|
||||||
http_errors_500=Something went wrong
|
pref_opds_summary=Complete OPDS URL including API key\nFormat: http://address:port/opds?apiKey=XXX
|
||||||
http_errors_401=There was an error logging in. Try again or reload the app
|
|
||||||
|
# ============== #
|
||||||
|
# System Messages #
|
||||||
|
# ============== #
|
||||||
|
restartapp_settings=Restart Mihon to apply changes
|
||||||
|
check_version=Requires Kavita v0.8.7+\nIf issues persist, contact support with logs
|
||||||
|
version_exceptions_chapters_parse=Chapter parsing error\nPlease report with logs
|
||||||
|
version_exceptions_smart_filter=Smart Filter error\nRequires Kavita v0.7.11+
|
||||||
|
|
||||||
|
|
||||||
|
# ============== #
|
||||||
|
# Filters #
|
||||||
|
# ============== #
|
||||||
|
# Filter headers
|
||||||
|
filters_special=These filters can't be combined with other filters
|
||||||
|
filters_people=People Filters
|
||||||
|
filters_special_list=Special Lists
|
||||||
|
filters_smart_filters=Smart Filters
|
||||||
|
|
||||||
|
# @todo
|
||||||
|
# Basic filters
|
||||||
|
filters_user_rating=User Rating
|
||||||
|
filters_status=Status
|
||||||
|
filters_sort=Sort By
|
||||||
|
filters_release_year=Release Year
|
||||||
|
filters_genres=Genres
|
||||||
|
filters_tags=Tags
|
||||||
|
filters_age_ratings=Age Ratings
|
||||||
|
filters_collections=Collections
|
||||||
|
filters_languages=Languages
|
||||||
|
filters_libraries=Libraries
|
||||||
|
filters_pub_status=Publication Status
|
||||||
|
|
||||||
|
# People filters
|
||||||
|
filters_writers=Writers
|
||||||
|
filters_pencillers=Pencillers
|
||||||
|
filters_inkers=Inkers
|
||||||
|
filters_colorists=Colorists
|
||||||
|
filters_letterers=Letterers
|
||||||
|
filters_cover_artists=Cover Artists
|
||||||
|
filters_editors=Editors
|
||||||
|
filters_publishers=Publishers
|
||||||
|
filters_characters=Characters
|
||||||
|
filters_translators=Translators
|
||||||
|
|
||||||
|
# Status options
|
||||||
|
filters_status_any=Any
|
||||||
|
filters_status_unread=Unread
|
||||||
|
filters_status_in_progress=In Progress
|
||||||
|
filters_status_read=Read
|
||||||
|
|
||||||
|
# Sort options
|
||||||
|
filters_sort_title=Title
|
||||||
|
filters_sort_rating=Rating
|
||||||
|
filters_sort_date_added=Date Added
|
||||||
|
filters_sort_release_date=Release Date
|
||||||
|
filters_sort_read_progress=Read Progress
|
||||||
|
|
||||||
|
# Error messages
|
||||||
|
filters_error_loading=Failed to load filters
|
||||||
|
filters_empty_list=No filters available
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,107 @@
|
|||||||
version_exceptions_chapters_parse=Exception non trait\u00E9e durant l'analyse des chapitres. Envoyez les logs aux d\u00E9velopeurs de Kavita.
|
# ================ #
|
||||||
pref_customsource_title=Nom d'affichage pour la source
|
# Authentification #
|
||||||
version_exceptions_smart_filter=\u00C9chec du d\u00E9codage de SmartFilter. Assurez-vous que vous utilisez au moins Kavita version 0.7.11
|
# ================ #
|
||||||
pref_opds_summary=L'URL OPDS a \u00E9t\u00E9 copi\u00E9e \u00E0 partir des param\u00E8tres de l'utilisateur. Ceci devrait inclure l'adresse et la cl\u00E9 API.
|
login_errors_failed_login=Échec de l'authentification. Vérifiez vos identifiants
|
||||||
pref_filters_summary=Afficher ces filtres dans la liste des filtres
|
login_errors_header_token_empty=Token d'autorisation manquant\nOuvrez d'abord l'extension pour générer un token
|
||||||
check_version=Assurez-vous que vous avez l'extension et Kavita mises \u00E0 jour. (version Mini\u202F: 0.7.8)\nSi le probl\u00E8me persiste, signalez-le aux d\u00E9veloppeurs de Kavita en fournissant des journaux
|
login_errors_invalid_url=URL du serveur invalide :
|
||||||
pref_filters_title=Filtres par d\u00E9faut affich\u00E9s
|
login_errors_parse_tokendto=Échec du traitement du token d'authentification
|
||||||
pref_edit_customsource_summary=Ici vous pouvez changer ce nom source.\nVous pouvez \u00E9crire un nom descriptif pour identifier cette URL opds
|
http_errors_401=Authentification expirée. Veuillez vous reconnecter
|
||||||
pref_opds_badformed_url=L'adresse OPDS n'est pas correcte. Veuillez la copier \u00E0 partir des param\u00E8tres de l'utilisateur - > Applis tierces -> URL OPDS
|
http_errors_500=Erreur du serveur
|
||||||
login_errors_parse_tokendto=Il y a eu une erreur pendant l'analyse du jeton d'authentification
|
|
||||||
restartapp_settings=Red\u00E9marrez Mihon pour appliquer le nouveau r\u00E9glage.
|
# ============== #
|
||||||
pref_opds_duplicated_source_url=L'URL est configur\u00E9e dans une autre source ->
|
# Préférences #
|
||||||
pref_opds_must_setup_address=Vous devez configurer l'adresse pour communiquer avec Kavita
|
# ============== #
|
||||||
login_errors_failed_login=\u00C9chec de la connexion. Quelque chose s'est mal pass\u00E9
|
pref_customsource_title=Nom d'affichage de la source
|
||||||
http_errors_500=Quelque chose s'est mal pass\u00E9
|
pref_edit_customsource_summary=Personnalisez l'affichage de cette instance Kavita\nExemple : "Serveur Maison" ou "Instance Cloud"
|
||||||
login_errors_header_token_empty=\u00AB\u00A0Erreur\u202F: le token jwt est vide.\nEssayez d'abord d'ouvrir l'extension\u00A0\u00BB
|
|
||||||
login_errors_invalid_url=URL invalide\u202F:
|
pref_group_tags_title=Groupement des tags (fork doit supporter le groupement)
|
||||||
http_errors_401=Il y a eu une erreur. Essayez de nouveau ou relancez l'application
|
pref_group_tags_summary_on=Afficher les tags avec préfixes
|
||||||
|
pref_group_tags_summary_off=Afficher les tags en liste plate
|
||||||
|
|
||||||
|
pref_last_volume_cover_title=Garder la couverture à jour
|
||||||
|
pref_last_volume_cover_summary_off=Conserver la couverture de la série
|
||||||
|
pref_last_volume_cover_summary_on=Toujours afficher la dernière couverture
|
||||||
|
|
||||||
|
pref_show_epub_title=Visibilité EPUB
|
||||||
|
pref_show_epub_summary_off=Masquer les EPUB
|
||||||
|
pref_show_epub_summary_on=Afficher les EPUB (illisibles dans Mihon)
|
||||||
|
|
||||||
|
pref_rd_date_title=Listes de Lecture: Affichage date de publication
|
||||||
|
pref_rd_date_summary_off=Masquer les dates de publication
|
||||||
|
pref_rd_date_summary_on=Afficher les dates de publication\nNote : Désactiver affichera toujours "N/A" après activation
|
||||||
|
|
||||||
|
pref_reset_title=Réinitialisation
|
||||||
|
pref_reset_summary=Effacer toutes les préférences pour cette instance Kavita
|
||||||
|
|
||||||
|
pref_filters_title=Filtres par défaut
|
||||||
|
pref_filters_summary=Sélectionnez les filtres visibles par défaut
|
||||||
|
|
||||||
|
# ============== #
|
||||||
|
# Configuration OPDS #
|
||||||
|
# ============== #
|
||||||
|
pref_opds_must_setup_address=URL OPDS requise pour la connexion
|
||||||
|
pref_opds_badformed_url=URL OPDS invalide\nCopiez depuis : Paramètres > Clé API / OPDS > URL OPDS
|
||||||
|
pref_opds_duplicated_source_url=URL déjà utilisée dans une autre source :
|
||||||
|
pref_opds_summary=URL OPDS complète incluant la clé API\nFormat : http://adresse:port/opds?apiKey=XXX
|
||||||
|
|
||||||
|
# ============== #
|
||||||
|
# Messages système #
|
||||||
|
# ============== #
|
||||||
|
restartapp_settings=Redémarrez Mihon pour appliquer les changements
|
||||||
|
check_version=Nécessite Kavita v0.8.7+\nSi problème persiste, contactez le support avec les logs
|
||||||
|
version_exceptions_chapters_parse=Erreur d'analyse des chapitres\nMerci de rapporter avec les logs
|
||||||
|
version_exceptions_smart_filter=Erreur Smart Filter\nNécessite Kavita v0.7.11+
|
||||||
|
|
||||||
|
|
||||||
|
# ============== #
|
||||||
|
# Filtres #
|
||||||
|
# ============== #
|
||||||
|
# Filter headers
|
||||||
|
filters_special=Ces filtres ne peuvent pas être combinés avec d'autres filtres
|
||||||
|
filters_people=Filtres Personnalités
|
||||||
|
|
||||||
|
# Special filters
|
||||||
|
filters_special_list=Listes Spéciales
|
||||||
|
filters_smart_filters=Filtres Intelligents
|
||||||
|
|
||||||
|
# Basic filters
|
||||||
|
filters_user_rating=Note Utilisateur
|
||||||
|
filters_status=Statut
|
||||||
|
filters_sort=Trier Par
|
||||||
|
filters_release_year=Année de Sortie
|
||||||
|
filters_genres=Genres
|
||||||
|
filters_tags=Étiquettes
|
||||||
|
filters_age_ratings=Classifications d'Âge
|
||||||
|
filters_collections=Collections
|
||||||
|
filters_languages=Langues
|
||||||
|
filters_libraries=Bibliothèques
|
||||||
|
filters_pub_status=Statut de Publication
|
||||||
|
|
||||||
|
# People filters
|
||||||
|
filters_writers=Auteur
|
||||||
|
filters_pencillers=Dessinateurs
|
||||||
|
filters_inkers=Encreurs
|
||||||
|
filters_colorists=Coloristes
|
||||||
|
filters_letterers=Lettrists
|
||||||
|
filters_cover_artists=Artistes de Couverture
|
||||||
|
filters_editors=Éditeurs
|
||||||
|
filters_publishers=Éditeurs
|
||||||
|
filters_characters=Personnalités
|
||||||
|
filters_translators=Traducteurs
|
||||||
|
|
||||||
|
# Status options
|
||||||
|
filters_status_any=Tous
|
||||||
|
filters_status_unread=Non Lu
|
||||||
|
filters_status_in_progress=En Cours
|
||||||
|
filters_status_read=Lu
|
||||||
|
|
||||||
|
# Sort options
|
||||||
|
filters_sort_title=Titre
|
||||||
|
filters_sort_rating=Note
|
||||||
|
filters_sort_date_added=Date d'Ajout
|
||||||
|
filters_sort_release_date=Date de Sortie
|
||||||
|
filters_sort_read_progress=Progrès de Lecture
|
||||||
|
|
||||||
|
# Error messages
|
||||||
|
filters_error_loading=Échec du chargement des filtres
|
||||||
|
filters_empty_list=Aucun filtre disponible
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ ext {
|
|||||||
kmkVersionCode = 1
|
kmkVersionCode = 1
|
||||||
extName = 'Kavita'
|
extName = 'Kavita'
|
||||||
extClass = '.KavitaFactory'
|
extClass = '.KavitaFactory'
|
||||||
extVersionCode = 19
|
extVersionCode = 20
|
||||||
isNsfw = false
|
isNsfw = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,25 +3,6 @@ package eu.kanade.tachiyomi.extension.all.kavita
|
|||||||
import eu.kanade.tachiyomi.extension.all.kavita.KavitaConstants.noSmartFilterSelected
|
import eu.kanade.tachiyomi.extension.all.kavita.KavitaConstants.noSmartFilterSelected
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
import eu.kanade.tachiyomi.source.model.Filter
|
||||||
|
|
||||||
class UserRating : Filter.Select<Int>(
|
|
||||||
"Minimum Rating",
|
|
||||||
arrayOf(
|
|
||||||
"Any",
|
|
||||||
"1 star",
|
|
||||||
"2 stars",
|
|
||||||
"3 stars",
|
|
||||||
"4 stars",
|
|
||||||
"5 stars",
|
|
||||||
).mapIndexed { index, _ -> index }.toTypedArray(),
|
|
||||||
) {
|
|
||||||
override fun toString(): String {
|
|
||||||
return when (state) {
|
|
||||||
0 -> "Any"
|
|
||||||
else -> "$state star${if (state > 1) "s" else ""}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SmartFiltersFilter(smartFilters: Array<String>) :
|
class SmartFiltersFilter(smartFilters: Array<String>) :
|
||||||
Filter.Select<String>("Smart Filters", arrayOf(noSmartFilterSelected) + smartFilters)
|
Filter.Select<String>("Smart Filters", arrayOf(noSmartFilterSelected) + smartFilters)
|
||||||
class SortFilter(sortables: Array<String>) : Filter.Sort("Sort by", sortables, Selection(0, true))
|
class SortFilter(sortables: Array<String>) : Filter.Sort("Sort by", sortables, Selection(0, true))
|
||||||
@@ -38,15 +19,22 @@ val sortableList = listOf(
|
|||||||
Pair("Random", 9),
|
Pair("Random", 9),
|
||||||
)
|
)
|
||||||
|
|
||||||
class SpecialListFilter : Filter.Select<String>(
|
class SpecialListFilter(name: String = "Special Lists") : Filter.Select<String>(
|
||||||
"Special Lists",
|
name,
|
||||||
arrayOf("None", "Want to Read", "Reading Lists"),
|
arrayOf("None", "Want to Read", "Reading Lists"),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Use Filter.CheckBox directly for status
|
class StatusFilter : Filter.Select<String>(
|
||||||
class StatusFilter(name: String) : Filter.CheckBox(name, false)
|
"Status",
|
||||||
class StatusFilterGroup(filters: List<StatusFilter>) :
|
arrayOf("Any", "Unread", "In Progress", "Read"),
|
||||||
Filter.Group<StatusFilter>("Status", filters)
|
)
|
||||||
|
class StatusSeparator :
|
||||||
|
Filter.Separator()
|
||||||
|
|
||||||
|
class StatusFilterGroup(name: String = "Status") : Filter.Group<StatusFilter>(
|
||||||
|
name,
|
||||||
|
listOf(StatusFilter()),
|
||||||
|
)
|
||||||
|
|
||||||
// Use Filter.Text directly for release year range
|
// Use Filter.Text directly for release year range
|
||||||
class ReleaseYearRange(name: String) : Filter.Text(name, "")
|
class ReleaseYearRange(name: String) : Filter.Text(name, "")
|
||||||
@@ -59,7 +47,8 @@ class GenreFilterGroup(genres: List<GenreFilter>) :
|
|||||||
Filter.Group<GenreFilter>("Genres", genres)
|
Filter.Group<GenreFilter>("Genres", genres)
|
||||||
|
|
||||||
class TagFilter(name: String) : Filter.TriState(name)
|
class TagFilter(name: String) : Filter.TriState(name)
|
||||||
class TagFilterGroup(tags: List<TagFilter>) : Filter.Group<TagFilter>("Tags", tags)
|
class TagFilterGroup(tags: List<TagFilter>) :
|
||||||
|
Filter.Group<TagFilter>("Tags", tags)
|
||||||
|
|
||||||
class AgeRatingFilter(name: String) : Filter.TriState(name)
|
class AgeRatingFilter(name: String) : Filter.TriState(name)
|
||||||
class AgeRatingFilterGroup(ageRatings: List<AgeRatingFilter>) :
|
class AgeRatingFilterGroup(ageRatings: List<AgeRatingFilter>) :
|
||||||
@@ -85,8 +74,29 @@ class PubStatusFilter(name: String) : Filter.CheckBox(name, false)
|
|||||||
class PubStatusFilterGroup(status: List<PubStatusFilter>) :
|
class PubStatusFilterGroup(status: List<PubStatusFilter>) :
|
||||||
Filter.Group<PubStatusFilter>("Publication Status", status)
|
Filter.Group<PubStatusFilter>("Publication Status", status)
|
||||||
|
|
||||||
|
class UserRating : Filter.Select<Int>(
|
||||||
|
"Minimum Rating",
|
||||||
|
arrayOf(
|
||||||
|
"Any",
|
||||||
|
"1 star",
|
||||||
|
"2 stars",
|
||||||
|
"3 stars",
|
||||||
|
"4 stars",
|
||||||
|
"5 stars",
|
||||||
|
).mapIndexed { index, _ -> index }.toTypedArray(),
|
||||||
|
) {
|
||||||
|
override fun toString(): String {
|
||||||
|
return when (state) {
|
||||||
|
0 -> "Any"
|
||||||
|
else -> "$state star${if (state > 1) "s" else ""}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class UserRatingSeparator :
|
||||||
|
Filter.Separator()
|
||||||
|
|
||||||
class PeopleHeaderFilter(name: String) :
|
class PeopleHeaderFilter(name: String) :
|
||||||
Filter.Header(name)
|
Filter.Header(name.toString())
|
||||||
class PeopleSeparatorFilter :
|
class PeopleSeparatorFilter :
|
||||||
Filter.Separator()
|
Filter.Separator()
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,11 @@ package eu.kanade.tachiyomi.extension.all.kavita
|
|||||||
|
|
||||||
object KavitaConstants {
|
object KavitaConstants {
|
||||||
|
|
||||||
|
const val UNNUMBERED_VOLUME = -100000
|
||||||
|
const val UNNUMBERED_VOLUME_STR = "-100000"
|
||||||
|
const val SPECIAL_NUMBER = 100_000
|
||||||
|
const val VOLUME_NUMBER_OFFSET = 10000f
|
||||||
|
|
||||||
val PERSON_ROLES = listOf(
|
val PERSON_ROLES = listOf(
|
||||||
"Writer", "Penciller", "Inker", "Colorist",
|
"Writer", "Penciller", "Inker", "Colorist",
|
||||||
"Letterer", "CoverArtist", "Editor",
|
"Letterer", "CoverArtist", "Editor",
|
||||||
@@ -23,18 +28,7 @@ object KavitaConstants {
|
|||||||
"Publication Status",
|
"Publication Status",
|
||||||
"Rating",
|
"Rating",
|
||||||
"Age Rating",
|
"Age Rating",
|
||||||
"Writers",
|
|
||||||
"Penciller",
|
|
||||||
"Inker",
|
|
||||||
"Colorist",
|
|
||||||
"Letterer",
|
|
||||||
"Cover Artist",
|
|
||||||
"Editor",
|
|
||||||
"Publisher",
|
|
||||||
"Character",
|
|
||||||
"Translators",
|
|
||||||
"ReleaseYearRange",
|
"ReleaseYearRange",
|
||||||
"Average Rating",
|
|
||||||
"Random",
|
"Random",
|
||||||
"Read Progress",
|
"Read Progress",
|
||||||
)
|
)
|
||||||
@@ -51,18 +45,7 @@ object KavitaConstants {
|
|||||||
"Publication Status",
|
"Publication Status",
|
||||||
"Rating",
|
"Rating",
|
||||||
"Age Rating",
|
"Age Rating",
|
||||||
"Writers",
|
|
||||||
"Penciller",
|
|
||||||
"Inker",
|
|
||||||
"Colorist",
|
|
||||||
"Letterer",
|
|
||||||
"CoverArtist",
|
|
||||||
"Editor",
|
|
||||||
"Publisher",
|
|
||||||
"Character",
|
|
||||||
"Translators",
|
|
||||||
"ReleaseYearRange",
|
"ReleaseYearRange",
|
||||||
"Average Rating",
|
|
||||||
"Random",
|
"Random",
|
||||||
"Read Progress",
|
"Read Progress",
|
||||||
)
|
)
|
||||||
@@ -79,18 +62,7 @@ object KavitaConstants {
|
|||||||
"Publication Status",
|
"Publication Status",
|
||||||
"Rating",
|
"Rating",
|
||||||
"Age Rating",
|
"Age Rating",
|
||||||
"Writers",
|
|
||||||
"Penciller",
|
|
||||||
"Inker",
|
|
||||||
"Colorist",
|
|
||||||
"Letterer",
|
|
||||||
"CoverArtist",
|
|
||||||
"Editor",
|
|
||||||
"Publisher",
|
|
||||||
"Character",
|
|
||||||
"Translators",
|
|
||||||
"ReleaseYearRange",
|
"ReleaseYearRange",
|
||||||
"Average Rating",
|
|
||||||
"Random",
|
"Random",
|
||||||
"Read Progress",
|
"Read Progress",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.extension.all.kavita
|
package eu.kanade.tachiyomi.extension.all.kavita
|
||||||
|
|
||||||
import android.util.Log
|
import android.annotation.SuppressLint
|
||||||
import eu.kanade.tachiyomi.extension.all.kavita.dto.ChapterDto
|
import eu.kanade.tachiyomi.extension.all.kavita.dto.ChapterDto
|
||||||
import eu.kanade.tachiyomi.extension.all.kavita.dto.ChapterType
|
import eu.kanade.tachiyomi.extension.all.kavita.dto.ChapterType
|
||||||
import eu.kanade.tachiyomi.extension.all.kavita.dto.LibraryTypeEnum
|
import eu.kanade.tachiyomi.extension.all.kavita.dto.LibraryTypeEnum
|
||||||
@@ -13,170 +13,204 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.TimeZone
|
|
||||||
|
|
||||||
class KavitaHelper {
|
class KavitaHelper {
|
||||||
val json = Json {
|
val json = Json {
|
||||||
isLenient = true
|
isLenient = true
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
|
coerceInputValues = true
|
||||||
|
explicitNulls = false
|
||||||
allowSpecialFloatingPointValues = true
|
allowSpecialFloatingPointValues = true
|
||||||
useArrayPolymorphism = true
|
useArrayPolymorphism = true
|
||||||
prettyPrint = true
|
prettyPrint = true
|
||||||
}
|
}
|
||||||
inline fun <reified T : Enum<T>> safeValueOf(type: String): T {
|
|
||||||
return java.lang.Enum.valueOf(T::class.java, type)
|
|
||||||
}
|
|
||||||
val dateFormatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSS", Locale.US)
|
|
||||||
.apply { timeZone = TimeZone.getTimeZone("UTC") }
|
|
||||||
fun parseDate(dateAsString: String): Long =
|
|
||||||
dateFormatter.parse(dateAsString)?.time ?: 0
|
|
||||||
|
|
||||||
fun hasNextPage(response: Response): Boolean {
|
fun hasNextPage(response: Response): Boolean {
|
||||||
val paginationHeader = response.header("Pagination")
|
val paginationHeader = response.header("Pagination")
|
||||||
var hasNextPage = false
|
var hasNextPage = false
|
||||||
if (!paginationHeader.isNullOrEmpty()) {
|
if (!paginationHeader.isNullOrEmpty()) {
|
||||||
val paginationInfo = json.decodeFromString<PaginationInfo>(paginationHeader)
|
val paginationInfo = json.decodeFromString<PaginationInfo>(paginationHeader)
|
||||||
hasNextPage = paginationInfo.currentPage + 1 > paginationInfo.totalPages
|
hasNextPage = paginationInfo.currentPage + 1 < paginationInfo.totalPages
|
||||||
}
|
}
|
||||||
return !hasNextPage
|
return hasNextPage
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getIdFromUrl(url: String): Int {
|
fun getIdFromUrl(url: String): Int {
|
||||||
return try {
|
return try {
|
||||||
val id = url.substringAfterLast("/").toInt()
|
val id = url.substringAfterLast("/").toInt()
|
||||||
Log.d("KavitaHelper", "Extracted ID $id from URL: $url")
|
// Log.d("KavitaHelper", "Extracted ID $id from URL: $url")
|
||||||
id
|
id
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("KavitaHelper", "Failed to extract ID from URL: $url", e)
|
// Log.e("KavitaHelper", "Failed to extract ID from URL: $url", e)
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rating Providers from Series-Details-Plus
|
// @todo Rating Providers from Series-Details-Plus
|
||||||
private fun getProviderName(provider: Int): String = when (provider) {
|
// private fun getProviderName(provider: Int): String = when (provider) {
|
||||||
0 -> "User"
|
// 0 -> "User"
|
||||||
1 -> "AniList"
|
// 1 -> "AniList"
|
||||||
2 -> "MyAnimeList"
|
// 2 -> "MyAnimeList"
|
||||||
3 -> "MangaUpdates"
|
// 3 -> "MangaUpdates"
|
||||||
else -> "Rating"
|
// else -> "Rating"
|
||||||
}
|
// }
|
||||||
|
|
||||||
fun createSeriesDto(obj: SeriesDto, baseUrl: String, apiUrl: String, apiKey: String): SManga =
|
fun createSeriesDto(obj: SeriesDto, baseUrl: String, apiKey: String): SManga =
|
||||||
SManga.create().apply {
|
SManga.create().apply {
|
||||||
// url = "$baseUrl/library/${obj.libraryId}/series/${obj.id}"
|
|
||||||
url = "$baseUrl/Series/${obj.id}"
|
url = "$baseUrl/Series/${obj.id}"
|
||||||
title = obj.name
|
title = obj.name
|
||||||
thumbnail_url = "$baseUrl/image/series-cover?seriesId=${obj.id}&apiKey=$apiKey"
|
thumbnail_url = "$baseUrl/image/series-cover?seriesId=${obj.id}&apiKey=$apiKey"
|
||||||
|
|
||||||
// Set status based on read progress
|
|
||||||
status = when {
|
|
||||||
obj.pagesRead >= obj.pages -> SManga.COMPLETED
|
|
||||||
obj.pagesRead > 0 -> SManga.ONGOING
|
|
||||||
else -> SManga.UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// class CompareChapters {
|
fun chapterFromVolume(
|
||||||
// companion object : Comparator<SChapter> {
|
chapter: ChapterDto,
|
||||||
// override fun compare(a: SChapter, b: SChapter): Int {
|
volume: VolumeDto,
|
||||||
// if (a.chapter_number < 1.0 && b.chapter_number < 1.0) {
|
singleFileVolumeNumber: Double? = null,
|
||||||
// // Both are volumes, multiply by 100 and do normal sort
|
libraryType: LibraryTypeEnum? = null,
|
||||||
// return if ((a.chapter_number * 100) < (b.chapter_number * 100)) {
|
isWebtoon: Boolean = false,
|
||||||
// 1
|
mangaTitle: String = "",
|
||||||
// } else {
|
): SChapter =
|
||||||
// -1
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (a.chapter_number < 1.0 && b.chapter_number >= 1.0) {
|
|
||||||
// // A is volume, b is not. A should sort first
|
|
||||||
// return 1
|
|
||||||
// } else if (a.chapter_number >= 1.0 && b.chapter_number < 1.0) {
|
|
||||||
// return -1
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (a.chapter_number < b.chapter_number) return 1
|
|
||||||
// if (a.chapter_number > b.chapter_number) return -1
|
|
||||||
// return 0
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun chapterFromVolume(chapter: ChapterDto, volume: VolumeDto, singleFileVolumeNumber: Int? = null, libraryType: LibraryTypeEnum? = null): SChapter =
|
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
val type = ChapterType.of(chapter, volume, libraryType)
|
val type = ChapterType.of(chapter, volume, libraryType)
|
||||||
|
val titleName = chapter.titleName
|
||||||
|
val title = chapter.title
|
||||||
|
val range = chapter.range
|
||||||
|
// For webtoon
|
||||||
|
val chapterLabel = if (isWebtoon) "Episode" else "Chapter"
|
||||||
|
val volumeLabel = if (isWebtoon) "Season" else "Volume"
|
||||||
|
|
||||||
|
if (titleName != null) {
|
||||||
name = when (type) {
|
name = when (type) {
|
||||||
ChapterType.Regular -> {
|
ChapterType.Regular -> {
|
||||||
val volumeNum = volume.number.toString().toIntOrNull()?.let {
|
val chapterNum = formatChapterNumber(chapter)
|
||||||
it.toString().padStart(2, '0')
|
|
||||||
} ?: volume.number.toString()
|
|
||||||
val chapterNum = chapter.number.toIntOrNull()?.let {
|
|
||||||
it.toString().padStart(2, '0')
|
|
||||||
} ?: chapter.number
|
|
||||||
when {
|
when {
|
||||||
chapter.titleName.isBlank() -> "Volume $volumeNum Chapter $chapterNum"
|
titleName.isNotBlank() && titleName.any { it.isLetter() } ->
|
||||||
chapter.titleName.trim().matches(Regex("^\\d+$")) -> "Volume $volumeNum Chapter ${chapter.titleName.trim().padStart(2, '0')}"
|
"$chapterNum - ${cleanChapterTitle(
|
||||||
else -> "Volume $volumeNum $chapterNum - ${chapter.titleName}"
|
titleName,
|
||||||
|
ChapterTitleContext(
|
||||||
|
mangaTitle = mangaTitle,
|
||||||
|
chapterNumber = chapterNum,
|
||||||
|
volumeName = volume.name.ifBlank { title },
|
||||||
|
),
|
||||||
|
)}"
|
||||||
|
|
||||||
|
else ->
|
||||||
|
"$volumeLabel ${formatVolumeNumber(volume)} $chapterLabel $chapterNum"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChapterType.SingleFileVolume -> {
|
ChapterType.SingleFileVolume -> {
|
||||||
|
val volumeNumber = formatVolumeNumber(volume)
|
||||||
|
val cleanVolumeName = volume.name.trim()
|
||||||
|
|
||||||
|
// Always use the API's volume number, never parse from title
|
||||||
when {
|
when {
|
||||||
volume.name.isBlank() -> "Volume ${volume.number}"
|
// If name is empty or just numbers (Kavita default)
|
||||||
volume.name.trim().matches(Regex("^\\d+$")) -> "Volume ${volume.name.trim().toIntOrNull()?.toString() ?: volume.name.trim()}"
|
cleanVolumeName.isEmpty() || cleanVolumeName.none { it.isLetter() } -> {
|
||||||
else -> "${volume.number} - ${volume.name}"
|
cleanChapterTitle("Volume $volumeNumber")
|
||||||
|
}
|
||||||
|
// If name already contains volume info (Vol. 3, V3, etc.)
|
||||||
|
cleanVolumeName.contains(Regex("(?i)(vol|volume|v)[.\\s]*\\d+")) -> {
|
||||||
|
cleanChapterTitle(cleanVolumeName)
|
||||||
|
}
|
||||||
|
// Normal case - prefix with volume number
|
||||||
|
else -> {
|
||||||
|
cleanChapterTitle("$volumeNumber - $cleanVolumeName")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChapterType.Special -> chapter.titleName.takeIf { it.isNotBlank() } ?: chapter.range
|
}
|
||||||
|
|
||||||
|
ChapterType.Special -> {
|
||||||
|
cleanChapterTitle(
|
||||||
|
when {
|
||||||
|
title.isNotBlank() -> title
|
||||||
|
range.isNotBlank() -> range
|
||||||
|
else -> "Special"
|
||||||
|
},
|
||||||
|
ChapterTitleContext(
|
||||||
|
mangaTitle = mangaTitle,
|
||||||
|
volumeName = volume.name,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
ChapterType.Chapter -> {
|
ChapterType.Chapter -> {
|
||||||
val chapterNum = chapter.number.toIntOrNull()?.let {
|
val chapterNum = formatChapterNumber(chapter)
|
||||||
it.toString().padStart(2, '0')
|
|
||||||
} ?: chapter.number
|
|
||||||
when {
|
when {
|
||||||
chapter.titleName.isBlank() -> "Chapter $chapterNum"
|
titleName.isNotBlank() && titleName.any { it.isLetter() } ->
|
||||||
chapter.titleName.trim().matches(Regex("^\\d+$")) -> "Chapter ${chapter.titleName.trim().padStart(2, '0')}"
|
"$chapterNum - ${cleanChapterTitle(
|
||||||
else -> "$chapterNum - ${chapter.titleName}"
|
titleName,
|
||||||
|
ChapterTitleContext(
|
||||||
|
mangaTitle = mangaTitle,
|
||||||
|
chapterNumber = chapterNum,
|
||||||
|
volumeName = volume.name,
|
||||||
|
),
|
||||||
|
)}"
|
||||||
|
|
||||||
|
else ->
|
||||||
|
"$chapterLabel $chapterNum"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChapterType.Issue -> {
|
ChapterType.Issue -> {
|
||||||
val issueNum = chapter.number.toIntOrNull()?.let {
|
val issueNum = chapter.number.toIntOrNull()?.toString()?.padStart(3, '0') ?: chapter.number
|
||||||
it.toString().padStart(3, '0')
|
cleanChapterTitle(
|
||||||
} ?: chapter.number
|
|
||||||
when {
|
when {
|
||||||
chapter.titleName.isNotBlank() && !chapter.titleName.trim().matches(Regex("^\\d+$")) ->
|
titleName.any { it.isLetter() } -> "$titleName (#$issueNum)"
|
||||||
"#$issueNum ${chapter.titleName}"
|
|
||||||
chapter.title.isNotBlank() && !chapter.title.trim().matches(Regex("^\\d+$")) ->
|
|
||||||
"#$issueNum ${chapter.title}"
|
|
||||||
else -> "Issue #$issueNum"
|
else -> "Issue #$issueNum"
|
||||||
|
},
|
||||||
|
ChapterTitleContext(
|
||||||
|
mangaTitle = mangaTitle,
|
||||||
|
chapterNumber = issueNum,
|
||||||
|
volumeName = volume.name,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// chapter_number = try {
|
// Handle decimal chapter numbers properly
|
||||||
// // if (type == ChapterType.SingleFileVolume) {
|
|
||||||
// // volume.number.toFloat() / 10000
|
|
||||||
// // } else {
|
|
||||||
// // chapter.number.toFloatOrNull() ?: 0f
|
|
||||||
// // }
|
|
||||||
// // } catch (e: NumberFormatException) {
|
|
||||||
// // 0f
|
|
||||||
// // }
|
|
||||||
|
|
||||||
chapter_number = when {
|
chapter_number = when {
|
||||||
type == ChapterType.SingleFileVolume && singleFileVolumeNumber != null -> singleFileVolumeNumber.toFloat()
|
type == ChapterType.SingleFileVolume && singleFileVolumeNumber != null ->
|
||||||
type != ChapterType.SingleFileVolume -> chapter.number.toFloatOrNull() ?: 0f
|
volume.minNumber.toFloat()
|
||||||
else -> 0f
|
|
||||||
|
type == ChapterType.SingleFileVolume -> {
|
||||||
|
// For standalone volumes, use positive numbers
|
||||||
|
volume.minNumber.toFloat()
|
||||||
|
}
|
||||||
|
|
||||||
|
// For regular chapters
|
||||||
|
type != ChapterType.SingleFileVolume && type != ChapterType.Special -> {
|
||||||
|
// Handle decimal chapter numbers
|
||||||
|
if (chapter.minNumber % 1 != 0.0) {
|
||||||
|
chapter.minNumber.toFloat()
|
||||||
|
} else {
|
||||||
|
chapter.minNumber.toInt().toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For volumes/specials in mixed content, place them below chapter 0
|
||||||
|
else -> {
|
||||||
|
val volumeNum = try {
|
||||||
|
if (volume.minNumber % 1 != 0.0) {
|
||||||
|
volume.minNumber.toFloat()
|
||||||
|
} else {
|
||||||
|
volume.minNumber.toInt().toFloat()
|
||||||
|
}
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
0f
|
||||||
|
}
|
||||||
|
volumeNum / KavitaConstants.VOLUME_NUMBER_OFFSET
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url = when {
|
url = when {
|
||||||
type == ChapterType.SingleFileVolume && singleFileVolumeNumber != null ->
|
type == ChapterType.SingleFileVolume && singleFileVolumeNumber != null ->
|
||||||
"volume_${volume.id}"
|
"volume_${volume.id}"
|
||||||
else -> chapter.id.toString()
|
else -> "chapter_${chapter.id}"
|
||||||
}
|
}
|
||||||
|
|
||||||
// url = chapter.id.toString()
|
|
||||||
|
|
||||||
if (chapter.fileCount > 1) {
|
if (chapter.fileCount > 1) {
|
||||||
// salt/offset to recognize chapters with new merged part-chapters as new and hence unread
|
// salt/offset to recognize chapters with new merged part-chapters as new and hence unread
|
||||||
chapter_number += 0.001f * chapter.fileCount
|
chapter_number += 0.001f * chapter.fileCount
|
||||||
@@ -185,11 +219,86 @@ class KavitaHelper {
|
|||||||
|
|
||||||
date_upload = parseDateSafe(chapter.created)
|
date_upload = parseDateSafe(chapter.created)
|
||||||
scanlator = when (type) {
|
scanlator = when (type) {
|
||||||
ChapterType.SingleFileVolume -> "Volume"
|
ChapterType.SingleFileVolume -> if (isWebtoon) "Season" else "Volume"
|
||||||
ChapterType.Special -> "Special"
|
ChapterType.Special -> "Special"
|
||||||
ChapterType.Issue -> "Issue"
|
ChapterType.Issue -> "Issue"
|
||||||
ChapterType.Chapter -> "Chapter"
|
ChapterType.Chapter -> if (isWebtoon) "Episode" else "Chapter"
|
||||||
ChapterType.Regular -> "Chapter"
|
ChapterType.Regular -> if (isWebtoon) "Episode" else "Chapter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatVolumeNumber(volume: VolumeDto): String {
|
||||||
|
return when {
|
||||||
|
volume.maxNumber > volume.minNumber ->
|
||||||
|
"${removeTrailingZero(volume.minNumber)}-${removeTrailingZero(volume.maxNumber)}"
|
||||||
|
else -> removeTrailingZero(volume.minNumber)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatChapterNumber(chapter: ChapterDto, padLength: Int = 2): String {
|
||||||
|
val chapterNum = when {
|
||||||
|
chapter.maxNumber > chapter.minNumber ->
|
||||||
|
"${removeTrailingZero(chapter.minNumber)}-${removeTrailingZero(chapter.maxNumber)}"
|
||||||
|
else -> removeTrailingZero(chapter.minNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only pad if it's a single whole number (not a range and not decimal)
|
||||||
|
return if (!chapterNum.contains('-') && !chapterNum.contains('.')) {
|
||||||
|
chapterNum.toIntOrNull()?.toString()?.padStart(padLength, '0') ?: chapterNum
|
||||||
|
} else {
|
||||||
|
chapterNum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to remove .0 from whole numbers while preserving actual decimals
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
private fun removeTrailingZero(number: Double): String {
|
||||||
|
return if (number % 1 == 0.0) {
|
||||||
|
number.toInt().toString()
|
||||||
|
} else {
|
||||||
|
// Use String.format to avoid scientific notation for very small decimals
|
||||||
|
String.format("%.10f", number).replace(",", ".").trimEnd('0').trimEnd('.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cleanChapterTitle(
|
||||||
|
originalTitle: String,
|
||||||
|
context: ChapterTitleContext? = null,
|
||||||
|
): String {
|
||||||
|
var title = originalTitle.trim()
|
||||||
|
val mangaTitle = context?.mangaTitle ?: ""
|
||||||
|
|
||||||
|
// Remove manga name if present
|
||||||
|
if (mangaTitle.isNotBlank()) {
|
||||||
|
title = title.replace(Regex("(?i)\\b${Regex.escape(mangaTitle)}\\b[\\s\\-:]*"), "").trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove chapter number patterns like c0116, c001, etc.
|
||||||
|
title = title.replace(Regex("""(?i)\bc\d+\b"""), "").trim()
|
||||||
|
|
||||||
|
// Clean up problematic hyphen/space patterns
|
||||||
|
title = title.replace(Regex("""\s*[-.]\s*[-.]\s*"""), " - ") // Handles -.-, - . -, etc.
|
||||||
|
.replace(Regex("""\s*-\s*-\s*"""), " - ") // Double hyphens with spaces
|
||||||
|
.replace(Regex("""^\s*[-.]\s*|\s*[-.]\s*$"""), "") // Leading/trailing hyphens or dots
|
||||||
|
.trim()
|
||||||
|
|
||||||
|
return title.ifBlank { originalTitle }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data class to hold context information for cleaning chapter titles
|
||||||
|
*/
|
||||||
|
data class ChapterTitleContext(
|
||||||
|
val mangaTitle: String = "",
|
||||||
|
val chapterNumber: String = "",
|
||||||
|
val volumeName: String = "",
|
||||||
|
val isWebtoon: Boolean = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun isWebtoonOrLongStrip(tags: List<String>): Boolean {
|
||||||
|
return tags.any {
|
||||||
|
val normalized = it.trim().lowercase()
|
||||||
|
normalized.contains("webtoon") || normalized.contains("long strip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,6 @@ import java.text.SimpleDateFormat
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.TimeZone
|
import java.util.TimeZone
|
||||||
|
|
||||||
val formatterDate = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
|
||||||
.apply { timeZone = TimeZone.getTimeZone("UTC") }
|
|
||||||
val formatterDateTime = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US)
|
|
||||||
.apply { timeZone = TimeZone.getTimeZone("UTC") }
|
|
||||||
|
|
||||||
fun parseDateSafe(date: String?): Long {
|
fun parseDateSafe(date: String?): Long {
|
||||||
return date?.let {
|
return date?.let {
|
||||||
try {
|
try {
|
||||||
@@ -80,7 +75,7 @@ fun PreferenceScreen.addEditTextPreference(
|
|||||||
val result = text.isBlank() || validate?.invoke(text) ?: true
|
val result = text.isBlank() || validate?.invoke(text) ?: true
|
||||||
|
|
||||||
if (restartRequired && result) {
|
if (restartRequired && result) {
|
||||||
Toast.makeText(context, "Restart Tachiyomi to apply new setting.", Toast.LENGTH_LONG).show()
|
Toast.makeText(context, "Restart Mihon to apply new setting.", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.extension.all.kavita.dto
|
package eu.kanade.tachiyomi.extension.all.kavita.dto
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.extension.all.kavita.KavitaConstants
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -8,7 +9,7 @@ interface ConvertibleToSManga {
|
|||||||
fun toSManga(baseUrl: String, apiUrl: String, apiKey: String): SManga
|
fun toSManga(baseUrl: String, apiUrl: String, apiKey: String): SManga
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable // https://github.com/Kareadita/Kavita/blob/develop/API/Entities/Enums/MangaFormat.cs
|
||||||
enum class MangaFormat(val format: Int) {
|
enum class MangaFormat(val format: Int) {
|
||||||
Image(0),
|
Image(0),
|
||||||
Archive(1),
|
Archive(1),
|
||||||
@@ -19,7 +20,6 @@ enum class MangaFormat(val format: Int) {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val map = values().associateBy(MangaFormat::format)
|
private val map = values().associateBy(MangaFormat::format)
|
||||||
fun fromInt(type: Int): MangaFormat? = map[type]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,8 +189,9 @@ data class AuthorDto(
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class VolumeDto(
|
data class VolumeDto(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val number: Int,
|
val minNumber: Double,
|
||||||
val name: String,
|
val maxNumber: Double,
|
||||||
|
val name: String = "",
|
||||||
val pages: Int,
|
val pages: Int,
|
||||||
val pagesRead: Int,
|
val pagesRead: Int,
|
||||||
val lastModified: String,
|
val lastModified: String,
|
||||||
@@ -202,27 +203,34 @@ data class VolumeDto(
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class ChapterType {
|
enum class ChapterType {
|
||||||
Regular, // chapter with volume information
|
Regular, // Chapter with volume information
|
||||||
Chapter, // manga chapter without volume information
|
Chapter, // Chapter without volume information
|
||||||
SingleFileVolume,
|
SingleFileVolume,
|
||||||
Special,
|
Special,
|
||||||
Issue, // For comics
|
Issue, // For comics
|
||||||
;
|
;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val UNNUMBERED_VOLUME_NUMBER = -100_000
|
||||||
|
|
||||||
fun of(chapter: ChapterDto, volume: VolumeDto, libraryType: LibraryTypeEnum? = null): ChapterType =
|
fun of(chapter: ChapterDto, volume: VolumeDto, libraryType: LibraryTypeEnum? = null): ChapterType =
|
||||||
when {
|
when {
|
||||||
volume.number == 100_000 -> Special
|
// Special
|
||||||
volume.number == -100_000 -> when (libraryType) {
|
volume.minNumber.toInt() == KavitaConstants.SPECIAL_NUMBER ||
|
||||||
|
chapter.minNumber.toInt() == KavitaConstants.SPECIAL_NUMBER -> Special
|
||||||
|
// Issue
|
||||||
|
volume.minNumber.toInt() == UNNUMBERED_VOLUME_NUMBER -> when (libraryType) {
|
||||||
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> Issue
|
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> Issue
|
||||||
LibraryTypeEnum.Manga, LibraryTypeEnum.LightNovel, LibraryTypeEnum.Book -> Chapter
|
else -> Chapter
|
||||||
else -> Chapter // Default to Chapter for other types
|
|
||||||
}
|
}
|
||||||
chapter.number == "-100000" -> SingleFileVolume
|
// SingleFileVolume
|
||||||
|
chapter.number == KavitaConstants.UNNUMBERED_VOLUME_STR -> SingleFileVolume
|
||||||
|
// Regular
|
||||||
|
volume.minNumber > 0 -> Regular
|
||||||
|
// Everything else depends on library type
|
||||||
else -> when (libraryType) {
|
else -> when (libraryType) {
|
||||||
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> Issue
|
LibraryTypeEnum.Comic, LibraryTypeEnum.ComicVine -> Issue
|
||||||
LibraryTypeEnum.Manga, LibraryTypeEnum.LightNovel, LibraryTypeEnum.Book -> Chapter
|
else -> Chapter
|
||||||
else -> Regular
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,12 +241,15 @@ data class ChapterDto(
|
|||||||
val id: Int,
|
val id: Int,
|
||||||
val range: String,
|
val range: String,
|
||||||
val number: String,
|
val number: String,
|
||||||
|
val minNumber: Double,
|
||||||
|
val maxNumber: Double,
|
||||||
val pages: Int,
|
val pages: Int,
|
||||||
val isSpecial: Boolean,
|
val isSpecial: Boolean,
|
||||||
val title: String,
|
val title: String,
|
||||||
val titleName: String,
|
val titleName: String?,
|
||||||
val pagesRead: Int,
|
val pagesRead: Int,
|
||||||
val coverImageLocked: Boolean,
|
val coverImageLocked: Boolean,
|
||||||
|
val coverImage: String,
|
||||||
val volumeId: Int,
|
val volumeId: Int,
|
||||||
val created: String,
|
val created: String,
|
||||||
val lastModifiedUtc: String,
|
val lastModifiedUtc: String,
|
||||||
@@ -259,13 +270,13 @@ data class ReadingListDto(
|
|||||||
val title: String,
|
val title: String,
|
||||||
val coverImage: String? = null,
|
val coverImage: String? = null,
|
||||||
val promoted: Boolean = false,
|
val promoted: Boolean = false,
|
||||||
val summary: String?,
|
val summary: String? = null,
|
||||||
val itemCount: Int,
|
val itemCount: Int,
|
||||||
val startingYear: Int,
|
val startingYear: Int,
|
||||||
val startingMonth: Int,
|
val startingMonth: Int,
|
||||||
val endingYear: Int,
|
val endingYear: Int,
|
||||||
val endingMonth: Int,
|
val endingMonth: Int,
|
||||||
val ownerUserName: String?,
|
val ownerUserName: String? = null,
|
||||||
@SerialName("items") val items: List<ReadingListItemDto> = emptyList(),
|
@SerialName("items") val items: List<ReadingListItemDto> = emptyList(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -278,11 +289,11 @@ data class ReadingListItemDto(
|
|||||||
val seriesName: String,
|
val seriesName: String,
|
||||||
val chapterNumber: String?,
|
val chapterNumber: String?,
|
||||||
val volumeNumber: String?,
|
val volumeNumber: String?,
|
||||||
val chapterTitleName: String?,
|
val chapterTitleName: String? = null,
|
||||||
val volumeId: Int?,
|
val volumeId: Int?,
|
||||||
val title: String?,
|
val title: String? = null,
|
||||||
val summary: String?,
|
val summary: String? = null,
|
||||||
val releaseDate: String?,
|
val releaseDate: String? = null,
|
||||||
val libraryName: String?,
|
val libraryName: String?,
|
||||||
@SerialName("readingListId") val readingListId: Int,
|
@SerialName("readingListId") val readingListId: Int,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ data class MetadataTag(val id: Int, val title: String)
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class MetadataAgeRatings(val value: Int, val title: String)
|
data class MetadataAgeRatings(val value: Int, val title: String)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MetadataUserRatings(val value: Int, val title: String)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MetadataLanguages(val isoCode: String, val title: String)
|
data class MetadataLanguages(val isoCode: String, val title: String)
|
||||||
|
|
||||||
@@ -37,40 +40,3 @@ data class SmartFilter(
|
|||||||
val name: String,
|
val name: String,
|
||||||
val filter: String,
|
val filter: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class MetadataPayload(
|
|
||||||
val forceUseMetadataPayload: Boolean = true,
|
|
||||||
var sorting: Int = 1,
|
|
||||||
var sorting_asc: Boolean = true,
|
|
||||||
var readStatus: ArrayList<String> = arrayListOf("notRead", "inProgress", "read"),
|
|
||||||
var genres_i: ArrayList<Int> = arrayListOf(),
|
|
||||||
var genres_e: ArrayList<Int> = arrayListOf(),
|
|
||||||
var tags_i: ArrayList<Int> = arrayListOf(),
|
|
||||||
var tags_e: ArrayList<Int> = arrayListOf(),
|
|
||||||
var ageRating_i: ArrayList<Int> = arrayListOf(),
|
|
||||||
var ageRating_e: ArrayList<Int> = arrayListOf(),
|
|
||||||
var formats: ArrayList<Int> = arrayListOf(),
|
|
||||||
var collections_i: ArrayList<Int> = arrayListOf(),
|
|
||||||
var collections_e: ArrayList<Int> = arrayListOf(),
|
|
||||||
var userRating: Int = 0,
|
|
||||||
var people: ArrayList<Int> = arrayListOf(),
|
|
||||||
var language_i: ArrayList<String> = arrayListOf(),
|
|
||||||
var language_e: ArrayList<String> = arrayListOf(),
|
|
||||||
var libraries_i: ArrayList<Int> = arrayListOf(),
|
|
||||||
var libraries_e: ArrayList<Int> = arrayListOf(),
|
|
||||||
var pubStatus: ArrayList<Int> = arrayListOf(),
|
|
||||||
var seriesNameQuery: String = "",
|
|
||||||
var releaseYearRangeMin: Int = 0,
|
|
||||||
var releaseYearRangeMax: Int = 0,
|
|
||||||
var peopleWriters: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peoplePenciller: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peopleInker: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peopleColorist: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peopleLetterer: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peopleCoverArtist: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peopleEditor: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peoplePublisher: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peopleCharacter: ArrayList<Int> = arrayListOf(),
|
|
||||||
var peopleTranslator: ArrayList<Int> = arrayListOf(),
|
|
||||||
)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user