From 8edd05aafe925e94e8f54745fe4e21ae98e6be88 Mon Sep 17 00:00:00 2001 From: Syer10 Date: Sat, 29 Jan 2022 15:36:48 -0500 Subject: [PATCH] Massive rewrite - Replace toothpick with kotlin-inject - Create a data module - Fix bugs from last rewrite - Start replacing java.nio.Path with okio.Path --- build.gradle.kts | 58 +++++- buildSrc/src/main/kotlin/Config.kt | 2 +- core/build.gradle.kts | 44 ++-- .../kotlin/ca/gosyer/core/prefs/Preference.kt | 10 + .../kotlin/ca/gosyer/core/io/AppDirs.kt | 24 +++ .../kotlin/ca/gosyer/core/logging}/Logging.kt | 2 +- .../kotlin/ca.gosyer/core/di/AppScope.kt | 25 +-- .../ca.gosyer/core/di/GenericsProvider.kt | 17 -- .../ca.gosyer/core/di/ModuleExtensions.kt | 16 -- data/build.gradle.kts | 90 +++++++++ data/src/androidMain/AndroidManifest.xml | 2 + .../kotlin/ca/gosyer/data/DataComponent.kt | 99 +++++++++ .../ca/gosyer/data/base}/WebsocketService.kt | 8 +- .../gosyer/data/catalog/CatalogPreferences.kt | 0 .../gosyer/data/download/DownloadService.kt | 6 +- .../data/download/model/DownloadChapter.kt | 0 .../data/download/model/DownloadState.kt | 0 .../data/download/model/DownloadStatus.kt | 0 .../data/download/model/DownloaderStatus.kt | 0 .../data/extension/ExtensionPreferences.kt | 0 .../gosyer/data/library/LibraryPreferences.kt | 0 .../data/library/LibraryUpdateService.kt | 6 +- .../gosyer/data/library/model/DisplayMode.kt | 0 .../ca/gosyer/data/library/model/JobStatus.kt | 0 .../gosyer/data/library/model/UpdateStatus.kt | 0 .../data/migration/MigrationPreferences.kt | 0 .../ca/gosyer/data/migration/Migrations.kt | 6 +- .../kotlin/ca/gosyer/data/models/About.kt | 0 .../data/models/BackupValidationResult.kt | 0 .../kotlin/ca/gosyer/data/models/Category.kt | 0 .../kotlin/ca/gosyer/data/models/Chapter.kt | 0 .../kotlin/ca/gosyer/data/models/Extension.kt | 0 .../kotlin/ca/gosyer/data/models/Manga.kt | 0 .../ca/gosyer/data/models/MangaAndChapter.kt | 0 .../kotlin/ca/gosyer/data/models/MangaPage.kt | 0 .../kotlin/ca/gosyer/data/models/Page.kt | 0 .../kotlin/ca/gosyer/data/models/Source.kt | 0 .../kotlin/ca/gosyer/data/models/Updates.kt | 0 .../models/sourcefilters/CheckBoxFilter.kt | 0 .../data/models/sourcefilters/GroupFilter.kt | 0 .../data/models/sourcefilters/HeaderFilter.kt | 0 .../data/models/sourcefilters/SelectFilter.kt | 0 .../models/sourcefilters/SeparatorFilter.kt | 0 .../data/models/sourcefilters/SortFilter.kt | 0 .../data/models/sourcefilters/SourceFilter.kt | 0 .../sourcefilters/SourceFilterChange.kt | 0 .../data/models/sourcefilters/TextFilter.kt | 0 .../models/sourcefilters/TriStateFilter.kt | 0 .../sourcepreference/CheckBoxPreference.kt | 0 .../sourcepreference/EditTextPreference.kt | 0 .../models/sourcepreference/ListPreference.kt | 0 .../MultiSelectListPreference.kt | 0 .../sourcepreference/SourcePreference.kt | 0 .../SourcePreferenceChange.kt | 0 .../sourcepreference/SwitchPreference.kt | 0 .../models/sourcepreference/TwoStateProps.kt | 0 .../data/reader/ReaderModePreferences.kt | 0 .../ca/gosyer/data/reader/ReaderModeWatch.kt | 2 +- .../gosyer/data/reader/ReaderPreferences.kt | 0 .../data/reader/model/DefaultReaderMode.kt | 0 .../ca/gosyer/data/reader/model/Direction.kt | 0 .../ca/gosyer/data/reader/model/ImageScale.kt | 0 .../data/reader/model/NavigationMode.kt | 0 .../data/reader/model/TappingInvertMode.kt | 0 .../ca/gosyer/data/server/HttpClient.kt | 13 +- .../data/server/ServerHostPreferences.kt | 0 .../gosyer/data/server/ServerPreferences.kt | 0 .../ca/gosyer/data/server/ServerService.kt | 51 +++-- .../gosyer/data/server/ServerUrlPreference.kt | 0 .../data/server/host/ServerHostPreference.kt | 0 .../interactions/BackupInteractionHandler.kt | 11 +- .../interactions/BaseInteractionHandler.kt | 0 .../CategoryInteractionHandler.kt | 2 +- .../interactions/ChapterInteractionHandler.kt | 7 +- .../DownloadInteractionHandler.kt | 2 +- .../ExtensionInteractionHandler.kt | 7 +- .../interactions/LibraryInteractionHandler.kt | 2 +- .../interactions/MangaInteractionHandler.kt | 7 +- .../interactions/SourceInteractionHandler.kt | 2 +- .../interactions/UpdatesInteractionHandler.kt | 2 +- .../ca/gosyer/data/server/model/Auth.kt | 0 .../ca/gosyer/data/server/model/Proxy.kt | 0 .../ca/gosyer/data/server/requests/Backup.kt | 0 .../gosyer/data/server/requests/Category.kt | 0 .../gosyer/data/server/requests/Chapters.kt | 0 .../gosyer/data/server/requests/Downloads.kt | 0 .../gosyer/data/server/requests/Extensions.kt | 0 .../ca/gosyer/data/server/requests/Library.kt | 0 .../ca/gosyer/data/server/requests/Manga.kt | 0 .../ca/gosyer/data/server/requests/Meta.kt | 0 .../data/server/requests/RestRequests.kt | 0 .../ca/gosyer/data/server/requests/Sources.kt | 0 .../ca/gosyer/data/server/requests/Updates.kt | 0 .../kotlin/ca/gosyer/data/ui/UiPreferences.kt | 0 .../ca/gosyer/data/ui/model/StartScreen.kt | 0 .../ca/gosyer/data/ui/model/ThemeMode.kt | 0 .../ca/gosyer/data/ui/model/WindowSettings.kt | 19 ++ .../ca/gosyer/data/update/UpdateChecker.kt | 12 +- .../gosyer/data/update/UpdatePreferences.kt | 0 .../gosyer/data/update/model/GithubRelease.kt | 0 desktop/build.gradle.kts | 48 ++--- .../src/main/kotlin/ca/gosyer/AppComponent.kt | 29 +++ .../ca/gosyer/core/logging/LoggingSetup.kt | 9 +- .../main/kotlin/ca/gosyer/data/DataModule.kt | 120 ----------- .../ca/gosyer/data/ui/model/WindowSettings.kt | 58 ------ .../kotlin/ca/gosyer/ui/base/UiComponent.kt | 42 ++++ .../kotlin/ca/gosyer/ui/base/WindowDialog.kt | 13 +- .../base/components/ChapterDownloadButtons.kt | 2 +- .../ui/base/components/LoadingScreen.kt | 2 +- .../ca/gosyer/ui/base/components/Toolbar.kt | 2 +- .../base/image}/KamelConfigProvider.kt | 11 +- .../ca/gosyer/ui/base/theme/AppTheme.kt | 4 +- .../ca/gosyer/ui/base/vm/ComposeViewModel.kt | 23 +-- .../ca/gosyer/ui/base/vm/ViewModelFactory.kt | 96 +++++++++ .../gosyer/ui/categories/CategoriesDialogs.kt | 2 +- .../ca/gosyer/ui/categories/CategoriesMenu.kt | 4 +- .../ui/categories/CategoriesMenuViewModel.kt | 4 +- .../ca/gosyer/ui/downloads/DownloadsMenu.kt | 8 +- .../ui/downloads/DownloadsMenuViewModel.kt | 2 +- .../ca/gosyer/ui/extensions/ExtensionsMenu.kt | 6 +- .../ui/extensions/ExtensionsMenuViewModel.kt | 4 +- .../ca/gosyer/ui/library/LibraryScreen.kt | 10 +- .../ui/library/LibraryScreenViewModel.kt | 6 +- .../kotlin/ca/gosyer/ui/main/MainViewModel.kt | 2 +- .../main/components/DebugOverlayViewModel.kt | 2 +- .../ui/main/components/DownloadsExtraInfo.kt | 2 +- .../ca/gosyer/ui/main/components/SideMenu.kt | 2 +- .../gosyer/ui/main/components/SideMenuItem.kt | 3 +- .../ca/gosyer/ui/main/components/Tray.kt | 2 +- .../ui/main/components/TrayViewModel.kt | 2 +- .../src/main/kotlin/ca/gosyer/ui/main/main.kt | 188 ++++++++---------- .../kotlin/ca/gosyer/ui/manga/ChapterItem.kt | 2 +- .../kotlin/ca/gosyer/ui/manga/MangaMenu.kt | 12 +- .../ca/gosyer/ui/manga/MangaMenuViewModel.kt | 4 +- .../ca/gosyer/ui/reader/ChapterLoader.kt | 2 +- .../kotlin/ca/gosyer/ui/reader/ReaderMenu.kt | 20 +- .../gosyer/ui/reader/ReaderMenuViewModel.kt | 10 +- .../ca/gosyer/ui/reader/ReaderSideMenu.kt | 6 +- .../ui/reader/loader/TachideskPageLoader.kt | 5 +- .../gosyer/ui/reader/model/ReaderChapter.kt | 2 +- .../ui/settings/SettingsAdvancedScreen.kt | 6 +- .../ui/settings/SettingsAppearanceScreen.kt | 6 +- .../ui/settings/SettingsBackupScreen.kt | 36 ++-- .../ui/settings/SettingsDownloadsScreen.kt | 2 +- .../ui/settings/SettingsGeneralScreen.kt | 2 +- .../ui/settings/SettingsLibraryScreen.kt | 6 +- .../SettingsParentalControlsScreen.kt | 2 +- .../ui/settings/SettingsReaderScreen.kt | 2 +- .../ca/gosyer/ui/settings/SettingsScreen.kt | 4 +- .../ui/settings/SettingsSecurityScreen.kt | 2 +- .../ui/settings/SettingsServerScreen.kt | 4 +- .../ui/settings/SettingsTrackingScreen.kt | 2 +- .../ca/gosyer/ui/sources/SourcesMenu.kt | 10 +- .../gosyer/ui/sources/SourcesMenuViewModel.kt | 4 +- .../ui/sources/components/SourceHomeScreen.kt | 8 +- .../components/SourceHomeScreenViewModel.kt | 8 +- .../ui/sources/components/SourceScreen.kt | 4 +- .../components/SourceScreenViewModel.kt | 6 +- .../components/filter/SourceFiltersMenu.kt | 8 +- .../filter/SourceFiltersViewModel.kt | 6 +- .../ui/sources/settings/SourceSettingsMenu.kt | 10 +- .../settings/SourceSettingsViewModel.kt | 6 +- .../ca/gosyer/ui/updates/UpdatesMenu.kt | 4 +- .../gosyer/ui/updates/UpdatesMenuViewModel.kt | 2 +- .../kotlin/ca/gosyer/util/compose/Image.kt | 6 +- .../ca/gosyer/util/compose/WindowGet.kt | 52 +++++ .../main/kotlin/ca/gosyer/util/system/File.kt | 21 -- .../ca/gosyer/util/system/Preference.kt | 20 -- .../data/translation/XmlResourceBundleTest.kt | 49 ----- gradle/libs.versions.toml | 8 +- i18n/build.gradle.kts | 8 +- settings.gradle.kts | 1 + 172 files changed, 902 insertions(+), 738 deletions(-) create mode 100644 core/src/desktopMain/kotlin/ca/gosyer/core/io/AppDirs.kt rename {desktop/src/main/kotlin/ca/gosyer/util/system => core/src/desktopMain/kotlin/ca/gosyer/core/logging}/Logging.kt (93%) delete mode 100644 core/src/jvmMain/kotlin/ca.gosyer/core/di/GenericsProvider.kt delete mode 100644 core/src/jvmMain/kotlin/ca.gosyer/core/di/ModuleExtensions.kt create mode 100644 data/build.gradle.kts create mode 100644 data/src/androidMain/AndroidManifest.xml create mode 100644 data/src/desktopMain/kotlin/ca/gosyer/data/DataComponent.kt rename {desktop/src/main/kotlin/ca/gosyer/core/service => data/src/desktopMain/kotlin/ca/gosyer/data/base}/WebsocketService.kt (95%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/catalog/CatalogPreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/download/DownloadService.kt (94%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/download/model/DownloadChapter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/download/model/DownloadState.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/download/model/DownloadStatus.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/download/model/DownloaderStatus.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/extension/ExtensionPreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/library/LibraryPreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/library/LibraryUpdateService.kt (89%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/library/model/DisplayMode.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/library/model/JobStatus.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/library/model/UpdateStatus.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/migration/MigrationPreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/migration/Migrations.kt (83%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/About.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/BackupValidationResult.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/Category.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/Chapter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/Extension.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/Manga.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/MangaAndChapter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/MangaPage.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/Page.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/Source.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/Updates.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/CheckBoxFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/GroupFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/HeaderFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/SelectFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/SeparatorFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/SortFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilterChange.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/TextFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcefilters/TriStateFilter.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcepreference/CheckBoxPreference.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcepreference/EditTextPreference.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcepreference/ListPreference.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcepreference/MultiSelectListPreference.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreference.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreferenceChange.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcepreference/SwitchPreference.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/models/sourcepreference/TwoStateProps.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/reader/ReaderModePreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/reader/ReaderModeWatch.kt (98%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/reader/ReaderPreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/reader/model/DefaultReaderMode.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/reader/model/Direction.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/reader/model/ImageScale.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/reader/model/NavigationMode.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/reader/model/TappingInvertMode.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/HttpClient.kt (91%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/ServerHostPreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/ServerPreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/ServerService.kt (83%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/ServerUrlPreference.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/host/ServerHostPreference.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/BackupInteractionHandler.kt (89%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/BaseInteractionHandler.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/CategoryInteractionHandler.kt (99%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/ChapterInteractionHandler.kt (98%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/DownloadInteractionHandler.kt (96%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/ExtensionInteractionHandler.kt (93%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/LibraryInteractionHandler.kt (96%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/MangaInteractionHandler.kt (94%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/SourceInteractionHandler.kt (99%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/interactions/UpdatesInteractionHandler.kt (97%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/model/Auth.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/model/Proxy.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Backup.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Category.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Chapters.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Downloads.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Extensions.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Library.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Manga.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Meta.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/RestRequests.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Sources.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/server/requests/Updates.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/ui/UiPreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/ui/model/StartScreen.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/ui/model/ThemeMode.kt (100%) create mode 100644 data/src/desktopMain/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/update/UpdateChecker.kt (86%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/update/UpdatePreferences.kt (100%) rename {desktop/src/main => data/src/desktopMain}/kotlin/ca/gosyer/data/update/model/GithubRelease.kt (100%) create mode 100644 desktop/src/main/kotlin/ca/gosyer/AppComponent.kt delete mode 100644 desktop/src/main/kotlin/ca/gosyer/data/DataModule.kt delete mode 100644 desktop/src/main/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt create mode 100644 desktop/src/main/kotlin/ca/gosyer/ui/base/UiComponent.kt rename desktop/src/main/kotlin/ca/gosyer/{data/server => ui/base/image}/KamelConfigProvider.kt (93%) create mode 100644 desktop/src/main/kotlin/ca/gosyer/ui/base/vm/ViewModelFactory.kt create mode 100644 desktop/src/main/kotlin/ca/gosyer/util/compose/WindowGet.kt delete mode 100644 desktop/src/main/kotlin/ca/gosyer/util/system/Preference.kt delete mode 100644 desktop/src/test/kotlin/ca/gosyer/data/translation/XmlResourceBundleTest.kt diff --git a/build.gradle.kts b/build.gradle.kts index 940fb6aa..28b0b978 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,17 @@ +import Config.migrationCode +import Config.serverCode +import Config.tachideskVersion +import com.codingfeline.buildkonfig.compiler.FieldSpec.Type + plugins { kotlin("multiplatform") version "1.6.10" apply false - kotlin("kapt") version "1.6.10" apply false kotlin("plugin.serialization") version "1.6.10" apply false id("com.android.library") version "7.0.4" apply false id("com.android.application") version "7.0.4" apply false id("org.jetbrains.compose") version "1.0.1" apply false + id("com.google.devtools.ksp") version "1.6.10-1.0.2" id("com.github.gmazzo.buildconfig") version "3.0.3" apply false + id("com.codingfeline.buildkonfig") version "0.11.0" apply false id("dev.icerock.mobile.multiplatform-resources") version "0.18.0" apply false id("org.jmailen.kotlinter") version "3.8.0" apply false id("com.github.ben-manes.versions") version "0.41.0" @@ -34,6 +40,21 @@ allprojects { } subprojects { + tasks.withType { + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + listOf( + "-Xjvm-default=compatibility", + ) + } + } + tasks.withType { + source(files("src")) + exclude("ca/gosyer/*/build") + } + tasks.withType { + source(files("src")) + exclude("ca/gosyer/*/build") + } plugins.withType { configure { compileSdkVersion(31) @@ -47,7 +68,7 @@ subprojects { }*/ } compileOptions { - //isCoreLibraryDesugaringEnabled = true + isCoreLibraryDesugaringEnabled = true sourceCompatibility(JavaVersion.VERSION_11) targetCompatibility(JavaVersion.VERSION_11) } @@ -60,7 +81,38 @@ subprojects { } } dependencies { - //add("coreLibraryDesugaring", Deps.desugarJdkLibs) + add("coreLibraryDesugaring", libs.desugarJdkLibs) + } + } + } + plugins.withType { + configure { + defaultConfigs { + buildConfigField(Type.STRING, "NAME", rootProject.name) + buildConfigField(Type.STRING, "VERSION", project.version.toString()) + buildConfigField(Type.INT, "MIGRATION_CODE", migrationCode.toString()) + buildConfigField(Type.BOOLEAN, "DEBUG", project.hasProperty("debugApp").toString()) + buildConfigField(Type.BOOLEAN, "IS_PREVIEW", project.hasProperty("preview").toString()) + buildConfigField(Type.INT, "PREVIEW_BUILD", project.properties["preview"]?.toString()?.trim('"') ?: 0.toString()) + + // Tachidesk + buildConfigField(Type.STRING, "TACHIDESK_SP_VERSION", tachideskVersion) + buildConfigField(Type.INT, "SERVER_CODE", serverCode.toString()) + } + } + } + plugins.withType { + configure { + experimentalRules = true + disabledRules = arrayOf("experimental:argument-list-wrapping", "experimental:trailing-comma") + } + } + + plugins.withType { + configure { + arg("me.tatarka.inject.generateCompanionExtensions", "true") + if (project.hasProperty("debugApp")) { + arg("me.tatarka.inject.dumpGraph", "true") } } } diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index 17f787f8..7ba461e6 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -10,5 +10,5 @@ object Config { const val preview = true const val previewCommit = "b714abddae9f13e91bc53c5daac54aeae564cd2a" - val jvmTarget = JavaVersion.VERSION_16 + val desktopJvmTarget = JavaVersion.VERSION_16 } \ No newline at end of file diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 244b89ee..5728aa58 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,9 +1,9 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile as KotlinJvmCompile - plugins { kotlin("multiplatform") - kotlin("kapt") id("com.android.library") + id("com.google.devtools.ksp") + id("com.codingfeline.buildkonfig") + id("org.jmailen.kotlinter") } group = "ca.gosyer" @@ -15,7 +15,13 @@ repositories { kotlin { android() - jvm("desktop") + jvm("desktop") { + compilations { + all { + kotlinOptions.jvmTarget = Config.desktopJvmTarget.toString() + } + } + } sourceSets { all { @@ -27,20 +33,23 @@ kotlin { } } val commonMain by getting { + kotlin.srcDir("build/generated/ksp/commonMain/kotlin") dependencies { api(kotlin("stdlib-common")) api(libs.coroutinesCore) api(libs.json) - api(libs.toothpickKsp) + api(libs.kotlinInjectRuntime) api(libs.ktorCore) api(libs.ktorSerialization) api(libs.okio) + api(libs.ktlogging) api(libs.multiplatformSettingsCore) api(libs.multiplatformSettingsCoroutines) api(libs.multiplatformSettingsSerialization) } } val commonTest by getting { + kotlin.srcDir("build/generated/ksp/commonTest/kotlin") dependencies { implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) @@ -49,43 +58,36 @@ kotlin { val desktopMain by getting { kotlin.srcDir("src/jvmMain/kotlin") + kotlin.srcDir("build/generated/ksp/desktopMain/kotlin") dependencies { api(kotlin("stdlib-jdk8")) + api(libs.appDirs) } } val desktopTest by getting { kotlin.srcDir("src/jvmTest/kotlin") + kotlin.srcDir("build/generated/ksp/desktopTest/kotlin") } val androidMain by getting { kotlin.srcDir("src/jvmMain/kotlin") + kotlin.srcDir("build/generated/ksp/androidMain/kotlin") dependencies { api(kotlin("stdlib-jdk8")) } } val androidTest by getting { kotlin.srcDir("src/jvmTest/kotlin") + kotlin.srcDir("build/generated/ksp/androidTest/kotlin") } } } dependencies { - add("kapt", libs.toothpickCompiler) + add("kspDesktop", libs.kotlinInjectCompiler) + add("kspAndroid", libs.kotlinInjectCompiler) } -tasks { - withType { - kotlinOptions { - freeCompilerArgs = listOf("-Xjvm-default=compatibility") - } - } +buildkonfig { + packageName = "ca.gosyer.core.build" } - -android { - compileSdk = 31 - sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") - defaultConfig { - minSdk = 21 - targetSdk = 31 - } -} \ No newline at end of file diff --git a/core/src/commonMain/kotlin/ca/gosyer/core/prefs/Preference.kt b/core/src/commonMain/kotlin/ca/gosyer/core/prefs/Preference.kt index 7085b006..dda504af 100644 --- a/core/src/commonMain/kotlin/ca/gosyer/core/prefs/Preference.kt +++ b/core/src/commonMain/kotlin/ca/gosyer/core/prefs/Preference.kt @@ -9,6 +9,9 @@ package ca.gosyer.core.prefs import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.merge +import kotlinx.coroutines.flow.onEach /** * A wrapper around application preferences without knowing implementation details. Instances of @@ -57,3 +60,10 @@ interface Preference { */ fun stateIn(scope: CoroutineScope): StateFlow } + +fun Preference.getAsFlow(action: (suspend (T) -> Unit)? = null): Flow { + val flow = merge(flowOf(get()), changes()) + return if (action != null) { + flow.onEach(action = action) + } else flow +} diff --git a/core/src/desktopMain/kotlin/ca/gosyer/core/io/AppDirs.kt b/core/src/desktopMain/kotlin/ca/gosyer/core/io/AppDirs.kt new file mode 100644 index 00000000..65e65cee --- /dev/null +++ b/core/src/desktopMain/kotlin/ca/gosyer/core/io/AppDirs.kt @@ -0,0 +1,24 @@ +/* + * 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.core.io + +import ca.gosyer.core.build.BuildKonfig +import mu.KotlinLogging +import net.harawata.appdirs.AppDirsFactory +import okio.FileSystem +import okio.Path +import okio.Path.Companion.toPath + +private val logger = KotlinLogging.logger {} + +val userDataDir: Path by lazy { + AppDirsFactory.getInstance().getUserDataDir(BuildKonfig.NAME, null, null).toPath().also { + if (!FileSystem.SYSTEM.exists(it)) { + logger.info("Attempted to create app data dir, result: {}", FileSystem.SYSTEM.createDirectories(it)) + } + } +} diff --git a/desktop/src/main/kotlin/ca/gosyer/util/system/Logging.kt b/core/src/desktopMain/kotlin/ca/gosyer/core/logging/Logging.kt similarity index 93% rename from desktop/src/main/kotlin/ca/gosyer/util/system/Logging.kt rename to core/src/desktopMain/kotlin/ca/gosyer/core/logging/Logging.kt index ce040519..63377d42 100644 --- a/desktop/src/main/kotlin/ca/gosyer/util/system/Logging.kt +++ b/core/src/desktopMain/kotlin/ca/gosyer/core/logging/Logging.kt @@ -4,7 +4,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package ca.gosyer.util.system +package ca.gosyer.core.logging import mu.KLogger import mu.KotlinLogging diff --git a/core/src/jvmMain/kotlin/ca.gosyer/core/di/AppScope.kt b/core/src/jvmMain/kotlin/ca.gosyer/core/di/AppScope.kt index f324e175..58f5fa37 100644 --- a/core/src/jvmMain/kotlin/ca.gosyer/core/di/AppScope.kt +++ b/core/src/jvmMain/kotlin/ca.gosyer/core/di/AppScope.kt @@ -6,25 +6,8 @@ package ca.gosyer.core.di -import toothpick.Scope -import toothpick.ktp.KTP +import me.tatarka.inject.annotations.Scope -/** - * The global scope for dependency injection that will provide all the application level components. - */ -object AppScope : Scope by KTP.openRootScope() { - - /** - * Returns a new subscope inheriting the root scope. - */ - fun subscope(any: Any): Scope { - return openSubScope(any) - } - - /** - * Returns an instance of [T] from the root scope. - */ - inline fun getInstance(): T { - return getInstance(T::class.java) - } -} +@Scope +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER) +annotation class AppScope diff --git a/core/src/jvmMain/kotlin/ca.gosyer/core/di/GenericsProvider.kt b/core/src/jvmMain/kotlin/ca.gosyer/core/di/GenericsProvider.kt deleted file mode 100644 index acd0c999..00000000 --- a/core/src/jvmMain/kotlin/ca.gosyer/core/di/GenericsProvider.kt +++ /dev/null @@ -1,17 +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.core.di - -import toothpick.Scope -import javax.inject.Provider - -class GenericsProvider(private val cls: Class, val scope: Scope = AppScope) : Provider { - - override fun get(): T { - return scope.getInstance(cls) - } -} diff --git a/core/src/jvmMain/kotlin/ca.gosyer/core/di/ModuleExtensions.kt b/core/src/jvmMain/kotlin/ca.gosyer/core/di/ModuleExtensions.kt deleted file mode 100644 index ee1123c3..00000000 --- a/core/src/jvmMain/kotlin/ca.gosyer/core/di/ModuleExtensions.kt +++ /dev/null @@ -1,16 +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.core.di - -import toothpick.config.Module - -/** - * Binds the given [instance] to its class. - */ -inline fun Module.bindInstance(instance: B) { - bind(B::class.java).toInstance(instance) -} diff --git a/data/build.gradle.kts b/data/build.gradle.kts new file mode 100644 index 00000000..ac26187a --- /dev/null +++ b/data/build.gradle.kts @@ -0,0 +1,90 @@ +plugins { + kotlin("multiplatform") + id("com.google.devtools.ksp") + kotlin("plugin.serialization") + id("com.android.library") + id("com.codingfeline.buildkonfig") + id("org.jmailen.kotlinter") +} + +kotlin { + android() + jvm("desktop") { + compilations { + all { + kotlinOptions.jvmTarget = Config.desktopJvmTarget.toString() + } + } + } + + sourceSets { + all { + languageSettings { + optIn("kotlin.RequiresOptIn") + optIn("kotlinx.coroutines.ExperimentalCoroutinesApi") + } + } + val commonMain by getting { + kotlin.srcDir("build/generated/ksp/commonMain/kotlin") + dependencies { + api(kotlin("stdlib-common")) + api(libs.coroutinesCore) + api(libs.json) + api(libs.kotlinInjectRuntime) + api(libs.ktorCore) + api(libs.ktorSerialization) + api(libs.ktorAuth) + api(libs.ktorLogging) + api(libs.ktorWebsockets) + api(libs.ktorOkHttp) + api(libs.okio) + api(project(":core")) + api(project(":i18n")) + } + } + val commonTest by getting { + kotlin.srcDir("build/generated/ksp/commonTest/kotlin") + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + + val desktopMain by getting { + kotlin.srcDir("src/jvmMain/kotlin") + kotlin.srcDir("build/generated/ksp/desktopMain/kotlin") + dependencies { + api(kotlin("stdlib-jdk8")) + } + } + val desktopTest by getting { + kotlin.srcDir("src/jvmTest/kotlin") + kotlin.srcDir("build/generated/ksp/desktopTest/kotlin") + } + + val androidMain by getting { + kotlin.srcDir("src/jvmMain/kotlin") + kotlin.srcDir("build/generated/ksp/androidMain/kotlin") + dependencies { + api(kotlin("stdlib-jdk8")) + } + } + val androidTest by getting { + kotlin.srcDir("src/jvmTest/kotlin") + kotlin.srcDir("build/generated/ksp/androidTest/kotlin") + } + } +} + +dependencies { + add("kspDesktop", libs.kotlinInjectCompiler) + add("kspAndroid", libs.kotlinInjectCompiler) +} + +tasks { + +} + +buildkonfig { + packageName = "ca.gosyer.data.build" +} diff --git a/data/src/androidMain/AndroidManifest.xml b/data/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..f0ad8144 --- /dev/null +++ b/data/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/data/src/desktopMain/kotlin/ca/gosyer/data/DataComponent.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/DataComponent.kt new file mode 100644 index 00000000..2e5ca6cb --- /dev/null +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/DataComponent.kt @@ -0,0 +1,99 @@ +/* + * 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.data + +import ca.gosyer.core.di.AppScope +import ca.gosyer.core.prefs.PreferenceStoreFactory +import ca.gosyer.data.catalog.CatalogPreferences +import ca.gosyer.data.download.DownloadService +import ca.gosyer.data.extension.ExtensionPreferences +import ca.gosyer.data.library.LibraryPreferences +import ca.gosyer.data.library.LibraryUpdateService +import ca.gosyer.data.migration.MigrationPreferences +import ca.gosyer.data.migration.Migrations +import ca.gosyer.data.reader.ReaderPreferences +import ca.gosyer.data.server.Http +import ca.gosyer.data.server.HttpProvider +import ca.gosyer.data.server.ServerHostPreferences +import ca.gosyer.data.server.ServerPreferences +import ca.gosyer.data.server.ServerService +import ca.gosyer.data.ui.UiPreferences +import ca.gosyer.data.update.UpdateChecker +import ca.gosyer.data.update.UpdatePreferences +import me.tatarka.inject.annotations.Component +import me.tatarka.inject.annotations.Provides + +@AppScope +@Component +abstract class DataComponent { + private val preferenceFactory = PreferenceStoreFactory() + protected abstract val httpProvider: HttpProvider + + abstract val serverService: ServerService + + abstract val downloadService: DownloadService + + abstract val libraryUpdateService: LibraryUpdateService + + abstract val migrations: Migrations + + abstract val updateChecker: UpdateChecker + + @get:AppScope + @get:Provides + val serverPreferences: ServerPreferences + get() = ServerPreferences(preferenceFactory.create("server")) + + @get:AppScope + @get:Provides + val serverHostPreferences: ServerHostPreferences + get() = ServerHostPreferences(preferenceFactory.create("host")) + + @get:AppScope + @get:Provides + val extensionPreferences: ExtensionPreferences + get() = ExtensionPreferences(preferenceFactory.create("extension")) + + @get:AppScope + @get:Provides + val catalogPreferences: CatalogPreferences + get() = CatalogPreferences(preferenceFactory.create("catalog")) + + @get:AppScope + @get:Provides + val libraryPreferences: LibraryPreferences + get() = LibraryPreferences(preferenceFactory.create("library")) + + @get:AppScope + @get:Provides + val readerPreferences: ReaderPreferences + get() = ReaderPreferences(preferenceFactory.create("reader")) { name -> + preferenceFactory.create("reader", name) + } + + @get:AppScope + @get:Provides + val uiPreferences: UiPreferences + get() = UiPreferences(preferenceFactory.create("ui")) + + @get:AppScope + @get:Provides + val migrationPreferences: MigrationPreferences + get() = MigrationPreferences(preferenceFactory.create("migration")) + + @get:AppScope + @get:Provides + val updatePreferences: UpdatePreferences + get() = UpdatePreferences(preferenceFactory.create("update")) + + @get:AppScope + @get:Provides + val http: Http + get() = httpProvider.get(serverPreferences) + + companion object +} diff --git a/desktop/src/main/kotlin/ca/gosyer/core/service/WebsocketService.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/base/WebsocketService.kt similarity index 95% rename from desktop/src/main/kotlin/ca/gosyer/core/service/WebsocketService.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/base/WebsocketService.kt index 879c492d..d7d0d1e5 100644 --- a/desktop/src/main/kotlin/ca/gosyer/core/service/WebsocketService.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/base/WebsocketService.kt @@ -4,13 +4,13 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package ca.gosyer.core.service +package ca.gosyer.data.base -import ca.gosyer.build.BuildConfig import ca.gosyer.core.lang.throwIfCancellation +import ca.gosyer.core.logging.CKLogger +import ca.gosyer.data.build.BuildKonfig import ca.gosyer.data.server.Http import ca.gosyer.data.server.ServerPreferences -import ca.gosyer.util.system.CKLogger import io.ktor.client.features.websocket.ws import io.ktor.http.cio.websocket.Frame import kotlinx.coroutines.CancellationException @@ -33,7 +33,7 @@ abstract class WebsocketService( protected val client: Http ) { protected val json = Json { - ignoreUnknownKeys = !BuildConfig.DEBUG + ignoreUnknownKeys = !BuildKonfig.DEBUG } private val _status = MutableStateFlow(Status.STARTING) val status = _status.asStateFlow() diff --git a/desktop/src/main/kotlin/ca/gosyer/data/catalog/CatalogPreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/catalog/CatalogPreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/catalog/CatalogPreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/catalog/CatalogPreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/download/DownloadService.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/download/DownloadService.kt similarity index 94% rename from desktop/src/main/kotlin/ca/gosyer/data/download/DownloadService.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/download/DownloadService.kt index 55f1592d..e4af3356 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/download/DownloadService.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/download/DownloadService.kt @@ -6,14 +6,14 @@ package ca.gosyer.data.download -import ca.gosyer.core.service.WebsocketService +import ca.gosyer.core.logging.CKLogger +import ca.gosyer.data.base.WebsocketService import ca.gosyer.data.download.model.DownloadChapter import ca.gosyer.data.download.model.DownloadStatus import ca.gosyer.data.download.model.DownloaderStatus import ca.gosyer.data.server.Http import ca.gosyer.data.server.ServerPreferences import ca.gosyer.data.server.requests.downloadsQuery -import ca.gosyer.util.system.CKLogger import io.ktor.http.cio.websocket.Frame import io.ktor.http.cio.websocket.readText import kotlinx.coroutines.DelicateCoroutinesApi @@ -22,7 +22,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.serialization.decodeFromString -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject @OptIn(DelicateCoroutinesApi::class) class DownloadService @Inject constructor( diff --git a/desktop/src/main/kotlin/ca/gosyer/data/download/model/DownloadChapter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/download/model/DownloadChapter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/download/model/DownloadChapter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/download/model/DownloadChapter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/download/model/DownloadState.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/download/model/DownloadState.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/download/model/DownloadState.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/download/model/DownloadState.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/download/model/DownloadStatus.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/download/model/DownloadStatus.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/download/model/DownloadStatus.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/download/model/DownloadStatus.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/download/model/DownloaderStatus.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/download/model/DownloaderStatus.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/download/model/DownloaderStatus.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/download/model/DownloaderStatus.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/extension/ExtensionPreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/extension/ExtensionPreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/extension/ExtensionPreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/extension/ExtensionPreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/library/LibraryPreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/library/LibraryPreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/library/LibraryPreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/library/LibraryPreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/library/LibraryUpdateService.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/library/LibraryUpdateService.kt similarity index 89% rename from desktop/src/main/kotlin/ca/gosyer/data/library/LibraryUpdateService.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/library/LibraryUpdateService.kt index 322e371c..80d3e4f1 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/library/LibraryUpdateService.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/library/LibraryUpdateService.kt @@ -6,17 +6,17 @@ package ca.gosyer.data.library -import ca.gosyer.core.service.WebsocketService +import ca.gosyer.core.logging.CKLogger +import ca.gosyer.data.base.WebsocketService import ca.gosyer.data.library.model.UpdateStatus import ca.gosyer.data.server.Http import ca.gosyer.data.server.ServerPreferences import ca.gosyer.data.server.requests.updatesQuery -import ca.gosyer.util.system.CKLogger import io.ktor.http.cio.websocket.Frame import io.ktor.http.cio.websocket.readText import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.serialization.decodeFromString -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject @OptIn(DelicateCoroutinesApi::class) class LibraryUpdateService @Inject constructor( diff --git a/desktop/src/main/kotlin/ca/gosyer/data/library/model/DisplayMode.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/library/model/DisplayMode.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/library/model/DisplayMode.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/library/model/DisplayMode.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/library/model/JobStatus.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/library/model/JobStatus.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/library/model/JobStatus.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/library/model/JobStatus.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/library/model/UpdateStatus.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/library/model/UpdateStatus.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/library/model/UpdateStatus.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/library/model/UpdateStatus.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/migration/MigrationPreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/migration/MigrationPreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/migration/MigrationPreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/migration/MigrationPreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/migration/Migrations.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/migration/Migrations.kt similarity index 83% rename from desktop/src/main/kotlin/ca/gosyer/data/migration/Migrations.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/migration/Migrations.kt index 53360d51..8aae3a64 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/migration/Migrations.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/migration/Migrations.kt @@ -6,9 +6,9 @@ package ca.gosyer.data.migration -import ca.gosyer.build.BuildConfig +import ca.gosyer.data.build.BuildKonfig import ca.gosyer.data.reader.ReaderPreferences -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class Migrations @Inject constructor( private val migrationPreferences: MigrationPreferences, @@ -21,7 +21,7 @@ class Migrations @Inject constructor( readerPreferences.modes().get().forEach { readerPreferences.getMode(it).direction().delete() } - migrationPreferences.version().set(BuildConfig.MIGRATION_CODE) + migrationPreferences.version().set(BuildKonfig.MIGRATION_CODE) return } } diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/About.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/About.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/About.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/About.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/BackupValidationResult.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/BackupValidationResult.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/BackupValidationResult.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/BackupValidationResult.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/Category.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/Category.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/Category.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/Category.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/Chapter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/Chapter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/Chapter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/Chapter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/Extension.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/Extension.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/Extension.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/Extension.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/Manga.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/Manga.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/Manga.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/Manga.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/MangaAndChapter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/MangaAndChapter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/MangaAndChapter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/MangaAndChapter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/MangaPage.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/MangaPage.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/MangaPage.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/MangaPage.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/Page.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/Page.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/Page.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/Page.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/Source.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/Source.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/Source.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/Source.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/Updates.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/Updates.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/Updates.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/Updates.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/CheckBoxFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/CheckBoxFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/CheckBoxFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/CheckBoxFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/GroupFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/GroupFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/GroupFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/GroupFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/HeaderFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/HeaderFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/HeaderFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/HeaderFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SelectFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SelectFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SelectFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SelectFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SeparatorFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SeparatorFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SeparatorFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SeparatorFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SortFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SortFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SortFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SortFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilterChange.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilterChange.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilterChange.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/SourceFilterChange.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/TextFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/TextFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/TextFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/TextFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/TriStateFilter.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/TriStateFilter.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcefilters/TriStateFilter.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcefilters/TriStateFilter.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/CheckBoxPreference.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/CheckBoxPreference.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/CheckBoxPreference.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/CheckBoxPreference.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/EditTextPreference.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/EditTextPreference.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/EditTextPreference.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/EditTextPreference.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/ListPreference.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/ListPreference.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/ListPreference.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/ListPreference.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/MultiSelectListPreference.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/MultiSelectListPreference.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/MultiSelectListPreference.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/MultiSelectListPreference.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreference.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreference.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreference.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreference.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreferenceChange.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreferenceChange.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreferenceChange.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/SourcePreferenceChange.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/SwitchPreference.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/SwitchPreference.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/SwitchPreference.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/SwitchPreference.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/TwoStateProps.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/TwoStateProps.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/models/sourcepreference/TwoStateProps.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/models/sourcepreference/TwoStateProps.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/reader/ReaderModePreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/ReaderModePreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/reader/ReaderModePreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/reader/ReaderModePreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/reader/ReaderModeWatch.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/ReaderModeWatch.kt similarity index 98% rename from desktop/src/main/kotlin/ca/gosyer/data/reader/ReaderModeWatch.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/reader/ReaderModeWatch.kt index d513c883..31b8adf0 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/reader/ReaderModeWatch.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/ReaderModeWatch.kt @@ -6,7 +6,7 @@ package ca.gosyer.data.reader -import ca.gosyer.util.system.getAsFlow +import ca.gosyer.core.prefs.getAsFlow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow diff --git a/desktop/src/main/kotlin/ca/gosyer/data/reader/ReaderPreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/ReaderPreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/reader/ReaderPreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/reader/ReaderPreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/reader/model/DefaultReaderMode.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/DefaultReaderMode.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/reader/model/DefaultReaderMode.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/DefaultReaderMode.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/reader/model/Direction.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/Direction.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/reader/model/Direction.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/Direction.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/reader/model/ImageScale.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/ImageScale.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/reader/model/ImageScale.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/ImageScale.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/reader/model/NavigationMode.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/NavigationMode.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/reader/model/NavigationMode.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/NavigationMode.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/reader/model/TappingInvertMode.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/TappingInvertMode.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/reader/model/TappingInvertMode.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/reader/model/TappingInvertMode.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/HttpClient.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/HttpClient.kt similarity index 91% rename from desktop/src/main/kotlin/ca/gosyer/data/server/HttpClient.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/HttpClient.kt index bc662b35..062364ae 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/HttpClient.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/HttpClient.kt @@ -6,7 +6,7 @@ package ca.gosyer.data.server -import ca.gosyer.build.BuildConfig +import ca.gosyer.data.build.BuildKonfig import ca.gosyer.data.server.model.Auth import ca.gosyer.data.server.model.Proxy import io.ktor.client.HttpClient @@ -24,16 +24,13 @@ import io.ktor.client.features.logging.Logging import io.ktor.client.features.websocket.WebSockets import io.ktor.http.URLBuilder import kotlinx.serialization.json.Json -import javax.inject.Inject -import javax.inject.Provider +import me.tatarka.inject.annotations.Inject import io.ktor.client.features.auth.Auth as AuthFeature typealias Http = HttpClient -internal class HttpProvider @Inject constructor( - private val serverPreferences: ServerPreferences -) : Provider { - override fun get(): Http { +class HttpProvider @Inject constructor() { + fun get(serverPreferences: ServerPreferences): Http { return HttpClient(OkHttp) { engine { proxy = when (serverPreferences.proxy().get()) { @@ -85,7 +82,7 @@ internal class HttpProvider @Inject constructor( } install(WebSockets) install(Logging) { - level = if (BuildConfig.DEBUG) { + level = if (BuildKonfig.DEBUG) { LogLevel.HEADERS } else { LogLevel.INFO diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/ServerHostPreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerHostPreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/ServerHostPreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerHostPreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/ServerPreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerPreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/ServerPreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerPreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/ServerService.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerService.kt similarity index 83% rename from desktop/src/main/kotlin/ca/gosyer/data/server/ServerService.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerService.kt index ef4613fe..7aff3a9c 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/ServerService.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerService.kt @@ -6,10 +6,11 @@ package ca.gosyer.data.server -import ca.gosyer.build.BuildConfig +import ca.gosyer.core.io.copyTo +import ca.gosyer.core.io.userDataDir import ca.gosyer.core.lang.withIOContext -import ca.gosyer.util.system.CKLogger -import ca.gosyer.util.system.userDataDir +import ca.gosyer.core.logging.CKLogger +import ca.gosyer.data.build.BuildKonfig import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope @@ -20,23 +21,22 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.merge import kotlinx.coroutines.launch +import me.tatarka.inject.annotations.Inject import mu.KotlinLogging +import okio.FileSystem +import okio.Path +import okio.Path.Companion.toPath +import okio.buffer +import okio.source import java.io.File.pathSeparatorChar import java.io.IOException import java.io.Reader -import java.nio.file.Path import java.util.jar.Attributes import java.util.jar.JarInputStream -import javax.inject.Inject import kotlin.concurrent.thread -import kotlin.io.path.Path import kotlin.io.path.absolutePathString -import kotlin.io.path.createDirectories import kotlin.io.path.exists -import kotlin.io.path.inputStream import kotlin.io.path.isExecutable -import kotlin.io.path.name -import kotlin.io.path.outputStream @OptIn(DelicateCoroutinesApi::class) class ServerService @Inject constructor( @@ -64,17 +64,14 @@ class ServerService @Inject constructor( } @Throws(IOException::class) - private fun copyJar(jarFile: Path) { - javaClass.getResourceAsStream("/Tachidesk.jar")?.buffered()?.use { input -> - jarFile.outputStream().use { output -> - input.copyTo(output) - } - } + private suspend fun copyJar(jarFile: Path) { + javaClass.getResourceAsStream("/Tachidesk.jar")?.source() + ?.copyTo(FileSystem.SYSTEM.sink(jarFile).buffer()) } private fun getJavaFromPath(javaPath: Path): String? { - val javaExeFile = javaPath.resolve("java.exe") - val javaUnixFile = javaPath.resolve("java") + val javaExeFile = javaPath.resolve("java.exe").toNioPath() + val javaUnixFile = javaPath.resolve("java").toNioPath() return when { javaExeFile.exists() && javaExeFile.isExecutable() -> javaExeFile.absolutePathString() javaUnixFile.exists() && javaUnixFile.isExecutable() -> javaUnixFile.absolutePathString() @@ -83,7 +80,7 @@ class ServerService @Inject constructor( } private fun getRuntimeJava(): String? { - return System.getProperty("java.home")?.let { getJavaFromPath(Path(it).resolve("bin")) } + return System.getProperty("java.home")?.let { getJavaFromPath(it.toPath().resolve("bin")) } } private fun getPossibleJava(): String? { @@ -91,8 +88,8 @@ class ServerService @Inject constructor( .orEmpty() .asSequence() .mapNotNull { - val file = Path(it) - if (file.absolutePathString().contains("java") || file.absolutePathString().contains("jdk")) { + val file = it.toPath() + if (file.toString().contains("java") || file.toString().contains("jdk")) { if (file.name.equals("bin", true)) { file } else file.resolve("bin") @@ -126,25 +123,25 @@ class ServerService @Inject constructor( } } GlobalScope.launch(handler) { - val jarFile = userDataDir.also { it.createDirectories() }.resolve("Tachidesk.jar") - if (!jarFile.exists()) { + val jarFile = userDataDir / "Tachidesk.jar" + if (!FileSystem.SYSTEM.exists(jarFile)) { info { "Copying server to resources" } withIOContext { copyJar(jarFile) } } else { try { val jarVersion = withIOContext { - JarInputStream(jarFile.inputStream()).use { jar -> + JarInputStream(FileSystem.SYSTEM.source(jarFile).buffer().inputStream()).use { jar -> jar.manifest?.mainAttributes?.getValue(Attributes.Name.IMPLEMENTATION_VERSION)?.toIntOrNull() } } - if (jarVersion != BuildConfig.SERVER_CODE) { + if (jarVersion != BuildKonfig.SERVER_CODE) { info { "Updating server file from resources" } withIOContext { copyJar(jarFile) } } } catch (e: IOException) { error(e) { - "Error accessing server jar, cannot update server, ${BuildConfig.NAME} may not work properly" + "Error accessing server jar, cannot update server, ${BuildKonfig.NAME} may not work properly" } } } @@ -156,7 +153,7 @@ class ServerService @Inject constructor( withIOContext { val reader: Reader - process = ProcessBuilder(javaPath, *properties, "-jar", jarFile.absolutePathString()) + process = ProcessBuilder(javaPath, *properties, "-jar", jarFile.toString()) .redirectErrorStream(true) .start() .also { diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/ServerUrlPreference.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerUrlPreference.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/ServerUrlPreference.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/ServerUrlPreference.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/host/ServerHostPreference.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/host/ServerHostPreference.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/host/ServerHostPreference.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/host/ServerHostPreference.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/BackupInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/BackupInteractionHandler.kt similarity index 89% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/BackupInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/BackupInteractionHandler.kt index baa3f212..d25d841b 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/BackupInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/BackupInteractionHandler.kt @@ -21,9 +21,10 @@ import io.ktor.client.statement.HttpResponse import io.ktor.http.ContentType import io.ktor.http.Headers import io.ktor.http.HttpHeaders -import java.nio.file.Path -import javax.inject.Inject -import kotlin.io.path.readBytes +import me.tatarka.inject.annotations.Inject +import okio.FileSystem +import okio.Path +import okio.buffer class BackupInteractionHandler @Inject constructor( client: Http, @@ -35,7 +36,7 @@ class BackupInteractionHandler @Inject constructor( serverUrl + backupFileImportRequest(), formData = formData { append( - "backup.proto.gz", file.readBytes(), + "backup.proto.gz", FileSystem.SYSTEM.source(file).buffer().readByteArray(), Headers.build { append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString()) append(HttpHeaders.ContentDisposition, "filename=backup.proto.gz") @@ -51,7 +52,7 @@ class BackupInteractionHandler @Inject constructor( serverUrl + validateBackupFileRequest(), formData = formData { append( - "backup.proto.gz", file.readBytes(), + "backup.proto.gz", FileSystem.SYSTEM.source(file).buffer().readByteArray(), Headers.build { append(HttpHeaders.ContentType, ContentType.MultiPart.FormData.toString()) append(HttpHeaders.ContentDisposition, "filename=backup.proto.gz") diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/BaseInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/BaseInteractionHandler.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/BaseInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/BaseInteractionHandler.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/CategoryInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/CategoryInteractionHandler.kt similarity index 99% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/CategoryInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/CategoryInteractionHandler.kt index 2472a13b..42560b66 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/CategoryInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/CategoryInteractionHandler.kt @@ -26,7 +26,7 @@ import io.ktor.client.request.get import io.ktor.client.statement.HttpResponse import io.ktor.http.HttpMethod import io.ktor.http.Parameters -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class CategoryInteractionHandler @Inject constructor( client: Http, diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/ChapterInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/ChapterInteractionHandler.kt similarity index 98% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/ChapterInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/ChapterInteractionHandler.kt index 644d8da4..e4d79105 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/ChapterInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/ChapterInteractionHandler.kt @@ -19,7 +19,6 @@ import ca.gosyer.data.server.requests.queueDownloadChapterRequest import ca.gosyer.data.server.requests.stopDownloadingChapterRequest import ca.gosyer.data.server.requests.updateChapterMetaRequest import ca.gosyer.data.server.requests.updateChapterRequest -import ca.gosyer.util.compose.imageFromUrl import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.delete import io.ktor.client.request.forms.submitForm @@ -28,7 +27,8 @@ import io.ktor.client.request.parameter import io.ktor.client.statement.HttpResponse import io.ktor.http.HttpMethod import io.ktor.http.Parameters -import javax.inject.Inject +import io.ktor.utils.io.ByteReadChannel +import me.tatarka.inject.annotations.Inject class ChapterInteractionHandler @Inject constructor( client: Http, @@ -123,8 +123,7 @@ class ChapterInteractionHandler @Inject constructor( ) suspend fun getPage(mangaId: Long, chapterIndex: Int, pageNum: Int, block: HttpRequestBuilder.() -> Unit) = withIOContext { - imageFromUrl( - client, + client.get( serverUrl + getPageQuery(mangaId, chapterIndex, pageNum), block ) diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/DownloadInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/DownloadInteractionHandler.kt similarity index 96% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/DownloadInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/DownloadInteractionHandler.kt index 0e5c4b07..fb2069e2 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/DownloadInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/DownloadInteractionHandler.kt @@ -14,7 +14,7 @@ import ca.gosyer.data.server.requests.downloadsStartRequest import ca.gosyer.data.server.requests.downloadsStopRequest import io.ktor.client.request.get import io.ktor.client.statement.HttpResponse -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class DownloadInteractionHandler @Inject constructor( client: Http, diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/ExtensionInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/ExtensionInteractionHandler.kt similarity index 93% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/ExtensionInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/ExtensionInteractionHandler.kt index 9f29e9cd..49232963 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/ExtensionInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/ExtensionInteractionHandler.kt @@ -15,11 +15,11 @@ import ca.gosyer.data.server.requests.apkInstallQuery import ca.gosyer.data.server.requests.apkUninstallQuery import ca.gosyer.data.server.requests.apkUpdateQuery import ca.gosyer.data.server.requests.extensionListQuery -import ca.gosyer.util.compose.imageFromUrl import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.get import io.ktor.client.statement.HttpResponse -import javax.inject.Inject +import io.ktor.utils.io.ByteReadChannel +import me.tatarka.inject.annotations.Inject class ExtensionInteractionHandler @Inject constructor( client: Http, @@ -51,8 +51,7 @@ class ExtensionInteractionHandler @Inject constructor( } suspend fun getApkIcon(extension: Extension, block: HttpRequestBuilder.() -> Unit) = withIOContext { - imageFromUrl( - client, + client.get( serverUrl + apkIconQuery(extension.apkName), block ) diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/LibraryInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/LibraryInteractionHandler.kt similarity index 96% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/LibraryInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/LibraryInteractionHandler.kt index 323d39d4..da2a9775 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/LibraryInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/LibraryInteractionHandler.kt @@ -15,7 +15,7 @@ import ca.gosyer.data.server.requests.removeMangaFromLibraryRequest import io.ktor.client.request.delete import io.ktor.client.request.get import io.ktor.client.statement.HttpResponse -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class LibraryInteractionHandler @Inject constructor( client: Http, diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/MangaInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/MangaInteractionHandler.kt similarity index 94% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/MangaInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/MangaInteractionHandler.kt index cb5b5d96..2b9b24c0 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/MangaInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/MangaInteractionHandler.kt @@ -13,7 +13,6 @@ import ca.gosyer.data.server.ServerPreferences import ca.gosyer.data.server.requests.mangaQuery import ca.gosyer.data.server.requests.mangaThumbnailQuery import ca.gosyer.data.server.requests.updateMangaMetaRequest -import ca.gosyer.util.compose.imageFromUrl import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.forms.submitForm import io.ktor.client.request.get @@ -21,7 +20,8 @@ import io.ktor.client.request.parameter import io.ktor.client.statement.HttpResponse import io.ktor.http.HttpMethod import io.ktor.http.Parameters -import javax.inject.Inject +import io.ktor.utils.io.ByteReadChannel +import me.tatarka.inject.annotations.Inject class MangaInteractionHandler @Inject constructor( client: Http, @@ -43,8 +43,7 @@ class MangaInteractionHandler @Inject constructor( suspend fun getManga(manga: Manga, refresh: Boolean = false) = getManga(manga.id, refresh) suspend fun getMangaThumbnail(mangaId: Long, block: HttpRequestBuilder.() -> Unit) = withIOContext { - imageFromUrl( - client, + client.get( serverUrl + mangaThumbnailQuery(mangaId), block ) diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/SourceInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/SourceInteractionHandler.kt similarity index 99% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/SourceInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/SourceInteractionHandler.kt index 086ed050..29fe0ffe 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/SourceInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/SourceInteractionHandler.kt @@ -33,7 +33,7 @@ import io.ktor.http.ContentType import io.ktor.http.contentType import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class SourceInteractionHandler @Inject constructor( client: Http, diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/UpdatesInteractionHandler.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/UpdatesInteractionHandler.kt similarity index 97% rename from desktop/src/main/kotlin/ca/gosyer/data/server/interactions/UpdatesInteractionHandler.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/UpdatesInteractionHandler.kt index 96aafdab..40f2143e 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/interactions/UpdatesInteractionHandler.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/server/interactions/UpdatesInteractionHandler.kt @@ -18,7 +18,7 @@ import io.ktor.client.request.get import io.ktor.client.request.post import io.ktor.client.statement.HttpResponse import io.ktor.http.Parameters -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class UpdatesInteractionHandler @Inject constructor( client: Http, diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/model/Auth.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/model/Auth.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/model/Auth.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/model/Auth.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/model/Proxy.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/model/Proxy.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/model/Proxy.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/model/Proxy.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Backup.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Backup.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Backup.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Backup.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Category.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Category.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Category.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Category.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Chapters.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Chapters.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Chapters.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Chapters.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Downloads.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Downloads.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Downloads.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Downloads.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Extensions.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Extensions.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Extensions.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Extensions.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Library.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Library.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Library.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Library.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Manga.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Manga.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Manga.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Manga.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Meta.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Meta.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Meta.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Meta.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/RestRequests.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/RestRequests.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/RestRequests.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/RestRequests.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Sources.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Sources.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Sources.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Sources.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/requests/Updates.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Updates.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/server/requests/Updates.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/server/requests/Updates.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/ui/UiPreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/ui/UiPreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/ui/UiPreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/ui/UiPreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/ui/model/StartScreen.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/ui/model/StartScreen.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/ui/model/StartScreen.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/ui/model/StartScreen.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/ui/model/ThemeMode.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/ui/model/ThemeMode.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/ui/model/ThemeMode.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/ui/model/ThemeMode.kt diff --git a/data/src/desktopMain/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt new file mode 100644 index 00000000..de7388c5 --- /dev/null +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt @@ -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.data.ui.model + +import kotlinx.serialization.Serializable + +@Serializable +data class WindowSettings( + val x: Int? = null, + val y: Int? = null, + val width: Int? = null, + val height: Int? = null, + val maximized: Boolean? = null, + val fullscreen: Boolean? = null +) diff --git a/desktop/src/main/kotlin/ca/gosyer/data/update/UpdateChecker.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/update/UpdateChecker.kt similarity index 86% rename from desktop/src/main/kotlin/ca/gosyer/data/update/UpdateChecker.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/update/UpdateChecker.kt index c5540539..6dbbe1c5 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/update/UpdateChecker.kt +++ b/data/src/desktopMain/kotlin/ca/gosyer/data/update/UpdateChecker.kt @@ -6,16 +6,16 @@ package ca.gosyer.data.update -import ca.gosyer.build.BuildConfig import ca.gosyer.core.lang.launch import ca.gosyer.core.lang.withIOContext +import ca.gosyer.data.build.BuildKonfig import ca.gosyer.data.server.Http import ca.gosyer.data.update.model.GithubRelease import io.ktor.client.request.get import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class UpdateChecker @Inject constructor( private val updatePreferences: UpdatePreferences, @@ -42,19 +42,19 @@ class UpdateChecker @Inject constructor( // Removes prefixes like "r" or "v" val newVersion = versionTag.replace("[^\\d.]".toRegex(), "") - return if (BuildConfig.IS_PREVIEW) { + return if (BuildKonfig.IS_PREVIEW) { // Preview builds: based on releases in "Suwayomi/Tachidesk-JUI-preview" repo // tagged as something like "r123" - newVersion.toInt() > BuildConfig.PREVIEW_BUILD + newVersion.toInt() > BuildKonfig.PREVIEW_BUILD } else { // Release builds: based on releases in "Suwayomi/Tachidesk-JUI" repo // tagged as something like "v1.1.2" - newVersion != BuildConfig.VERSION + newVersion != BuildKonfig.VERSION } } companion object { - private val GITHUB_REPO = if (BuildConfig.IS_PREVIEW) { + private val GITHUB_REPO = if (BuildKonfig.IS_PREVIEW) { "Suwayomi/Tachidesk-JUI-preview" } else { "Suwayomi/Tachidesk-JUI" diff --git a/desktop/src/main/kotlin/ca/gosyer/data/update/UpdatePreferences.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/update/UpdatePreferences.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/update/UpdatePreferences.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/update/UpdatePreferences.kt diff --git a/desktop/src/main/kotlin/ca/gosyer/data/update/model/GithubRelease.kt b/data/src/desktopMain/kotlin/ca/gosyer/data/update/model/GithubRelease.kt similarity index 100% rename from desktop/src/main/kotlin/ca/gosyer/data/update/model/GithubRelease.kt rename to data/src/desktopMain/kotlin/ca/gosyer/data/update/model/GithubRelease.kt diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts index 5e340c5f..e21457ea 100644 --- a/desktop/build.gradle.kts +++ b/desktop/build.gradle.kts @@ -5,17 +5,14 @@ import org.gradle.jvm.tasks.Jar import org.jetbrains.compose.compose import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.jmailen.gradle.kotlinter.tasks.FormatTask -import org.jmailen.gradle.kotlinter.tasks.LintTask import proguard.gradle.ProGuardTask import java.nio.file.Files import kotlin.streams.asSequence plugins { kotlin("jvm") - kotlin("kapt") - kotlin("plugin.serialization") id("org.jetbrains.compose") + id("com.google.devtools.ksp") id("com.github.gmazzo.buildconfig") id("org.jmailen.kotlinter") } @@ -23,6 +20,7 @@ plugins { dependencies { implementation(project(":core")) implementation(project(":i18n")) + implementation(project(":data")) // UI (Compose) implementation(compose.desktop.currentOs) @@ -49,8 +47,8 @@ dependencies { implementation(libs.xmlUtilSerialization) // Dependency Injection - implementation(libs.toothpickKsp) - kapt(libs.toothpickCompiler) + implementation(libs.kotlinInjectRuntime) + ksp(libs.kotlinInjectCompiler) // Http client implementation(libs.ktorCore) @@ -91,15 +89,14 @@ dependencies { } java { - sourceCompatibility = Config.jvmTarget - targetCompatibility = Config.jvmTarget + sourceCompatibility = Config.desktopJvmTarget + targetCompatibility = Config.desktopJvmTarget } tasks { withType { - //dependsOn(formatKotlinMain) kotlinOptions { - jvmTarget = Config.jvmTarget.toString() + jvmTarget = Config.desktopJvmTarget.toString() freeCompilerArgs = listOf( "-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlin.time.ExperimentalTime", @@ -123,16 +120,6 @@ tasks { exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA") } - withType { - source(files("src")) - exclude("ca/gosyer/build") - } - - withType { - source(files("src")) - exclude("ca/gosyer/build") - } - registerTachideskTasks(project) task("generateResourceConstants") { @@ -141,6 +128,7 @@ tasks { doFirst { val langs = listOf("en") + Files.list(rootDir.toPath().resolve("i18n/src/commonMain/resources/MR/values")).asSequence() .map { it.fileName.toString().replace("-r", "-") } + .filter { it != "base" } .toList() buildResources.buildConfigField("ca.gosyer.i18n.StringList", "LANGUAGES", langs.joinToString(prefix = "listOf(", postfix = ")") { it.wrap() }) } @@ -172,6 +160,15 @@ tasks { } } +kotlin { + sourceSets.main { + kotlin.srcDir("build/generated/ksp/main/kotlin") + } + sourceSets.test { + kotlin.srcDir("build/generated/ksp/test/kotlin") + } +} + fun isNonStable(version: String): Boolean { val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.contains(it, true) } val regex = "^[0-9,.v-]+(-r)?$".toRegex() @@ -236,7 +233,7 @@ compose.desktop { fun String.wrap() = """"$this"""" buildConfig { className("BuildConfig") - packageName(project.group.toString() + ".build") + packageName(project.group.toString() + ".desktop.build") useKotlinOutput { internalVisibility = true } buildConfigField("String", "NAME", rootProject.name.wrap()) @@ -250,12 +247,3 @@ buildConfig { buildConfigField("String", "TACHIDESK_SP_VERSION", tachideskVersion.wrap()) buildConfigField("int", "SERVER_CODE", serverCode.toString()) } - -kotlinter { - experimentalRules = true - disabledRules = arrayOf("experimental:argument-list-wrapping", "experimental:trailing-comma") -} - -kapt { - includeCompileClasspath = false -} diff --git a/desktop/src/main/kotlin/ca/gosyer/AppComponent.kt b/desktop/src/main/kotlin/ca/gosyer/AppComponent.kt new file mode 100644 index 00000000..5b9b1322 --- /dev/null +++ b/desktop/src/main/kotlin/ca/gosyer/AppComponent.kt @@ -0,0 +1,29 @@ +/* + * 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 + +import ca.gosyer.core.di.AppScope +import ca.gosyer.data.DataComponent +import ca.gosyer.data.create +import ca.gosyer.ui.base.UiComponent +import ca.gosyer.ui.base.create +import me.tatarka.inject.annotations.Component + +@AppScope +class AppComponent private constructor( + @Component + val dataComponent: DataComponent = DataComponent.create(), + @Component + val uiComponent: UiComponent = UiComponent.create(dataComponent) +) { + companion object { + private var appComponentInstance: AppComponent? = null + + fun getInstance() = appComponentInstance ?: AppComponent() + .also { appComponentInstance = it } + } +} diff --git a/desktop/src/main/kotlin/ca/gosyer/core/logging/LoggingSetup.kt b/desktop/src/main/kotlin/ca/gosyer/core/logging/LoggingSetup.kt index 22ab1cd1..bb3f46ac 100644 --- a/desktop/src/main/kotlin/ca/gosyer/core/logging/LoggingSetup.kt +++ b/desktop/src/main/kotlin/ca/gosyer/core/logging/LoggingSetup.kt @@ -6,9 +6,10 @@ package ca.gosyer.core.logging -import ca.gosyer.build.BuildConfig +import ca.gosyer.desktop.build.BuildConfig import com.github.weisj.darklaf.LafManager import mu.KotlinLogging +import okio.Path import org.apache.logging.log4j.Level import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.core.LoggerContext @@ -16,8 +17,6 @@ import org.apache.logging.log4j.core.appender.ConsoleAppender import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory import org.slf4j.bridge.SLF4JBridgeHandler -import java.nio.file.Path -import kotlin.io.path.absolutePathString import java.util.logging.LogManager as JLogManager const val consolePattern = @@ -60,11 +59,11 @@ fun initializeLogger(loggingLocation: Path) { newAppender("Rolling", "RollingFile") .addAttribute( "fileName", - loggingLocation.absolutePathString().trimEnd('/', '\\') + "/rolling.log" + loggingLocation.toString().trimEnd('/', '\\') + "/rolling.log" ) .addAttribute( "filePattern", - loggingLocation.absolutePathString().trimEnd('/', '\\') + "/archive/rolling-%d{yyyy-MM-dd-}.log.gz" + loggingLocation.toString().trimEnd('/', '\\') + "/archive/rolling-%d{yyyy-MM-dd-}.log.gz" ) .add( newLayout("PatternLayout") diff --git a/desktop/src/main/kotlin/ca/gosyer/data/DataModule.kt b/desktop/src/main/kotlin/ca/gosyer/data/DataModule.kt deleted file mode 100644 index 5e120a7e..00000000 --- a/desktop/src/main/kotlin/ca/gosyer/data/DataModule.kt +++ /dev/null @@ -1,120 +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.data - -import ca.gosyer.core.prefs.PreferenceStoreFactory -import ca.gosyer.data.catalog.CatalogPreferences -import ca.gosyer.data.download.DownloadService -import ca.gosyer.data.extension.ExtensionPreferences -import ca.gosyer.data.library.LibraryPreferences -import ca.gosyer.data.library.LibraryUpdateService -import ca.gosyer.data.migration.MigrationPreferences -import ca.gosyer.data.migration.Migrations -import ca.gosyer.data.reader.ReaderPreferences -import ca.gosyer.data.server.Http -import ca.gosyer.data.server.HttpProvider -import ca.gosyer.data.server.KamelConfigProvider -import ca.gosyer.data.server.ServerHostPreferences -import ca.gosyer.data.server.ServerPreferences -import ca.gosyer.data.server.ServerService -import ca.gosyer.data.server.interactions.BackupInteractionHandler -import ca.gosyer.data.server.interactions.CategoryInteractionHandler -import ca.gosyer.data.server.interactions.ChapterInteractionHandler -import ca.gosyer.data.server.interactions.DownloadInteractionHandler -import ca.gosyer.data.server.interactions.ExtensionInteractionHandler -import ca.gosyer.data.server.interactions.LibraryInteractionHandler -import ca.gosyer.data.server.interactions.MangaInteractionHandler -import ca.gosyer.data.server.interactions.SourceInteractionHandler -import ca.gosyer.data.ui.UiPreferences -import ca.gosyer.data.update.UpdateChecker -import ca.gosyer.data.update.UpdatePreferences -import io.kamel.core.config.KamelConfig -import toothpick.ktp.binding.bind -import toothpick.ktp.binding.module - -@Suppress("FunctionName") -val DataModule = module { - val preferenceFactory = PreferenceStoreFactory() - - bind() - .toProviderInstance { ServerPreferences(preferenceFactory.create("server")) } - .providesSingleton() - bind() - .toProviderInstance { ServerHostPreferences(preferenceFactory.create("host")) } - .providesSingleton() - - bind() - .toProviderInstance { ExtensionPreferences(preferenceFactory.create("extension")) } - .providesSingleton() - - bind() - .toProviderInstance { CatalogPreferences(preferenceFactory.create("catalog")) } - .providesSingleton() - - bind() - .toProviderInstance { LibraryPreferences(preferenceFactory.create("library")) } - .providesSingleton() - - bind() - .toProviderInstance { ReaderPreferences(preferenceFactory.create("reader")) { name -> preferenceFactory.create("reader", name) } } - .providesSingleton() - - bind() - .toProviderInstance { UiPreferences(preferenceFactory.create("ui")) } - .providesSingleton() - - bind() - .toProviderInstance { MigrationPreferences(preferenceFactory.create("migration")) } - .providesSingleton() - - bind() - .toProviderInstance { UpdatePreferences(preferenceFactory.create("update")) } - .providesSingleton() - - bind() - .toProvider(HttpProvider::class) - .providesSingleton() - - bind() - .toProvider(KamelConfigProvider::class) - .providesSingleton() - - bind() - .toClass() - bind() - .toClass() - bind() - .toClass() - bind() - .toClass() - bind() - .toClass() - bind() - .toClass() - bind() - .toClass() - bind() - .toClass() - - bind() - .toClass() - .singleton() - - bind() - .toClass() - .singleton() - bind() - .toClass() - .singleton() - - bind() - .toClass() - .singleton() - bind() - .toClass() - .singleton() -} diff --git a/desktop/src/main/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt b/desktop/src/main/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt deleted file mode 100644 index a381fd53..00000000 --- a/desktop/src/main/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt +++ /dev/null @@ -1,58 +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.data.ui.model - -import androidx.compose.ui.unit.DpSize -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.WindowPlacement -import androidx.compose.ui.window.WindowPosition -import kotlinx.serialization.Serializable - -@Serializable -data class WindowSettings( - val x: Int? = null, - val y: Int? = null, - val width: Int? = null, - val height: Int? = null, - val maximized: Boolean? = null, - val fullscreen: Boolean? = null -) { - fun get(): WindowGet { - // Maximize and Fullscreen messes with the other parameters so set them to default - if (maximized == true) { - return WindowGet( - WindowPosition.PlatformDefault, - DpSize(800.dp, 600.dp), - WindowPlacement.Maximized - ) - } else if (fullscreen == true) { - return WindowGet( - WindowPosition.PlatformDefault, - DpSize(800.dp, 600.dp), - WindowPlacement.Fullscreen - ) - } - - val offset = if (x != null && y != null) { - WindowPosition(x.dp, y.dp) - } else { - WindowPosition.PlatformDefault - } - val size = DpSize((width ?: 800).dp, (height ?: 600).dp) - return WindowGet( - offset, - size, - WindowPlacement.Floating - ) - } - - data class WindowGet( - val offset: WindowPosition, - val size: DpSize, - val placement: WindowPlacement - ) -} diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/base/UiComponent.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/UiComponent.kt new file mode 100644 index 00000000..b58ce021 --- /dev/null +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/UiComponent.kt @@ -0,0 +1,42 @@ +/* + * 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.ui.base + +import androidx.compose.runtime.compositionLocalOf +import ca.gosyer.core.di.AppScope +import ca.gosyer.data.DataComponent +import ca.gosyer.ui.base.image.KamelConfigProvider +import ca.gosyer.ui.base.vm.ViewModelFactory +import io.kamel.core.config.KamelConfig +import io.kamel.image.config.LocalKamelConfig +import me.tatarka.inject.annotations.Component +import me.tatarka.inject.annotations.Provides + +val LocalViewModelFactory = + compositionLocalOf { throw IllegalArgumentException("Unset") } + +@AppScope +@Component +abstract class UiComponent( + @Component protected val dataComponent: DataComponent +) { + protected abstract val kamelConfigProvider: KamelConfigProvider + + abstract val viewModelFactory: ViewModelFactory + + @get:AppScope + @get:Provides + val kamelConfig: KamelConfig + get() = kamelConfigProvider.get() + + fun getHooks() = arrayOf( + LocalViewModelFactory provides viewModelFactory, + LocalKamelConfig provides kamelConfig + ) + + companion object +} diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/base/WindowDialog.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/WindowDialog.kt index 2e12fc98..e1409c88 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/base/WindowDialog.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/WindowDialog.kt @@ -23,7 +23,6 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.key.Key @@ -35,11 +34,9 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window import androidx.compose.ui.window.WindowPosition import androidx.compose.ui.window.rememberWindowState -import ca.gosyer.core.di.AppScope +import ca.gosyer.AppComponent import ca.gosyer.ui.base.theme.AppTheme import ca.gosyer.util.lang.launchApplication -import io.kamel.core.config.KamelConfig -import io.kamel.image.config.LocalKamelConfig import kotlinx.coroutines.DelicateCoroutinesApi @OptIn(DelicateCoroutinesApi::class) @@ -69,7 +66,7 @@ fun WindowDialog( } val icon = painterResource("icon.png") - val kamelConfig = remember { AppScope.getInstance() } + val hooks = AppComponent.getInstance().uiComponent.getHooks() val windowState = rememberWindowState(size = size, position = WindowPosition(Alignment.Center)) Window( @@ -96,7 +93,7 @@ fun WindowDialog( alwaysOnTop = forceFocus ) { CompositionLocalProvider( - LocalKamelConfig provides kamelConfig + *hooks ) { AppTheme { Surface { @@ -145,7 +142,7 @@ fun WindowDialog( } val icon = painterResource("icon.png") - val kamelConfig = remember { AppScope.getInstance() } + val hooks = AppComponent.getInstance().uiComponent.getHooks() val windowState = rememberWindowState(size = size, position = WindowPosition.Aligned(Alignment.Center)) Window( @@ -164,7 +161,7 @@ fun WindowDialog( alwaysOnTop = forceFocus, ) { CompositionLocalProvider( - LocalKamelConfig provides kamelConfig + *hooks ) { AppTheme { Surface { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/base/components/ChapterDownloadButtons.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/components/ChapterDownloadButtons.kt index e9e6e815..d50171b1 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/base/components/ChapterDownloadButtons.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/components/ChapterDownloadButtons.kt @@ -37,8 +37,8 @@ import ca.gosyer.data.download.model.DownloadState import ca.gosyer.data.models.Chapter import ca.gosyer.data.models.Manga import ca.gosyer.data.server.interactions.ChapterInteractionHandler -import dev.icerock.moko.resources.compose.stringResource import ca.gosyer.i18n.MR +import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/base/components/LoadingScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/components/LoadingScreen.kt index 7cee459f..3fcb2b50 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/base/components/LoadingScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/components/LoadingScreen.kt @@ -15,8 +15,8 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import dev.icerock.moko.resources.compose.stringResource import ca.gosyer.i18n.MR +import dev.icerock.moko.resources.compose.stringResource @Composable fun LoadingScreen( diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/base/components/Toolbar.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/components/Toolbar.kt index 89304087..de9b1a77 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/base/components/Toolbar.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/components/Toolbar.kt @@ -63,8 +63,8 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import dev.icerock.moko.resources.compose.stringResource import ca.gosyer.i18n.MR +import dev.icerock.moko.resources.compose.stringResource @Composable fun Toolbar( diff --git a/desktop/src/main/kotlin/ca/gosyer/data/server/KamelConfigProvider.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/image/KamelConfigProvider.kt similarity index 93% rename from desktop/src/main/kotlin/ca/gosyer/data/server/KamelConfigProvider.kt rename to desktop/src/main/kotlin/ca/gosyer/ui/base/image/KamelConfigProvider.kt index 39f46197..d8cd10fa 100644 --- a/desktop/src/main/kotlin/ca/gosyer/data/server/KamelConfigProvider.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/image/KamelConfigProvider.kt @@ -4,11 +4,13 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package ca.gosyer.data.server +package ca.gosyer.ui.base.image import ca.gosyer.data.models.Extension import ca.gosyer.data.models.Manga import ca.gosyer.data.models.Source +import ca.gosyer.data.server.Http +import ca.gosyer.data.server.ServerPreferences import ca.gosyer.ui.base.prefs.asStateIn import io.kamel.core.config.DefaultCacheSize import io.kamel.core.config.KamelConfig @@ -25,17 +27,16 @@ import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import javax.inject.Inject -import javax.inject.Provider +import me.tatarka.inject.annotations.Inject class KamelConfigProvider @Inject constructor( private val http: Http, serverPreferences: ServerPreferences -) : Provider { +) { @OptIn(DelicateCoroutinesApi::class) val serverUrl = serverPreferences.serverUrl().asStateIn(GlobalScope) - override fun get(): KamelConfig { + fun get(): KamelConfig { return KamelConfig { // Default config imageBitmapCacheSize = DefaultCacheSize diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/base/theme/AppTheme.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/theme/AppTheme.kt index c5986ea8..7d5ebc59 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/base/theme/AppTheme.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/theme/AppTheme.kt @@ -29,7 +29,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.cancelChildren -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject /** * Composable used to apply the application colors to [content]. @@ -56,7 +56,7 @@ fun AppTheme(content: @Composable () -> Unit) { } } -private class AppThemeViewModel @Inject constructor( +class AppThemeViewModel @Inject constructor( private val uiPreferences: UiPreferences ) : ViewModel() { private val themeMode = uiPreferences.themeMode().asStateFlow() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/base/vm/ComposeViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/vm/ComposeViewModel.kt index c0ac18f3..0a56e8ca 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/base/vm/ComposeViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/vm/ComposeViewModel.kt @@ -10,15 +10,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.DisallowComposableCalls import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.remember -import ca.gosyer.core.di.AppScope -import toothpick.Toothpick -import toothpick.ktp.binding.module -import toothpick.ktp.extension.getInstance +import ca.gosyer.ui.base.LocalViewModelFactory @Composable inline fun viewModel(key: Any? = Unit): VM { + val viewModelFactory = LocalViewModelFactory.current val viewModel = remember(key) { - AppScope.getInstance() + viewModelFactory.instantiate() } DisposableEffect(viewModel) { onDispose { @@ -31,22 +29,15 @@ inline fun viewModel(key: Any? = Unit): VM { @Composable inline fun viewModel( key: Any? = Unit, - crossinline binding: @DisallowComposableCalls () -> Any, + crossinline factory: @DisallowComposableCalls ViewModelFactory.() -> VM ): VM { - val (viewModel, submodule) = remember(key) { - val submodule = module { - binding().let { bind(it.javaClass).toInstance(it) } - } - val subscope = AppScope.subscope(submodule).also { - it.installModules(submodule) - } - val viewModel = subscope.getInstance() - Pair(viewModel, submodule) + val viewModelFactory = LocalViewModelFactory.current + val viewModel = remember(key) { + viewModelFactory.factory() } DisposableEffect(viewModel) { onDispose { viewModel.destroy() - Toothpick.closeScope(submodule) } } return viewModel diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/base/vm/ViewModelFactory.kt b/desktop/src/main/kotlin/ca/gosyer/ui/base/vm/ViewModelFactory.kt new file mode 100644 index 00000000..2c90a55a --- /dev/null +++ b/desktop/src/main/kotlin/ca/gosyer/ui/base/vm/ViewModelFactory.kt @@ -0,0 +1,96 @@ +/* + * 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.ui.base.vm + +import ca.gosyer.ui.base.theme.AppThemeViewModel +import ca.gosyer.ui.categories.CategoriesMenuViewModel +import ca.gosyer.ui.downloads.DownloadsMenuViewModel +import ca.gosyer.ui.extensions.ExtensionsMenuViewModel +import ca.gosyer.ui.library.LibraryScreenViewModel +import ca.gosyer.ui.main.MainViewModel +import ca.gosyer.ui.main.components.DebugOverlayViewModel +import ca.gosyer.ui.main.components.TrayViewModel +import ca.gosyer.ui.manga.MangaMenuViewModel +import ca.gosyer.ui.reader.ReaderMenuViewModel +import ca.gosyer.ui.settings.SettingsAdvancedViewModel +import ca.gosyer.ui.settings.SettingsBackupViewModel +import ca.gosyer.ui.settings.SettingsGeneralViewModel +import ca.gosyer.ui.settings.SettingsLibraryViewModel +import ca.gosyer.ui.settings.SettingsReaderViewModel +import ca.gosyer.ui.settings.SettingsServerViewModel +import ca.gosyer.ui.settings.ThemesViewModel +import ca.gosyer.ui.sources.SourcesMenuViewModel +import ca.gosyer.ui.sources.components.SourceHomeScreenViewModel +import ca.gosyer.ui.sources.components.SourceScreenViewModel +import ca.gosyer.ui.sources.components.filter.SourceFiltersViewModel +import ca.gosyer.ui.sources.settings.SourceSettingsViewModel +import ca.gosyer.ui.updates.UpdatesMenuViewModel +import com.github.zsoltk.compose.savedinstancestate.Bundle +import me.tatarka.inject.annotations.Inject +import kotlin.reflect.KClass + +@Inject +class ViewModelFactory( + private val appThemeFactory: () -> AppThemeViewModel, + private val categoryFactory: () -> CategoriesMenuViewModel, + private val downloadsFactory: () -> DownloadsMenuViewModel, + private val extensionsFactory: () -> ExtensionsMenuViewModel, + private val libraryFactory: (bundle: Bundle) -> LibraryScreenViewModel, + private val debugOverlayFactory: () -> DebugOverlayViewModel, + private val trayFactory: () -> TrayViewModel, + private val mainFactory: () -> MainViewModel, + private val mangaFactory: (params: MangaMenuViewModel.Params) -> MangaMenuViewModel, + private val readerFactory: (params: ReaderMenuViewModel.Params) -> ReaderMenuViewModel, + private val settingsAdvancedFactory: () -> SettingsAdvancedViewModel, + private val themesFactory: () -> ThemesViewModel, + private val settingsBackupFactory: () -> SettingsBackupViewModel, + private val settingsGeneralFactory: () -> SettingsGeneralViewModel, + private val settingsLibraryFactory: () -> SettingsLibraryViewModel, + private val settingsReaderFactory: () -> SettingsReaderViewModel, + private val settingsServerFactory: () -> SettingsServerViewModel, + private val sourceFiltersFactory: (params: SourceFiltersViewModel.Params) -> SourceFiltersViewModel, + private val sourceSettingsFactory: (params: SourceSettingsViewModel.Params) -> SourceSettingsViewModel, + private val sourceHomeFactory: (bundle: Bundle) -> SourceHomeScreenViewModel, + private val sourceFactory: (params: SourceScreenViewModel.Params) -> SourceScreenViewModel, + private val sourcesFactory: (bundle: Bundle) -> SourcesMenuViewModel, + private val updatesFactory: () -> UpdatesMenuViewModel +) { + + inline fun instantiate(arg1: Any? = null): VM { + return instantiate(VM::class, arg1) + } + + fun instantiate(klass: KClass, arg1: Any? = null): VM { + @Suppress("UNCHECKED_CAST") + return when (klass) { + AppThemeViewModel::class -> appThemeFactory() + CategoriesMenuViewModel::class -> categoryFactory() + DownloadsMenuViewModel::class -> downloadsFactory() + ExtensionsMenuViewModel::class -> extensionsFactory() + LibraryScreenViewModel::class -> libraryFactory(arg1 as Bundle) + DebugOverlayViewModel::class -> debugOverlayFactory() + TrayViewModel::class -> trayFactory() + MainViewModel::class -> mainFactory() + MangaMenuViewModel::class -> mangaFactory(arg1 as MangaMenuViewModel.Params) + ReaderMenuViewModel::class -> readerFactory(arg1 as ReaderMenuViewModel.Params) + SettingsAdvancedViewModel::class -> settingsAdvancedFactory() + ThemesViewModel::class -> themesFactory() + SettingsBackupViewModel::class -> settingsBackupFactory() + SettingsGeneralViewModel::class -> settingsGeneralFactory() + SettingsLibraryViewModel::class -> settingsLibraryFactory() + SettingsReaderViewModel::class -> settingsReaderFactory() + SettingsServerViewModel::class -> settingsServerFactory() + SourceFiltersViewModel::class -> sourceFiltersFactory(arg1 as SourceFiltersViewModel.Params) + SourceSettingsViewModel::class -> sourceSettingsFactory(arg1 as SourceSettingsViewModel.Params) + SourceHomeScreenViewModel::class -> sourceHomeFactory(arg1 as Bundle) + SourceScreenViewModel::class -> sourceFactory(arg1 as SourceScreenViewModel.Params) + SourcesMenuViewModel::class -> sourcesFactory(arg1 as Bundle) + UpdatesMenuViewModel::class -> updatesFactory() + else -> throw IllegalArgumentException("Unknown ViewModel $klass") + } as VM + } +} diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesDialogs.kt b/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesDialogs.kt index 8b30da29..49254887 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesDialogs.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesDialogs.kt @@ -11,7 +11,7 @@ import androidx.compose.material.TextField import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.text.input.TextFieldValue -import ca.gosyer.build.BuildConfig +import ca.gosyer.desktop.build.BuildConfig import ca.gosyer.i18n.MR import ca.gosyer.ui.base.WindowDialog import dev.icerock.moko.resources.compose.stringResource diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesMenu.kt index 41b9460c..6a4de00f 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesMenu.kt @@ -45,12 +45,12 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import ca.gosyer.build.BuildConfig -import dev.icerock.moko.resources.compose.stringResource +import ca.gosyer.desktop.build.BuildConfig import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.util.compose.ThemedWindow import ca.gosyer.util.lang.launchApplication +import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesMenuViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesMenuViewModel.kt index 4c48d452..c6c56fa3 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesMenuViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/categories/CategoriesMenuViewModel.kt @@ -7,14 +7,14 @@ package ca.gosyer.ui.categories import ca.gosyer.core.lang.throwIfCancellation +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.models.Category import ca.gosyer.data.server.interactions.CategoryInteractionHandler import ca.gosyer.ui.base.vm.ViewModel -import ca.gosyer.util.system.CKLogger import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class CategoriesMenuViewModel @Inject constructor( private val categoryHandler: CategoryInteractionHandler diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/downloads/DownloadsMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/downloads/DownloadsMenu.kt index 6117c1f8..8c43e779 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/downloads/DownloadsMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/downloads/DownloadsMenu.kt @@ -44,10 +44,11 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp -import ca.gosyer.build.BuildConfig import ca.gosyer.data.download.model.DownloadChapter import ca.gosyer.data.download.model.DownloaderStatus import ca.gosyer.data.models.Chapter +import ca.gosyer.desktop.build.BuildConfig +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.ActionIcon import ca.gosyer.ui.base.components.DropdownIconButton import ca.gosyer.ui.base.components.MangaListItem @@ -57,12 +58,11 @@ import ca.gosyer.ui.base.components.MangaListItemSubtitle import ca.gosyer.ui.base.components.MangaListItemTitle import ca.gosyer.ui.base.components.Toolbar import ca.gosyer.ui.base.components.mangaAspectRatio -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.ui.manga.openMangaMenu import ca.gosyer.util.compose.ThemedWindow import ca.gosyer.util.lang.launchApplication +import dev.icerock.moko.resources.compose.stringResource import io.kamel.image.lazyPainterResource import kotlinx.coroutines.DelicateCoroutinesApi @@ -151,7 +151,7 @@ fun DownloadsItem( fontWeight = FontWeight.SemiBold ) val progress = if (item.chapter.pageCount != null && item.chapter.pageCount != -1) { - " - " + "${(item.chapter.pageCount * item.progress).toInt()}/${item.chapter.pageCount}" + " - " + "${(item.chapter.pageCount!! * item.progress).toInt()}/${item.chapter.pageCount}" } else "" MangaListItemSubtitle( text = item.chapter.name + progress diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/downloads/DownloadsMenuViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/downloads/DownloadsMenuViewModel.kt index 620207b2..f894f223 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/downloads/DownloadsMenuViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/downloads/DownloadsMenuViewModel.kt @@ -12,7 +12,7 @@ import ca.gosyer.data.server.interactions.ChapterInteractionHandler import ca.gosyer.data.server.interactions.DownloadInteractionHandler import ca.gosyer.ui.base.vm.ViewModel import kotlinx.coroutines.launch -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class DownloadsMenuViewModel @Inject constructor( private val downloadService: DownloadService, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenu.kt index 17aa46bd..289e1899 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenu.kt @@ -46,19 +46,19 @@ import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.rememberWindowState -import ca.gosyer.build.BuildConfig import ca.gosyer.data.models.Extension +import ca.gosyer.desktop.build.BuildConfig +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.WindowDialog import ca.gosyer.ui.base.components.KamelImage import ca.gosyer.ui.base.components.LoadingScreen import ca.gosyer.ui.base.components.TextActionIcon import ca.gosyer.ui.base.components.Toolbar -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.util.compose.ThemedWindow import ca.gosyer.util.compose.persistentLazyListState import ca.gosyer.util.lang.launchApplication +import dev.icerock.moko.resources.compose.stringResource import io.kamel.image.lazyPainterResource import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenuViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenuViewModel.kt index 314c956d..4b6b2013 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenuViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenuViewModel.kt @@ -7,20 +7,20 @@ package ca.gosyer.ui.extensions import ca.gosyer.core.lang.throwIfCancellation +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.extension.ExtensionPreferences import ca.gosyer.data.models.Extension import ca.gosyer.data.server.interactions.ExtensionInteractionHandler import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.ViewModel -import ca.gosyer.util.system.CKLogger import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import me.tatarka.inject.annotations.Inject import java.util.Locale -import javax.inject.Inject class ExtensionsMenuViewModel @Inject constructor( private val extensionHandler: ExtensionInteractionHandler, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/library/LibraryScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/library/LibraryScreen.kt index a33f6c48..e9e77be6 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/library/LibraryScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/library/LibraryScreen.kt @@ -26,14 +26,13 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEachIndexed -import ca.gosyer.build.BuildConfig import ca.gosyer.data.library.model.DisplayMode import ca.gosyer.data.models.Category import ca.gosyer.data.models.Manga +import ca.gosyer.desktop.build.BuildConfig +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.LoadingScreen import ca.gosyer.ui.base.components.Toolbar -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.ui.manga.openMangaMenu import ca.gosyer.util.compose.ThemedWindow @@ -42,6 +41,7 @@ import com.github.zsoltk.compose.savedinstancestate.Bundle import com.github.zsoltk.compose.savedinstancestate.LocalSavedInstanceState import com.google.accompanist.pager.HorizontalPager import com.google.accompanist.pager.rememberPagerState +import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.DelicateCoroutinesApi @OptIn(DelicateCoroutinesApi::class) @@ -66,8 +66,8 @@ fun LibraryScreen(onClickManga: (Long) -> Unit = ::openMangaMenu) { @Composable fun LibraryScreen(bundle: Bundle, onClickManga: (Long) -> Unit = ::openMangaMenu) { - val vm = viewModel { - bundle + val vm = viewModel { + instantiate(bundle) } val categories by vm.categories.collectAsState() val selectedCategoryIndex by vm.selectedCategoryIndex.collectAsState() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/library/LibraryScreenViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/library/LibraryScreenViewModel.kt index c6933be6..6e7aa827 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/library/LibraryScreenViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/library/LibraryScreenViewModel.kt @@ -31,7 +31,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.toList import kotlinx.coroutines.launch -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject private typealias CategoryItems = Pair>, MutableStateFlow>> private typealias LibraryMap = MutableMap @@ -71,11 +71,11 @@ private suspend fun filterManga(query: String?, mangaList: List): List Unit) { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/main/components/Tray.kt b/desktop/src/main/kotlin/ca/gosyer/ui/main/components/Tray.kt index d7362786..e4fc97a8 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/main/components/Tray.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/main/components/Tray.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.window.ApplicationScope import androidx.compose.ui.window.Notification import androidx.compose.ui.window.Tray import androidx.compose.ui.window.rememberTrayState -import ca.gosyer.build.BuildConfig +import ca.gosyer.desktop.build.BuildConfig import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import kotlinx.coroutines.launch diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/main/components/TrayViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/main/components/TrayViewModel.kt index ca464aa5..3376f120 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/main/components/TrayViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/main/components/TrayViewModel.kt @@ -8,7 +8,7 @@ package ca.gosyer.ui.main.components import ca.gosyer.data.update.UpdateChecker import ca.gosyer.ui.base.vm.ViewModel -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class TrayViewModel @Inject constructor( private val updateChecker: UpdateChecker diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/main/main.kt b/desktop/src/main/kotlin/ca/gosyer/ui/main/main.kt index b707b822..92408e5c 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/main/main.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/main/main.kt @@ -24,23 +24,21 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.window.Window import androidx.compose.ui.window.awaitApplication import androidx.compose.ui.window.rememberWindowState -import ca.gosyer.build.BuildConfig +import ca.gosyer.AppComponent +import ca.gosyer.core.io.userDataDir import ca.gosyer.core.lang.withUIContext import ca.gosyer.core.logging.initializeLogger -import ca.gosyer.data.DataModule -import ca.gosyer.data.migration.Migrations -import ca.gosyer.data.server.ServerService +import ca.gosyer.core.prefs.getAsFlow import ca.gosyer.data.server.ServerService.ServerResult -import ca.gosyer.data.ui.UiPreferences import ca.gosyer.data.ui.model.ThemeMode +import ca.gosyer.desktop.build.BuildConfig import ca.gosyer.i18n.MR import ca.gosyer.ui.base.WindowDialog import ca.gosyer.ui.base.components.LoadingScreen import ca.gosyer.ui.base.prefs.asStateIn import ca.gosyer.ui.base.theme.AppTheme import ca.gosyer.ui.main.components.Tray -import ca.gosyer.util.system.getAsFlow -import ca.gosyer.util.system.userDataDir +import ca.gosyer.util.compose.WindowGet import com.github.weisj.darklaf.LafManager import com.github.weisj.darklaf.theme.DarculaTheme import com.github.weisj.darklaf.theme.IntelliJTheme @@ -48,17 +46,12 @@ import com.github.zsoltk.compose.backpress.BackPressHandler import com.github.zsoltk.compose.backpress.LocalBackPressHandler import com.github.zsoltk.compose.savedinstancestate.Bundle import dev.icerock.moko.resources.compose.stringResource -import io.kamel.core.config.KamelConfig -import io.kamel.image.config.LocalKamelConfig import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import org.jetbrains.skiko.SystemTheme import org.jetbrains.skiko.currentSystemTheme -import toothpick.configuration.Configuration -import toothpick.ktp.KTP -import toothpick.ktp.extension.getInstance import java.util.Locale import kotlin.system.exitProcess @@ -70,23 +63,13 @@ suspend fun main() { System.setProperty("kotlinx.coroutines.debug", "on") } - KTP.setConfiguration( - if (BuildConfig.DEBUG) { - Configuration.forDevelopment() - } else { - Configuration.forProduction() - } - ) - - val scope = KTP.openRootScope() - .installModules( - DataModule - ) - - scope.getInstance().runMigrations() - - val serverService = scope.getInstance() - val uiPreferences = scope.getInstance() + val appComponent = AppComponent.getInstance() + val dataComponent = appComponent.dataComponent + val uiComponent = appComponent.uiComponent + dataComponent.migrations.runMigrations() + val serverService = dataComponent.serverService + val uiPreferences = dataComponent.uiPreferences + val uiHooks = uiComponent.getHooks() // Call setDefault before getting a resource bundle val language = uiPreferences.language().get() @@ -97,8 +80,6 @@ suspend fun main() { } } - val kamelConfig = scope.getInstance() - // Set the Compose constants before any // Swing functions are called configureSwingGlobalsForCompose() @@ -127,88 +108,89 @@ suspend fun main() { position, size, placement - ) = windowSettings.get().get() + ) = WindowGet.from(windowSettings.get()) val confirmExit = uiPreferences.confirmExit().asStateIn(GlobalScope) val displayDebugInfoFlow = MutableStateFlow(false) awaitApplication { - // Exit the whole application when this window closes - DisposableEffect(Unit) { - onDispose { - exitProcess(0) - } - } - - val backPressHandler = remember { BackPressHandler() } - - val rootBundle = remember { Bundle() } - val windowState = rememberWindowState( - size = size, - position = position, - placement = placement - ) - - val icon = painterResource("icon.png") - - Tray(icon) - - Window( - onCloseRequest = { - if (confirmExit.value) { - WindowDialog( - title = MR.strings.confirm_exit.localized(), - onPositiveButton = ::exitApplication - ) { - Text(stringResource(MR.strings.confirm_exit_message)) - } - } else { - exitApplication() + CompositionLocalProvider(*uiHooks) { + // Exit the whole application when this window closes + DisposableEffect(Unit) { + onDispose { + exitProcess(0) } - }, - title = BuildConfig.NAME, - icon = icon, - state = windowState, - onKeyEvent = { - if (it.type == KeyEventType.KeyUp) { - when (it.key) { - Key.Home -> { - backPressHandler.handle() - } - Key.F3 -> { - displayDebugInfoFlow.value = !displayDebugInfoFlow.value - true - } - else -> false - } - } else false } - ) { - AppTheme { - CompositionLocalProvider( - LocalBackPressHandler provides backPressHandler, - LocalKamelConfig provides kamelConfig - ) { - Crossfade(serverService.initialized.collectAsState().value) { initialized -> - when (initialized) { - ServerResult.STARTED, ServerResult.UNUSED -> { - Box { - MainMenu(rootBundle) - val displayDebugInfo by displayDebugInfoFlow.collectAsState() - if (displayDebugInfo) { - DebugOverlay() + + val backPressHandler = remember { BackPressHandler() } + + val rootBundle = remember { Bundle() } + val windowState = rememberWindowState( + size = size, + position = position, + placement = placement + ) + + val icon = painterResource("icon.png") + + Tray(icon) + + Window( + onCloseRequest = { + if (confirmExit.value) { + WindowDialog( + title = MR.strings.confirm_exit.localized(), + onPositiveButton = ::exitApplication + ) { + Text(stringResource(MR.strings.confirm_exit_message)) + } + } else { + exitApplication() + } + }, + title = BuildConfig.NAME, + icon = icon, + state = windowState, + onKeyEvent = { + if (it.type == KeyEventType.KeyUp) { + when (it.key) { + Key.Home -> { + backPressHandler.handle() + } + Key.F3 -> { + displayDebugInfoFlow.value = !displayDebugInfoFlow.value + true + } + else -> false + } + } else false + } + ) { + AppTheme { + CompositionLocalProvider( + LocalBackPressHandler provides backPressHandler, + ) { + Crossfade(serverService.initialized.collectAsState().value) { initialized -> + when (initialized) { + ServerResult.STARTED, ServerResult.UNUSED -> { + Box { + MainMenu(rootBundle) + val displayDebugInfo by displayDebugInfoFlow.collectAsState() + if (displayDebugInfo) { + DebugOverlay() + } } } - } - ServerResult.STARTING, ServerResult.FAILED -> { - Surface { - LoadingScreen( - initialized == ServerResult.STARTING, - errorMessage = stringResource(MR.strings.unable_to_start_server), - retryMessage = stringResource(MR.strings.action_start_anyway), - retry = serverService::startAnyway - ) + ServerResult.STARTING, ServerResult.FAILED -> { + Surface { + LoadingScreen( + initialized == ServerResult.STARTING, + errorMessage = stringResource(MR.strings.unable_to_start_server), + retryMessage = stringResource(MR.strings.action_start_anyway), + retry = serverService::startAnyway + ) + } } } } diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/manga/ChapterItem.kt b/desktop/src/main/kotlin/ca/gosyer/ui/manga/ChapterItem.kt index ca72f9c5..37c8c2f5 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/manga/ChapterItem.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/manga/ChapterItem.kt @@ -98,7 +98,7 @@ fun ChapterItem( } if (!chapter.scanlator.isNullOrBlank()) { if (length > 0) append(" • ") - append(chapter.scanlator) + append(chapter.scanlator!!) } } SelectionContainer { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/manga/MangaMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/manga/MangaMenu.kt index 4a66b97a..6fc0b5f2 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/manga/MangaMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/manga/MangaMenu.kt @@ -48,9 +48,9 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.util.fastForEach -import ca.gosyer.build.BuildConfig import ca.gosyer.data.models.Category import ca.gosyer.data.models.Manga +import ca.gosyer.desktop.build.BuildConfig import ca.gosyer.i18n.MR import ca.gosyer.ui.base.WindowDialog import ca.gosyer.ui.base.components.ErrorScreen @@ -83,8 +83,8 @@ fun openMangaMenu(mangaId: Long) { @Composable fun MangaMenu(mangaId: Long, menuController: MenuController? = LocalMenuController.current) { - val vm = viewModel { - MangaMenuViewModel.Params(mangaId) + val vm = viewModel { + instantiate(MangaMenuViewModel.Params(mangaId)) } val manga by vm.manga.collectAsState() val chapters by vm.chapters.collectAsState() @@ -221,13 +221,13 @@ private fun MangaInfo(manga: Manga, modifier: Modifier = Modifier) { Column(modifier) { Text(manga.title, fontSize = 22.sp, fontWeight = FontWeight.Bold) if (!manga.author.isNullOrEmpty()) { - Text(manga.author, fontSize = 18.sp) + Text(manga.author!!, fontSize = 18.sp) } if (!manga.artist.isNullOrEmpty() && manga.artist != manga.author) { - Text(manga.artist, fontSize = 18.sp) + Text(manga.artist!!, fontSize = 18.sp) } if (!manga.description.isNullOrEmpty()) { - Text(manga.description) + Text(manga.description!!) } if (manga.genre.isNotEmpty()) { FlowRow { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/manga/MangaMenuViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/manga/MangaMenuViewModel.kt index 1b8bf90b..e73ccc05 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/manga/MangaMenuViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/manga/MangaMenuViewModel.kt @@ -27,20 +27,20 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.launch +import me.tatarka.inject.annotations.Inject import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.format.FormatStyle import java.util.Locale -import javax.inject.Inject class MangaMenuViewModel @Inject constructor( - private val params: Params, private val mangaHandler: MangaInteractionHandler, private val chapterHandler: ChapterInteractionHandler, private val categoryHandler: CategoryInteractionHandler, private val libraryHandler: LibraryInteractionHandler, private val downloadService: DownloadService, uiPreferences: UiPreferences, + private val params: Params, ) : ViewModel() { private val downloadingChapters = downloadService.registerWatch(params.mangaId) diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/reader/ChapterLoader.kt b/desktop/src/main/kotlin/ca/gosyer/ui/reader/ChapterLoader.kt index c6107f2d..72b53364 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/reader/ChapterLoader.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/reader/ChapterLoader.kt @@ -6,12 +6,12 @@ package ca.gosyer.ui.reader +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.reader.ReaderPreferences import ca.gosyer.data.server.interactions.ChapterInteractionHandler import ca.gosyer.ui.reader.loader.TachideskPageLoader import ca.gosyer.ui.reader.model.ReaderChapter import ca.gosyer.ui.reader.model.ReaderPage -import ca.gosyer.util.system.CKLogger import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.launchIn diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderMenu.kt index a5711bdc..e476d31f 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderMenu.kt @@ -53,13 +53,12 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window import androidx.compose.ui.window.WindowPlacement import androidx.compose.ui.window.rememberWindowState -import ca.gosyer.build.BuildConfig -import ca.gosyer.core.di.AppScope +import ca.gosyer.AppComponent import ca.gosyer.data.reader.model.Direction import ca.gosyer.data.reader.model.ImageScale import ca.gosyer.data.reader.model.NavigationMode -import ca.gosyer.data.ui.UiPreferences import ca.gosyer.data.ui.model.WindowSettings +import ca.gosyer.desktop.build.BuildConfig import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.ErrorScreen import ca.gosyer.ui.base.components.LoadingScreen @@ -76,10 +75,9 @@ import ca.gosyer.ui.reader.navigation.RightAndLeftNavigation import ca.gosyer.ui.reader.navigation.navigationClickable import ca.gosyer.ui.reader.viewer.ContinuousReader import ca.gosyer.ui.reader.viewer.PagerReader +import ca.gosyer.util.compose.WindowGet import ca.gosyer.util.lang.launchApplication import dev.icerock.moko.resources.compose.stringResource -import io.kamel.core.config.KamelConfig -import io.kamel.image.config.LocalKamelConfig import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow @@ -99,15 +97,15 @@ val supportedKeyList = listOf( @OptIn(DelicateCoroutinesApi::class) fun openReaderMenu(chapterIndex: Int, mangaId: Long) { - val windowSettings = AppScope.getInstance() + val windowSettings = AppComponent.getInstance().dataComponent.uiPreferences .readerWindow() val ( position, size, placement - ) = windowSettings.get().get() + ) = WindowGet.from(windowSettings.get()) - val kamelConfig = AppScope.getInstance() + val hooks = AppComponent.getInstance().uiComponent.getHooks() launchApplication { val scope = rememberCoroutineScope() @@ -142,7 +140,7 @@ fun openReaderMenu(chapterIndex: Int, mangaId: Long) { } ) { CompositionLocalProvider( - LocalKamelConfig provides kamelConfig + *hooks ) { AppTheme { ReaderMenu(chapterIndex, mangaId, hotkeyFlow) @@ -158,8 +156,8 @@ fun ReaderMenu( mangaId: Long, hotkeyFlow: SharedFlow ) { - val vm = viewModel { - ReaderMenuViewModel.Params(chapterIndex, mangaId) + val vm = viewModel { + instantiate(ReaderMenuViewModel.Params(chapterIndex, mangaId)) } val state by vm.state.collectAsState() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderMenuViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderMenuViewModel.kt index a741de10..11b45bd7 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderMenuViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderMenuViewModel.kt @@ -7,6 +7,8 @@ package ca.gosyer.ui.reader import ca.gosyer.core.lang.throwIfCancellation +import ca.gosyer.core.logging.CKLogger +import ca.gosyer.core.prefs.getAsFlow import ca.gosyer.data.models.Chapter import ca.gosyer.data.models.Manga import ca.gosyer.data.models.MangaMeta @@ -23,8 +25,6 @@ import ca.gosyer.ui.reader.model.PageMove import ca.gosyer.ui.reader.model.ReaderChapter import ca.gosyer.ui.reader.model.ReaderPage import ca.gosyer.ui.reader.model.ViewerChapters -import ca.gosyer.util.system.CKLogger -import ca.gosyer.util.system.getAsFlow import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -39,13 +39,13 @@ import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class ReaderMenuViewModel @Inject constructor( - private val params: Params, private val readerPreferences: ReaderPreferences, private val mangaHandler: MangaInteractionHandler, - private val chapterHandler: ChapterInteractionHandler + private val chapterHandler: ChapterInteractionHandler, + private val params: Params, ) : ViewModel() { private val _manga = MutableStateFlow(null) private val viewerChapters = ViewerChapters( diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderSideMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderSideMenu.kt index 751a8a81..a99fecbc 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderSideMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/reader/ReaderSideMenu.kt @@ -39,15 +39,15 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import ca.gosyer.core.logging.kLogger import ca.gosyer.core.util.replace import ca.gosyer.data.models.Chapter import ca.gosyer.data.models.ChapterMeta import ca.gosyer.data.models.MangaMeta -import ca.gosyer.ui.base.components.Spinner -import dev.icerock.moko.resources.compose.stringResource import ca.gosyer.i18n.MR +import ca.gosyer.ui.base.components.Spinner import ca.gosyer.ui.reader.model.ReaderChapter -import ca.gosyer.util.system.kLogger +import dev.icerock.moko.resources.compose.stringResource import kotlin.math.roundToInt import kotlin.time.Duration.Companion.milliseconds diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/reader/loader/TachideskPageLoader.kt b/desktop/src/main/kotlin/ca/gosyer/ui/reader/loader/TachideskPageLoader.kt index 04a952a5..8ea987f0 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/reader/loader/TachideskPageLoader.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/reader/loader/TachideskPageLoader.kt @@ -7,11 +7,12 @@ package ca.gosyer.ui.reader.loader import ca.gosyer.core.lang.throwIfCancellation +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.reader.ReaderPreferences import ca.gosyer.data.server.interactions.ChapterInteractionHandler import ca.gosyer.ui.reader.model.ReaderChapter import ca.gosyer.ui.reader.model.ReaderPage -import ca.gosyer.util.system.CKLogger +import ca.gosyer.util.compose.toImageBitmap import io.github.kerubistan.kroki.coroutines.priorityChannel import io.ktor.client.features.onDownload import kotlinx.coroutines.CoroutineScope @@ -62,7 +63,7 @@ class TachideskPageLoader( onDownload { bytesSentTotal, contentLength -> page.progress.value = (bytesSentTotal.toFloat() / contentLength).coerceAtMost(1.0F) } - } + }.toImageBitmap() page.status.value = ReaderPage.Status.READY page.error.value = null } catch (e: Exception) { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/reader/model/ReaderChapter.kt b/desktop/src/main/kotlin/ca/gosyer/ui/reader/model/ReaderChapter.kt index 46169122..3ba883fa 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/reader/model/ReaderChapter.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/reader/model/ReaderChapter.kt @@ -6,9 +6,9 @@ package ca.gosyer.ui.reader.model +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.models.Chapter import ca.gosyer.ui.reader.loader.PageLoader -import ca.gosyer.util.system.CKLogger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsAdvancedScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsAdvancedScreen.kt index 5f876ce2..518c28a7 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsAdvancedScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsAdvancedScreen.kt @@ -20,14 +20,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import ca.gosyer.data.update.UpdatePreferences +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import ca.gosyer.ui.base.prefs.SwitchPreference -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.ViewModel import ca.gosyer.ui.base.vm.viewModel -import javax.inject.Inject +import dev.icerock.moko.resources.compose.stringResource +import me.tatarka.inject.annotations.Inject class SettingsAdvancedViewModel @Inject constructor( updatePreferences: UpdatePreferences, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsAppearanceScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsAppearanceScreen.kt index bc8567c4..8086cbf6 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsAppearanceScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsAppearanceScreen.kt @@ -36,13 +36,12 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import ca.gosyer.data.ui.UiPreferences import ca.gosyer.data.ui.model.ThemeMode +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import ca.gosyer.ui.base.prefs.ChoicePreference import ca.gosyer.ui.base.prefs.ColorPreference import ca.gosyer.ui.base.prefs.SwitchPreference -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.theme.AppColorsPreferenceState import ca.gosyer.ui.base.theme.Theme import ca.gosyer.ui.base.theme.asStateFlow @@ -51,7 +50,8 @@ import ca.gosyer.ui.base.theme.getLightColors import ca.gosyer.ui.base.theme.themes import ca.gosyer.ui.base.vm.ViewModel import ca.gosyer.ui.base.vm.viewModel -import javax.inject.Inject +import dev.icerock.moko.resources.compose.stringResource +import me.tatarka.inject.annotations.Inject class ThemesViewModel @Inject constructor( private val uiPreferences: UiPreferences, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsBackupScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsBackupScreen.kt index a6ad7ba8..3366e673 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsBackupScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsBackupScreen.kt @@ -32,33 +32,35 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import ca.gosyer.core.io.copyTo import ca.gosyer.core.lang.throwIfCancellation +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.server.interactions.BackupInteractionHandler +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.WindowDialog import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import ca.gosyer.ui.base.prefs.PreferenceRow -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.ViewModel import ca.gosyer.ui.base.vm.viewModel -import ca.gosyer.util.system.CKLogger import ca.gosyer.util.system.filePicker import ca.gosyer.util.system.fileSaver +import dev.icerock.moko.resources.compose.stringResource import io.ktor.client.features.onDownload import io.ktor.client.features.onUpload import io.ktor.http.isSuccess -import io.ktor.utils.io.jvm.javaio.copyTo +import io.ktor.utils.io.jvm.javaio.toInputStream import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import java.nio.file.Path -import javax.inject.Inject -import kotlin.io.path.absolutePathString -import kotlin.io.path.notExists -import kotlin.io.path.outputStream +import me.tatarka.inject.annotations.Inject +import okio.FileSystem +import okio.Path +import okio.Path.Companion.toOkioPath +import okio.buffer +import okio.source class SettingsBackupViewModel @Inject constructor( private val backupHandler: BackupInteractionHandler @@ -83,8 +85,8 @@ class SettingsBackupViewModel @Inject constructor( fun restoreFile(file: Path?) { scope.launch { - if (file == null || file.notExists()) { - info { "Invalid file ${file?.absolutePathString()}" } + if (file == null || !FileSystem.SYSTEM.exists(file)) { + info { "Invalid file ${file?.toString()}" } _restoreStatus.value = Status.Error _restoring.value = false } else { @@ -154,9 +156,11 @@ class SettingsBackupViewModel @Inject constructor( (backup.headers["content-disposition"]?.substringAfter("filename=")?.trim('"') ?: "backup") to { scope.launch { try { - it.outputStream().use { - backup.content.copyTo(it) - } + backup.content.toInputStream() + .source() + .copyTo( + FileSystem.SYSTEM.sink(it).buffer() + ) _creatingStatus.value = Status.Success } catch (e: Exception) { e.throwIfCancellation() @@ -199,7 +203,7 @@ fun SettingsBackupScreen(menuController: MenuController) { launch { vm.createFlow.collect { (filename, function) -> fileSaver(filename, "proto.gz") { - function(it.selectedFile.toPath()) + function(it.selectedFile.toOkioPath()) } } } @@ -219,7 +223,7 @@ fun SettingsBackupScreen(menuController: MenuController) { restoreStatus ) { filePicker("gz") { - vm.restoreFile(it.selectedFile.toPath()) + vm.restoreFile(it.selectedFile.toOkioPath()) } } PreferenceFile( diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsDownloadsScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsDownloadsScreen.kt index 6fc8c9b6..ba579fa4 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsDownloadsScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsDownloadsScreen.kt @@ -19,10 +19,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR @Composable fun SettingsDownloadsScreen(menuController: MenuController) { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsGeneralScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsGeneralScreen.kt index e675e2f5..e1e69b79 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsGeneralScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsGeneralScreen.kt @@ -31,12 +31,12 @@ import ca.gosyer.ui.base.prefs.SwitchPreference import ca.gosyer.ui.base.vm.ViewModel import ca.gosyer.ui.base.vm.viewModel import dev.icerock.moko.resources.compose.stringResource +import me.tatarka.inject.annotations.Inject import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.format.FormatStyle import java.util.Locale -import javax.inject.Inject class SettingsGeneralViewModel @Inject constructor( uiPreferences: UiPreferences, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsLibraryScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsLibraryScreen.kt index f2ec84b2..ddfcdf39 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsLibraryScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsLibraryScreen.kt @@ -22,19 +22,19 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import ca.gosyer.data.library.LibraryPreferences import ca.gosyer.data.server.interactions.CategoryInteractionHandler +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import ca.gosyer.ui.base.prefs.PreferenceRow import ca.gosyer.ui.base.prefs.SwitchPreference -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.ViewModel import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.ui.categories.openCategoriesMenu +import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class SettingsLibraryViewModel @Inject constructor( libraryPreferences: LibraryPreferences, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsParentalControlsScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsParentalControlsScreen.kt index 43c460d9..64180521 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsParentalControlsScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsParentalControlsScreen.kt @@ -19,10 +19,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR @Composable fun SettingsParentalControlsScreen(menuController: MenuController) { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsReaderScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsReaderScreen.kt index 2a307672..68839849 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsReaderScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsReaderScreen.kt @@ -44,7 +44,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class SettingsReaderViewModel @Inject constructor( readerPreferences: ReaderPreferences diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsScreen.kt index 35fab212..4abf1302 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsScreen.kt @@ -28,12 +28,12 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import ca.gosyer.ui.base.prefs.PreferenceRow -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.main.Routes +import dev.icerock.moko.resources.compose.stringResource @Composable fun SettingsScreen(menuController: MenuController) { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsSecurityScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsSecurityScreen.kt index 99ef72cc..54f0915f 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsSecurityScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsSecurityScreen.kt @@ -19,10 +19,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR @Composable fun SettingsSecurityScreen(menuController: MenuController) { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsServerScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsServerScreen.kt index 24680f04..c83c6eb0 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsServerScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsServerScreen.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.unit.dp +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.server.ServerHostPreferences import ca.gosyer.data.server.ServerPreferences import ca.gosyer.data.server.ServerService @@ -43,13 +44,12 @@ import ca.gosyer.ui.base.prefs.asStateIn import ca.gosyer.ui.base.prefs.asStringStateIn import ca.gosyer.ui.base.vm.ViewModel import ca.gosyer.ui.base.vm.viewModel -import ca.gosyer.util.system.CKLogger import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class SettingsServerViewModel @Inject constructor( serverPreferences: ServerPreferences, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsTrackingScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsTrackingScreen.kt index a90a10c8..aff021ee 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsTrackingScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/settings/SettingsTrackingScreen.kt @@ -19,10 +19,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.MenuController import ca.gosyer.ui.base.components.Toolbar import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR @Composable fun SettingsTrackingScreen(menuController: MenuController) { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenu.kt index a1a27515..db40bac2 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenu.kt @@ -38,12 +38,11 @@ import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp -import ca.gosyer.build.BuildConfig import ca.gosyer.data.models.Source +import ca.gosyer.desktop.build.BuildConfig +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.KamelImage import ca.gosyer.ui.base.components.combinedMouseClickable -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.ui.manga.openMangaMenu import ca.gosyer.ui.sources.components.SourceHomeScreen @@ -54,6 +53,7 @@ import ca.gosyer.util.lang.launchApplication import com.github.zsoltk.compose.savedinstancestate.Bundle import com.github.zsoltk.compose.savedinstancestate.BundleScope import com.github.zsoltk.compose.savedinstancestate.LocalSavedInstanceState +import dev.icerock.moko.resources.compose.stringResource import io.kamel.image.lazyPainterResource import kotlinx.coroutines.DelicateCoroutinesApi @@ -82,8 +82,8 @@ fun SourcesMenu(onSourceSettingsClick: (Long) -> Unit, onMangaClick: (Long) -> U @Composable fun SourcesMenu(bundle: Bundle, onSourceSettingsClick: (Long) -> Unit, onMangaClick: (Long) -> Unit) { - val vm = viewModel { - bundle + val vm = viewModel { + instantiate(bundle) } val sourceTabs by vm.sourceTabs.collectAsState() val selectedSourceTab by vm.selectedSourceTab.collectAsState() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenuViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenuViewModel.kt index 01b1cc0b..fa73c545 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenuViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenuViewModel.kt @@ -6,16 +6,16 @@ package ca.gosyer.ui.sources +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.models.Source import ca.gosyer.ui.base.vm.ViewModel -import ca.gosyer.util.system.CKLogger import com.github.zsoltk.compose.savedinstancestate.Bundle import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class SourcesMenuViewModel @Inject constructor( private val bundle: Bundle diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreen.kt index 1a527f1a..bcfc5ba3 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreen.kt @@ -42,15 +42,15 @@ import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import ca.gosyer.data.models.Source +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.KamelImage import ca.gosyer.ui.base.components.LoadingScreen import ca.gosyer.ui.base.components.TextActionIcon import ca.gosyer.ui.base.components.Toolbar -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.ui.extensions.LanguageDialog import com.github.zsoltk.compose.savedinstancestate.Bundle +import dev.icerock.moko.resources.compose.stringResource import io.kamel.image.lazyPainterResource import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -61,8 +61,8 @@ fun SourceHomeScreen( onAddSource: (Source) -> Unit, onLoadSources: (List) -> Unit ) { - val vm = viewModel { - bundle + val vm = viewModel { + instantiate(bundle) } val sources by vm.sources.collectAsState() val isLoading by vm.isLoading.collectAsState() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreenViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreenViewModel.kt index 96ccc080..1b3a92e7 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreenViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreenViewModel.kt @@ -7,21 +7,21 @@ package ca.gosyer.ui.sources.components import ca.gosyer.core.lang.throwIfCancellation +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.catalog.CatalogPreferences import ca.gosyer.data.models.Source import ca.gosyer.data.server.interactions.SourceInteractionHandler import ca.gosyer.ui.base.vm.ViewModel -import ca.gosyer.util.system.CKLogger import com.github.zsoltk.compose.savedinstancestate.Bundle import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class SourceHomeScreenViewModel @Inject constructor( - private val bundle: Bundle, private val sourceHandler: SourceInteractionHandler, - catalogPreferences: CatalogPreferences + catalogPreferences: CatalogPreferences, + private val bundle: Bundle, ) : ViewModel() { private val _isLoading = MutableStateFlow(true) val isLoading = _isLoading.asStateFlow() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceScreen.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceScreen.kt index 0a47cf20..14600ea4 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceScreen.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceScreen.kt @@ -51,8 +51,8 @@ fun SourceScreen( onCloseSourceTabClick: (Source) -> Unit, onSourceSettingsClick: (Long) -> Unit ) { - val vm = viewModel(source.id) { - SourceScreenViewModel.Params(source, bundle) + val vm = viewModel(source.id) { + instantiate(SourceScreenViewModel.Params(source, bundle)) } val mangas by vm.mangas.collectAsState() val hasNextPage by vm.hasNextPage.collectAsState() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceScreenViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceScreenViewModel.kt index 317224cd..e32a3637 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceScreenViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/SourceScreenViewModel.kt @@ -20,7 +20,7 @@ import com.github.zsoltk.compose.savedinstancestate.Bundle import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class SourceScreenViewModel( private val source: Source, @@ -29,8 +29,8 @@ class SourceScreenViewModel( ) : ViewModel() { @Inject constructor( - params: Params, - sourceHandler: SourceInteractionHandler + sourceHandler: SourceInteractionHandler, + params: Params ) : this( params.source, params.bundle, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/filter/SourceFiltersMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/filter/SourceFiltersMenu.kt index ed6b3c9c..9e2c250b 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/filter/SourceFiltersMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/filter/SourceFiltersMenu.kt @@ -65,14 +65,14 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import ca.gosyer.data.models.sourcefilters.SortFilter +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.Spinner import ca.gosyer.ui.base.prefs.ExpandablePreference -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.ui.sources.components.filter.model.SourceFiltersView import ca.gosyer.util.compose.persistentLazyListState import com.github.zsoltk.compose.savedinstancestate.Bundle +import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.launch @@ -86,8 +86,8 @@ fun SourceFiltersMenu( onResetClicked: () -> Unit, showFiltersButton: (Boolean) -> Unit ) { - val vm = viewModel(sourceId) { - SourceFiltersViewModel.Params(bundle, sourceId) + val vm = viewModel(sourceId) { + instantiate(SourceFiltersViewModel.Params(bundle, sourceId)) } val filters by vm.filters.collectAsState() DisposableEffect(filters) { diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/filter/SourceFiltersViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/filter/SourceFiltersViewModel.kt index b7d87b40..8d79bfa3 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/filter/SourceFiltersViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/components/filter/SourceFiltersViewModel.kt @@ -7,11 +7,11 @@ package ca.gosyer.ui.sources.components.filter import ca.gosyer.core.lang.throwIfCancellation +import ca.gosyer.core.logging.CKLogger import ca.gosyer.data.models.sourcefilters.SourceFilter import ca.gosyer.data.server.interactions.SourceInteractionHandler import ca.gosyer.ui.base.vm.ViewModel import ca.gosyer.ui.sources.components.filter.model.SourceFiltersView -import ca.gosyer.util.system.CKLogger import com.github.zsoltk.compose.savedinstancestate.Bundle import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableSharedFlow @@ -23,8 +23,8 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import me.tatarka.inject.annotations.Inject import java.util.concurrent.CopyOnWriteArrayList -import javax.inject.Inject class SourceFiltersViewModel( private val bundle: Bundle, @@ -32,8 +32,8 @@ class SourceFiltersViewModel( private val sourceHandler: SourceInteractionHandler ) : ViewModel() { @Inject constructor( + sourceHandler: SourceInteractionHandler, params: Params, - sourceHandler: SourceInteractionHandler ) : this( params.bundle, params.sourceId, diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/settings/SourceSettingsMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/settings/SourceSettingsMenu.kt index fa6c698a..8a4b8633 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/settings/SourceSettingsMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/settings/SourceSettingsMenu.kt @@ -30,7 +30,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp -import ca.gosyer.build.BuildConfig +import ca.gosyer.desktop.build.BuildConfig +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.WindowDialog import ca.gosyer.ui.base.components.LocalMenuController import ca.gosyer.ui.base.components.MenuController @@ -38,8 +39,6 @@ import ca.gosyer.ui.base.components.Toolbar import ca.gosyer.ui.base.prefs.ChoiceDialog import ca.gosyer.ui.base.prefs.MultiSelectDialog import ca.gosyer.ui.base.prefs.PreferenceRow -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel import ca.gosyer.ui.sources.settings.model.SourceSettingsView.CheckBox import ca.gosyer.ui.sources.settings.model.SourceSettingsView.EditText @@ -49,6 +48,7 @@ import ca.gosyer.ui.sources.settings.model.SourceSettingsView.Switch import ca.gosyer.ui.sources.settings.model.SourceSettingsView.TwoState import ca.gosyer.util.compose.ThemedWindow import ca.gosyer.util.lang.launchApplication +import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow @@ -63,8 +63,8 @@ fun openSourceSettingsMenu(sourceId: Long) { @Composable fun SourceSettingsMenu(sourceId: Long, menuController: MenuController? = LocalMenuController.current) { - val vm = viewModel { - SourceSettingsViewModel.Params(sourceId) + val vm = viewModel { + instantiate(SourceSettingsViewModel.Params(sourceId)) } val settings by vm.sourceSettings.collectAsState() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/sources/settings/SourceSettingsViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/sources/settings/SourceSettingsViewModel.kt index c7683bbb..a3b75db3 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/sources/settings/SourceSettingsViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/sources/settings/SourceSettingsViewModel.kt @@ -19,12 +19,12 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import me.tatarka.inject.annotations.Inject import java.util.concurrent.CopyOnWriteArrayList -import javax.inject.Inject class SourceSettingsViewModel @Inject constructor( - private val params: Params, - private val sourceHandler: SourceInteractionHandler + private val sourceHandler: SourceInteractionHandler, + private val params: Params ) : ViewModel() { private val _loading = MutableStateFlow(true) val loading = _loading.asStateFlow() diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/updates/UpdatesMenu.kt b/desktop/src/main/kotlin/ca/gosyer/ui/updates/UpdatesMenu.kt index 42059471..bb4d31da 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/updates/UpdatesMenu.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/updates/UpdatesMenu.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import ca.gosyer.data.models.Chapter +import ca.gosyer.i18n.MR import ca.gosyer.ui.base.components.ChapterDownloadIcon import ca.gosyer.ui.base.components.ChapterDownloadItem import ca.gosyer.ui.base.components.LoadingScreen @@ -43,9 +44,8 @@ import ca.gosyer.ui.base.components.MangaListItemSubtitle import ca.gosyer.ui.base.components.MangaListItemTitle import ca.gosyer.ui.base.components.Toolbar import ca.gosyer.ui.base.components.mangaAspectRatio -import dev.icerock.moko.resources.compose.stringResource -import ca.gosyer.i18n.MR import ca.gosyer.ui.base.vm.viewModel +import dev.icerock.moko.resources.compose.stringResource import io.kamel.image.lazyPainterResource @Composable diff --git a/desktop/src/main/kotlin/ca/gosyer/ui/updates/UpdatesMenuViewModel.kt b/desktop/src/main/kotlin/ca/gosyer/ui/updates/UpdatesMenuViewModel.kt index 31e69f7e..1c26886c 100644 --- a/desktop/src/main/kotlin/ca/gosyer/ui/updates/UpdatesMenuViewModel.kt +++ b/desktop/src/main/kotlin/ca/gosyer/ui/updates/UpdatesMenuViewModel.kt @@ -20,7 +20,7 @@ import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex -import javax.inject.Inject +import me.tatarka.inject.annotations.Inject class UpdatesMenuViewModel @Inject constructor( private val chapterHandler: ChapterInteractionHandler, diff --git a/desktop/src/main/kotlin/ca/gosyer/util/compose/Image.kt b/desktop/src/main/kotlin/ca/gosyer/util/compose/Image.kt index 8faf56ac..ec298ab4 100644 --- a/desktop/src/main/kotlin/ca/gosyer/util/compose/Image.kt +++ b/desktop/src/main/kotlin/ca/gosyer/util/compose/Image.kt @@ -23,8 +23,12 @@ fun imageFromFile(file: Path): ImageBitmap { } suspend fun imageFromUrl(client: Http, url: String, block: HttpRequestBuilder.() -> Unit): ImageBitmap { + return client.get(url, block).toImageBitmap() +} + +suspend fun ByteReadChannel.toImageBitmap(): ImageBitmap { val bytes = ByteArrayOutputStream().use { - client.get(url, block).copyTo(it) + this.copyTo(it) it.toByteArray() } return Image.makeFromEncoded(bytes).toComposeImageBitmap() diff --git a/desktop/src/main/kotlin/ca/gosyer/util/compose/WindowGet.kt b/desktop/src/main/kotlin/ca/gosyer/util/compose/WindowGet.kt new file mode 100644 index 00000000..bc7bb960 --- /dev/null +++ b/desktop/src/main/kotlin/ca/gosyer/util/compose/WindowGet.kt @@ -0,0 +1,52 @@ +/* + * 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.util.compose + +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.WindowPlacement +import androidx.compose.ui.window.WindowPosition +import ca.gosyer.data.ui.model.WindowSettings + +data class WindowGet( + val offset: WindowPosition, + val size: DpSize, + val placement: WindowPlacement +) { + companion object { + fun from(windowSettings: WindowSettings): WindowGet { + return with(windowSettings) { + // Maximize and Fullscreen messes with the other parameters so set them to default + if (maximized == true) { + return WindowGet( + WindowPosition.PlatformDefault, + DpSize(800.dp, 600.dp), + WindowPlacement.Maximized + ) + } else if (fullscreen == true) { + return WindowGet( + WindowPosition.PlatformDefault, + DpSize(800.dp, 600.dp), + WindowPlacement.Fullscreen + ) + } + + val offset = if (x != null && y != null) { + WindowPosition(x!!.dp, y!!.dp) + } else { + WindowPosition.PlatformDefault + } + val size = DpSize((width ?: 800).dp, (height ?: 600).dp) + WindowGet( + offset, + size, + WindowPlacement.Floating + ) + } + } + } +} diff --git a/desktop/src/main/kotlin/ca/gosyer/util/system/File.kt b/desktop/src/main/kotlin/ca/gosyer/util/system/File.kt index 42a1fb90..0b8276ee 100644 --- a/desktop/src/main/kotlin/ca/gosyer/util/system/File.kt +++ b/desktop/src/main/kotlin/ca/gosyer/util/system/File.kt @@ -6,32 +6,11 @@ package ca.gosyer.util.system -import ca.gosyer.build.BuildConfig import ca.gosyer.core.lang.launchUI import kotlinx.coroutines.DelicateCoroutinesApi -import mu.KotlinLogging -import net.harawata.appdirs.AppDirs -import net.harawata.appdirs.AppDirsFactory -import java.nio.file.Path import javax.swing.JFileChooser import javax.swing.filechooser.FileNameExtensionFilter import kotlin.io.path.Path -import kotlin.io.path.createDirectories -import kotlin.io.path.exists - -private val logger = KotlinLogging.logger {} - -val appDirs: AppDirs by lazy { - AppDirsFactory.getInstance() -} - -val userDataDir: Path by lazy { - Path(appDirs.getUserDataDir(BuildConfig.NAME, null, null)).also { - if (!it.exists()) { - logger.info("Attempted to create app data dir, result: {}", it.createDirectories()) - } - } -} fun filePicker( vararg extensions: String, diff --git a/desktop/src/main/kotlin/ca/gosyer/util/system/Preference.kt b/desktop/src/main/kotlin/ca/gosyer/util/system/Preference.kt deleted file mode 100644 index 99d3391c..00000000 --- a/desktop/src/main/kotlin/ca/gosyer/util/system/Preference.kt +++ /dev/null @@ -1,20 +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.util.system - -import ca.gosyer.core.prefs.Preference -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.merge -import kotlinx.coroutines.flow.onEach - -fun Preference.getAsFlow(action: (suspend (T) -> Unit)? = null): Flow { - val flow = merge(flowOf(get()), changes()) - return if (action != null) { - flow.onEach(action = action) - } else flow -} diff --git a/desktop/src/test/kotlin/ca/gosyer/data/translation/XmlResourceBundleTest.kt b/desktop/src/test/kotlin/ca/gosyer/data/translation/XmlResourceBundleTest.kt deleted file mode 100644 index d886b62d..00000000 --- a/desktop/src/test/kotlin/ca/gosyer/data/translation/XmlResourceBundleTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -package ca.gosyer.data.translation - -import org.junit.Before -import java.io.File -import java.util.Locale -import kotlin.test.Test - -class XmlResourceBundleTest { - - lateinit var rootBundle: XmlResourceBundle - lateinit var bundles: List> - - @Before - fun `load root bundle`() { - rootBundle = XmlResourceBundle.forLocale(Locale.ENGLISH) - val url = XmlResourceBundleTest::class.java.getResource("/values/") - requireNotNull(url) - bundles = requireNotNull( - File(url.toURI()).listFiles()?.mapNotNull { - if (it.name == "values") return@mapNotNull null - it.name.substringAfter("values-") to XmlResourceBundle.forLocale(Locale.forLanguageTag(it.name.substringAfter("values-"))) - } - ) - } - - @Test - fun `test each language parameters`() { - rootBundle.lookup.entries.forEach { (key, value) -> - if (value !is String || !value.contains("[^\\\\]?%\\d".toRegex())) return@forEach - val testValues: Array = value.split('%').drop(1).map { - when (val char = it[2]) { - 's' -> "Test string" - 'd' -> 69 - 'f' -> 6.9 - else -> { - throw IllegalArgumentException("Unknown value key $char in $key") - } - } - }.toTypedArray() - bundles.forEach { (lang, bundle) -> - try { - bundle.getString(key, *testValues) - } catch (e: Exception) { - throw Exception("Broken translation in $lang with $key", e) - } - } - } - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9899cd84..42f97814 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ kamel = "0.3.0" darklaf = "2.7.3" # Dependency Injection -toothpick = "3.1.0" +kotlinInject = "0.4.1" # Network ktor = "1.6.7" @@ -35,6 +35,7 @@ multiplatformSettings = "0.8.1" # Utility kroki = "1.22" +desugarJdkLibs = "1.1.5" # Localization moko = "0.18.0" @@ -60,8 +61,8 @@ kamel = { module = "com.alialbaali.kamel:kamel-image", version.ref = "kamel" } darklaf = { module = "com.github.weisj:darklaf-core", version.ref = "darklaf" } # Dependency Injection -toothpickKsp = { module = "com.github.stephanenicolas.toothpick:ktp", version.ref = "toothpick" } -toothpickCompiler = { module = "com.github.stephanenicolas.toothpick:toothpick-compiler", version.ref = "toothpick" } +kotlinInjectRuntime = { module = "me.tatarka.inject:kotlin-inject-runtime", version.ref = "kotlinInject" } +kotlinInjectCompiler = { module = "me.tatarka.inject:kotlin-inject-compiler-ksp", version.ref = "kotlinInject" } # Network ktorCore = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } @@ -90,6 +91,7 @@ multiplatformSettingsCoroutines = { module = "com.russhwolf:multiplatform-settin # Utility krokiCoroutines = { module = "io.github.kerubistan.kroki:kroki-coroutines", version.ref = "kroki" } +desugarJdkLibs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugarJdkLibs" } # Localization mokoCore = { module = "dev.icerock.moko:resources", version.ref = "moko" } diff --git a/i18n/build.gradle.kts b/i18n/build.gradle.kts index 3f593ceb..b719430f 100644 --- a/i18n/build.gradle.kts +++ b/i18n/build.gradle.kts @@ -9,7 +9,13 @@ plugins { kotlin { android() - jvm("desktop") + jvm("desktop") { + compilations { + all { + kotlinOptions.jvmTarget = Config.desktopJvmTarget.toString() + } + } + } sourceSets { val commonMain by getting { diff --git a/settings.gradle.kts b/settings.gradle.kts index e8d95f0a..4e1a4194 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,6 +12,7 @@ rootProject.name = "Tachidesk-JUI" include("desktop") include("core") include("i18n") +include("data") enableFeaturePreview("VERSION_CATALOGS")