90% converted to GQL

This commit is contained in:
Syer10
2025-10-03 19:21:50 -04:00
parent 35ea833510
commit e171d10588
126 changed files with 4145 additions and 1090 deletions

View File

@@ -0,0 +1,74 @@
query GetMangaCategories($id: Int!) {
manga(id: $id) {
categories {
nodes {
...CategoryFragment
}
}
}
}
mutation AddMangaToCategories($id: Int!, $addToCategories: [Int!]!) {
updateMangaCategories(
input: {id: $id, patch: {addToCategories: $addToCategories}}
) {
clientMutationId
}
}
mutation RemoveMangaFromCategories($id: Int!, $removeFromCategories: [Int!]!) {
updateMangaCategories(
input: {id: $id, patch: {removeFromCategories: $removeFromCategories}}
) {
clientMutationId
}
}
query GetCategories {
categories(orderBy: ORDER, orderByType: ASC) {
nodes {
...CategoryFragment
}
}
}
mutation CreateCategory($name: String!) {
createCategory(input: {name: $name}) {
clientMutationId
}
}
mutation ModifyCategory($id: Int!, $name: String!) {
updateCategory(input: {id: $id, patch: {name: $name}}) {
clientMutationId
}
}
mutation ReorderCategory($id: Int!, $position: Int!) {
updateCategoryOrder(input: {id: $id, position: $position}) {
clientMutationId
}
}
mutation DeleteCategory($categoryId: Int!) {
deleteCategory(input: {categoryId: $categoryId}) {
clientMutationId
}
}
query GetCategoryManga($categoryId: [Int!]!) {
mangas(orderBy: ID, condition: {categoryIds: $categoryId}) {
nodes {
...MangaFragment
}
}
}
mutation SetCategoryMeta($categoryId: Int!, $key: String!, $value: String!) {
setCategoryMeta(
input: {meta: {categoryId: $categoryId, key: $key, value: $value}}
) {
clientMutationId
}
}

View File

@@ -1,26 +1,3 @@
fragment ChapterFragment on ChapterType {
chapterNumber
fetchedAt
id
isBookmarked
isDownloaded
isRead
lastPageRead
lastReadAt
mangaId
name
pageCount
realUrl
scanlator
sourceOrder
uploadDate
url
meta {
key
value
}
}
query GetChapter($id: Int!) {
chapter(id: $id) {
...ChapterFragment

View File

@@ -0,0 +1,41 @@
mutation StartDownloader {
startDownloader(input: {}) {
clientMutationId
}
}
mutation StopDownloader {
stopDownloader(input: {}) {
clientMutationId
}
}
mutation ClearDownloader {
clearDownloader(input: {}) {
clientMutationId
}
}
mutation EnqueueChapterDownload($id: Int!) {
enqueueChapterDownload(input: {id: $id}) {
clientMutationId
}
}
mutation DequeueChapterDownload($id: Int!) {
dequeueChapterDownload(input: {id: $id}) {
clientMutationId
}
}
mutation ReorderChapterDownload($chapterId: Int!, $to: Int!) {
reorderChapterDownload(input: {chapterId: $chapterId, to: $to}) {
clientMutationId
}
}
mutation EnqueueChapterDownloads($ids: [Int!]!) {
enqueueChapterDownloads(input: {ids: $ids}) {
clientMutationId
}
}

View File

@@ -0,0 +1,32 @@
mutation FetchExtensions {
fetchExtensions(input: {}) {
extensions {
...ExtensionFragment
}
}
}
mutation InstallExtension($pkgName: String!) {
updateExtension(input: {id: $pkgName, patch: {install: true}}) {
clientMutationId
}
}
mutation InstallExternalExtension($extensionFile: Upload!) {
installExternalExtension(input: {extensionFile: $extensionFile}) {
clientMutationId
}
}
mutation UninstallExtension($pkgName: String!) {
updateExtension(input: {id: $pkgName, patch: {uninstall: true}}) {
clientMutationId
}
}
mutation UpdateExtension($pkgName: String!) {
updateExtension(input: {id: $pkgName, patch: {update: true}}) {
clientMutationId
}
}

View File

@@ -0,0 +1,14 @@
query GetGlobalMeta {
metas {
nodes {
key
value
}
}
}
mutation SetGlobalMeta($key: String!, $value: String!) {
setGlobalMeta(input: {meta: {key: $key, value: $value}}) {
clientMutationId
}
}

View File

@@ -0,0 +1,5 @@
mutation SetMangaInLibrary($id: Int!, $inLibrary: Boolean!) {
updateManga(input: {id: $id, patch: {inLibrary: $inLibrary}}) {
clientMutationId
}
}

View File

@@ -0,0 +1,32 @@
mutation RefreshManga($id: Int!) {
fetchManga(input: {id: $id}) {
manga {
...MangaFragment
}
}
}
query GetManga($id: Int!) {
manga(id: $id) {
...MangaFragment
}
}
query GetMangaLibrary($id: Int!) {
manga(id: $id) {
...LibraryMangaFragment
}
}
mutation SetMangaMeta($mangaId: Int!, $key: String!, $value: String!) {
setMangaMeta(input: {meta: {key: $key, mangaId: $mangaId, value: $value}}) {
clientMutationId
}
}
query GetThumbnailUrl($id: Int!) {
manga(id: $id) {
thumbnailUrl
thumbnailUrlLastFetched
}
}

View File

@@ -1,15 +1,25 @@
fragment SettingsTypeFragment on SettingsType {
authMode
authPassword
authUsername
autoDownloadIgnoreReUploads
autoDownloadNewChapters
autoDownloadNewChaptersLimit
backupInterval
backupPath
backupTTL
backupTime
basicAuthEnabled
basicAuthPassword
basicAuthUsername
databasePassword
databaseType
databaseUrl
databaseUsername
debugLogsEnabled
downloadAsCbz
downloadConversions {
compressionLevel
mimeType
target
}
downloadsPath
electronPath
excludeCompleted
@@ -17,17 +27,38 @@ fragment SettingsTypeFragment on SettingsType {
excludeNotStarted
excludeUnreadChapters
extensionRepos
flareSolverrAsResponseFallback
flareSolverrEnabled
flareSolverrSessionName
flareSolverrSessionTtl
flareSolverrTimeout
flareSolverrUrl
globalUpdateInterval
gqlDebugLogsEnabled
initialOpenInBrowserEnabled
ip
jwtAudience
jwtRefreshExpiry
jwtTokenExpiry
koreaderSyncChecksumMethod
koreaderSyncDeviceId
koreaderSyncPercentageTolerance
koreaderSyncServerUrl
koreaderSyncStrategyBackward
koreaderSyncStrategyForward
koreaderSyncUserkey
koreaderSyncUsername
localSourcePath
maxLogFileSize
maxLogFiles
maxLogFolderSize
maxSourcesInParallel
opdsChapterSortOrder
opdsEnablePageReadProgress
opdsItemsPerPage
opdsMarkAsReadOnDownload
opdsShowOnlyDownloadedChapters
opdsShowOnlyUnreadChapters
opdsUseBinaryFileSizes
port
socksProxyEnabled
socksProxyHost
@@ -50,17 +81,23 @@ query AllSettings {
}
mutation SetSettings(
$authMode: AuthMode = null,
$authPassword: String = null,
$authUsername: String = null,
$autoDownloadIgnoreReUploads: Boolean = null,
$autoDownloadNewChapters: Boolean = null,
$autoDownloadNewChaptersLimit: Int = null,
$backupInterval: Int = null,
$backupPath: String = null,
$backupTTL: Int = null,
$backupTime: String = null,
$basicAuthEnabled: Boolean = null,
$basicAuthPassword: String = null,
$basicAuthUsername: String = null,
$databasePassword: String = null,
$databaseType: DatabaseType = null,
$databaseUrl: String = null,
$databaseUsername: String = null,
$debugLogsEnabled: Boolean = null,
$downloadAsCbz: Boolean = null,
$downloadConversions: [SettingsDownloadConversionTypeInput!] = null,
$downloadsPath: String = null,
$electronPath: String = null,
$excludeCompleted: Boolean = null,
@@ -68,17 +105,38 @@ mutation SetSettings(
$excludeNotStarted: Boolean = null,
$excludeUnreadChapters: Boolean = null,
$extensionRepos: [String!] = null,
$flareSolverrAsResponseFallback: Boolean = null,
$flareSolverrEnabled: Boolean = null,
$flareSolverrSessionName: String = null,
$flareSolverrSessionTtl: Int = null,
$flareSolverrTimeout: Int = null,
$flareSolverrUrl: String = null,
$globalUpdateInterval: Float = null,
$gqlDebugLogsEnabled: Boolean = null,
$initialOpenInBrowserEnabled: Boolean = null,
$ip: String = null,
$jwtAudience: String = null,
$jwtRefreshExpiry: Duration = null,
$jwtTokenExpiry: Duration = null,
$koreaderSyncChecksumMethod: KoreaderSyncChecksumMethod = null,
$koreaderSyncDeviceId: String = null,
$koreaderSyncPercentageTolerance: Float = null,
$koreaderSyncServerUrl: String = null,
$koreaderSyncStrategyBackward: KoreaderSyncConflictStrategy = null,
$koreaderSyncStrategyForward: KoreaderSyncConflictStrategy = null,
$koreaderSyncUserkey: String = null,
$koreaderSyncUsername: String = null,
$localSourcePath: String = null,
$maxLogFileSize: String = null,
$maxLogFiles: Int = null,
$maxLogFolderSize: String = null,
$maxSourcesInParallel: Int = null,
$opdsChapterSortOrder: SortOrder = null,
$opdsEnablePageReadProgress: Boolean = null,
$opdsItemsPerPage: Int = null,
$opdsMarkAsReadOnDownload: Boolean = null,
$opdsShowOnlyDownloadedChapters: Boolean = null,
$opdsShowOnlyUnreadChapters: Boolean = null,
$opdsUseBinaryFileSizes: Boolean = null,
$port: Int = null,
$socksProxyEnabled: Boolean = null,
$socksProxyHost: String = null,
@@ -96,17 +154,23 @@ mutation SetSettings(
setSettings(
input: {
settings: {
authMode: $authMode,
authPassword: $authPassword,
authUsername: $authUsername,
autoDownloadIgnoreReUploads: $autoDownloadIgnoreReUploads,
autoDownloadNewChapters: $autoDownloadNewChapters,
autoDownloadNewChaptersLimit: $autoDownloadNewChaptersLimit,
backupInterval: $backupInterval,
backupPath: $backupPath,
backupTTL: $backupTTL,
backupTime: $backupTime,
basicAuthEnabled: $basicAuthEnabled,
basicAuthPassword: $basicAuthPassword,
basicAuthUsername: $basicAuthUsername,
databasePassword: $databasePassword,
databaseType: $databaseType,
databaseUrl: $databaseUrl,
databaseUsername: $databaseUsername,
debugLogsEnabled: $debugLogsEnabled,
downloadAsCbz: $downloadAsCbz,
downloadConversions: $downloadConversions,
downloadsPath: $downloadsPath,
electronPath: $electronPath,
excludeCompleted: $excludeCompleted,
@@ -114,17 +178,38 @@ mutation SetSettings(
excludeNotStarted: $excludeNotStarted,
excludeUnreadChapters: $excludeUnreadChapters,
extensionRepos: $extensionRepos,
flareSolverrAsResponseFallback: $flareSolverrAsResponseFallback,
flareSolverrEnabled: $flareSolverrEnabled,
flareSolverrSessionName: $flareSolverrSessionName,
flareSolverrSessionTtl: $flareSolverrSessionTtl,
flareSolverrTimeout: $flareSolverrTimeout,
flareSolverrUrl: $flareSolverrUrl,
globalUpdateInterval: $globalUpdateInterval,
gqlDebugLogsEnabled: $gqlDebugLogsEnabled,
initialOpenInBrowserEnabled: $initialOpenInBrowserEnabled,
ip: $ip,
jwtAudience: $jwtAudience,
jwtRefreshExpiry: $jwtRefreshExpiry,
jwtTokenExpiry: $jwtTokenExpiry,
koreaderSyncChecksumMethod: $koreaderSyncChecksumMethod,
koreaderSyncDeviceId: $koreaderSyncDeviceId,
koreaderSyncPercentageTolerance: $koreaderSyncPercentageTolerance,
koreaderSyncServerUrl: $koreaderSyncServerUrl,
koreaderSyncStrategyBackward: $koreaderSyncStrategyBackward,
koreaderSyncStrategyForward: $koreaderSyncStrategyForward,
koreaderSyncUserkey: $koreaderSyncUserkey,
koreaderSyncUsername: $koreaderSyncUsername,
localSourcePath: $localSourcePath,
maxLogFileSize: $maxLogFileSize,
maxLogFiles: $maxLogFiles,
maxLogFolderSize: $maxLogFolderSize,
maxSourcesInParallel: $maxSourcesInParallel,
opdsChapterSortOrder: $opdsChapterSortOrder,
opdsEnablePageReadProgress: $opdsEnablePageReadProgress,
opdsItemsPerPage: $opdsItemsPerPage,
opdsMarkAsReadOnDownload: $opdsMarkAsReadOnDownload,
opdsShowOnlyDownloadedChapters: $opdsShowOnlyDownloadedChapters,
opdsShowOnlyUnreadChapters: $opdsShowOnlyUnreadChapters,
opdsUseBinaryFileSizes: $opdsUseBinaryFileSizes,
port: $port,
socksProxyEnabled: $socksProxyEnabled,
socksProxyHost: $socksProxyHost,

View File

@@ -0,0 +1,205 @@
query GetSourceList {
sources {
nodes {
...SourceFragment
}
}
}
query GetSource($id: LongString!) {
source(id: $id) {
...SourceFragment
}
}
mutation FetchPopularManga($source: LongString!, $page: Int!) {
fetchSourceManga(input: {page: $page, source: $source, type: POPULAR}) {
hasNextPage
mangas {
...MangaFragment
}
}
}
mutation FetchLatestManga($source: LongString!, $page: Int!) {
fetchSourceManga(input: {page: $page, source: $source, type: LATEST}) {
hasNextPage
mangas {
...MangaFragment
}
}
}
mutation FetchSearchManga($source: LongString!, $page: Int!, $query: String, $filters: [FilterChangeInput!]) {
fetchSourceManga(
input: {page: $page, source: $source, type: SEARCH, query: $query, filters: $filters}
) {
hasNextPage
mangas {
...MangaFragment
}
}
}
query GetSourceFilters($id: LongString!) {
source(id: $id) {
filters {
... on CheckBoxFilter {
type: __typename
checkBoxFilterDefault: default
name
}
... on HeaderFilter {
type: __typename
name
}
... on SelectFilter {
type: __typename
selectFilterDefault: default
name
values
}
... on TriStateFilter {
type: __typename
triStateFilterDefault: default
name
}
... on TextFilter {
type: __typename
textFilterDefault: default
name
}
... on SortFilter {
type: __typename
sortFilterDefault: default {
ascending
index
}
name
values
}
... on SeparatorFilter {
type: __typename
name
}
... on GroupFilter {
type: __typename
name
filters {
... on CheckBoxFilter {
type: __typename
checkBoxFilterDefault: default
name
}
... on HeaderFilter {
type: __typename
name
}
... on SelectFilter {
type: __typename
selectFilterDefault: default
name
values
}
... on TriStateFilter {
type: __typename
triStateFilterDefault: default
name
}
... on TextFilter {
type: __typename
textFilterDefault: default
name
}
... on SortFilter {
type: __typename
sortFilterDefault: default {
ascending
index
}
name
values
}
... on SeparatorFilter {
type: __typename
name
}
}
}
}
}
}
query GetSourcePreferences($id: LongString!) {
source(id: $id) {
preferences {
... on CheckBoxPreference {
type: __typename
checkBoxCheckBoxCurrentValue: currentValue
summary
checkBoxDefault: default
visible
enabled
key
checkBoxTitle: title
}
... on EditTextPreference {
type: __typename
editTextPreferenceCurrentValue: currentValue
editTextPreferenceDefault: default
editTextPreferenceTitle: title
text
summary
key
visible
enabled
dialogTitle
dialogMessage
}
... on SwitchPreference {
type: __typename
switchPreferenceCurrentValue: currentValue
summary
key
visible
enabled
switchPreferenceDefault: default
switchPreferenceTitle: title
}
... on MultiSelectListPreference {
type: __typename
dialogMessage
dialogTitle
multiSelectListPreferenceTitle: title
summary
key
visible
enabled
entryValues
entries
multiSelectListPreferenceDefault: default
multiSelectListPreferenceCurrentValue: currentValue
}
... on ListPreference {
type: __typename
listPreferenceCurrentValue: currentValue
listPreferenceDefault: default
listPreferenceTitle: title
summary
key
visible
enabled
entryValues
entries
}
}
}
}
mutation SetSourceSetting($source: LongString!, $change: SourcePreferenceChangeInput!) {
updateSourcePreference(input: {change: $change, source: $source}) {
clientMutationId
}
}

View File

@@ -0,0 +1,31 @@
query GetChapterUpdates($first: Int!, $offset: Int!) {
chapters(
filter: {inLibrary: {equalTo:true}}
first: $first
offset: $offset
order: [
{ by: FETCHED_AT, byType: DESC },
{ by: SOURCE_ORDER, byType: DESC },
]
) {
nodes {
...ChapterWithMangaFragment
}
pageInfo {
hasNextPage
}
totalCount
}
}
mutation UpdateLibrary {
updateLibraryManga(input: {}) {
clientMutationId
}
}
mutation UpdateCategory($categories: [Int!]!) {
updateCategoryManga(input: {categories: $categories}) {
clientMutationId
}
}

View File

@@ -0,0 +1,12 @@
fragment CategoryFragment on CategoryType {
id
name
order
default
includeInDownload
includeInUpdate
meta {
key
value
}
}

View File

@@ -0,0 +1,29 @@
fragment ChapterFragment on ChapterType {
chapterNumber
fetchedAt
id
isBookmarked
isDownloaded
isRead
lastPageRead
lastReadAt
mangaId
name
pageCount
realUrl
scanlator
sourceOrder
uploadDate
url
meta {
key
value
}
}
fragment ChapterWithMangaFragment on ChapterType {
...ChapterFragment
manga {
...MangaFragment
}
}

View File

@@ -0,0 +1,14 @@
fragment ExtensionFragment on ExtensionType {
apkName
hasUpdate
iconUrl
isInstalled
isNsfw
isObsolete
lang
name
pkgName
repo
versionCode
versionName
}

View File

@@ -0,0 +1,79 @@
fragment MangaFragment on MangaType {
title
artist
author
description
status
sourceId
id
url
thumbnailUrl
thumbnailUrlLastFetched
initialized
genre
inLibrary
inLibraryAt
updateStrategy
meta {
key
value
}
realUrl
lastFetchedAt
chaptersLastFetchedAt
age
}
fragment LibraryMangaFragment on MangaType {
title
artist
author
description
status
sourceId
id
url
thumbnailUrl
thumbnailUrlLastFetched
initialized
genre
inLibrary
inLibraryAt
updateStrategy
meta {
key
value
}
realUrl
lastFetchedAt
chaptersLastFetchedAt
downloadCount
chapters {
totalCount
}
lastReadChapter {
lastReadAt
}
age
bookmarkCount
chaptersAge
unreadCount
highestNumberedChapter {
chapterNumber
}
firstUnreadChapter {
id
}
latestUploadedChapter {
uploadDate
}
latestReadChapter {
lastReadAt
}
latestFetchedChapter {
sourceOrder
}
source {
...SourceFragment
}
}

View File

@@ -0,0 +1,11 @@
fragment SourceFragment on SourceType {
id
name
displayName
baseUrl
iconUrl
isConfigurable
isNsfw
lang
supportsLatest
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,13 +8,29 @@ package ca.gosyer.jui.data
import ca.gosyer.jui.core.lang.addSuffix
import ca.gosyer.jui.data.backup.BackupRepositoryImpl
import ca.gosyer.jui.data.category.CategoryRepositoryImpl
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl
import ca.gosyer.jui.data.download.DownloadRepositoryImpl
import ca.gosyer.jui.data.extension.ExtensionRepositoryImpl
import ca.gosyer.jui.data.global.GlobalRepositoryImpl
import ca.gosyer.jui.data.library.LibraryRepositoryImpl
import ca.gosyer.jui.data.manga.MangaRepositoryImpl
import ca.gosyer.jui.data.settings.SettingsRepositoryImpl
import ca.gosyer.jui.data.source.SourceRepositoryImpl
import ca.gosyer.jui.data.updates.UpdatesRepositoryImpl
import ca.gosyer.jui.domain.backup.service.BackupRepository
import ca.gosyer.jui.domain.category.service.CategoryRepository
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
import ca.gosyer.jui.domain.download.service.DownloadRepository
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import ca.gosyer.jui.domain.global.service.GlobalRepository
import ca.gosyer.jui.domain.library.service.LibraryRepository
import ca.gosyer.jui.domain.manga.service.MangaRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.server.service.ServerPreferences
import ca.gosyer.jui.domain.settings.service.SettingsRepository
import ca.gosyer.jui.domain.source.service.SourceRepository
import ca.gosyer.jui.domain.updates.service.UpdatesRepository
import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.network.ws.GraphQLWsProtocol
import com.apollographql.ktor.ktorClient
@@ -55,6 +71,13 @@ interface DataComponent : SharedDataComponent {
@Provides
fun settingsRepository(apolloClient: ApolloClient): SettingsRepository = SettingsRepositoryImpl(apolloClient)
@Provides
fun categoryRepository(
apolloClient: ApolloClient,
http: Http,
serverPreferences: ServerPreferences,
): CategoryRepository = CategoryRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun chapterRepository(
apolloClient: ApolloClient,
@@ -62,6 +85,55 @@ interface DataComponent : SharedDataComponent {
serverPreferences: ServerPreferences,
): ChapterRepository = ChapterRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun downloadRepository(
apolloClient: ApolloClient,
http: Http,
serverPreferences: ServerPreferences,
): DownloadRepository = DownloadRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun extensionRepository(
apolloClient: ApolloClient,
http: Http,
serverPreferences: ServerPreferences,
): ExtensionRepository = ExtensionRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun globalRepository(
apolloClient: ApolloClient,
http: Http,
serverPreferences: ServerPreferences,
): GlobalRepository = GlobalRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun libraryRepository(
apolloClient: ApolloClient,
http: Http,
serverPreferences: ServerPreferences,
): LibraryRepository = LibraryRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun mangaRepository(
apolloClient: ApolloClient,
http: Http,
serverPreferences: ServerPreferences,
): MangaRepository = MangaRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun sourceRepository(
apolloClient: ApolloClient,
http: Http,
serverPreferences: ServerPreferences,
): SourceRepository = SourceRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun updatesRepository(
apolloClient: ApolloClient,
http: Http,
serverPreferences: ServerPreferences,
): UpdatesRepository = UpdatesRepositoryImpl(apolloClient, http, serverPreferences.serverUrl().get())
@Provides
fun backupRepository(
apolloClient: ApolloClient,

View File

@@ -111,6 +111,8 @@ class BackupRepositoryImpl(
BackupRestoreState.FAILURE -> RestoreState.FAILURE
BackupRestoreState.RESTORING_CATEGORIES -> RestoreState.RESTORING_CATEGORIES
BackupRestoreState.RESTORING_MANGA -> RestoreState.RESTORING_MANGA
BackupRestoreState.RESTORING_META -> RestoreState.RESTORING_META
BackupRestoreState.RESTORING_SETTINGS -> RestoreState.RESTORING_SETTINGS
BackupRestoreState.UNKNOWN__ -> RestoreState.UNKNOWN
},
mangaProgress,

View File

@@ -0,0 +1,173 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.data.category
import ca.gosyer.jui.data.graphql.AddMangaToCategoriesMutation
import ca.gosyer.jui.data.graphql.CreateCategoryMutation
import ca.gosyer.jui.data.graphql.DeleteCategoryMutation
import ca.gosyer.jui.data.graphql.GetCategoriesQuery
import ca.gosyer.jui.data.graphql.GetCategoryMangaQuery
import ca.gosyer.jui.data.graphql.GetMangaCategoriesQuery
import ca.gosyer.jui.data.graphql.ModifyCategoryMutation
import ca.gosyer.jui.data.graphql.RemoveMangaFromCategoriesMutation
import ca.gosyer.jui.data.graphql.ReorderCategoryMutation
import ca.gosyer.jui.data.graphql.SetCategoryMetaMutation
import ca.gosyer.jui.data.graphql.fragment.CategoryFragment
import ca.gosyer.jui.data.manga.MangaRepositoryImpl.Companion.toManga
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.category.model.CategoryMeta
import ca.gosyer.jui.domain.category.service.CategoryRepository
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.server.Http
import com.apollographql.apollo.ApolloClient
import io.ktor.http.Url
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class CategoryRepositoryImpl(
private val apolloClient: ApolloClient,
private val http: Http,
private val serverUrl: Url,
): CategoryRepository {
override fun getMangaCategories(mangaId: Long): Flow<List<Category>> {
return apolloClient.query(
GetMangaCategoriesQuery(mangaId.toInt())
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.manga.categories.nodes.map { it.categoryFragment.toCategory() }
}
}
override fun addMangaToCategory(
mangaId: Long,
categoryId: Long,
): Flow<Unit> {
return apolloClient.mutation(
AddMangaToCategoriesMutation(mangaId.toInt(), listOf(categoryId.toInt()))
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.updateMangaCategories!!.clientMutationId
}
}
override fun removeMangaFromCategory(
mangaId: Long,
categoryId: Long,
): Flow<Unit> {
return apolloClient.mutation(
RemoveMangaFromCategoriesMutation(mangaId.toInt(), listOf(categoryId.toInt()))
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.updateMangaCategories!!.clientMutationId
}
}
override fun getCategories(): Flow<List<Category>> {
return apolloClient.query(
GetCategoriesQuery()
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.categories.nodes.map { it.categoryFragment.toCategory() }
}
}
override fun createCategory(name: String): Flow<Unit> {
return apolloClient.mutation(
CreateCategoryMutation(name)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.createCategory!!.clientMutationId
}
}
override fun modifyCategory(
categoryId: Long,
name: String,
): Flow<Unit> {
return apolloClient.mutation(
ModifyCategoryMutation(categoryId.toInt(), name)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.updateCategory!!.clientMutationId
}
}
override fun reorderCategory(
categoryId: Long,
position: Int,
): Flow<Unit> {
return apolloClient.mutation(
ReorderCategoryMutation(categoryId.toInt(), position)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.updateCategoryOrder!!.clientMutationId
}
}
override fun deleteCategory(categoryId: Long): Flow<Unit> {
return apolloClient.mutation(
DeleteCategoryMutation(categoryId.toInt())
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.deleteCategory!!.clientMutationId
}
}
override fun getMangaFromCategory(categoryId: Long): Flow<List<Manga>> {
return apolloClient.query(
GetCategoryMangaQuery(listOf(categoryId.toInt()))
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.mangas.nodes.map { it.mangaFragment.toManga() }
}
}
override fun updateCategoryMeta(
categoryId: Long,
key: String,
value: String,
): Flow<Unit> {
return apolloClient.mutation(
SetCategoryMetaMutation(categoryId.toInt(), key, value)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.setCategoryMeta!!.clientMutationId
}
}
companion object {
internal fun CategoryFragment.toCategory(): Category {
return Category(
id = id.toLong(),
order = order,
name = name,
default = default,
meta = CategoryMeta()
)
}
}
}

View File

@@ -10,11 +10,14 @@ import ca.gosyer.jui.data.graphql.UpdateChapterMetaMutation
import ca.gosyer.jui.data.graphql.UpdateChapterMutation
import ca.gosyer.jui.data.graphql.UpdateChaptersMutation
import ca.gosyer.jui.data.graphql.fragment.ChapterFragment
import ca.gosyer.jui.data.graphql.fragment.ChapterWithMangaFragment
import ca.gosyer.jui.data.graphql.type.UpdateChapterPatchInput
import ca.gosyer.jui.data.manga.MangaRepositoryImpl.Companion.toManga
import ca.gosyer.jui.domain.chapter.model.Chapter
import ca.gosyer.jui.domain.chapter.model.ChapterMeta
import ca.gosyer.jui.domain.chapter.service.ChapterRepository
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.updates.model.MangaAndChapter
import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.api.Optional
import io.ktor.client.request.HttpRequestBuilder
@@ -153,7 +156,7 @@ class ChapterRepositoryImpl(
.toFlow()
.map {
val chapters = it.dataAssertNoErrors
chapters.fetchChapters.chapters.map { it.chapterFragment.toChapter() }
chapters.fetchChapters!!.chapters.map { it.chapterFragment.toChapter() }
}
}
@@ -166,7 +169,7 @@ class ChapterRepositoryImpl(
.toFlow()
.map {
val chapters = it.dataAssertNoErrors
chapters.fetchChapterPages.pages
chapters.fetchChapterPages!!.pages
}
}
@@ -204,5 +207,12 @@ class ChapterRepositoryImpl(
)
)
}
internal fun ChapterWithMangaFragment.toMangaAndChapter(): MangaAndChapter {
return MangaAndChapter(
manga.mangaFragment.toManga(),
chapterFragment.toChapter(),
)
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.data.download
import ca.gosyer.jui.data.graphql.ClearDownloaderMutation
import ca.gosyer.jui.data.graphql.DequeueChapterDownloadMutation
import ca.gosyer.jui.data.graphql.EnqueueChapterDownloadMutation
import ca.gosyer.jui.data.graphql.EnqueueChapterDownloadsMutation
import ca.gosyer.jui.data.graphql.ReorderChapterDownloadMutation
import ca.gosyer.jui.data.graphql.StartDownloaderMutation
import ca.gosyer.jui.data.graphql.StopDownloaderMutation
import ca.gosyer.jui.domain.download.service.DownloadRepository
import ca.gosyer.jui.domain.server.Http
import com.apollographql.apollo.ApolloClient
import io.ktor.http.Url
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class DownloadRepositoryImpl(
private val apolloClient: ApolloClient,
private val http: Http,
private val serverUrl: Url,
): DownloadRepository {
override fun startDownloading(): Flow<Unit> {
return apolloClient.mutation(
StartDownloaderMutation()
)
.toFlow()
.map {
it.dataAssertNoErrors
}
}
override fun stopDownloading(): Flow<Unit> {
return apolloClient.mutation(
StopDownloaderMutation()
)
.toFlow()
.map {
it.dataAssertNoErrors
}
}
override fun clearDownloadQueue(): Flow<Unit> {
return apolloClient.mutation(
ClearDownloaderMutation()
)
.toFlow()
.map {
it.dataAssertNoErrors
}
}
override fun queueChapterDownload(chapterId: Long): Flow<Unit> {
return apolloClient.mutation(
EnqueueChapterDownloadMutation(chapterId.toInt())
)
.toFlow()
.map {
it.dataAssertNoErrors
}
}
override fun stopChapterDownload(chapterId: Long): Flow<Unit> {
return apolloClient.mutation(
DequeueChapterDownloadMutation(chapterId.toInt())
)
.toFlow()
.map {
it.dataAssertNoErrors
}
}
override fun reorderChapterDownload(
chapterId: Long,
to: Int,
): Flow<Unit> {
return apolloClient.mutation(
ReorderChapterDownloadMutation(chapterId.toInt(), to)
)
.toFlow()
.map {
it.dataAssertNoErrors
}
}
override fun batchDownload(chapterIds: List<Long>): Flow<Unit> {
return apolloClient.mutation(
EnqueueChapterDownloadsMutation(chapterIds.map { it.toInt() })
)
.toFlow()
.map {
it.dataAssertNoErrors
}
}
}

View File

@@ -0,0 +1,105 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.data.extension
import ca.gosyer.jui.data.graphql.FetchExtensionsMutation
import ca.gosyer.jui.data.graphql.InstallExtensionMutation
import ca.gosyer.jui.data.graphql.InstallExternalExtensionMutation
import ca.gosyer.jui.data.graphql.UninstallExtensionMutation
import ca.gosyer.jui.data.graphql.UpdateExtensionMutation
import ca.gosyer.jui.data.graphql.fragment.ExtensionFragment
import ca.gosyer.jui.domain.extension.model.Extension
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import ca.gosyer.jui.domain.server.Http
import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.api.DefaultUpload
import io.ktor.http.Url
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import okio.Source
class ExtensionRepositoryImpl(
private val apolloClient: ApolloClient,
private val http: Http,
private val serverUrl: Url,
): ExtensionRepository {
override fun getExtensionList(): Flow<List<Extension>> {
return apolloClient.mutation(
FetchExtensionsMutation()
)
.toFlow()
.map {
it.dataAssertNoErrors.fetchExtensions!!.extensions.map { it.extensionFragment.toExtension() }
}
}
override fun installExtension(source: Source): Flow<Unit> {
return apolloClient.mutation(
InstallExternalExtensionMutation(
DefaultUpload.Builder()
.content {
it.writeAll(source)
}
.fileName("extension.apk")
.contentType("application/octet-stream")
.build()
)
)
.toFlow()
.map {
it.dataAssertNoErrors.installExternalExtension!!
}
}
override fun installExtension(pkgName: String): Flow<Unit> {
return apolloClient.mutation(
InstallExtensionMutation(pkgName)
)
.toFlow()
.map {
it.dataAssertNoErrors.updateExtension
}
}
override fun updateExtension(pkgName: String): Flow<Unit> {
return apolloClient.mutation(
UpdateExtensionMutation(pkgName)
)
.toFlow()
.map {
it.dataAssertNoErrors.updateExtension
}
}
override fun uninstallExtension(pkgName: String): Flow<Unit> {
return apolloClient.mutation(
UninstallExtensionMutation(pkgName)
)
.toFlow()
.map {
it.dataAssertNoErrors.updateExtension
}
}
companion object {
internal fun ExtensionFragment.toExtension(): Extension {
return Extension(
name = name,
pkgName = pkgName,
versionName = versionName,
versionCode = versionCode,
lang = lang,
apkName = apkName,
iconUrl = iconUrl,
installed = isInstalled,
hasUpdate = hasUpdate,
obsolete = isObsolete,
isNsfw = isNsfw,
)
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.data.global
import ca.gosyer.jui.data.graphql.GetGlobalMetaQuery
import ca.gosyer.jui.data.graphql.SetGlobalMetaMutation
import ca.gosyer.jui.domain.global.model.GlobalMeta
import ca.gosyer.jui.domain.global.service.GlobalRepository
import ca.gosyer.jui.domain.server.Http
import com.apollographql.apollo.ApolloClient
import io.ktor.http.Url
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class GlobalRepositoryImpl(
private val apolloClient: ApolloClient,
private val http: Http,
private val serverUrl: Url,
): GlobalRepository {
override fun getGlobalMeta(): Flow<GlobalMeta> {
return apolloClient.query(
GetGlobalMetaQuery()
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
GlobalMeta(data.metas.nodes.find { it.key == "example" }?.value?.toIntOrNull() ?: 0)
}
}
override fun updateGlobalMeta(key: String, value: String): Flow<Unit> {
return apolloClient.mutation(
SetGlobalMetaMutation(key, value)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.setGlobalMeta!!.clientMutationId
}
}
}

View File

@@ -0,0 +1,34 @@
package ca.gosyer.jui.data.library
import ca.gosyer.jui.data.graphql.SetMangaInLibraryMutation
import ca.gosyer.jui.domain.library.service.LibraryRepository
import ca.gosyer.jui.domain.server.Http
import com.apollographql.apollo.ApolloClient
import io.ktor.http.Url
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class LibraryRepositoryImpl(
private val apolloClient: ApolloClient,
private val http: Http,
private val serverUrl: Url,
) : LibraryRepository {
fun setMangaInLibrary(mangaId: Long, inLibrary: Boolean): Flow<Unit> {
return apolloClient.mutation(
SetMangaInLibraryMutation(mangaId.toInt(), inLibrary)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.updateManga!!.clientMutationId
}
}
override fun addMangaToLibrary(mangaId: Long): Flow<Unit> {
return setMangaInLibrary(mangaId, true)
}
override fun removeMangaFromLibrary(mangaId: Long): Flow<Unit> {
return setMangaInLibrary(mangaId, false)
}
}

View File

@@ -0,0 +1,188 @@
package ca.gosyer.jui.data.manga
import ca.gosyer.jui.data.graphql.GetMangaLibraryQuery
import ca.gosyer.jui.data.graphql.GetMangaQuery
import ca.gosyer.jui.data.graphql.GetThumbnailUrlQuery
import ca.gosyer.jui.data.graphql.RefreshMangaMutation
import ca.gosyer.jui.data.graphql.SetMangaMetaMutation
import ca.gosyer.jui.data.graphql.fragment.LibraryMangaFragment
import ca.gosyer.jui.data.graphql.fragment.MangaFragment
import ca.gosyer.jui.data.source.SourceRepositoryImpl.Companion.toSource
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.manga.model.MangaMeta
import ca.gosyer.jui.domain.manga.model.MangaStatus
import ca.gosyer.jui.domain.manga.model.UpdateStrategy
import ca.gosyer.jui.domain.manga.service.MangaRepository
import ca.gosyer.jui.domain.server.Http
import com.apollographql.apollo.ApolloClient
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsChannel
import io.ktor.http.Url
import io.ktor.utils.io.ByteReadChannel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import ca.gosyer.jui.data.graphql.type.MangaStatus as GqlMangaStatus
import ca.gosyer.jui.data.graphql.type.UpdateStrategy as GqlUpdateStrategy
class MangaRepositoryImpl(
private val apolloClient: ApolloClient,
private val http: Http,
private val serverUrl: Url,
) : MangaRepository {
override fun getManga(mangaId: Long): Flow<Manga> {
return apolloClient.query(
GetMangaQuery(mangaId.toInt())
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.manga.mangaFragment.toManga()
}
}
override fun refreshManga(mangaId: Long): Flow<Manga> {
return apolloClient.mutation(
RefreshMangaMutation(mangaId.toInt())
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.fetchManga!!.manga.mangaFragment.toManga()
}
}
override fun getMangaLibrary(mangaId: Long): Flow<Manga> {
return apolloClient.query(
GetMangaLibraryQuery(mangaId.toInt())
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.manga.libraryMangaFragment.toManga()
}
}
override fun getMangaThumbnail(
mangaId: Long,
block: HttpRequestBuilder.() -> Unit,
): Flow<ByteReadChannel> {
return apolloClient.query(
GetThumbnailUrlQuery(mangaId.toInt())
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
http.get(data.manga.thumbnailUrl!!).bodyAsChannel()
}
}
override fun updateMangaMeta(
mangaId: Long,
key: String,
value: String,
): Flow<Unit> {
return apolloClient.mutation(
SetMangaMetaMutation(mangaId.toInt(), key, value)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.setMangaMeta!!.clientMutationId
}
}
companion object {
internal fun MangaFragment.toManga(): Manga {
return Manga(
id = id.toLong(),
sourceId = sourceId,
url = url,
title = title,
thumbnailUrl = thumbnailUrl,
thumbnailUrlLastFetched = thumbnailUrlLastFetched ?: 0,
initialized = initialized,
artist = artist,
author = author,
description = description,
genre = genre,
status = when (status) {
GqlMangaStatus.ONGOING -> MangaStatus.ONGOING
GqlMangaStatus.COMPLETED -> MangaStatus.COMPLETED
GqlMangaStatus.LICENSED -> MangaStatus.LICENSED
GqlMangaStatus.PUBLISHING_FINISHED -> MangaStatus.PUBLISHING_FINISHED
GqlMangaStatus.CANCELLED -> MangaStatus.CANCELLED
GqlMangaStatus.ON_HIATUS -> MangaStatus.ON_HIATUS
GqlMangaStatus.UNKNOWN, GqlMangaStatus.UNKNOWN__ -> MangaStatus.UNKNOWN
},
inLibrary = inLibrary,
source = null,
updateStrategy = when (updateStrategy) {
GqlUpdateStrategy.ALWAYS_UPDATE -> UpdateStrategy.ALWAYS_UPDATE
GqlUpdateStrategy.ONLY_FETCH_ONCE -> UpdateStrategy.ONLY_FETCH_ONCE
GqlUpdateStrategy.UNKNOWN__ -> UpdateStrategy.ALWAYS_UPDATE
},
freshData = false,
meta = MangaMeta(
meta.find { it.key == "juiReaderMode" }?.value.orEmpty(),
),
realUrl = realUrl,
lastFetchedAt = lastFetchedAt,
chaptersLastFetchedAt = chaptersLastFetchedAt,
inLibraryAt = inLibraryAt,
unreadCount = null,
downloadCount = null,
chapterCount = null,
lastChapterReadTime = null,
age = age,
chaptersAge = null,
)
}
internal fun LibraryMangaFragment.toManga(): Manga {
return Manga(
id = id.toLong(),
sourceId = sourceId,
url = url,
title = title,
thumbnailUrl = thumbnailUrl,
thumbnailUrlLastFetched = thumbnailUrlLastFetched ?: 0,
initialized = initialized,
artist = artist,
author = author,
description = description,
genre = genre,
status = when (status) {
GqlMangaStatus.ONGOING -> MangaStatus.ONGOING
GqlMangaStatus.COMPLETED -> MangaStatus.COMPLETED
GqlMangaStatus.LICENSED -> MangaStatus.LICENSED
GqlMangaStatus.PUBLISHING_FINISHED -> MangaStatus.PUBLISHING_FINISHED
GqlMangaStatus.CANCELLED -> MangaStatus.CANCELLED
GqlMangaStatus.ON_HIATUS -> MangaStatus.ON_HIATUS
GqlMangaStatus.UNKNOWN, GqlMangaStatus.UNKNOWN__ -> MangaStatus.UNKNOWN
},
inLibrary = inLibrary,
source = source?.sourceFragment?.toSource(),
updateStrategy = when (updateStrategy) {
GqlUpdateStrategy.ALWAYS_UPDATE -> UpdateStrategy.ALWAYS_UPDATE
GqlUpdateStrategy.ONLY_FETCH_ONCE -> UpdateStrategy.ONLY_FETCH_ONCE
GqlUpdateStrategy.UNKNOWN__ -> UpdateStrategy.ALWAYS_UPDATE
},
freshData = false,
meta = MangaMeta(
meta.find { it.key == "juiReaderMode" }?.value.orEmpty(),
),
realUrl = realUrl,
lastFetchedAt = lastFetchedAt,
chaptersLastFetchedAt = chaptersLastFetchedAt,
inLibraryAt = inLibraryAt,
unreadCount = unreadCount,
downloadCount = downloadCount,
chapterCount = chapters.totalCount,
lastChapterReadTime = lastReadChapter?.lastReadAt ?: 0,
age = age,
chaptersAge = null,
)
}
}
}

View File

@@ -9,6 +9,13 @@ package ca.gosyer.jui.data.settings
import ca.gosyer.jui.data.graphql.AllSettingsQuery
import ca.gosyer.jui.data.graphql.SetSettingsMutation
import ca.gosyer.jui.data.graphql.fragment.SettingsTypeFragment
import ca.gosyer.jui.data.graphql.fragment.SettingsTypeFragment.DownloadConversion
import ca.gosyer.jui.data.graphql.type.AuthMode
import ca.gosyer.jui.data.graphql.type.DatabaseType
import ca.gosyer.jui.data.graphql.type.KoreaderSyncChecksumMethod
import ca.gosyer.jui.data.graphql.type.KoreaderSyncConflictStrategy
import ca.gosyer.jui.data.graphql.type.SettingsDownloadConversionTypeInput
import ca.gosyer.jui.data.graphql.type.SortOrder
import ca.gosyer.jui.data.graphql.type.WebUIChannel
import ca.gosyer.jui.data.graphql.type.WebUIFlavor
import ca.gosyer.jui.data.graphql.type.WebUIInterface
@@ -22,6 +29,12 @@ import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import ca.gosyer.jui.domain.settings.model.AuthMode as DomainAuthMode
import ca.gosyer.jui.domain.settings.model.DatabaseType as DomainDatabaseType
import ca.gosyer.jui.domain.settings.model.DownloadConversion as DomainDownloadConversion
import ca.gosyer.jui.domain.settings.model.KoreaderSyncChecksumMethod as DomainKoreaderSyncChecksumMethod
import ca.gosyer.jui.domain.settings.model.KoreaderSyncConflictStrategy as DomainKoreaderSyncConflictStrategy
import ca.gosyer.jui.domain.settings.model.SortOrder as DomainSortOrder
import ca.gosyer.jui.domain.settings.model.WebUIChannel as DomainWebUIChannel
import ca.gosyer.jui.domain.settings.model.WebUIFlavor as DomainWebUIFlavor
import ca.gosyer.jui.domain.settings.model.WebUIInterface as DomainWebUIInterface
@@ -31,17 +44,23 @@ class SettingsRepositoryImpl(
) : SettingsRepository {
private fun SettingsTypeFragment.toSettings() =
Settings(
authMode = authMode.toDomain(),
authPassword = authPassword,
authUsername = authUsername,
autoDownloadIgnoreReUploads = autoDownloadIgnoreReUploads,
autoDownloadNewChapters = autoDownloadNewChapters,
autoDownloadNewChaptersLimit = autoDownloadNewChaptersLimit,
backupInterval = backupInterval,
backupPath = backupPath,
backupTTL = backupTTL,
backupTime = backupTime,
basicAuthEnabled = basicAuthEnabled,
basicAuthPassword = basicAuthPassword,
basicAuthUsername = basicAuthUsername,
databasePassword = databasePassword,
databaseType = databaseType.toDomain(),
databaseUrl = databaseUrl,
databaseUsername = databaseUsername,
debugLogsEnabled = debugLogsEnabled,
downloadAsCbz = downloadAsCbz,
downloadConversions = downloadConversions.map { it.toDomain() },
downloadsPath = downloadsPath,
electronPath = electronPath,
excludeCompleted = excludeCompleted,
@@ -49,17 +68,38 @@ class SettingsRepositoryImpl(
excludeNotStarted = excludeNotStarted,
excludeUnreadChapters = excludeUnreadChapters,
extensionRepos = extensionRepos,
flareSolverrAsResponseFallback = flareSolverrAsResponseFallback,
flareSolverrEnabled = flareSolverrEnabled,
flareSolverrSessionName = flareSolverrSessionName,
flareSolverrSessionTtl = flareSolverrSessionTtl,
flareSolverrTimeout = flareSolverrTimeout,
flareSolverrUrl = flareSolverrUrl,
globalUpdateInterval = globalUpdateInterval,
gqlDebugLogsEnabled = gqlDebugLogsEnabled,
initialOpenInBrowserEnabled = initialOpenInBrowserEnabled,
ip = ip,
jwtAudience = jwtAudience,
jwtRefreshExpiry = jwtRefreshExpiry,
jwtTokenExpiry = jwtTokenExpiry,
koreaderSyncChecksumMethod = koreaderSyncChecksumMethod.toDomain(),
koreaderSyncDeviceId = koreaderSyncDeviceId,
koreaderSyncPercentageTolerance = koreaderSyncPercentageTolerance,
koreaderSyncServerUrl = koreaderSyncServerUrl,
koreaderSyncStrategyBackward = koreaderSyncStrategyBackward.toDomain(),
koreaderSyncStrategyForward = koreaderSyncStrategyForward.toDomain(),
koreaderSyncUserkey = koreaderSyncUserkey,
koreaderSyncUsername = koreaderSyncUsername,
localSourcePath = localSourcePath,
maxLogFileSize = maxLogFileSize,
maxLogFiles = maxLogFiles,
maxLogFolderSize = maxLogFolderSize,
maxSourcesInParallel = maxSourcesInParallel,
opdsChapterSortOrder = opdsChapterSortOrder.toDomain(),
opdsEnablePageReadProgress = opdsEnablePageReadProgress,
opdsItemsPerPage = opdsItemsPerPage,
opdsMarkAsReadOnDownload = opdsMarkAsReadOnDownload,
opdsShowOnlyDownloadedChapters = opdsShowOnlyDownloadedChapters,
opdsShowOnlyUnreadChapters = opdsShowOnlyUnreadChapters,
opdsUseBinaryFileSizes = opdsUseBinaryFileSizes,
port = port,
socksProxyEnabled = socksProxyEnabled,
socksProxyHost = socksProxyHost,
@@ -75,6 +115,57 @@ class SettingsRepositoryImpl(
webUIUpdateCheckInterval = webUIUpdateCheckInterval,
)
private fun AuthMode.toDomain() =
when (this) {
AuthMode.NONE -> DomainAuthMode.NONE
AuthMode.BASIC_AUTH -> DomainAuthMode.BASIC_AUTH
AuthMode.SIMPLE_LOGIN -> DomainAuthMode.SIMPLE_LOGIN
AuthMode.UI_LOGIN -> DomainAuthMode.UI_LOGIN
AuthMode.UNKNOWN__ -> DomainAuthMode.UNKNOWN__
}
private fun DatabaseType.toDomain() =
when (this) {
DatabaseType.H2 -> DomainDatabaseType.H2
DatabaseType.POSTGRESQL -> DomainDatabaseType.POSTGRESQL
DatabaseType.UNKNOWN__ -> DomainDatabaseType.UNKNOWN__
}
private fun DownloadConversion.toDomain() =
DomainDownloadConversion(
compressionLevel = compressionLevel,
mimeType = mimeType,
target = target,
)
private fun KoreaderSyncConflictStrategy.toDomain() =
when (this) {
KoreaderSyncConflictStrategy.PROMPT -> DomainKoreaderSyncConflictStrategy.PROMPT
KoreaderSyncConflictStrategy.KEEP_LOCAL -> DomainKoreaderSyncConflictStrategy.KEEP_LOCAL
KoreaderSyncConflictStrategy.KEEP_REMOTE -> DomainKoreaderSyncConflictStrategy.KEEP_REMOTE
KoreaderSyncConflictStrategy.DISABLED -> DomainKoreaderSyncConflictStrategy.DISABLED
KoreaderSyncConflictStrategy.UNKNOWN__ -> DomainKoreaderSyncConflictStrategy.UNKNOWN__
}
private fun KoreaderSyncChecksumMethod.toDomain() =
when (this) {
KoreaderSyncChecksumMethod.BINARY -> DomainKoreaderSyncChecksumMethod.BINARY
KoreaderSyncChecksumMethod.FILENAME -> DomainKoreaderSyncChecksumMethod.FILENAME
KoreaderSyncChecksumMethod.UNKNOWN__ -> DomainKoreaderSyncChecksumMethod.UNKNOWN__
}
private fun SortOrder.toDomain() =
when (this) {
SortOrder.ASC -> DomainSortOrder.ASC
SortOrder.DESC -> DomainSortOrder.DESC
SortOrder.ASC_NULLS_FIRST -> DomainSortOrder.ASC_NULLS_FIRST
SortOrder.DESC_NULLS_FIRST -> DomainSortOrder.DESC_NULLS_FIRST
SortOrder.ASC_NULLS_LAST -> DomainSortOrder.ASC_NULLS_LAST
SortOrder.DESC_NULLS_LAST -> DomainSortOrder.DESC_NULLS_LAST
SortOrder.UNKNOWN__ -> DomainSortOrder.UNKNOWN__
}
private fun WebUIChannel.toDomain() =
when (this) {
WebUIChannel.BUNDLED -> DomainWebUIChannel.BUNDLED
@@ -98,6 +189,56 @@ class SettingsRepositoryImpl(
WebUIInterface.UNKNOWN__ -> DomainWebUIInterface.UNKNOWN__
}
private fun DomainAuthMode.toGraphQL() =
when (this) {
DomainAuthMode.NONE -> AuthMode.NONE
DomainAuthMode.BASIC_AUTH -> AuthMode.BASIC_AUTH
DomainAuthMode.SIMPLE_LOGIN -> AuthMode.SIMPLE_LOGIN
DomainAuthMode.UI_LOGIN -> AuthMode.UI_LOGIN
DomainAuthMode.UNKNOWN__ -> AuthMode.UNKNOWN__
}
private fun DomainDatabaseType.toGraphQL() =
when (this) {
DomainDatabaseType.H2 -> DatabaseType.H2
DomainDatabaseType.POSTGRESQL -> DatabaseType.POSTGRESQL
DomainDatabaseType.UNKNOWN__ -> DatabaseType.UNKNOWN__
}
private fun DomainDownloadConversion.toGraphQL() =
SettingsDownloadConversionTypeInput(
compressionLevel = compressionLevel.toOptional(),
mimeType = mimeType,
target = target,
)
private fun DomainKoreaderSyncChecksumMethod.toGraphQL() =
when (this) {
DomainKoreaderSyncChecksumMethod.BINARY -> KoreaderSyncChecksumMethod.BINARY
DomainKoreaderSyncChecksumMethod.FILENAME -> KoreaderSyncChecksumMethod.FILENAME
DomainKoreaderSyncChecksumMethod.UNKNOWN__ -> KoreaderSyncChecksumMethod.UNKNOWN__
}
private fun DomainKoreaderSyncConflictStrategy.toGraphQL() =
when (this) {
DomainKoreaderSyncConflictStrategy.PROMPT -> KoreaderSyncConflictStrategy.PROMPT
DomainKoreaderSyncConflictStrategy.KEEP_LOCAL -> KoreaderSyncConflictStrategy.KEEP_LOCAL
DomainKoreaderSyncConflictStrategy.KEEP_REMOTE -> KoreaderSyncConflictStrategy.KEEP_REMOTE
DomainKoreaderSyncConflictStrategy.DISABLED -> KoreaderSyncConflictStrategy.DISABLED
DomainKoreaderSyncConflictStrategy.UNKNOWN__ -> KoreaderSyncConflictStrategy.UNKNOWN__
}
private fun DomainSortOrder.toGraphQL() =
when (this) {
DomainSortOrder.ASC -> SortOrder.ASC
DomainSortOrder.DESC -> SortOrder.DESC
DomainSortOrder.ASC_NULLS_FIRST -> SortOrder.ASC_NULLS_FIRST
DomainSortOrder.DESC_NULLS_FIRST -> SortOrder.DESC_NULLS_FIRST
DomainSortOrder.ASC_NULLS_LAST -> SortOrder.ASC_NULLS_LAST
DomainSortOrder.DESC_NULLS_LAST -> SortOrder.DESC_NULLS_LAST
DomainSortOrder.UNKNOWN__ -> SortOrder.UNKNOWN__
}
private fun DomainWebUIChannel.toGraphQL() =
when (this) {
DomainWebUIChannel.BUNDLED -> WebUIChannel.BUNDLED
@@ -130,17 +271,23 @@ class SettingsRepositoryImpl(
private fun SetSettingsInput.toMutation() =
SetSettingsMutation(
authMode = authMode?.toGraphQL().toOptional(),
authPassword = authPassword.toOptional(),
authUsername = authUsername.toOptional(),
autoDownloadIgnoreReUploads = autoDownloadIgnoreReUploads.toOptional(),
autoDownloadNewChapters = autoDownloadNewChapters.toOptional(),
autoDownloadNewChaptersLimit = autoDownloadNewChaptersLimit.toOptional(),
backupInterval = backupInterval.toOptional(),
backupPath = backupPath.toOptional(),
backupTTL = backupTTL.toOptional(),
backupTime = backupTime.toOptional(),
basicAuthEnabled = basicAuthEnabled.toOptional(),
basicAuthPassword = basicAuthPassword.toOptional(),
basicAuthUsername = basicAuthUsername.toOptional(),
databasePassword = databasePassword.toOptional(),
databaseType = databaseType?.toGraphQL().toOptional(),
databaseUrl = databaseUrl.toOptional(),
databaseUsername = databaseUsername.toOptional(),
debugLogsEnabled = debugLogsEnabled.toOptional(),
downloadAsCbz = downloadAsCbz.toOptional(),
downloadConversions = downloadConversions?.map { it.toGraphQL() }.toOptional(),
downloadsPath = downloadsPath.toOptional(),
electronPath = electronPath.toOptional(),
excludeCompleted = excludeCompleted.toOptional(),
@@ -148,17 +295,38 @@ class SettingsRepositoryImpl(
excludeNotStarted = excludeNotStarted.toOptional(),
excludeUnreadChapters = excludeUnreadChapters.toOptional(),
extensionRepos = extensionRepos.toOptional(),
flareSolverrAsResponseFallback = flareSolverrAsResponseFallback.toOptional(),
flareSolverrEnabled = flareSolverrEnabled.toOptional(),
flareSolverrSessionName = flareSolverrSessionName.toOptional(),
flareSolverrSessionTtl = flareSolverrSessionTtl.toOptional(),
flareSolverrTimeout = flareSolverrTimeout.toOptional(),
flareSolverrUrl = flareSolverrUrl.toOptional(),
globalUpdateInterval = globalUpdateInterval.toOptional(),
gqlDebugLogsEnabled = gqlDebugLogsEnabled.toOptional(),
initialOpenInBrowserEnabled = initialOpenInBrowserEnabled.toOptional(),
ip = ip.toOptional(),
jwtAudience = jwtAudience.toOptional(),
jwtRefreshExpiry = jwtRefreshExpiry.toOptional(),
jwtTokenExpiry = jwtTokenExpiry.toOptional(),
koreaderSyncChecksumMethod = koreaderSyncChecksumMethod?.toGraphQL().toOptional(),
koreaderSyncDeviceId = koreaderSyncDeviceId.toOptional(),
koreaderSyncPercentageTolerance = koreaderSyncPercentageTolerance.toOptional(),
koreaderSyncServerUrl = koreaderSyncServerUrl.toOptional(),
koreaderSyncStrategyBackward = koreaderSyncStrategyBackward?.toGraphQL().toOptional(),
koreaderSyncStrategyForward = koreaderSyncStrategyForward?.toGraphQL().toOptional(),
koreaderSyncUserkey = koreaderSyncUserkey.toOptional(),
koreaderSyncUsername = koreaderSyncUsername.toOptional(),
localSourcePath = localSourcePath.toOptional(),
maxLogFileSize = maxLogFileSize.toOptional(),
maxLogFiles = maxLogFiles.toOptional(),
maxLogFolderSize = maxLogFolderSize.toOptional(),
maxSourcesInParallel = maxSourcesInParallel.toOptional(),
opdsChapterSortOrder = opdsChapterSortOrder?.toGraphQL().toOptional(),
opdsEnablePageReadProgress = opdsEnablePageReadProgress.toOptional(),
opdsItemsPerPage = opdsItemsPerPage.toOptional(),
opdsMarkAsReadOnDownload = opdsMarkAsReadOnDownload.toOptional(),
opdsShowOnlyDownloadedChapters = opdsShowOnlyDownloadedChapters.toOptional(),
opdsShowOnlyUnreadChapters = opdsShowOnlyUnreadChapters.toOptional(),
opdsUseBinaryFileSizes = opdsUseBinaryFileSizes.toOptional(),
port = port.toOptional(),
socksProxyEnabled = socksProxyEnabled.toOptional(),
socksProxyHost = socksProxyHost.toOptional(),

View File

@@ -0,0 +1,452 @@
package ca.gosyer.jui.data.source
import ca.gosyer.jui.data.graphql.FetchLatestMangaMutation
import ca.gosyer.jui.data.graphql.FetchPopularMangaMutation
import ca.gosyer.jui.data.graphql.FetchSearchMangaMutation
import ca.gosyer.jui.data.graphql.GetSourceFiltersQuery
import ca.gosyer.jui.data.graphql.GetSourceListQuery
import ca.gosyer.jui.data.graphql.GetSourcePreferencesQuery
import ca.gosyer.jui.data.graphql.GetSourceQuery
import ca.gosyer.jui.data.graphql.SetSourceSettingMutation
import ca.gosyer.jui.data.graphql.fragment.SourceFragment
import ca.gosyer.jui.data.graphql.type.FilterChangeInput
import ca.gosyer.jui.data.graphql.type.SortSelectionInput
import ca.gosyer.jui.data.graphql.type.SourcePreferenceChangeInput
import ca.gosyer.jui.data.graphql.type.TriState
import ca.gosyer.jui.data.manga.MangaRepositoryImpl.Companion.toManga
import ca.gosyer.jui.data.util.toOptional
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.source.model.MangaPage
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilter
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilter.TriState.TriStateValue
import ca.gosyer.jui.domain.source.model.sourcepreference.CheckBoxSourcePreference
import ca.gosyer.jui.domain.source.model.sourcepreference.EditTextSourcePreference
import ca.gosyer.jui.domain.source.model.sourcepreference.ListSourcePreference
import ca.gosyer.jui.domain.source.model.sourcepreference.MultiSelectListSourcePreference
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreference
import ca.gosyer.jui.domain.source.model.sourcepreference.SwitchSourcePreference
import ca.gosyer.jui.domain.source.service.SourceRepository
import com.apollographql.apollo.ApolloClient
import io.ktor.http.Url
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class SourceRepositoryImpl(
private val apolloClient: ApolloClient,
private val http: Http,
private val serverUrl: Url,
) : SourceRepository {
override fun getSourceList(): Flow<List<Source>> {
return apolloClient.query(
GetSourceListQuery()
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.sources.nodes.map { it.sourceFragment.toSource() }
}
}
override fun getSourceInfo(sourceId: Long): Flow<Source> {
return apolloClient.query(
GetSourceQuery(sourceId)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.source.sourceFragment.toSource()
}
}
override fun getPopularManga(
sourceId: Long,
pageNum: Int,
): Flow<MangaPage> {
return apolloClient.mutation(
FetchPopularMangaMutation(sourceId, pageNum)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
MangaPage(
data.fetchSourceManga!!.mangas.map { it.mangaFragment.toManga() },
data.fetchSourceManga.hasNextPage
)
}
}
override fun getLatestManga(
sourceId: Long,
pageNum: Int,
): Flow<MangaPage> {
return apolloClient.mutation(
FetchLatestMangaMutation(sourceId, pageNum)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
MangaPage(
data.fetchSourceManga!!.mangas.map { it.mangaFragment.toManga() },
data.fetchSourceManga.hasNextPage
)
}
}
override fun getFilterList(
sourceId: Long,
): Flow<List<SourceFilter>> {
return apolloClient.query(
GetSourceFiltersQuery(sourceId)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.source.filters.mapIndexed { index, filter ->
when (filter.__typename) {
"CheckBoxFilter" -> {
val filter = filter.onCheckBoxFilter!!
SourceFilter.Checkbox(
index,
filter.name,
filter.checkBoxFilterDefault,
)
}
"HeaderFilter" -> {
val filter = filter.onHeaderFilter!!
SourceFilter.Header(
index,
filter.name,
)
}
"SelectFilter" -> {
val filter = filter.onSelectFilter!!
SourceFilter.Select(
index,
filter.name,
filter.values,
filter.selectFilterDefault
)
}
"TriStateFilter" -> {
val filter = filter.onTriStateFilter!!
SourceFilter.TriState(
index,
filter.name,
when (filter.triStateFilterDefault) {
TriState.IGNORE -> TriStateValue.IGNORE
TriState.INCLUDE -> TriStateValue.INCLUDE
TriState.EXCLUDE -> TriStateValue.EXCLUDE
TriState.UNKNOWN__ -> TriStateValue.IGNORE
},
)
}
"TextFilter" -> {
val filter = filter.onTextFilter!!
SourceFilter.Text(
index,
filter.name,
filter.textFilterDefault,
)
}
"SortFilter" -> {
val filter = filter.onSortFilter!!
SourceFilter.Sort(
index,
filter.name,
filter.values,
filter.sortFilterDefault?.let {
SourceFilter.Sort.SelectionChange(it.ascending, it.index)
},
)
}
"SeparatorFilter" -> {
val filter = filter.onSeparatorFilter!!
SourceFilter.Separator(
index,
filter.name,
)
}
"GroupFilter" -> {
SourceFilter.Group(
index,
filter.onGroupFilter!!.name,
filter.onGroupFilter.filters.mapIndexed { index, filter ->
when (filter.__typename) {
"CheckBoxFilter" -> {
val filter = filter.onCheckBoxFilter!!
SourceFilter.Checkbox(
index,
filter.name,
filter.checkBoxFilterDefault,
)
}
"HeaderFilter" -> {
val filter = filter.onHeaderFilter!!
SourceFilter.Header(
index,
filter.name,
)
}
"SelectFilter" -> {
val filter = filter.onSelectFilter!!
SourceFilter.Select(
index,
filter.name,
filter.values,
filter.selectFilterDefault
)
}
"TriStateFilter" -> {
val filter = filter.onTriStateFilter!!
SourceFilter.TriState(
index,
filter.name,
when (filter.triStateFilterDefault) {
TriState.IGNORE -> TriStateValue.IGNORE
TriState.INCLUDE -> TriStateValue.INCLUDE
TriState.EXCLUDE -> TriStateValue.EXCLUDE
TriState.UNKNOWN__ -> TriStateValue.IGNORE
},
)
}
"TextFilter" -> {
val filter = filter.onTextFilter!!
SourceFilter.Text(
index,
filter.name,
filter.textFilterDefault,
)
}
"SortFilter" -> {
val filter = filter.onSortFilter!!
SourceFilter.Sort(
index,
filter.name,
filter.values,
filter.sortFilterDefault?.let {
SourceFilter.Sort.SelectionChange(it.ascending, it.index)
},
)
}
"SeparatorFilter" -> {
val filter = filter.onSeparatorFilter!!
SourceFilter.Separator(
index,
filter.name,
)
}
else -> SourceFilter.Header(index, "")
}
}
)
}
else -> SourceFilter.Header(index, "")
}
}
}
}
fun SourceFilter.toFilterChange(): List<FilterChangeInput>? {
return when (this) {
is SourceFilter.Checkbox -> if (value != default) {
listOf(FilterChangeInput(position = position, checkBoxState = value.toOptional()))
} else {
null
}
is SourceFilter.Header -> null
is SourceFilter.Select -> if (value != default) {
listOf(FilterChangeInput(position = position, selectState = value.toOptional()))
} else {
null
}
is SourceFilter.Separator -> null
is SourceFilter.Sort -> if (value != default) {
listOf(
FilterChangeInput(
position = position,
sortState = value?.let { SortSelectionInput(it.ascending, it.index) }.toOptional()
)
)
} else {
null
}
is SourceFilter.Text -> if (value != default) {
listOf(FilterChangeInput(position = position, textState = value.toOptional()))
} else {
null
}
is SourceFilter.TriState -> if (value != default) {
listOf(
FilterChangeInput(
position = position,
triState = when (value) {
TriStateValue.IGNORE -> TriState.IGNORE
TriStateValue.INCLUDE -> TriState.INCLUDE
TriStateValue.EXCLUDE -> TriState.EXCLUDE
}.toOptional(),
)
)
} else {
null
}
is SourceFilter.Group -> value.mapNotNull {
FilterChangeInput(
position = position,
groupChange = it.toFilterChange()
?.firstOrNull()
?.toOptional()
?: return@mapNotNull null
)
}
}
}
override fun getSearchResults(
sourceId: Long,
pageNum: Int,
searchTerm: String?,
filters: List<SourceFilter>?,
): Flow<MangaPage> {
return apolloClient.mutation(
FetchSearchMangaMutation(
sourceId,
pageNum,
searchTerm.toOptional(),
filters?.mapNotNull {
it.toFilterChange()
}?.flatten().toOptional(),
),
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
MangaPage(
data.fetchSourceManga!!.mangas.map { it.mangaFragment.toManga() },
data.fetchSourceManga.hasNextPage
)
}
}
override fun getSourceSettings(sourceId: Long): Flow<List<SourcePreference>> {
return apolloClient.query(
GetSourcePreferencesQuery(sourceId)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.source.preferences.mapIndexedNotNull { index, preference ->
println("Test " + preference.__typename + " $index")
when (preference.__typename) {
"CheckBoxPreference" -> preference.onCheckBoxPreference!!.let {
CheckBoxSourcePreference(
position = index,
key = it.key,
title = it.checkBoxTitle,
summary = it.summary,
visible = it.visible,
enabled = it.enabled,
currentValue = it.checkBoxCheckBoxCurrentValue,
default = it.checkBoxDefault,
)
}
"EditTextPreference" -> preference.onEditTextPreference!!.let {
EditTextSourcePreference(
position = index,
key = it.key,
title = it.editTextPreferenceTitle,
summary = it.summary,
visible = it.visible,
enabled = it.enabled,
currentValue = it.editTextPreferenceCurrentValue,
default = it.editTextPreferenceDefault,
dialogTitle = it.dialogTitle,
dialogMessage = it.dialogMessage,
text = it.text,
)
}
"SwitchPreference" -> preference.onSwitchPreference!!.let {
SwitchSourcePreference(
position = index,
key = it.key,
title = it.switchPreferenceTitle,
summary = it.summary,
visible = it.visible,
enabled = it.enabled,
currentValue = it.switchPreferenceCurrentValue,
default = it.switchPreferenceDefault,
)
}
"MultiSelectListPreference" -> preference.onMultiSelectListPreference!!.let {
MultiSelectListSourcePreference(
position = index,
key = it.key,
title = it.multiSelectListPreferenceTitle,
summary = it.summary,
visible = it.visible,
enabled = it.enabled,
currentValue = it.multiSelectListPreferenceCurrentValue,
default = it.multiSelectListPreferenceDefault,
dialogTitle = it.dialogTitle,
dialogMessage = it.dialogMessage,
entries = it.entries,
entryValues = it.entryValues
)
}
"ListPreference" -> preference.onListPreference!!.let {
ListSourcePreference(
position = index,
key = it.key,
title = it.listPreferenceTitle,
summary = it.summary,
visible = it.visible,
enabled = it.enabled,
currentValue = it.listPreferenceCurrentValue,
default = it.listPreferenceDefault,
entries = it.entries,
entryValues = it.entryValues
)
}
else -> null
}
}
}
}
override fun setSourceSetting(
sourceId: Long,
sourcePreference: SourcePreference,
): Flow<Unit> {
return apolloClient.mutation(
SetSourceSettingMutation(
sourceId,
SourcePreferenceChangeInput(
position = sourcePreference.position,
checkBoxState = (sourcePreference as? CheckBoxSourcePreference)?.currentValue.toOptional(),
switchState = (sourcePreference as? SwitchSourcePreference)?.currentValue.toOptional(),
editTextState = (sourcePreference as? EditTextSourcePreference)?.currentValue.toOptional(),
multiSelectState = (sourcePreference as? MultiSelectListSourcePreference)?.currentValue.toOptional(),
listState = (sourcePreference as? ListSourcePreference)?.currentValue.toOptional(),
)
)
)
.toFlow()
.map {
it.dataAssertNoErrors.updateSourcePreference!!.clientMutationId
}
}
companion object {
internal fun SourceFragment.toSource(): Source {
return Source(
id,
name,
lang,
iconUrl,
supportsLatest,
isConfigurable,
isNsfw,
displayName
)
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.data.updates
import ca.gosyer.jui.data.chapter.ChapterRepositoryImpl.Companion.toMangaAndChapter
import ca.gosyer.jui.data.graphql.GetChapterUpdatesQuery
import ca.gosyer.jui.data.graphql.UpdateCategoryMutation
import ca.gosyer.jui.data.graphql.UpdateLibraryMutation
import ca.gosyer.jui.domain.server.Http
import ca.gosyer.jui.domain.updates.model.Updates
import ca.gosyer.jui.domain.updates.service.UpdatesRepository
import com.apollographql.apollo.ApolloClient
import io.ktor.http.Url
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class UpdatesRepositoryImpl(
private val apolloClient: ApolloClient,
private val http: Http,
private val serverUrl: Url,
): UpdatesRepository {
override fun getRecentUpdates(pageNum: Int): Flow<Updates> {
return apolloClient.query(
GetChapterUpdatesQuery(50, pageNum * 50)
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
Updates(
data.chapters.nodes.map { it.chapterWithMangaFragment.toMangaAndChapter() },
data.chapters.pageInfo.hasNextPage
)
}
}
override fun updateLibrary(): Flow<Unit> {
return apolloClient.mutation(
UpdateLibraryMutation()
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.updateLibraryManga!!.clientMutationId
}
}
override fun updateCategory(categoryId: Long): Flow<Unit> {
return apolloClient.mutation(
UpdateCategoryMutation(listOf(categoryId.toInt()))
)
.toFlow()
.map {
val data = it.dataAssertNoErrors
data.updateCategoryManga!!.clientMutationId
}
}
}

View File

@@ -14,6 +14,8 @@ enum class RestoreState {
FAILURE,
RESTORING_CATEGORIES,
RESTORING_MANGA,
RESTORING_META,
RESTORING_SETTINGS,
UNKNOWN,
}

View File

@@ -8,7 +8,7 @@ package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import ca.gosyer.jui.domain.manga.model.Manga
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
@@ -20,7 +20,7 @@ import org.lighthousegames.logging.logging
class AddMangaToCategory
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
private val serverListeners: ServerListeners,
) {
suspend fun await(
@@ -49,7 +49,7 @@ class AddMangaToCategory
mangaId: Long,
categoryId: Long,
) = if (categoryId != 0L) {
categoryRepositoryOld.addMangaToCategory(mangaId, categoryId)
categoryRepository.addMangaToCategory(mangaId, categoryId)
.map { serverListeners.updateCategoryManga(categoryId) }
} else {
flow {
@@ -62,7 +62,7 @@ class AddMangaToCategory
manga: Manga,
category: Category,
) = if (category.id != 0L) {
categoryRepositoryOld.addMangaToCategory(manga.id, category.id)
categoryRepository.addMangaToCategory(manga.id, category.id)
.map { serverListeners.updateCategoryManga(category.id) }
} else {
flow {

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
class CreateCategory
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
) {
suspend fun await(
name: String,
@@ -27,7 +27,7 @@ class CreateCategory
}
.collect()
fun asFlow(name: String) = categoryRepositoryOld.createCategory(name)
fun asFlow(name: String) = categoryRepository.createCategory(name)
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class DeleteCategory
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
) {
suspend fun await(
categoryId: Long,
@@ -38,9 +38,9 @@ class DeleteCategory
}
.collect()
fun asFlow(categoryId: Long) = categoryRepositoryOld.deleteCategory(categoryId)
fun asFlow(categoryId: Long) = categoryRepository.deleteCategory(categoryId)
fun asFlow(category: Category) = categoryRepositoryOld.deleteCategory(category.id)
fun asFlow(category: Category) = categoryRepository.deleteCategory(category.id)
companion object {
private val log = logging()

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.singleOrNull
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class GetCategories
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
) {
suspend fun await(
dropDefault: Boolean = false,
@@ -29,7 +29,7 @@ class GetCategories
.singleOrNull()
fun asFlow(dropDefault: Boolean = false) =
categoryRepositoryOld.getCategories()
categoryRepository.getCategories()
.map { categories ->
if (dropDefault) {
categories.filterNot { it.name.equals("default", true) }

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import ca.gosyer.jui.domain.manga.model.Manga
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class GetMangaCategories
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
) {
suspend fun await(
mangaId: Long,
@@ -38,9 +38,9 @@ class GetMangaCategories
}
.singleOrNull()
fun asFlow(mangaId: Long) = categoryRepositoryOld.getMangaCategories(mangaId)
fun asFlow(mangaId: Long) = categoryRepository.getMangaCategories(mangaId)
fun asFlow(manga: Manga) = categoryRepositoryOld.getMangaCategories(manga.id)
fun asFlow(manga: Manga) = categoryRepository.getMangaCategories(manga.id)
companion object {
private val log = logging()

View File

@@ -8,7 +8,7 @@ package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.flow.take
@@ -18,7 +18,7 @@ import org.lighthousegames.logging.logging
class GetMangaListFromCategory
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
private val serverListeners: ServerListeners,
) {
suspend fun await(
@@ -45,12 +45,12 @@ class GetMangaListFromCategory
fun asFlow(categoryId: Long) =
serverListeners.combineCategoryManga(
categoryRepositoryOld.getMangaFromCategory(categoryId),
categoryRepository.getMangaFromCategory(categoryId),
) { categoryId == it }
fun asFlow(category: Category) =
serverListeners.combineCategoryManga(
categoryRepositoryOld.getMangaFromCategory(category.id),
categoryRepository.getMangaFromCategory(category.id),
) { category.id == it }
companion object {

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class ModifyCategory
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
) {
suspend fun await(
categoryId: Long,
@@ -45,7 +45,7 @@ class ModifyCategory
fun asFlow(
categoryId: Long,
name: String,
) = categoryRepositoryOld.modifyCategory(
) = categoryRepository.modifyCategory(
categoryId = categoryId,
name = name,
)
@@ -53,7 +53,7 @@ class ModifyCategory
fun asFlow(
category: Category,
name: String? = null,
) = categoryRepositoryOld.modifyCategory(
) = categoryRepository.modifyCategory(
categoryId = category.id,
name = name ?: category.name,
)

View File

@@ -8,7 +8,7 @@ package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import ca.gosyer.jui.domain.manga.model.Manga
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
@@ -20,7 +20,7 @@ import org.lighthousegames.logging.logging
class RemoveMangaFromCategory
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
private val serverListeners: ServerListeners,
) {
suspend fun await(
@@ -49,7 +49,7 @@ class RemoveMangaFromCategory
mangaId: Long,
categoryId: Long,
) = if (categoryId != 0L) {
categoryRepositoryOld.removeMangaFromCategory(mangaId, categoryId)
categoryRepository.removeMangaFromCategory(mangaId, categoryId)
.map { serverListeners.updateCategoryManga(categoryId) }
} else {
flow {
@@ -62,7 +62,7 @@ class RemoveMangaFromCategory
manga: Manga,
category: Category,
) = if (category.id != 0L) {
categoryRepositoryOld.removeMangaFromCategory(manga.id, category.id)
categoryRepository.removeMangaFromCategory(manga.id, category.id)
.map { serverListeners.updateCategoryManga(category.id) }
} else {
flow {

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -15,23 +15,23 @@ import org.lighthousegames.logging.logging
class ReorderCategory
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
) {
suspend fun await(
to: Int,
from: Int,
categoryId: Long,
position: Int,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(to, from)
) = asFlow(categoryId, position)
.catch {
onError(it)
log.warn(it) { "Failed to move category from $from to $to" }
log.warn(it) { "Failed to move category $categoryId to $position" }
}
.collect()
fun asFlow(
to: Int,
from: Int,
) = categoryRepositoryOld.reorderCategory(to, from)
categoryId: Long,
position: Int,
) = categoryRepository.reorderCategory(categoryId, position)
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.category.interactor
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.category.service.CategoryRepositoryOld
import ca.gosyer.jui.domain.category.service.CategoryRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
class UpdateCategoryMeta
@Inject
constructor(
private val categoryRepositoryOld: CategoryRepositoryOld,
private val categoryRepository: CategoryRepository,
) {
suspend fun await(
category: Category,
@@ -35,7 +35,7 @@ class UpdateCategoryMeta
example: Int = category.meta.example,
) = flow {
if (example != category.meta.example) {
categoryRepositoryOld.updateCategoryMeta(
categoryRepository.updateCategoryMeta(
category.id,
"example",
example.toString(),

View File

@@ -0,0 +1,58 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.category.service
import ca.gosyer.jui.domain.category.model.Category
import ca.gosyer.jui.domain.manga.model.Manga
import kotlinx.coroutines.flow.Flow
interface CategoryRepository {
fun getMangaCategories(
mangaId: Long,
): Flow<List<Category>>
fun addMangaToCategory(
mangaId: Long,
categoryId: Long,
): Flow<Unit>
fun removeMangaFromCategory(
mangaId: Long,
categoryId: Long,
): Flow<Unit>
fun getCategories(): Flow<List<Category>>
fun createCategory(
name: String,
): Flow<Unit>
fun modifyCategory(
categoryId: Long,
name: String,
): Flow<Unit>
fun reorderCategory(
categoryId: Long,
position: Int,
): Flow<Unit>
fun deleteCategory(
categoryId: Long,
): Flow<Unit>
fun getMangaFromCategory(
categoryId: Long,
): Flow<List<Manga>>
fun updateCategoryMeta(
categoryId: Long,
key: String,
value: String,
): Flow<Unit>
}

View File

@@ -6,8 +6,7 @@
package ca.gosyer.jui.domain.download.interactor
import ca.gosyer.jui.domain.download.model.DownloadEnqueue
import ca.gosyer.jui.domain.download.service.DownloadRepositoryOld
import ca.gosyer.jui.domain.download.service.DownloadRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -16,7 +15,7 @@ import org.lighthousegames.logging.logging
class BatchChapterDownload
@Inject
constructor(
private val downloadRepositoryOld: DownloadRepositoryOld,
private val downloadRepository: DownloadRepository,
) {
suspend fun await(
chapterIds: List<Long>,
@@ -38,9 +37,9 @@ class BatchChapterDownload
}
.collect()
fun asFlow(chapterIds: List<Long>) = downloadRepositoryOld.batchDownload(DownloadEnqueue(chapterIds))
fun asFlow(chapterIds: List<Long>) = downloadRepository.batchDownload(chapterIds)
fun asFlow(vararg chapterIds: Long) = downloadRepositoryOld.batchDownload(DownloadEnqueue(chapterIds.asList()))
fun asFlow(vararg chapterIds: Long) = downloadRepository.batchDownload(chapterIds.asList())
companion object {
private val log = logging()

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.download.interactor
import ca.gosyer.jui.domain.download.service.DownloadRepositoryOld
import ca.gosyer.jui.domain.download.service.DownloadRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
class ClearDownloadQueue
@Inject
constructor(
private val downloadRepositoryOld: DownloadRepositoryOld,
private val downloadRepository: DownloadRepository,
) {
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
asFlow()
@@ -25,7 +25,7 @@ class ClearDownloadQueue
}
.collect()
fun asFlow() = downloadRepositoryOld.clearDownloadQueue()
fun asFlow() = downloadRepository.clearDownloadQueue()
companion object {
private val log = logging()

View File

@@ -6,9 +6,7 @@
package ca.gosyer.jui.domain.download.interactor
import ca.gosyer.jui.domain.chapter.model.Chapter
import ca.gosyer.jui.domain.download.service.DownloadRepositoryOld
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.download.service.DownloadRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -17,51 +15,21 @@ import org.lighthousegames.logging.logging
class QueueChapterDownload
@Inject
constructor(
private val downloadRepositoryOld: DownloadRepositoryOld,
private val downloadRepository: DownloadRepository,
) {
suspend fun await(
mangaId: Long,
index: Int,
chapterId: Long,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(mangaId, index)
) = asFlow(chapterId)
.catch {
onError(it)
log.warn(it) { "Failed to queue chapter $index of $mangaId for a download" }
}
.collect()
suspend fun await(
manga: Manga,
index: Int,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(manga, index)
.catch {
onError(it)
log.warn(it) { "Failed to queue chapter $index of ${manga.title}(${manga.id}) for a download" }
}
.collect()
suspend fun await(
chapter: Chapter,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(chapter)
.catch {
onError(it)
log.warn(it) { "Failed to queue chapter ${chapter.index} of ${chapter.mangaId} for a download" }
log.warn(it) { "Failed to queue chapter ${chapterId} for a download" }
}
.collect()
fun asFlow(
mangaId: Long,
index: Int,
) = downloadRepositoryOld.queueChapterDownload(mangaId, index)
fun asFlow(
manga: Manga,
index: Int,
) = downloadRepositoryOld.queueChapterDownload(manga.id, index)
fun asFlow(chapter: Chapter) = downloadRepositoryOld.queueChapterDownload(chapter.mangaId, chapter.index)
chapterId: Long,
) = downloadRepository.queueChapterDownload(chapterId)
companion object {
private val log = logging()

View File

@@ -6,9 +6,7 @@
package ca.gosyer.jui.domain.download.interactor
import ca.gosyer.jui.domain.chapter.model.Chapter
import ca.gosyer.jui.domain.download.service.DownloadRepositoryOld
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.download.service.DownloadRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -17,59 +15,23 @@ import org.lighthousegames.logging.logging
class ReorderChapterDownload
@Inject
constructor(
private val downloadRepositoryOld: DownloadRepositoryOld,
private val downloadRepository: DownloadRepository,
) {
suspend fun await(
mangaId: Long,
index: Int,
chapterId: Long,
to: Int,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(mangaId, index, to)
) = asFlow(chapterId, to)
.catch {
onError(it)
log.warn(it) { "Failed to reorder chapter download for $index of $mangaId to $to" }
}
.collect()
suspend fun await(
manga: Manga,
index: Int,
to: Int,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(manga, index, to)
.catch {
onError(it)
log.warn(it) { "Failed to reorder chapter download for $index of ${manga.title}(${manga.id}) to $to" }
}
.collect()
suspend fun await(
chapter: Chapter,
to: Int,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(chapter, to)
.catch {
onError(it)
log.warn(it) { "Failed to reorder chapter download for ${chapter.index} of ${chapter.mangaId} to $to" }
log.warn(it) { "Failed to reorder chapter download for $chapterId to $to" }
}
.collect()
fun asFlow(
mangaId: Long,
index: Int,
chapterId: Long,
to: Int,
) = downloadRepositoryOld.reorderChapterDownload(mangaId, index, to)
fun asFlow(
manga: Manga,
index: Int,
to: Int,
) = downloadRepositoryOld.reorderChapterDownload(manga.id, index, to)
fun asFlow(
chapter: Chapter,
to: Int,
) = downloadRepositoryOld.reorderChapterDownload(chapter.mangaId, chapter.index, to)
) = downloadRepository.reorderChapterDownload(chapterId, to)
companion object {
private val log = logging()

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.download.interactor
import ca.gosyer.jui.domain.download.service.DownloadRepositoryOld
import ca.gosyer.jui.domain.download.service.DownloadRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
class StartDownloading
@Inject
constructor(
private val downloadRepositoryOld: DownloadRepositoryOld,
private val downloadRepository: DownloadRepository,
) {
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
asFlow()
@@ -25,7 +25,7 @@ class StartDownloading
}
.collect()
fun asFlow() = downloadRepositoryOld.startDownloading()
fun asFlow() = downloadRepository.startDownloading()
companion object {
private val log = logging()

View File

@@ -6,9 +6,7 @@
package ca.gosyer.jui.domain.download.interactor
import ca.gosyer.jui.domain.chapter.model.Chapter
import ca.gosyer.jui.domain.download.service.DownloadRepositoryOld
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.download.service.DownloadRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -17,51 +15,19 @@ import org.lighthousegames.logging.logging
class StopChapterDownload
@Inject
constructor(
private val downloadRepositoryOld: DownloadRepositoryOld,
private val downloadRepository: DownloadRepository,
) {
suspend fun await(
mangaId: Long,
index: Int,
chapterId: Long,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(mangaId, index)
) = asFlow(chapterId)
.catch {
onError(it)
log.warn(it) { "Failed to stop chapter download for $index of $mangaId" }
log.warn(it) { "Failed to stop chapter download for $chapterId" }
}
.collect()
suspend fun await(
manga: Manga,
index: Int,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(manga, index)
.catch {
onError(it)
log.warn(it) { "Failed to stop chapter download for $index of ${manga.title}(${manga.id})" }
}
.collect()
suspend fun await(
chapter: Chapter,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(chapter)
.catch {
onError(it)
log.warn(it) { "Failed to stop chapter download for ${chapter.index} of ${chapter.mangaId}" }
}
.collect()
fun asFlow(
mangaId: Long,
index: Int,
) = downloadRepositoryOld.stopChapterDownload(mangaId, index)
fun asFlow(
manga: Manga,
index: Int,
) = downloadRepositoryOld.stopChapterDownload(manga.id, index)
fun asFlow(chapter: Chapter) = downloadRepositoryOld.stopChapterDownload(chapter.mangaId, chapter.index)
fun asFlow(chapterId: Long) = downloadRepository.stopChapterDownload(chapterId)
companion object {
private val log = logging()

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.download.interactor
import ca.gosyer.jui.domain.download.service.DownloadRepositoryOld
import ca.gosyer.jui.domain.download.service.DownloadRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
class StopDownloading
@Inject
constructor(
private val downloadRepositoryOld: DownloadRepositoryOld,
private val downloadRepository: DownloadRepository,
) {
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
asFlow()
@@ -25,7 +25,7 @@ class StopDownloading
}
.collect()
fun asFlow() = downloadRepositoryOld.stopDownloading()
fun asFlow() = downloadRepository.stopDownloading()
companion object {
private val log = logging()

View File

@@ -0,0 +1,35 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.download.service
import kotlinx.coroutines.flow.Flow
interface DownloadRepository {
fun startDownloading(): Flow<Unit>
fun stopDownloading(): Flow<Unit>
fun clearDownloadQueue(): Flow<Unit>
fun queueChapterDownload(
chapterId: Long,
): Flow<Unit>
fun stopChapterDownload(
chapterId: Long,
): Flow<Unit>
fun reorderChapterDownload(
chapterId: Long,
to: Int,
): Flow<Unit>
fun batchDownload(
chapterIds: List<Long>,
): Flow<Unit>
}

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.extension.interactor
import ca.gosyer.jui.domain.extension.service.ExtensionRepositoryOld
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
class GetExtensionList
@Inject
constructor(
private val extensionRepositoryOld: ExtensionRepositoryOld,
private val extensionRepository: ExtensionRepository,
) {
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
asFlow()
@@ -25,7 +25,7 @@ class GetExtensionList
}
.singleOrNull()
fun asFlow() = extensionRepositoryOld.getExtensionList()
fun asFlow() = extensionRepository.getExtensionList()
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.extension.interactor
import ca.gosyer.jui.domain.extension.model.Extension
import ca.gosyer.jui.domain.extension.service.ExtensionRepositoryOld
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class InstallExtension
@Inject
constructor(
private val extensionRepositoryOld: ExtensionRepositoryOld,
private val extensionRepository: ExtensionRepository,
) {
suspend fun await(
extension: Extension,
@@ -28,7 +28,7 @@ class InstallExtension
}
.collect()
fun asFlow(extension: Extension) = extensionRepositoryOld.installExtension(extension.pkgName)
fun asFlow(extension: Extension) = extensionRepository.installExtension(extension.pkgName)
companion object {
private val log = logging()

View File

@@ -6,17 +6,19 @@
package ca.gosyer.jui.domain.extension.interactor
import ca.gosyer.jui.domain.extension.service.ExtensionRepositoryOld
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
import okio.FileSystem
import okio.Path
import okio.SYSTEM
import org.lighthousegames.logging.logging
class InstallExtensionFile
@Inject
constructor(
private val extensionRepositoryOld: ExtensionRepositoryOld,
private val extensionRepository: ExtensionRepository,
) {
suspend fun await(
path: Path,
@@ -28,7 +30,7 @@ class InstallExtensionFile
}
.collect()
fun asFlow(path: Path) = extensionRepositoryOld.installExtension(ExtensionRepositoryOld.buildExtensionFormData(path))
fun asFlow(path: Path) = extensionRepository.installExtension(FileSystem.SYSTEM.source(path))
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.extension.interactor
import ca.gosyer.jui.domain.extension.model.Extension
import ca.gosyer.jui.domain.extension.service.ExtensionRepositoryOld
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class UninstallExtension
@Inject
constructor(
private val extensionRepositoryOld: ExtensionRepositoryOld,
private val extensionRepository: ExtensionRepository,
) {
suspend fun await(
extension: Extension,
@@ -28,7 +28,7 @@ class UninstallExtension
}
.collect()
fun asFlow(extension: Extension) = extensionRepositoryOld.uninstallExtension(extension.pkgName)
fun asFlow(extension: Extension) = extensionRepository.uninstallExtension(extension.pkgName)
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.extension.interactor
import ca.gosyer.jui.domain.extension.model.Extension
import ca.gosyer.jui.domain.extension.service.ExtensionRepositoryOld
import ca.gosyer.jui.domain.extension.service.ExtensionRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class UpdateExtension
@Inject
constructor(
private val extensionRepositoryOld: ExtensionRepositoryOld,
private val extensionRepository: ExtensionRepository,
) {
suspend fun await(
extension: Extension,
@@ -28,7 +28,7 @@ class UpdateExtension
}
.collect()
fun asFlow(extension: Extension) = extensionRepositoryOld.updateExtension(extension.pkgName)
fun asFlow(extension: Extension) = extensionRepository.updateExtension(extension.pkgName)
companion object {
private val log = logging()

View File

@@ -0,0 +1,32 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.extension.service
import ca.gosyer.jui.domain.extension.model.Extension
import kotlinx.coroutines.flow.Flow
import okio.Source
interface ExtensionRepository {
fun getExtensionList(): Flow<List<Extension>>
fun installExtension(
source: Source,
): Flow<Unit>
fun installExtension(
pkgName: String,
): Flow<Unit>
fun updateExtension(
pkgName: String,
): Flow<Unit>
fun uninstallExtension(
pkgName: String,
): Flow<Unit>
}

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.global.interactor
import ca.gosyer.jui.domain.global.service.GlobalRepositoryOld
import ca.gosyer.jui.domain.global.service.GlobalRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
class GetGlobalMeta
@Inject
constructor(
private val globalRepositoryOld: GlobalRepositoryOld,
private val globalRepository: GlobalRepository,
) {
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
asFlow()
@@ -25,7 +25,7 @@ class GetGlobalMeta
}
.singleOrNull()
fun asFlow() = globalRepositoryOld.getGlobalMeta()
fun asFlow() = globalRepository.getGlobalMeta()
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.global.interactor
import ca.gosyer.jui.domain.global.model.GlobalMeta
import ca.gosyer.jui.domain.global.service.GlobalRepositoryOld
import ca.gosyer.jui.domain.global.service.GlobalRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
@@ -17,7 +17,7 @@ import org.lighthousegames.logging.logging
class UpdateGlobalMeta
@Inject
constructor(
private val globalRepositoryOld: GlobalRepositoryOld,
private val globalRepository: GlobalRepository,
) {
suspend fun await(
globalMeta: GlobalMeta,
@@ -35,7 +35,7 @@ class UpdateGlobalMeta
example: Int = globalMeta.example,
) = flow {
if (example != globalMeta.example) {
globalRepositoryOld.updateGlobalMeta(
globalRepository.updateGlobalMeta(
"example",
example.toString(),
).collect()

View File

@@ -0,0 +1,19 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.global.service
import ca.gosyer.jui.domain.global.model.GlobalMeta
import kotlinx.coroutines.flow.Flow
interface GlobalRepository {
fun getGlobalMeta(): Flow<GlobalMeta>
fun updateGlobalMeta(
key: String,
value: String,
): Flow<Unit>
}

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.library.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.library.service.LibraryRepositoryOld
import ca.gosyer.jui.domain.library.service.LibraryRepository
import ca.gosyer.jui.domain.manga.model.Manga
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.onEach
@@ -18,7 +18,7 @@ import org.lighthousegames.logging.logging
class AddMangaToLibrary
@Inject
constructor(
private val libraryRepositoryOld: LibraryRepositoryOld,
private val libraryRepository: LibraryRepository,
private val serverListeners: ServerListeners,
) {
suspend fun await(
@@ -42,11 +42,11 @@ class AddMangaToLibrary
.singleOrNull()
fun asFlow(mangaId: Long) =
libraryRepositoryOld.addMangaToLibrary(mangaId)
libraryRepository.addMangaToLibrary(mangaId)
.onEach { serverListeners.updateManga(mangaId) }
fun asFlow(manga: Manga) =
libraryRepositoryOld.addMangaToLibrary(manga.id)
libraryRepository.addMangaToLibrary(manga.id)
.onEach { serverListeners.updateManga(manga.id) }
companion object {

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.library.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.library.service.LibraryRepositoryOld
import ca.gosyer.jui.domain.library.service.LibraryRepository
import ca.gosyer.jui.domain.manga.model.Manga
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.onEach
@@ -18,7 +18,7 @@ import org.lighthousegames.logging.logging
class RemoveMangaFromLibrary
@Inject
constructor(
private val libraryRepositoryOld: LibraryRepositoryOld,
private val libraryRepository: LibraryRepository,
private val serverListeners: ServerListeners,
) {
suspend fun await(
@@ -42,11 +42,11 @@ class RemoveMangaFromLibrary
.singleOrNull()
fun asFlow(mangaId: Long) =
libraryRepositoryOld.removeMangaFromLibrary(mangaId)
libraryRepository.removeMangaFromLibrary(mangaId)
.onEach { serverListeners.updateManga(mangaId) }
fun asFlow(manga: Manga) =
libraryRepositoryOld.removeMangaFromLibrary(manga.id)
libraryRepository.removeMangaFromLibrary(manga.id)
.onEach { serverListeners.updateManga(manga.id) }
companion object {

View File

@@ -0,0 +1,19 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.library.service
import kotlinx.coroutines.flow.Flow
interface LibraryRepository {
fun addMangaToLibrary(
mangaId: Long,
): Flow<Unit>
fun removeMangaFromLibrary(
mangaId: Long,
): Flow<Unit>
}

View File

@@ -8,7 +8,7 @@ package ca.gosyer.jui.domain.manga.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.manga.service.MangaRepositoryOld
import ca.gosyer.jui.domain.manga.service.MangaRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.flow.take
@@ -18,7 +18,7 @@ import org.lighthousegames.logging.logging
class GetManga
@Inject
constructor(
private val mangaRepositoryOld: MangaRepositoryOld,
private val mangaRepository: MangaRepository,
private val serverListeners: ServerListeners,
) {
suspend fun await(
@@ -45,12 +45,12 @@ class GetManga
fun asFlow(mangaId: Long) =
serverListeners.combineMangaUpdates(
mangaRepositoryOld.getManga(mangaId),
mangaRepository.getManga(mangaId),
) { mangaId in it }
fun asFlow(manga: Manga) =
serverListeners.combineMangaUpdates(
mangaRepositoryOld.getManga(manga.id),
mangaRepository.getManga(manga.id),
) { manga.id in it }
companion object {

View File

@@ -1,59 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.manga.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.manga.service.MangaRepositoryOld
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.flow.take
import me.tatarka.inject.annotations.Inject
import org.lighthousegames.logging.logging
class GetMangaFull
@Inject
constructor(
private val mangaRepositoryOld: MangaRepositoryOld,
private val serverListeners: ServerListeners,
) {
suspend fun await(
mangaId: Long,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(mangaId)
.take(1)
.catch {
onError(it)
log.warn(it) { "Failed to get full manga $mangaId" }
}
.singleOrNull()
suspend fun await(
manga: Manga,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(manga)
.take(1)
.catch {
onError(it)
log.warn(it) { "Failed to get full manga ${manga.title}(${manga.id})" }
}
.singleOrNull()
fun asFlow(mangaId: Long) =
serverListeners.combineMangaUpdates(
mangaRepositoryOld.getMangaFull(mangaId),
) { mangaId in it }
fun asFlow(manga: Manga) =
serverListeners.combineMangaUpdates(
mangaRepositoryOld.getMangaFull(manga.id),
) { manga.id in it }
companion object {
private val log = logging()
}
}

View File

@@ -8,7 +8,7 @@ package ca.gosyer.jui.domain.manga.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.manga.service.MangaRepositoryOld
import ca.gosyer.jui.domain.manga.service.MangaRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.singleOrNull
@@ -19,7 +19,7 @@ import org.lighthousegames.logging.logging
class RefreshManga
@Inject
constructor(
private val mangaRepositoryOld: MangaRepositoryOld,
private val mangaRepository: MangaRepository,
private val serverListeners: ServerListeners,
) {
suspend fun await(
@@ -44,9 +44,9 @@ class RefreshManga
}
.singleOrNull()
fun asFlow(mangaId: Long) = mangaRepositoryOld.getManga(mangaId, true).onEach { serverListeners.updateManga(mangaId) }
fun asFlow(mangaId: Long) = mangaRepository.refreshManga(mangaId).onEach { serverListeners.updateManga(mangaId) }
fun asFlow(manga: Manga) = mangaRepositoryOld.getManga(manga.id, true).onEach { serverListeners.updateManga(manga.id) }
fun asFlow(manga: Manga) = mangaRepository.refreshManga(manga.id).onEach { serverListeners.updateManga(manga.id) }
companion object {
private val log = logging()

View File

@@ -1,54 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.manga.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.manga.service.MangaRepositoryOld
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.flow.take
import me.tatarka.inject.annotations.Inject
import org.lighthousegames.logging.logging
class RefreshMangaFull
@Inject
constructor(
private val mangaRepositoryOld: MangaRepositoryOld,
private val serverListeners: ServerListeners,
) {
suspend fun await(
mangaId: Long,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(mangaId)
.take(1)
.catch {
onError(it)
log.warn(it) { "Failed to refresh full manga $mangaId" }
}
.singleOrNull()
suspend fun await(
manga: Manga,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(manga)
.take(1)
.catch {
onError(it)
log.warn(it) { "Failed to refresh full manga ${manga.title}(${manga.id})" }
}
.singleOrNull()
fun asFlow(mangaId: Long) = mangaRepositoryOld.getMangaFull(mangaId, true).onEach { serverListeners.updateManga(mangaId) }
fun asFlow(manga: Manga) = mangaRepositoryOld.getMangaFull(manga.id, true).onEach { serverListeners.updateManga(manga.id) }
companion object {
private val log = logging()
}
}

View File

@@ -8,7 +8,7 @@ package ca.gosyer.jui.domain.manga.interactor
import ca.gosyer.jui.domain.ServerListeners
import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.manga.service.MangaRepositoryOld
import ca.gosyer.jui.domain.manga.service.MangaRepository
import io.ktor.http.decodeURLQueryComponent
import io.ktor.http.encodeURLQueryComponent
import kotlinx.coroutines.flow.catch
@@ -20,7 +20,7 @@ import org.lighthousegames.logging.logging
class UpdateMangaMeta
@Inject
constructor(
private val mangaRepositoryOld: MangaRepositoryOld,
private val mangaRepository: MangaRepository,
private val serverListeners: ServerListeners,
) {
suspend fun await(
@@ -39,7 +39,7 @@ class UpdateMangaMeta
readerMode: String = manga.meta.juiReaderMode.decodeURLQueryComponent(),
) = flow {
if (readerMode.encodeURLQueryComponent() != manga.meta.juiReaderMode) {
mangaRepositoryOld.updateMangaMeta(
mangaRepository.updateMangaMeta(
manga.id,
"juiReaderMode",
readerMode,

View File

@@ -8,7 +8,6 @@ package ca.gosyer.jui.domain.manga.model
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import ca.gosyer.jui.domain.chapter.model.Chapter
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.i18n.MR
import dev.icerock.moko.resources.StringResource
@@ -42,7 +41,7 @@ data class Manga(
val unreadCount: Int?,
val downloadCount: Int?,
val chapterCount: Int?,
val lastChapterRead: Chapter? = null,
val lastChapterReadTime: Long? = null,
val age: Long?,
val chaptersAge: Long?,
)

View File

@@ -0,0 +1,38 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.manga.service
import ca.gosyer.jui.domain.manga.model.Manga
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.utils.io.ByteReadChannel
import kotlinx.coroutines.flow.Flow
interface MangaRepository {
fun getManga(
mangaId: Long,
): Flow<Manga>
fun refreshManga(
mangaId: Long,
): Flow<Manga>
fun getMangaLibrary(
mangaId: Long,
): Flow<Manga>
fun getMangaThumbnail(
mangaId: Long,
block: HttpRequestBuilder.() -> Unit,
): Flow<ByteReadChannel>
fun updateMangaMeta(
mangaId: Long,
key: String,
value: String,
): Flow<Unit>
}

View File

@@ -0,0 +1,9 @@
package ca.gosyer.jui.domain.settings.model
enum class AuthMode {
NONE,
BASIC_AUTH,
SIMPLE_LOGIN,
UI_LOGIN,
UNKNOWN__,
}

View File

@@ -0,0 +1,8 @@
package ca.gosyer.jui.domain.settings.model
enum class DatabaseType {
H2,
POSTGRESQL,
UNKNOWN__,
;
}

View File

@@ -0,0 +1,7 @@
package ca.gosyer.jui.domain.settings.model
class DownloadConversion(
val compressionLevel: Double?,
val mimeType: String,
val target: String,
)

View File

@@ -0,0 +1,7 @@
package ca.gosyer.jui.domain.settings.model
enum class KoreaderSyncChecksumMethod {
BINARY,
FILENAME,
UNKNOWN__,
}

View File

@@ -0,0 +1,9 @@
package ca.gosyer.jui.domain.settings.model
enum class KoreaderSyncConflictStrategy {
PROMPT,
KEEP_LOCAL,
KEEP_REMOTE,
DISABLED,
UNKNOWN__,
}

View File

@@ -7,17 +7,23 @@
package ca.gosyer.jui.domain.settings.model
class SetSettingsInput(
val authMode: AuthMode? = null,
val authPassword: String? = null,
val authUsername: String? = null,
val autoDownloadIgnoreReUploads: Boolean? = null,
val autoDownloadNewChapters: Boolean? = null,
val autoDownloadNewChaptersLimit: Int? = null,
val backupInterval: Int? = null,
val backupPath: String? = null,
val backupTTL: Int? = null,
val backupTime: String? = null,
val basicAuthEnabled: Boolean? = null,
val basicAuthPassword: String? = null,
val basicAuthUsername: String? = null,
val databasePassword: String? = null,
val databaseType: DatabaseType? = null,
val databaseUrl: String? = null,
val databaseUsername: String? = null,
val debugLogsEnabled: Boolean? = null,
val downloadAsCbz: Boolean? = null,
val downloadConversions: List<DownloadConversion>? = null,
val downloadsPath: String? = null,
val electronPath: String? = null,
val excludeCompleted: Boolean? = null,
@@ -25,17 +31,38 @@ class SetSettingsInput(
val excludeNotStarted: Boolean? = null,
val excludeUnreadChapters: Boolean? = null,
val extensionRepos: List<String>? = null,
val flareSolverrAsResponseFallback: Boolean? = null,
val flareSolverrEnabled: Boolean? = null,
val flareSolverrSessionName: String? = null,
val flareSolverrSessionTtl: Int? = null,
val flareSolverrTimeout: Int? = null,
val flareSolverrUrl: String? = null,
val globalUpdateInterval: Double? = null,
val gqlDebugLogsEnabled: Boolean? = null,
val initialOpenInBrowserEnabled: Boolean? = null,
val ip: String? = null,
val jwtAudience: String? = null,
val jwtRefreshExpiry: Any? = null,
val jwtTokenExpiry: Any? = null,
val koreaderSyncChecksumMethod: KoreaderSyncChecksumMethod? = null,
val koreaderSyncDeviceId: String? = null,
val koreaderSyncPercentageTolerance: Double? = null,
val koreaderSyncServerUrl: String? = null,
val koreaderSyncStrategyBackward: KoreaderSyncConflictStrategy? = null,
val koreaderSyncStrategyForward: KoreaderSyncConflictStrategy? = null,
val koreaderSyncUserkey: String? = null,
val koreaderSyncUsername: String? = null,
val localSourcePath: String? = null,
val maxLogFileSize: String? = null,
val maxLogFiles: Int? = null,
val maxLogFolderSize: String? = null,
val maxSourcesInParallel: Int? = null,
val opdsChapterSortOrder: SortOrder? = null,
val opdsEnablePageReadProgress: Boolean? = null,
val opdsItemsPerPage: Int? = null,
val opdsMarkAsReadOnDownload: Boolean? = null,
val opdsShowOnlyDownloadedChapters: Boolean? = null,
val opdsShowOnlyUnreadChapters: Boolean? = null,
val opdsUseBinaryFileSizes: Boolean? = null,
val port: Int? = null,
val socksProxyEnabled: Boolean? = null,
val socksProxyHost: String? = null,

View File

@@ -10,17 +10,23 @@ import androidx.compose.runtime.Stable
@Stable
class Settings(
val authMode: AuthMode,
val authPassword: String,
val authUsername: String,
val autoDownloadIgnoreReUploads: Boolean,
val autoDownloadNewChapters: Boolean,
val autoDownloadNewChaptersLimit: Int,
val backupInterval: Int,
val backupPath: String,
val backupTTL: Int,
val backupTime: String,
val basicAuthEnabled: Boolean,
val basicAuthPassword: String,
val basicAuthUsername: String,
val databasePassword: String,
val databaseType: DatabaseType,
val databaseUrl: String,
val databaseUsername: String,
val debugLogsEnabled: Boolean,
val downloadAsCbz: Boolean,
val downloadConversions: List<DownloadConversion>,
val downloadsPath: String,
val electronPath: String,
val excludeCompleted: Boolean,
@@ -28,17 +34,38 @@ class Settings(
val excludeNotStarted: Boolean,
val excludeUnreadChapters: Boolean,
val extensionRepos: List<String>,
val flareSolverrAsResponseFallback: Boolean,
val flareSolverrEnabled: Boolean,
val flareSolverrSessionName: String,
val flareSolverrSessionTtl: Int,
val flareSolverrTimeout: Int,
val flareSolverrUrl: String,
val globalUpdateInterval: Double,
val gqlDebugLogsEnabled: Boolean,
val initialOpenInBrowserEnabled: Boolean,
val ip: String,
val jwtAudience: String,
val jwtRefreshExpiry: Any,
val jwtTokenExpiry: Any,
val koreaderSyncChecksumMethod: KoreaderSyncChecksumMethod,
val koreaderSyncDeviceId: String,
val koreaderSyncPercentageTolerance: Double,
val koreaderSyncServerUrl: String,
val koreaderSyncStrategyBackward: KoreaderSyncConflictStrategy,
val koreaderSyncStrategyForward: KoreaderSyncConflictStrategy,
val koreaderSyncUserkey: String,
val koreaderSyncUsername: String,
val localSourcePath: String,
val maxLogFileSize: String,
val maxLogFiles: Int,
val maxLogFolderSize: String,
val maxSourcesInParallel: Int,
val opdsChapterSortOrder: SortOrder,
val opdsEnablePageReadProgress: Boolean,
val opdsItemsPerPage: Int,
val opdsMarkAsReadOnDownload: Boolean,
val opdsShowOnlyDownloadedChapters: Boolean,
val opdsShowOnlyUnreadChapters: Boolean,
val opdsUseBinaryFileSizes: Boolean,
val port: Int,
val socksProxyEnabled: Boolean,
val socksProxyHost: String,

View File

@@ -0,0 +1,11 @@
package ca.gosyer.jui.domain.settings.model
enum class SortOrder {
ASC,
DESC,
ASC_NULLS_FIRST,
DESC_NULLS_FIRST,
ASC_NULLS_LAST,
DESC_NULLS_LAST,
UNKNOWN__,
}

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import ca.gosyer.jui.domain.source.service.SourceRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
@@ -16,39 +16,35 @@ import org.lighthousegames.logging.logging
class GetFilterList
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
private val sourceRepository: SourceRepository,
) {
suspend fun await(
source: Source,
reset: Boolean,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(source.id, reset)
) = asFlow(source.id)
.catch {
onError(it)
log.warn(it) { "Failed to get filter list for ${source.displayName} with reset = $reset" }
log.warn(it) { "Failed to get filter list for ${source.displayName}" }
}
.singleOrNull()
suspend fun await(
sourceId: Long,
reset: Boolean,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(sourceId, reset)
) = asFlow(sourceId)
.catch {
onError(it)
log.warn(it) { "Failed to get filter list for $sourceId with reset = $reset" }
log.warn(it) { "Failed to get filter list for $sourceId" }
}
.singleOrNull()
fun asFlow(
source: Source,
reset: Boolean,
) = sourceRepositoryOld.getFilterList(source.id, reset)
) = sourceRepository.getFilterList(source.id)
fun asFlow(
sourceId: Long,
reset: Boolean,
) = sourceRepositoryOld.getFilterList(sourceId, reset)
) = sourceRepository.getFilterList(sourceId)
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import ca.gosyer.jui.domain.source.service.SourceRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class GetLatestManga
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
private val sourceRepository: SourceRepository,
) {
suspend fun await(
source: Source,
@@ -43,12 +43,12 @@ class GetLatestManga
fun asFlow(
source: Source,
page: Int,
) = sourceRepositoryOld.getLatestManga(source.id, page)
) = sourceRepository.getLatestManga(source.id, page)
fun asFlow(
sourceId: Long,
page: Int,
) = sourceRepositoryOld.getLatestManga(sourceId, page)
) = sourceRepository.getLatestManga(sourceId, page)
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import ca.gosyer.jui.domain.source.service.SourceRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class GetPopularManga
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
private val sourceRepository: SourceRepository,
) {
suspend fun await(
source: Source,
@@ -43,12 +43,12 @@ class GetPopularManga
fun asFlow(
source: Source,
page: Int,
) = sourceRepositoryOld.getPopularManga(source.id, page)
) = sourceRepository.getPopularManga(source.id, page)
fun asFlow(
sourceId: Long,
page: Int,
) = sourceRepositoryOld.getPopularManga(sourceId, page)
) = sourceRepository.getPopularManga(sourceId, page)
companion object {
private val log = logging()

View File

@@ -1,80 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterChange
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterData
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
import org.lighthousegames.logging.logging
class GetQuickSearchManga
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
) {
suspend fun await(
source: Source,
searchTerm: String?,
page: Int,
filters: List<SourceFilterChange>?,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(source.id, searchTerm, page, filters)
.catch {
onError(it)
log.warn(it) { "Failed to get quick search results from ${source.displayName} on page $page with query '$searchTerm'" }
}
.singleOrNull()
suspend fun await(
sourceId: Long,
searchTerm: String?,
page: Int,
filters: List<SourceFilterChange>?,
onError: suspend (Throwable) -> Unit = {},
) = asFlow(sourceId, searchTerm, page, filters)
.catch {
onError(it)
log.warn(it) { "Failed to get quick search results from $sourceId on page $page with query '$searchTerm'" }
}
.singleOrNull()
fun asFlow(
source: Source,
searchTerm: String?,
page: Int,
filters: List<SourceFilterChange>?,
) = sourceRepositoryOld.getQuickSearchResults(
source.id,
page,
SourceFilterData(
searchTerm?.ifBlank { null },
filters?.ifEmpty { null },
),
)
fun asFlow(
sourceId: Long,
searchTerm: String?,
page: Int,
filters: List<SourceFilterChange>?,
) = sourceRepositoryOld.getQuickSearchResults(
sourceId,
page,
SourceFilterData(
searchTerm?.ifBlank { null },
filters?.ifEmpty { null },
),
)
companion object {
private val log = logging()
}
}

View File

@@ -7,7 +7,8 @@
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilter
import ca.gosyer.jui.domain.source.service.SourceRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
@@ -16,15 +17,16 @@ import org.lighthousegames.logging.logging
class GetSearchManga
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
private val sourceRepository: SourceRepository,
) {
suspend fun await(
source: Source,
searchTerm: String?,
page: Int,
searchTerm: String?,
filters: List<SourceFilter>?,
onError: suspend (Throwable) -> Unit = {
},
) = asFlow(source.id, searchTerm, page)
) = asFlow(source.id, page, searchTerm, filters)
.catch {
onError(it)
log.warn(it) { "Failed to get search results from ${source.displayName} on page $page with query '$searchTerm'" }
@@ -35,9 +37,10 @@ class GetSearchManga
sourceId: Long,
searchTerm: String?,
page: Int,
filters: List<SourceFilter>?,
onError: suspend (Throwable) -> Unit = {
},
) = asFlow(sourceId, searchTerm, page)
) = asFlow(sourceId, page, searchTerm, filters)
.catch {
onError(it)
log.warn(it) { "Failed to get search results from $sourceId on page $page with query '$searchTerm'" }
@@ -46,22 +49,26 @@ class GetSearchManga
fun asFlow(
source: Source,
searchTerm: String?,
page: Int,
) = sourceRepositoryOld.getSearchResults(
searchTerm: String?,
filters: List<SourceFilter>?,
) = sourceRepository.getSearchResults(
source.id,
searchTerm?.ifBlank { null },
page,
searchTerm?.ifBlank { null },
filters,
)
fun asFlow(
sourceId: Long,
searchTerm: String?,
page: Int,
) = sourceRepositoryOld.getSearchResults(
searchTerm: String?,
filters: List<SourceFilter>?,
) = sourceRepository.getSearchResults(
sourceId,
searchTerm?.ifBlank { null },
page,
searchTerm?.ifBlank { null },
filters,
)
companion object {

View File

@@ -6,7 +6,7 @@
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import ca.gosyer.jui.domain.source.service.SourceRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
@@ -15,7 +15,7 @@ import org.lighthousegames.logging.logging
class GetSourceList
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
private val sourceRepository: SourceRepository,
) {
suspend fun await(onError: suspend (Throwable) -> Unit = {}) =
asFlow()
@@ -25,7 +25,7 @@ class GetSourceList
}
.singleOrNull()
fun asFlow() = sourceRepositoryOld.getSourceList()
fun asFlow() = sourceRepository.getSourceList()
companion object {
private val log = logging()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import ca.gosyer.jui.domain.source.service.SourceRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.singleOrNull
import me.tatarka.inject.annotations.Inject
@@ -16,7 +16,7 @@ import org.lighthousegames.logging.logging
class GetSourceSettings
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
private val sourceRepository: SourceRepository,
) {
suspend fun await(
source: Source,
@@ -38,9 +38,9 @@ class GetSourceSettings
}
.singleOrNull()
fun asFlow(source: Source) = sourceRepositoryOld.getSourceSettings(source.id)
fun asFlow(source: Source) = sourceRepository.getSourceSettings(source.id)
fun asFlow(sourceId: Long) = sourceRepositoryOld.getSourceSettings(sourceId)
fun asFlow(sourceId: Long) = sourceRepository.getSourceSettings(sourceId)
companion object {
private val log = logging()

View File

@@ -1,125 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.model.sourcefilters.SourceFilterChange
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import me.tatarka.inject.annotations.Inject
import org.lighthousegames.logging.logging
class SetSourceFilter
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
) {
suspend fun await(
source: Source,
filterIndex: Int,
filter: Any,
onError: suspend (Throwable) -> Unit = {
},
) = asFlow(source, filterIndex, filter)
.catch {
onError(it)
log.warn(it) { "Failed to set filter for ${source.displayName} with index = $filterIndex and value = $filter" }
}
.collect()
suspend fun await(
sourceId: Long,
filterIndex: Int,
filter: Any,
onError: suspend (Throwable) -> Unit = {
},
) = asFlow(sourceId, filterIndex, filter)
.catch {
onError(it)
log.warn(it) { "Failed to set filter for $sourceId with index = $filterIndex and value = $filter" }
}
.collect()
suspend fun await(
source: Source,
filterIndex: Int,
childFilterIndex: Int,
filter: Any,
onError: suspend (Throwable) -> Unit = {
},
) = asFlow(source, filterIndex, childFilterIndex, filter)
.catch {
onError(it)
log.warn(it) {
"Failed to set filter for ${source.displayName} with index = $filterIndex " +
"and childIndex = $childFilterIndex and value = $filter"
}
}
.collect()
suspend fun await(
sourceId: Long,
filterIndex: Int,
childFilterIndex: Int,
filter: Any,
onError: suspend (Throwable) -> Unit = {
},
) = asFlow(sourceId, filterIndex, childFilterIndex, filter)
.catch {
onError(it)
log.warn(it) {
"Failed to set filter for $sourceId with index = $filterIndex " +
"and childIndex = $childFilterIndex and value = $filter"
}
}
.collect()
fun asFlow(
source: Source,
filterIndex: Int,
filter: Any,
) = sourceRepositoryOld.setFilter(
source.id,
SourceFilterChange(filterIndex, filter),
)
fun asFlow(
sourceId: Long,
filterIndex: Int,
filter: Any,
) = sourceRepositoryOld.setFilter(
sourceId,
SourceFilterChange(filterIndex, filter),
)
fun asFlow(
source: Source,
filterIndex: Int,
childFilterIndex: Int,
filter: Any,
) = sourceRepositoryOld.setFilter(
source.id,
SourceFilterChange(filterIndex, Json.encodeToString(SourceFilterChange(childFilterIndex, filter))),
)
fun asFlow(
sourceId: Long,
filterIndex: Int,
childFilterIndex: Int,
filter: Any,
) = sourceRepositoryOld.setFilter(
sourceId,
SourceFilterChange(filterIndex, Json.encodeToString(SourceFilterChange(childFilterIndex, filter))),
)
companion object {
private val log = logging()
}
}

View File

@@ -6,9 +6,8 @@
package ca.gosyer.jui.domain.source.interactor
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreferenceChange
import ca.gosyer.jui.domain.source.service.SourceRepositoryOld
import ca.gosyer.jui.domain.source.model.sourcepreference.SourcePreference
import ca.gosyer.jui.domain.source.service.SourceRepository
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import me.tatarka.inject.annotations.Inject
@@ -17,50 +16,26 @@ import org.lighthousegames.logging.logging
class SetSourceSetting
@Inject
constructor(
private val sourceRepositoryOld: SourceRepositoryOld,
private val sourceRepository: SourceRepository,
) {
suspend fun await(
source: Source,
settingIndex: Int,
setting: Any,
onError: suspend (Throwable) -> Unit = {
},
) = asFlow(source, settingIndex, setting)
.catch {
onError(it)
log.warn(it) { "Failed to set setting for ${source.displayName} with index = $settingIndex and value = $setting" }
}
.collect()
suspend fun await(
sourceId: Long,
settingIndex: Int,
setting: Any,
sourcePreference: SourcePreference,
onError: suspend (Throwable) -> Unit = {
},
) = asFlow(sourceId, settingIndex, setting)
) = asFlow(sourceId, sourcePreference)
.catch {
onError(it)
log.warn(it) { "Failed to set setting for $sourceId with index = $settingIndex and value = $setting" }
log.warn(it) { "Failed to set setting for $sourceId with index = ${sourcePreference.position}" }
}
.collect()
fun asFlow(
source: Source,
settingIndex: Int,
setting: Any,
) = sourceRepositoryOld.setSourceSetting(
source.id,
SourcePreferenceChange(settingIndex, setting),
)
fun asFlow(
sourceId: Long,
settingIndex: Int,
setting: Any,
) = sourceRepositoryOld.setSourceSetting(
sourcePreference: SourcePreference,
) = sourceRepository.setSourceSetting(
sourceId,
SourcePreferenceChange(settingIndex, setting),
sourcePreference,
)
companion object {

View File

@@ -11,9 +11,9 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("CheckBox")
data class CheckBoxFilter(
data class CheckBoxFilterOld(
override val filter: CheckBoxProps,
) : SourceFilter() {
) : SourceFilterOld() {
@Serializable
data class CheckBoxProps(
override val name: String,

View File

@@ -11,12 +11,12 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("Group")
data class GroupFilter(
data class GroupFilterOld(
override val filter: GroupProps,
) : SourceFilter() {
) : SourceFilterOld() {
@Serializable
data class GroupProps(
override val name: String,
override val state: List<SourceFilter>,
) : Props<List<SourceFilter>>
override val state: List<SourceFilterOld>,
) : Props<List<SourceFilterOld>>
}

View File

@@ -12,9 +12,9 @@ import kotlinx.serialization.Transient
@Serializable
@SerialName("Header")
data class HeaderFilter(
data class HeaderFilterOld(
override val filter: HeaderProps,
) : SourceFilter() {
) : SourceFilterOld() {
@Serializable
data class HeaderProps(
override val name: String,

View File

@@ -12,9 +12,9 @@ import kotlinx.serialization.json.JsonElement
@Serializable
@SerialName("Select")
data class SelectFilter(
data class SelectFilterOld(
override val filter: SelectProps,
) : SourceFilter() {
) : SourceFilterOld() {
@Serializable
data class SelectProps(
override val name: String,

View File

@@ -12,9 +12,9 @@ import kotlinx.serialization.Transient
@Serializable
@SerialName("Separator")
data class SeparatorFilter(
data class SeparatorFilterOld(
override val filter: SeparatorProps,
) : SourceFilter() {
) : SourceFilterOld() {
@Serializable
data class SeparatorProps(
override val name: String,

View File

@@ -11,9 +11,9 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("Sort")
data class SortFilter(
data class SortFilterOld(
override val filter: SortProps,
) : SourceFilter() {
) : SourceFilterOld() {
@Serializable
data class SortProps(
override val name: String,

View File

@@ -11,16 +11,84 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@Serializable
data class SourceFilterChange(
data class SourceFilterChangeOld(
val position: Int,
val state: String,
) {
constructor(position: Int, state: Any) : this(
position,
if (state is SortFilter.Selection) {
if (state is SortFilterOld.Selection) {
Json.encodeToString(state)
} else {
state.toString()
},
)
}
sealed interface SourceFilter {
val position: Int
data class Checkbox(
override val position: Int,
val name: String,
val default: Boolean,
val value: Boolean = default,
): SourceFilter
data class Header(
override val position: Int,
val name: String,
): SourceFilter
data class Separator(
override val position: Int,
val name: String,
): SourceFilter
data class Group(
override val position: Int,
val name: String,
val value: List<SourceFilter>,
): SourceFilter
data class Select(
override val position: Int,
val name: String,
val values: List<String>,
val default: Int,
val value: Int = default,
): SourceFilter
data class Sort(
override val position: Int,
val name: String,
val values: List<String>,
val default: SelectionChange?,
val value: SelectionChange? = default,
): SourceFilter {
data class SelectionChange(
val ascending: Boolean,
val index: Int
)
}
data class Text(
override val position: Int,
val name: String,
val default: String,
val value: String = default,
): SourceFilter
data class TriState(
override val position: Int,
val name: String,
val default: TriStateValue,
val value: TriStateValue = default,
): SourceFilter {
enum class TriStateValue {
IGNORE,
INCLUDE,
EXCLUDE
}
}
}

View File

@@ -11,5 +11,5 @@ import kotlinx.serialization.Serializable
@Serializable
data class SourceFilterData(
val searchTerm: String?,
val filter: List<SourceFilterChange>?,
val filter: List<SourceFilterChangeOld>?,
)

View File

@@ -9,7 +9,7 @@ package ca.gosyer.jui.domain.source.model.sourcefilters
import kotlinx.serialization.Serializable
@Serializable
sealed class SourceFilter {
sealed class SourceFilterOld {
abstract val filter: Props<*>
}

View File

@@ -11,9 +11,9 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("Text")
data class TextFilter(
data class TextFilterOld(
override val filter: TextProps,
) : SourceFilter() {
) : SourceFilterOld() {
@Serializable
data class TextProps(
override val name: String,

View File

@@ -11,9 +11,9 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("TriState")
data class TriStateFilter(
data class TriStateFilterOld(
override val filter: TriStateProps,
) : SourceFilter() {
) : SourceFilterOld() {
@Serializable
data class TriStateProps(
override val name: String,

View File

@@ -13,6 +13,6 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("CheckBoxPreference")
@Immutable
data class CheckBoxPreference(
data class CheckBoxPreferenceOld(
override val props: TwoStateProps,
) : SourcePreference()
) : SourcePreferenceOld()

View File

@@ -13,9 +13,9 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("EditTextPreference")
@Immutable
data class EditTextPreference(
data class EditTextPreferenceOld(
override val props: EditTextProps,
) : SourcePreference() {
) : SourcePreferenceOld() {
@Serializable
@Immutable
data class EditTextProps(

View File

@@ -13,9 +13,9 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("ListPreference")
@Immutable
data class ListPreference(
data class ListPreferenceOld(
override val props: ListProps,
) : SourcePreference() {
) : SourcePreferenceOld() {
@Serializable
@Immutable
data class ListProps(

View File

@@ -13,9 +13,9 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("MultiSelectListPreference")
@Immutable
data class MultiSelectListPreference(
data class MultiSelectListPreferenceOld(
override val props: MultiSelectListProps,
) : SourcePreference() {
) : SourcePreferenceOld() {
@Serializable
@Immutable
data class MultiSelectListProps(

View File

@@ -11,7 +11,7 @@ import kotlinx.serialization.Serializable
@Serializable
@Immutable
sealed class SourcePreference {
sealed class SourcePreferenceOld {
abstract val props: Props<*>
}
@@ -24,3 +24,71 @@ interface Props<T> {
val defaultValue: T
val defaultValueType: String
}
sealed interface SourcePreference {
val position: Int
}
data class SwitchSourcePreference(
override val position: Int,
val key: String?,
val title: String?,
val summary: String?,
val visible: Boolean,
val enabled: Boolean,
val currentValue: Boolean?,
val default: Boolean,
) : SourcePreference
data class CheckBoxSourcePreference(
override val position: Int,
val key: String?,
val title: String?,
val summary: String?,
val visible: Boolean,
val enabled: Boolean,
val currentValue: Boolean?,
val default: Boolean,
) : SourcePreference
data class EditTextSourcePreference(
override val position: Int,
val key: String?,
val title: String?,
val summary: String?,
val visible: Boolean,
val enabled: Boolean,
val currentValue: String?,
val default: String?,
val dialogTitle: String?,
val dialogMessage: String?,
val text: String?,
) : SourcePreference
data class ListSourcePreference(
override val position: Int,
val key: String?,
val title: String?,
val summary: String?,
val visible: Boolean,
val enabled: Boolean,
val currentValue: String?,
val default: String?,
val entries: List<String>,
val entryValues: List<String>,
) : SourcePreference
data class MultiSelectListSourcePreference(
override val position: Int,
val key: String?,
val title: String?,
val summary: String?,
val visible: Boolean,
val enabled: Boolean,
val currentValue: List<String>?,
val default: List<String>?,
val dialogTitle: String?,
val dialogMessage: String?,
val entries: List<String>,
val entryValues: List<String>,
) : SourcePreference

Some files were not shown because too many files have changed in this diff Show More