Multiple module changes and rewrites

- Strings are now in a separate module
- Strings are now using Moko resources
- Rename common module to core
This commit is contained in:
Syer10
2022-01-26 18:30:44 -05:00
parent f7d5a4af5c
commit d2009541e8
139 changed files with 692 additions and 605 deletions

View File

@@ -4,7 +4,7 @@
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-PdebugApp" />
<option name="scriptParameters" value="-PdebugApp --stacktrace" />
<option name="taskDescriptions">
<list />
</option>
@@ -14,6 +14,7 @@
<option value="run" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>

View File

@@ -2,8 +2,11 @@ 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.github.gmazzo.buildconfig") version "3.0.3" 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"
}
@@ -29,3 +32,36 @@ allprojects {
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}
subprojects {
plugins.withType<com.android.build.gradle.BasePlugin> {
configure<com.android.build.gradle.BaseExtension> {
compileSdkVersion(31)
defaultConfig {
minSdk = 21
targetSdk = 31
/*versionCode(Config.versionCode)
versionName(Config.versionName)
ndk {
version = Config.ndk
}*/
}
compileOptions {
//isCoreLibraryDesugaringEnabled = true
sourceCompatibility(JavaVersion.VERSION_11)
targetCompatibility(JavaVersion.VERSION_11)
}
sourceSets {
named("main") {
val altManifest = file("src/androidMain/AndroidManifest.xml")
if (altManifest.exists()) {
manifest.srcFile(altManifest.path)
}
}
}
dependencies {
//add("coreLibraryDesugaring", Deps.desugarJdkLibs)
}
}
}
}

91
core/build.gradle.kts Normal file
View File

@@ -0,0 +1,91 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile as KotlinJvmCompile
plugins {
kotlin("multiplatform")
kotlin("kapt")
id("com.android.library")
}
group = "ca.gosyer"
version = "1.2.1"
repositories {
mavenCentral()
}
kotlin {
android()
jvm("desktop")
sourceSets {
all {
languageSettings {
optIn("kotlin.RequiresOptIn")
optIn("kotlinx.serialization.ExperimentalSerializationApi")
optIn("com.russhwolf.settings.ExperimentalSettingsApi")
optIn("com.russhwolf.settings.ExperimentalSettingsImplementation")
}
}
val commonMain by getting {
dependencies {
api(kotlin("stdlib-common"))
api(libs.coroutinesCore)
api(libs.json)
api(libs.toothpickKsp)
api(libs.ktorCore)
api(libs.ktorSerialization)
api(libs.okio)
api(libs.multiplatformSettingsCore)
api(libs.multiplatformSettingsCoroutines)
api(libs.multiplatformSettingsSerialization)
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val desktopMain by getting {
kotlin.srcDir("src/jvmMain/kotlin")
dependencies {
api(kotlin("stdlib-jdk8"))
}
}
val desktopTest by getting {
kotlin.srcDir("src/jvmTest/kotlin")
}
val androidMain by getting {
kotlin.srcDir("src/jvmMain/kotlin")
dependencies {
api(kotlin("stdlib-jdk8"))
}
}
val androidTest by getting {
kotlin.srcDir("src/jvmTest/kotlin")
}
}
}
dependencies {
add("kapt", libs.toothpickCompiler)
}
tasks {
withType<KotlinJvmCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjvm-default=compatibility")
}
}
}
android {
compileSdk = 31
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
targetSdk = 31
}
}

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="ca.gosyer.core"/>

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.prefs
package ca.gosyer.core.prefs
import kotlinx.serialization.KSerializer
import kotlinx.serialization.modules.SerializersModule

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.prefs
package ca.gosyer.core.prefs
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.prefs
package ca.gosyer.core.prefs
import kotlinx.serialization.KSerializer
import kotlinx.serialization.modules.EmptySerializersModule

View File

@@ -6,7 +6,6 @@
package ca.gosyer.core.prefs
import ca.gosyer.common.prefs.Preference
import com.russhwolf.settings.ObservableSettings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose

View File

@@ -6,8 +6,6 @@
package ca.gosyer.core.prefs
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import com.russhwolf.settings.ObservableSettings
import kotlinx.serialization.KSerializer
import kotlinx.serialization.modules.SerializersModule

View File

@@ -6,7 +6,6 @@
package ca.gosyer.core.prefs
import ca.gosyer.common.prefs.PreferenceStore
import com.russhwolf.settings.JvmPreferencesSettings
import java.util.prefs.Preferences

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.di
package ca.gosyer.core.di
import toothpick.Scope
import toothpick.ktp.KTP

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.di
package ca.gosyer.core.di
import toothpick.Scope
import javax.inject.Provider

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.di
package ca.gosyer.core.di
import toothpick.config.Module

View File

@@ -4,9 +4,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.io
package ca.gosyer.core.io
import ca.gosyer.common.util.decodeBase64
import ca.gosyer.core.util.decodeBase64
import okio.Buffer
import okio.Source
import okio.Timeout

View File

@@ -4,13 +4,14 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.io
package ca.gosyer.core.io
import ca.gosyer.util.lang.withIOContext
import ca.gosyer.core.lang.withIOContext
import okio.BufferedSink
import okio.Source
import okio.buffer
import okio.sink
import okio.use
import java.nio.file.Path
suspend fun Source.saveTo(path: Path) {

View File

@@ -0,0 +1,71 @@
/*
* 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.lang
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@DelicateCoroutinesApi
fun launch(
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) = GlobalScope.launch(Dispatchers.Default, start, block)
@DelicateCoroutinesApi
fun launchUI(
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) = GlobalScope.launch(Dispatchers.Main, start, block)
@DelicateCoroutinesApi
fun launchIO(
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) = GlobalScope.launch(Dispatchers.IO, start, block)
fun CoroutineScope.launchDefault(
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) = launch(Dispatchers.Default, start, block)
fun CoroutineScope.launchUI(
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) = launch(Dispatchers.Main, start, block)
fun CoroutineScope.launchIO(
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) = launch(Dispatchers.IO, start, block)
suspend fun <T> withDefaultContext(
block: suspend CoroutineScope.() -> T
): T = withContext(Dispatchers.Default, block)
suspend fun <T> withUIContext(
block: suspend CoroutineScope.() -> T
): T = withContext(Dispatchers.Main, block)
suspend fun <T> withIOContext(
block: suspend CoroutineScope.() -> T
): T = withContext(Dispatchers.IO, block)
fun Throwable.throwIfCancellation() { if (this is CancellationException) throw this }
fun <T> Result<T>.throwIfCancellation(): Result<T> {
if (isFailure) {
val exception = exceptionOrNull()
if (exception is CancellationException) throw exception
}
return this
}

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.util.lang
package ca.gosyer.core.lang
import java.util.Locale

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.util
package ca.gosyer.core.util
import okio.ByteString.Companion.decodeBase64
import okio.ByteString.Companion.encode

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.util
package ca.gosyer.core.util
/**
* Returns a new list that replaces the item at the given [position] with [newItem].

View File

@@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.common.util
package ca.gosyer.core.util
object ImageUtil {

View File

@@ -8,6 +8,8 @@ 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")
@@ -19,6 +21,9 @@ plugins {
}
dependencies {
implementation(project(":core"))
implementation(project(":i18n"))
// UI (Compose)
implementation(compose.desktop.currentOs)
implementation(compose.uiTooling)
@@ -63,7 +68,8 @@ dependencies {
implementation(libs.log4jSlf4j)
implementation(libs.ktlogging)
// User storage
// Storage
implementation(libs.okio)
implementation(libs.appDirs)
// Preferences
@@ -74,6 +80,10 @@ dependencies {
// Utility
implementation(libs.krokiCoroutines)
// Localization
implementation(libs.mokoCore)
implementation(libs.mokoCompose)
// Testing
testImplementation(kotlin("test-junit"))
testImplementation(compose("org.jetbrains.compose.ui:ui-test-junit4"))
@@ -126,14 +136,13 @@ tasks {
registerTachideskTasks(project)
task("generateResourceConstants") {
val buildResources = buildConfig.forClass(project.group.toString()+ ".build", "BuildResources")
val buildResources = buildConfig.forClass("${project.group}.build", "BuildResources")
doFirst {
val langs = listOf("en") + sourceSets["main"].resources
.filter { it.name == "strings.xml" }
.drop(1)
.map { it.absolutePath.substringAfter("values-").substringBefore(File.separatorChar) }
buildResources.buildConfigField("Array<String>", "LANGUAGES", langs.joinToString(prefix = "arrayOf(", postfix = ")") { it.wrap() })
val langs = listOf("en") + Files.list(rootDir.toPath().resolve("i18n/src/commonMain/resources/MR/values")).asSequence()
.map { it.fileName.toString().replace("-r", "-") }
.toList()
buildResources.buildConfigField("ca.gosyer.i18n.StringList", "LANGUAGES", langs.joinToString(prefix = "listOf(", postfix = ")") { it.wrap() })
}
generateBuildConfig {
@@ -176,6 +185,8 @@ compose.desktop {
mainClass = "ca.gosyer.ui.main.MainKt"
nativeDistributions {
targetFormats(
// All
TargetFormat.AppImage,
// Windows
TargetFormat.Msi,
TargetFormat.Exe,
@@ -228,7 +239,7 @@ buildConfig {
packageName(project.group.toString() + ".build")
useKotlinOutput { internalVisibility = true }
buildConfigField("String", "NAME", project.name.wrap())
buildConfigField("String", "NAME", rootProject.name.wrap())
buildConfigField("String", "VERSION", project.version.toString().wrap())
buildConfigField("int", "MIGRATION_CODE", migrationCode.toString())
buildConfigField("boolean", "DEBUG", project.hasProperty("debugApp").toString())

View File

@@ -7,9 +7,9 @@
package ca.gosyer.core.service
import ca.gosyer.build.BuildConfig
import ca.gosyer.core.lang.throwIfCancellation
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
import ca.gosyer.util.lang.throwIfCancellation
import ca.gosyer.util.system.CKLogger
import io.ktor.client.features.websocket.ws
import io.ktor.http.cio.websocket.Frame

View File

@@ -29,8 +29,6 @@ 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.translation.ResourceProvider
import ca.gosyer.data.translation.XmlResourceBundle
import ca.gosyer.data.ui.UiPreferences
import ca.gosyer.data.update.UpdateChecker
import ca.gosyer.data.update.UpdatePreferences
@@ -85,10 +83,6 @@ val DataModule = module {
.toProvider(KamelConfigProvider::class)
.providesSingleton()
bind<XmlResourceBundle>()
.toProvider(ResourceProvider::class)
.providesSingleton()
bind<BackupInteractionHandler>()
.toClass<BackupInteractionHandler>()
bind<CategoryInteractionHandler>()

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.catalog
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import java.util.Locale
class CatalogPreferences(private val preferenceStore: PreferenceStore) {

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.extension
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import java.util.Locale
class ExtensionPreferences(private val preferenceStore: PreferenceStore) {

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.library
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import ca.gosyer.data.library.model.DisplayMode
class LibraryPreferences(private val preferenceStore: PreferenceStore) {

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.migration
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
class MigrationPreferences(private val preferenceStore: PreferenceStore) {
fun version(): Preference<Int> {

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.reader
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import ca.gosyer.data.reader.model.DefaultReaderMode
import ca.gosyer.data.reader.model.Direction
import ca.gosyer.data.reader.model.ImageScale

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.reader
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import ca.gosyer.data.reader.model.DefaultReaderMode
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.serializer

View File

@@ -6,12 +6,15 @@
package ca.gosyer.data.reader.model
import ca.gosyer.i18n.MR
import dev.icerock.moko.resources.StringResource
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
@Serializable
enum class Direction(val res: String) {
Down("dir_down"),
Left("dir_rtl"),
Right("dir_ltr"),
Up("dir_up")
enum class Direction(@Transient val res: StringResource) {
Down(MR.strings.dir_down),
Left(MR.strings.dir_rtl),
Right(MR.strings.dir_ltr),
Up(MR.strings.dir_up)
}

View File

@@ -6,14 +6,17 @@
package ca.gosyer.data.reader.model
import ca.gosyer.i18n.MR
import dev.icerock.moko.resources.StringResource
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
@Serializable
enum class ImageScale(val res: String) {
FitScreen("scale_fit_screen"),
Stretch("scale_stretch"),
FitWidth("scale_fit_width"),
FitHeight("scale_fit_height"),
OriginalSize("scale_original"),
SmartFit("scale_smart"),
enum class ImageScale(@Transient val res: StringResource) {
FitScreen(MR.strings.scale_fit_screen),
Stretch(MR.strings.scale_stretch),
FitWidth(MR.strings.scale_fit_width),
FitHeight(MR.strings.scale_fit_height),
OriginalSize(MR.strings.scale_original),
SmartFit(MR.strings.scale_smart),
}

View File

@@ -6,12 +6,15 @@
package ca.gosyer.data.reader.model
import ca.gosyer.i18n.MR
import dev.icerock.moko.resources.StringResource
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
@Serializable
enum class NavigationMode(val res: String) {
LNavigation("nav_l_shaped"),
KindlishNavigation("nav_kindle_ish"),
EdgeNavigation("nav_edge"),
RightAndLeftNavigation("nav_left_right"),
enum class NavigationMode(@Transient val res: StringResource) {
LNavigation(MR.strings.nav_l_shaped),
KindlishNavigation(MR.strings.nav_kindle_ish),
EdgeNavigation(MR.strings.nav_edge),
RightAndLeftNavigation(MR.strings.nav_left_right),
}

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.server
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import ca.gosyer.data.server.host.ServerHostPreference
class ServerHostPreferences(preferenceStore: PreferenceStore) {

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.server
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import ca.gosyer.data.server.model.Auth
import ca.gosyer.data.server.model.Proxy

View File

@@ -7,7 +7,7 @@
package ca.gosyer.data.server
import ca.gosyer.build.BuildConfig
import ca.gosyer.util.lang.withIOContext
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.util.system.CKLogger
import ca.gosyer.util.system.userDataDir
import kotlinx.coroutines.CoroutineExceptionHandler

View File

@@ -6,7 +6,7 @@
package ca.gosyer.data.server
import ca.gosyer.common.prefs.Preference
import ca.gosyer.core.prefs.Preference
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.server.host
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
sealed class ServerHostPreference<T : Any> {
protected abstract val propertyName: String

View File

@@ -6,13 +6,13 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.BackupValidationResult
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
import ca.gosyer.data.server.requests.backupFileExportRequest
import ca.gosyer.data.server.requests.backupFileImportRequest
import ca.gosyer.data.server.requests.validateBackupFileRequest
import ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.forms.formData
import io.ktor.client.request.forms.submitFormWithBinaryData

View File

@@ -6,6 +6,7 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Category
import ca.gosyer.data.models.Manga
import ca.gosyer.data.server.Http
@@ -19,7 +20,6 @@ import ca.gosyer.data.server.requests.getCategoriesQuery
import ca.gosyer.data.server.requests.getMangaCategoriesQuery
import ca.gosyer.data.server.requests.getMangaInCategoryQuery
import ca.gosyer.data.server.requests.removeMangaFromCategoryRequest
import ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.delete
import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.get

View File

@@ -6,6 +6,7 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Chapter
import ca.gosyer.data.models.Manga
import ca.gosyer.data.server.Http
@@ -19,7 +20,6 @@ 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 ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.delete
import io.ktor.client.request.forms.submitForm

View File

@@ -6,12 +6,12 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
import ca.gosyer.data.server.requests.downloadsClearRequest
import ca.gosyer.data.server.requests.downloadsStartRequest
import ca.gosyer.data.server.requests.downloadsStopRequest
import ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import javax.inject.Inject

View File

@@ -6,6 +6,7 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Extension
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
@@ -15,7 +16,6 @@ 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 ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse

View File

@@ -6,12 +6,12 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Manga
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
import ca.gosyer.data.server.requests.addMangaToLibraryQuery
import ca.gosyer.data.server.requests.removeMangaFromLibraryRequest
import ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.delete
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse

View File

@@ -6,6 +6,7 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Manga
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
@@ -13,7 +14,6 @@ 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 ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.get

View File

@@ -6,6 +6,7 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.MangaPage
import ca.gosyer.data.models.Source
import ca.gosyer.data.models.sourcefilters.SourceFilter
@@ -24,7 +25,6 @@ import ca.gosyer.data.server.requests.sourceListQuery
import ca.gosyer.data.server.requests.sourcePopularQuery
import ca.gosyer.data.server.requests.sourceSearchQuery
import ca.gosyer.data.server.requests.updateSourceSettingQuery
import ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.client.request.post

View File

@@ -6,13 +6,13 @@
package ca.gosyer.data.server.interactions
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.models.Category
import ca.gosyer.data.models.Updates
import ca.gosyer.data.server.Http
import ca.gosyer.data.server.ServerPreferences
import ca.gosyer.data.server.requests.fetchUpdatesRequest
import ca.gosyer.data.server.requests.recentUpdatesQuery
import ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.forms.submitForm
import io.ktor.client.request.get
import io.ktor.client.request.post

View File

@@ -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.data.translation
import java.util.Locale
import javax.inject.Inject
import javax.inject.Provider
class ResourceProvider @Inject constructor() : Provider<XmlResourceBundle> {
override fun get(): XmlResourceBundle {
return XmlResourceBundle.forLocale(Locale.getDefault())
}
}

View File

@@ -1,91 +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.translation
import ca.gosyer.data.translation.xml.Resources
import nl.adaptivity.xmlutil.StAXReader
import nl.adaptivity.xmlutil.serialization.XML
import java.io.InputStream
import java.io.Reader
import java.nio.charset.Charset
import java.util.Collections
import java.util.Enumeration
import java.util.Formatter
import java.util.Locale
import java.util.ResourceBundle
import java.util.concurrent.ConcurrentHashMap
class XmlResourceBundle internal constructor(internal val lookup: ConcurrentHashMap<String, Any>) : ResourceBundle() {
constructor(stream: InputStream, charset: Charset = Charsets.UTF_8) : this(
stream.reader(charset)
)
constructor(reader: Reader) : this(
ConcurrentHashMap(
format.decodeFromReader<Resources>(
StAXReader(reader)
).values.associate { it.name to it.value }
)
)
public override fun handleGetObject(key: String): Any? {
return lookup[key]
}
override fun getKeys(): Enumeration<String> {
return Collections.enumeration(keySet())
}
override fun handleKeySet(): Set<String> {
return lookup.keys
}
operator fun plus(other: XmlResourceBundle): XmlResourceBundle {
return XmlResourceBundle(ConcurrentHashMap(lookup + other.lookup))
}
private fun String.replaceAndroid() = replace("\\n", "%n")
fun getStringA(key: String): String {
return Formatter().use {
it.format(getString(key).replaceAndroid())
.toString()
}
}
fun getString(key: String, vararg replacements: Any?): String {
return Formatter().use {
it.format(getString(key).replaceAndroid(), *replacements)
.toString()
}
}
companion object {
private val format by lazy {
XML {
autoPolymorphic = true
indentString = "\t"
}
}
fun forLocale(locale: Locale): XmlResourceBundle {
val classLoader = this::class.java.classLoader
val rootBundle = classLoader.getResourceAsStream("values/values/strings.xml")!!
.use { XmlResourceBundle(it) }
val languageBundle = classLoader.getResourceAsStream("values/values-${locale.toLanguageTag()}/strings.xml")
?.use { XmlResourceBundle(it) }
return if (languageBundle != null) {
rootBundle + languageBundle
} else {
rootBundle
}
}
}
}

View File

@@ -1,14 +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.translation.xml
import kotlinx.serialization.Serializable
import nl.adaptivity.xmlutil.serialization.XmlSerialName
@Serializable
@XmlSerialName("resources", "", "")
data class Resources(val values: List<XmlString>)

View File

@@ -1,21 +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.translation.xml
import kotlinx.serialization.Serializable
import nl.adaptivity.xmlutil.serialization.XmlElement
import nl.adaptivity.xmlutil.serialization.XmlSerialName
import nl.adaptivity.xmlutil.serialization.XmlValue
@Serializable
@XmlSerialName("string", "", "")
data class XmlString(
@XmlElement(false)
val name: String,
@XmlValue(true)
val value: String
)

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.ui
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
import ca.gosyer.data.ui.model.StartScreen
import ca.gosyer.data.ui.model.ThemeMode
import ca.gosyer.data.ui.model.WindowSettings

View File

@@ -7,10 +7,10 @@
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.server.Http
import ca.gosyer.data.update.model.GithubRelease
import ca.gosyer.util.lang.launch
import ca.gosyer.util.lang.withIOContext
import io.ktor.client.request.get
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow

View File

@@ -6,8 +6,8 @@
package ca.gosyer.data.update
import ca.gosyer.common.prefs.Preference
import ca.gosyer.common.prefs.PreferenceStore
import ca.gosyer.core.prefs.Preference
import ca.gosyer.core.prefs.PreferenceStore
class UpdatePreferences(private val preferenceStore: PreferenceStore) {
fun enabled(): Preference<Boolean> {

View File

@@ -35,9 +35,7 @@ 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.common.di.AppScope
import ca.gosyer.data.translation.XmlResourceBundle
import ca.gosyer.ui.base.resources.LocalResources
import ca.gosyer.core.di.AppScope
import ca.gosyer.ui.base.theme.AppTheme
import ca.gosyer.util.lang.launchApplication
import io.kamel.core.config.KamelConfig
@@ -71,7 +69,6 @@ fun WindowDialog(
}
val icon = painterResource("icon.png")
val resources = remember { AppScope.getInstance<XmlResourceBundle>() }
val kamelConfig = remember { AppScope.getInstance<KamelConfig>() }
val windowState = rememberWindowState(size = size, position = WindowPosition(Alignment.Center))
@@ -99,7 +96,6 @@ fun WindowDialog(
alwaysOnTop = forceFocus
) {
CompositionLocalProvider(
LocalResources provides resources,
LocalKamelConfig provides kamelConfig
) {
AppTheme {
@@ -149,7 +145,6 @@ fun WindowDialog(
}
val icon = painterResource("icon.png")
val resources = remember { AppScope.getInstance<XmlResourceBundle>() }
val kamelConfig = remember { AppScope.getInstance<KamelConfig>() }
val windowState = rememberWindowState(size = size, position = WindowPosition.Aligned(Alignment.Center))
@@ -169,7 +164,6 @@ fun WindowDialog(
alwaysOnTop = forceFocus,
) {
CompositionLocalProvider(
LocalResources provides resources,
LocalKamelConfig provides kamelConfig
) {
AppTheme {

View File

@@ -37,7 +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 ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -143,7 +144,7 @@ private fun DownloadingIconButton(downloadChapter: DownloadChapter?, onClick: ()
downloadChapter?.mangaId to downloadChapter?.chapterIndex,
{
DropdownMenuItem(onClick = onClick) {
Text(stringResource("action_cancel"))
Text(stringResource(MR.strings.action_cancel))
}
}
) {
@@ -215,7 +216,7 @@ private fun DownloadedIconButton(chapter: Pair<Long, Int?>, onClick: () -> Unit)
chapter,
{
DropdownMenuItem(onClick = onClick) {
Text(stringResource("action_delete"))
Text(stringResource(MR.strings.action_delete))
}
}
) {

View File

@@ -15,7 +15,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
@Composable
fun LoadingScreen(
@@ -24,7 +25,7 @@ fun LoadingScreen(
/*@FloatRange(from = 0.0, to = 1.0)*/
progress: Float = 0.0F,
errorMessage: String? = null,
retryMessage: String = stringResource("action_retry"),
retryMessage: String = stringResource(MR.strings.action_retry),
retry: (() -> Unit)? = null
) {
BoxWithConstraints(modifier) {

View File

@@ -63,7 +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 ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
@Composable
fun Toolbar(
@@ -120,7 +121,7 @@ fun Toolbar(
Row {
actions()
if (closable) {
TextActionIcon(onClick = onClose, stringResource("action_close"), Icons.Rounded.Close)
TextActionIcon(onClick = onClose, stringResource(MR.strings.action_close), Icons.Rounded.Close)
}
}
}

View File

@@ -8,7 +8,7 @@ package ca.gosyer.ui.base.prefs
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import ca.gosyer.common.prefs.Preference
import ca.gosyer.core.prefs.Preference
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted

View File

@@ -6,7 +6,7 @@
package ca.gosyer.ui.base.prefs
import ca.gosyer.common.prefs.Preference
import ca.gosyer.core.prefs.Preference
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted

View File

@@ -6,7 +6,7 @@
package ca.gosyer.ui.base.prefs
import ca.gosyer.common.prefs.Preference
import ca.gosyer.core.prefs.Preference
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn

View File

@@ -1,30 +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.ui.base.resources
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.compositionLocalOf
import ca.gosyer.data.translation.XmlResourceBundle
val LocalResources: ProvidableCompositionLocal<XmlResourceBundle> =
compositionLocalOf { throw IllegalStateException("resources have not been not initialized") }
@Composable
@ReadOnlyComposable
fun stringResource(key: String): String {
val resources = LocalResources.current
return resources.getStringA(key)
}
@Composable
@ReadOnlyComposable
fun stringResource(key: String, vararg replacements: Any): String {
val resources = LocalResources.current
return resources.getString(key, *replacements)
}

View File

@@ -0,0 +1,32 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package dev.icerock.moko.resources.compose
import androidx.compose.runtime.Composable
import dev.icerock.moko.resources.PluralsResource
import dev.icerock.moko.resources.StringResource
import dev.icerock.moko.resources.desc.Plural
import dev.icerock.moko.resources.desc.PluralFormatted
import dev.icerock.moko.resources.desc.Resource
import dev.icerock.moko.resources.desc.ResourceFormatted
import dev.icerock.moko.resources.desc.StringDesc
@Composable
fun stringResource(resource: StringResource): String =
StringDesc.Resource(resource).localized()
@Composable
fun stringResource(resource: StringResource, vararg args: Any): String =
StringDesc.ResourceFormatted(resource, *args).localized()
@Composable
fun stringResource(resource: PluralsResource, quantity: Int): String =
StringDesc.Plural(resource, quantity).localized()
@Composable
fun stringResource(resource: PluralsResource, quantity: Int, vararg args: Any): String =
StringDesc.PluralFormatted(resource, quantity, *args).localized()

View File

@@ -7,7 +7,7 @@
package ca.gosyer.ui.base.theme
import androidx.compose.ui.graphics.Color
import ca.gosyer.common.prefs.Preference
import ca.gosyer.core.prefs.Preference
import ca.gosyer.data.ui.UiPreferences
import ca.gosyer.ui.base.prefs.PreferenceMutableStateFlow
import ca.gosyer.ui.base.prefs.asColor

View File

@@ -10,7 +10,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisallowComposableCalls
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import ca.gosyer.common.di.AppScope
import ca.gosyer.core.di.AppScope
import toothpick.Toothpick
import toothpick.ktp.binding.module
import toothpick.ktp.extension.getInstance

View File

@@ -6,7 +6,7 @@
package ca.gosyer.ui.base.vm
import ca.gosyer.common.prefs.Preference
import ca.gosyer.core.prefs.Preference
import ca.gosyer.ui.base.prefs.PreferenceMutableStateFlow
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel

View File

@@ -12,8 +12,9 @@ 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.i18n.MR
import ca.gosyer.ui.base.WindowDialog
import ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.flow.MutableStateFlow
fun openRenameDialog(
@@ -54,7 +55,7 @@ fun openDeleteDialog(
},
negativeButtonText = "No"
) {
Text(stringResource("categories_delete_confirm", category.name))
Text(stringResource(MR.strings.categories_delete_confirm, category.name))
}
}

View File

@@ -46,7 +46,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.build.BuildConfig
import ca.gosyer.ui.base.resources.stringResource
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.lang.launchApplication
@@ -114,7 +115,7 @@ fun CategoriesMenu(notifyFinished: (() -> Unit)? = null) {
}
}
ExtendedFloatingActionButton(
text = { Text(text = stringResource("action_add")) },
text = { Text(text = stringResource(MR.strings.action_add)) },
icon = { Icon(imageVector = Icons.Rounded.Add, contentDescription = null) },
modifier = Modifier.align(Alignment.BottomEnd).padding(16.dp),
onClick = {

View File

@@ -6,10 +6,10 @@
package ca.gosyer.ui.categories
import ca.gosyer.core.lang.throwIfCancellation
import ca.gosyer.data.models.Category
import ca.gosyer.data.server.interactions.CategoryInteractionHandler
import ca.gosyer.ui.base.vm.ViewModel
import ca.gosyer.util.lang.throwIfCancellation
import ca.gosyer.util.system.CKLogger
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow

View File

@@ -57,7 +57,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 ca.gosyer.ui.base.resources.stringResource
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
@@ -83,16 +84,16 @@ fun DownloadsMenu(onMangaClick: (Long) -> Unit) {
Column {
Toolbar(
stringResource("location_downloads"),
stringResource(MR.strings.location_downloads),
closable = false,
actions = {
val downloadStatus by vm.downloaderStatus.collectAsState()
if (downloadStatus == DownloaderStatus.Started) {
ActionIcon(onClick = vm::pause, stringResource("action_pause"), Icons.Rounded.Pause)
ActionIcon(onClick = vm::pause, stringResource(MR.strings.action_pause), Icons.Rounded.Pause)
} else {
ActionIcon(onClick = vm::start, stringResource("action_continue"), Icons.Rounded.PlayArrow)
ActionIcon(onClick = vm::start, stringResource(MR.strings.action_continue), Icons.Rounded.PlayArrow)
}
ActionIcon(onClick = vm::clear, stringResource("action_clear_queue"), Icons.Rounded.ClearAll)
ActionIcon(onClick = vm::clear, stringResource(MR.strings.action_clear_queue), Icons.Rounded.ClearAll)
}
)
Box {
@@ -170,10 +171,10 @@ fun DownloadsItem(
item.mangaId to item.chapterIndex,
{
DropdownMenuItem(onClick = { onClickCancel(item.chapter) }) {
Text(stringResource("action_cancel"))
Text(stringResource(MR.strings.action_cancel))
}
DropdownMenuItem(onClick = { onClickMoveToBottom(item.chapter) }) {
Text(stringResource("action_move_to_bottom"))
Text(stringResource(MR.strings.action_move_to_bottom))
}
}
) {

View File

@@ -53,7 +53,8 @@ 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 ca.gosyer.ui.base.resources.stringResource
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
@@ -146,7 +147,7 @@ fun ExtensionsToolbar(
setEnabledLanguages: (Set<String>) -> Unit
) {
Toolbar(
stringResource("location_extensions"),
stringResource(MR.strings.location_extensions),
closable = false,
searchText = searchText,
search = search,
@@ -158,7 +159,7 @@ fun ExtensionsToolbar(
setEnabledLanguages(enabledLangs.value)
}
},
stringResource("enabled_languages"),
stringResource(MR.strings.enabled_languages),
Icons.Rounded.Translate
)
}
@@ -209,9 +210,9 @@ fun ExtensionItem(
) {
Text(
when {
extension.hasUpdate -> stringResource("action_update")
extension.installed -> stringResource("action_uninstall")
else -> stringResource("action_install")
extension.hasUpdate -> stringResource(MR.strings.action_update)
extension.installed -> stringResource(MR.strings.action_uninstall)
else -> stringResource(MR.strings.action_install)
}
)
}

View File

@@ -6,12 +6,12 @@
package ca.gosyer.ui.extensions
import ca.gosyer.core.lang.throwIfCancellation
import ca.gosyer.data.extension.ExtensionPreferences
import ca.gosyer.data.models.Extension
import ca.gosyer.data.server.interactions.ExtensionInteractionHandler
import ca.gosyer.data.translation.XmlResourceBundle
import ca.gosyer.i18n.MR
import ca.gosyer.ui.base.vm.ViewModel
import ca.gosyer.util.lang.throwIfCancellation
import ca.gosyer.util.system.CKLogger
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -24,7 +24,6 @@ import javax.inject.Inject
class ExtensionsMenuViewModel @Inject constructor(
private val extensionHandler: ExtensionInteractionHandler,
private val resources: XmlResourceBundle,
extensionPreferences: ExtensionPreferences
) : ViewModel() {
private val _enabledLangs = extensionPreferences.languages().asStateFlow()
@@ -129,10 +128,10 @@ class ExtensionsMenuViewModel @Inject constructor(
val available = filter { !it.installed }.sortedWith(comparator)
return mapOf(
resources.getStringA("installed") to (obsolete + updates + installed),
MR.strings.installed.localized() to (obsolete + updates + installed),
).filterNot { it.value.isEmpty() } + available.groupBy { it.lang }.mapKeys {
if (it.key == "all") {
resources.getStringA("all")
MR.strings.all.localized()
} else {
Locale.forLanguageTag(it.key).displayName
}

View File

@@ -32,7 +32,8 @@ import ca.gosyer.data.models.Category
import ca.gosyer.data.models.Manga
import ca.gosyer.ui.base.components.LoadingScreen
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
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
@@ -100,7 +101,7 @@ fun LibraryScreen(bundle: Bundle, onClickManga: (Long) -> Unit = ::openMangaMenu
}
)*/
Toolbar(
stringResource("location_library"),
stringResource(MR.strings.location_library),
closable = false,
searchText = query,
search = vm::updateQuery

View File

@@ -6,6 +6,8 @@
package ca.gosyer.ui.library
import ca.gosyer.core.lang.throwIfCancellation
import ca.gosyer.core.lang.withDefaultContext
import ca.gosyer.data.library.LibraryPreferences
import ca.gosyer.data.models.Category
import ca.gosyer.data.models.Manga
@@ -15,8 +17,6 @@ import ca.gosyer.data.server.interactions.UpdatesInteractionHandler
import ca.gosyer.ui.base.vm.ViewModel
import ca.gosyer.util.compose.saveIntInBundle
import ca.gosyer.util.compose.saveStringInBundle
import ca.gosyer.util.lang.throwIfCancellation
import ca.gosyer.util.lang.withDefaultContext
import com.github.zsoltk.compose.savedinstancestate.Bundle
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll

View File

@@ -21,14 +21,16 @@ import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material.icons.rounded.Store
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.vector.ImageVector
import ca.gosyer.i18n.MR
import ca.gosyer.ui.extensions.openExtensionsMenu
import ca.gosyer.ui.library.openLibraryMenu
import ca.gosyer.ui.main.components.DownloadsExtraInfo
import ca.gosyer.ui.sources.openSourcesMenu
import com.github.zsoltk.compose.router.BackStack
import dev.icerock.moko.resources.StringResource
enum class TopLevelMenus(
val textKey: String,
val textKey: StringResource,
val unselectedIcon: ImageVector,
val selectedIcon: ImageVector,
val menu: Routes,
@@ -36,12 +38,12 @@ enum class TopLevelMenus(
val openInNewWindow: () -> Unit = {},
val extraInfo: (@Composable () -> Unit)? = null
) {
Library("location_library", Icons.Outlined.Book, Icons.Rounded.Book, Routes.Library, true, ::openLibraryMenu),
Updates("location_updates", Icons.Outlined.NewReleases, Icons.Rounded.NewReleases, Routes.Updates, true, ::openLibraryMenu),
Sources("location_sources", Icons.Outlined.Explore, Icons.Rounded.Explore, Routes.Sources, true, ::openSourcesMenu),
Extensions("location_extensions", Icons.Outlined.Store, Icons.Rounded.Store, Routes.Extensions, true, ::openExtensionsMenu),
Downloads("location_downloads", Icons.Outlined.Download, Icons.Rounded.Download, Routes.Downloads, false, extraInfo = { DownloadsExtraInfo() }),
Settings("location_settings", Icons.Outlined.Settings, Icons.Rounded.Settings, Routes.Settings, false);
Library(MR.strings.location_library, Icons.Outlined.Book, Icons.Rounded.Book, Routes.Library, true, ::openLibraryMenu),
Updates(MR.strings.location_updates, Icons.Outlined.NewReleases, Icons.Rounded.NewReleases, Routes.Updates, true, ::openLibraryMenu),
Sources(MR.strings.location_sources, Icons.Outlined.Explore, Icons.Rounded.Explore, Routes.Sources, true, ::openSourcesMenu),
Extensions(MR.strings.location_extensions, Icons.Outlined.Store, Icons.Rounded.Store, Routes.Extensions, true, ::openExtensionsMenu),
Downloads(MR.strings.location_downloads, Icons.Outlined.Download, Icons.Rounded.Download, Routes.Downloads, false, extraInfo = { DownloadsExtraInfo() }),
Settings(MR.strings.location_settings, Icons.Outlined.Settings, Icons.Rounded.Settings, Routes.Settings, false);
fun isSelected(backStack: BackStack<Routes>) = backStack.elements.first() == menu
}

View File

@@ -18,9 +18,10 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import ca.gosyer.core.service.WebsocketService
import ca.gosyer.ui.base.resources.stringResource
import ca.gosyer.i18n.MR
import ca.gosyer.ui.base.vm.viewModel
import ca.gosyer.ui.downloads.DownloadsMenuViewModel
import dev.icerock.moko.resources.compose.stringResource
@Composable
fun DownloadsExtraInfo() {
@@ -28,10 +29,10 @@ fun DownloadsExtraInfo() {
val status by vm.serviceStatus.collectAsState()
val list by vm.downloadQueue.collectAsState()
val text = when (status) {
WebsocketService.Status.STARTING -> stringResource("downloads_loading")
WebsocketService.Status.STARTING -> stringResource(MR.strings.downloads_loading)
WebsocketService.Status.RUNNING -> {
if (list.isNotEmpty()) {
stringResource("downloads_remaining", list.size)
stringResource(MR.strings.downloads_remaining, list.size)
} else null
}
WebsocketService.Status.STOPPED -> null
@@ -45,7 +46,7 @@ fun DownloadsExtraInfo() {
} else if (status == WebsocketService.Status.STOPPED) {
Surface(onClick = vm::restartDownloader, shape = RoundedCornerShape(4.dp)) {
Text(
stringResource("downloads_stopped"),
stringResource(MR.strings.downloads_stopped),
style = MaterialTheme.typography.body2,
color = Color.Red.copy(alpha = ContentAlpha.disabled)
)

View File

@@ -26,7 +26,8 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.combinedMouseClickable
import ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
import ca.gosyer.ui.main.Routes
import ca.gosyer.ui.main.TopLevelMenus

View File

@@ -14,12 +14,13 @@ 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.data.translation.XmlResourceBundle
import ca.gosyer.i18n.MR
import ca.gosyer.ui.base.vm.viewModel
import kotlinx.coroutines.launch
import java.util.Locale
@Composable
fun ApplicationScope.Tray(icon: Painter, resources: XmlResourceBundle) {
fun ApplicationScope.Tray(icon: Painter) {
val vm = viewModel<TrayViewModel>()
val trayState = rememberTrayState()
Tray(
@@ -27,7 +28,7 @@ fun ApplicationScope.Tray(icon: Painter, resources: XmlResourceBundle) {
trayState,
tooltip = BuildConfig.NAME,
menu = {
Item(resources.getStringA("action_close"), onClick = ::exitApplication)
Item(MR.strings.action_close.localized(), onClick = ::exitApplication)
}
)
@@ -36,8 +37,8 @@ fun ApplicationScope.Tray(icon: Painter, resources: XmlResourceBundle) {
vm.updateFound.collect {
trayState.sendNotification(
Notification(
resources.getStringA("new_update_title"),
resources.getString("new_update_message", it.version),
MR.strings.new_update_title.localized(),
MR.strings.new_update_message.localized(Locale.getDefault(), it.version),
Notification.Type.Info
)
)

View File

@@ -25,22 +25,20 @@ 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.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.data.server.ServerService.ServerResult
import ca.gosyer.data.translation.XmlResourceBundle
import ca.gosyer.data.ui.UiPreferences
import ca.gosyer.data.ui.model.ThemeMode
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.resources.LocalResources
import ca.gosyer.ui.base.resources.stringResource
import ca.gosyer.ui.base.theme.AppTheme
import ca.gosyer.ui.main.components.Tray
import ca.gosyer.util.lang.withUIContext
import ca.gosyer.util.system.getAsFlow
import ca.gosyer.util.system.userDataDir
import com.github.weisj.darklaf.LafManager
@@ -49,6 +47,7 @@ import com.github.weisj.darklaf.theme.IntelliJTheme
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
@@ -98,7 +97,6 @@ suspend fun main() {
}
}
val resources = scope.getInstance<XmlResourceBundle>()
val kamelConfig = scope.getInstance<KamelConfig>()
// Set the Compose constants before any
@@ -154,16 +152,16 @@ suspend fun main() {
val icon = painterResource("icon.png")
Tray(icon, resources)
Tray(icon)
Window(
onCloseRequest = {
if (confirmExit.value) {
WindowDialog(
title = resources.getStringA("confirm_exit"),
title = MR.strings.confirm_exit.localized(),
onPositiveButton = ::exitApplication
) {
Text(stringResource("confirm_exit_message"))
Text(stringResource(MR.strings.confirm_exit_message))
}
} else {
exitApplication()
@@ -190,7 +188,6 @@ suspend fun main() {
AppTheme {
CompositionLocalProvider(
LocalBackPressHandler provides backPressHandler,
LocalResources provides resources,
LocalKamelConfig provides kamelConfig
) {
Crossfade(serverService.initialized.collectAsState().value) { initialized ->
@@ -208,8 +205,8 @@ suspend fun main() {
Surface {
LoadingScreen(
initialized == ServerResult.STARTING,
errorMessage = stringResource("unable_to_start_server"),
retryMessage = stringResource("action_start_anyway"),
errorMessage = stringResource(MR.strings.unable_to_start_server),
retryMessage = stringResource(MR.strings.action_start_anyway),
retry = serverService::startAnyway
)
}

View File

@@ -29,10 +29,11 @@ import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
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.contextMenuClickable
import ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import java.time.Instant
@Composable
@@ -90,7 +91,7 @@ fun ChapterItem(
if (length > 0) append("")
append(
AnnotatedString(
stringResource("page_progress", (chapter.lastPageRead + 1)),
stringResource(MR.strings.page_progress, (chapter.lastPageRead + 1)),
SpanStyle(color = LocalContentColor.current.copy(alpha = ContentAlpha.disabled))
)
)

View File

@@ -51,6 +51,7 @@ 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.i18n.MR
import ca.gosyer.ui.base.WindowDialog
import ca.gosyer.ui.base.components.ErrorScreen
import ca.gosyer.ui.base.components.KamelImage
@@ -59,12 +60,12 @@ import ca.gosyer.ui.base.components.LocalMenuController
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.TextActionIcon
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
import ca.gosyer.ui.base.vm.viewModel
import ca.gosyer.ui.reader.openReaderMenu
import ca.gosyer.util.compose.ThemedWindow
import ca.gosyer.util.lang.launchApplication
import com.google.accompanist.flowlayout.FlowRow
import dev.icerock.moko.resources.compose.stringResource
import io.kamel.image.lazyPainterResource
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -100,20 +101,20 @@ fun MangaMenu(mangaId: Long, menuController: MenuController? = LocalMenuControll
Box {
Column {
Toolbar(
stringResource("location_manga"),
stringResource(MR.strings.location_manga),
menuController,
menuController != null,
actions = {
AnimatedVisibility(categoriesExist && manga?.inLibrary == true) {
TextActionIcon(
vm::setCategories,
stringResource("edit_categories"),
stringResource(MR.strings.edit_categories),
Icons.Rounded.Label
)
}
TextActionIcon(
vm::toggleFavorite,
stringResource(if (manga?.inLibrary == true) "action_remove_favorite" else "action_favorite"),
stringResource(if (manga?.inLibrary == true) MR.strings.action_remove_favorite else MR.strings.action_favorite),
if (manga?.inLibrary == true) {
Icons.Rounded.Favorite
} else {
@@ -123,7 +124,7 @@ fun MangaMenu(mangaId: Long, menuController: MenuController? = LocalMenuControll
)
TextActionIcon(
vm::refreshManga,
stringResource("action_refresh_manga"),
stringResource(MR.strings.action_refresh_manga),
Icons.Rounded.Refresh,
!isLoading
)
@@ -155,7 +156,7 @@ fun MangaMenu(mangaId: Long, menuController: MenuController? = LocalMenuControll
} else if (!isLoading) {
item {
ErrorScreen(
stringResource("no_chapters_found"),
stringResource(MR.strings.no_chapters_found),
Modifier.height(400.dp).fillMaxWidth(),
retry = vm::loadChapters
)
@@ -170,7 +171,7 @@ fun MangaMenu(mangaId: Long, menuController: MenuController? = LocalMenuControll
)
}
} else if (!isLoading) {
ErrorScreen(stringResource("failed_manga_fetch"), retry = vm::loadManga)
ErrorScreen(stringResource(MR.strings.failed_manga_fetch), retry = vm::loadManga)
}
}
}

View File

@@ -6,6 +6,8 @@
package ca.gosyer.ui.manga
import ca.gosyer.core.lang.throwIfCancellation
import ca.gosyer.core.lang.withIOContext
import ca.gosyer.data.download.DownloadService
import ca.gosyer.data.models.Category
import ca.gosyer.data.models.Chapter
@@ -17,8 +19,6 @@ import ca.gosyer.data.server.interactions.MangaInteractionHandler
import ca.gosyer.data.ui.UiPreferences
import ca.gosyer.ui.base.components.ChapterDownloadItem
import ca.gosyer.ui.base.vm.ViewModel
import ca.gosyer.util.lang.throwIfCancellation
import ca.gosyer.util.lang.withIOContext
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow

View File

@@ -54,18 +54,16 @@ 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.common.di.AppScope
import ca.gosyer.core.di.AppScope
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.translation.XmlResourceBundle
import ca.gosyer.data.ui.UiPreferences
import ca.gosyer.data.ui.model.WindowSettings
import ca.gosyer.i18n.MR
import ca.gosyer.ui.base.components.ErrorScreen
import ca.gosyer.ui.base.components.LoadingScreen
import ca.gosyer.ui.base.components.mangaAspectRatio
import ca.gosyer.ui.base.resources.LocalResources
import ca.gosyer.ui.base.resources.stringResource
import ca.gosyer.ui.base.theme.AppTheme
import ca.gosyer.ui.base.vm.viewModel
import ca.gosyer.ui.reader.model.Navigation
@@ -79,6 +77,7 @@ 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.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
@@ -108,7 +107,6 @@ fun openReaderMenu(chapterIndex: Int, mangaId: Long) {
placement
) = windowSettings.get().get()
val resources = AppScope.getInstance<XmlResourceBundle>()
val kamelConfig = AppScope.getInstance<KamelConfig>()
launchApplication {
@@ -144,7 +142,6 @@ fun openReaderMenu(chapterIndex: Int, mangaId: Long) {
}
) {
CompositionLocalProvider(
LocalResources provides resources,
LocalKamelConfig provides kamelConfig
) {
AppTheme {
@@ -292,7 +289,7 @@ fun ReaderMenu(
SideMenuButton(sideMenuOpen, onOpenSideMenuClicked = { sideMenuOpen = true })
}
} else {
ErrorScreen(stringResource("no_pages_found"))
ErrorScreen(stringResource(MR.strings.no_pages_found))
}
} else {
LoadingScreen(
@@ -354,15 +351,15 @@ fun ChapterSeparator(
Column {
when {
previousChapter == null && nextChapter != null -> {
Text(stringResource("no_previous_chapter"))
Text(stringResource(MR.strings.no_previous_chapter))
}
previousChapter != null && nextChapter != null -> {
Text(stringResource("previous_chapter", previousChapter.chapter.name))
Text(stringResource(MR.strings.previous_chapter, previousChapter.chapter.name))
Spacer(Modifier.height(8.dp))
Text(stringResource("next_chapter", nextChapter.chapter.name))
Text(stringResource(MR.strings.next_chapter, nextChapter.chapter.name))
}
previousChapter != null && nextChapter == null -> {
Text(stringResource("no_next_chapter"))
Text(stringResource(MR.strings.no_next_chapter))
}
}
}

View File

@@ -6,6 +6,7 @@
package ca.gosyer.ui.reader
import ca.gosyer.core.lang.throwIfCancellation
import ca.gosyer.data.models.Chapter
import ca.gosyer.data.models.Manga
import ca.gosyer.data.models.MangaMeta
@@ -22,7 +23,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.lang.throwIfCancellation
import ca.gosyer.util.system.CKLogger
import ca.gosyer.util.system.getAsFlow
import kotlinx.coroutines.DelicateCoroutinesApi

View File

@@ -39,12 +39,13 @@ 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.common.util.replace
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 ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
import ca.gosyer.ui.reader.model.ReaderChapter
import ca.gosyer.util.system.kLogger
import kotlin.math.roundToInt
@@ -78,7 +79,7 @@ fun ReaderSideMenu(
@Composable
fun ReaderModeSetting(readerModes: List<String>, selectedMode: String, onSetReaderMode: (String) -> Unit) {
val modes = remember(readerModes) { listOf(MangaMeta.DEFAULT_READER_MODE) + readerModes }
val defaultModeString = stringResource("default_reader_mode")
val defaultModeString = stringResource(MR.strings.default_reader_mode)
val displayModes = remember(modes, defaultModeString) { modes.replace(0, defaultModeString) }
val selectedModeIndex = remember(modes, selectedMode) { modes.indexOf(selectedMode) }
Row(
@@ -88,7 +89,7 @@ fun ReaderModeSetting(readerModes: List<String>, selectedMode: String, onSetRead
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(stringResource("reader_mode"), Modifier.weight(0.25f), maxLines = 2, fontSize = 14.sp)
Text(stringResource(MR.strings.reader_mode), Modifier.weight(0.25f), maxLines = 2, fontSize = 14.sp)
Spacer(Modifier.width(8.dp))
Spinner(
modifier = Modifier.weight(0.75f),
@@ -144,14 +145,14 @@ private fun NavigateChapters(loadPrevChapter: () -> Unit, loadNextChapter: () ->
Row(horizontalArrangement = Arrangement.SpaceBetween,) {
OutlinedButton(loadPrevChapter, Modifier.weight(0.5F)) {
Row(verticalAlignment = Alignment.CenterVertically) {
val nextChapter = stringResource("nav_prev_chapter")
val nextChapter = stringResource(MR.strings.nav_prev_chapter)
Icon(Icons.Rounded.NavigateBefore, nextChapter)
Text(nextChapter, fontSize = 10.sp)
}
}
OutlinedButton(loadNextChapter, Modifier.weight(0.5F)) {
Row(verticalAlignment = Alignment.CenterVertically) {
val nextChapter = stringResource("nav_next_chapter")
val nextChapter = stringResource(MR.strings.nav_next_chapter)
Text(nextChapter, fontSize = 10.sp)
Icon(Icons.Rounded.NavigateNext, nextChapter)
}

View File

@@ -6,11 +6,11 @@
package ca.gosyer.ui.reader.loader
import ca.gosyer.core.lang.throwIfCancellation
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.lang.throwIfCancellation
import ca.gosyer.util.system.CKLogger
import io.github.kerubistan.kroki.coroutines.priorityChannel
import io.ktor.client.features.onDownload

View File

@@ -23,7 +23,8 @@ import ca.gosyer.data.update.UpdatePreferences
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.prefs.SwitchPreference
import ca.gosyer.ui.base.resources.stringResource
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
@@ -38,12 +39,12 @@ class SettingsAdvancedViewModel @Inject constructor(
fun SettingsAdvancedScreen(menuController: MenuController) {
val vm = viewModel<SettingsAdvancedViewModel>()
Column {
Toolbar(stringResource("settings_advanced_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_advanced_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
SwitchPreference(preference = vm.updatesEnabled, title = stringResource("update_checker"))
SwitchPreference(preference = vm.updatesEnabled, title = stringResource(MR.strings.update_checker))
}
}
VerticalScrollbar(

View File

@@ -41,7 +41,8 @@ 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 ca.gosyer.ui.base.resources.stringResource
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
@@ -81,7 +82,7 @@ fun SettingsAppearance(menuController: MenuController) {
}
Column {
Toolbar(stringResource("settings_appearance_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_appearance_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
@@ -89,16 +90,16 @@ fun SettingsAppearance(menuController: MenuController) {
ChoicePreference(
preference = vm.themeMode,
choices = mapOf(
ThemeMode.System to stringResource("theme_follow_system"),
ThemeMode.Light to stringResource("theme_light"),
ThemeMode.Dark to stringResource("theme_dark")
ThemeMode.System to stringResource(MR.strings.theme_follow_system),
ThemeMode.Light to stringResource(MR.strings.theme_light),
ThemeMode.Dark to stringResource(MR.strings.theme_dark)
),
title = stringResource("theme")
title = stringResource(MR.strings.theme)
)
}
item {
Text(
stringResource("preset_themes"),
stringResource(MR.strings.preset_themes),
modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 4.dp)
)
LazyRow(modifier = Modifier.padding(horizontal = 8.dp)) {
@@ -117,24 +118,24 @@ fun SettingsAppearance(menuController: MenuController) {
item {
ColorPreference(
preference = activeColors.primaryStateFlow,
title = stringResource("color_primary"),
subtitle = stringResource("color_primary_sub"),
title = stringResource(MR.strings.color_primary),
subtitle = stringResource(MR.strings.color_primary_sub),
unsetColor = MaterialTheme.colors.primary
)
}
item {
ColorPreference(
preference = activeColors.secondaryStateFlow,
title = stringResource("color_secondary"),
subtitle = stringResource("color_secondary_sub"),
title = stringResource(MR.strings.color_secondary),
subtitle = stringResource(MR.strings.color_secondary_sub),
unsetColor = MaterialTheme.colors.secondary
)
}
item {
SwitchPreference(
vm.windowDecorations,
stringResource("window_decorations"),
stringResource("window_decorations_sub")
stringResource(MR.strings.window_decorations),
stringResource(MR.strings.window_decorations_sub)
)
}
}
@@ -176,7 +177,7 @@ private fun ThemeItem(
.weight(1f)
.padding(6.dp)
) {
Text(stringResource("theme_text"), fontSize = 11.sp)
Text(stringResource(MR.strings.theme_text), fontSize = 11.sp)
Button(
onClick = {},
enabled = false,

View File

@@ -32,15 +32,16 @@ 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.lang.throwIfCancellation
import ca.gosyer.data.server.interactions.BackupInteractionHandler
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 ca.gosyer.ui.base.resources.stringResource
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.lang.throwIfCancellation
import ca.gosyer.util.system.CKLogger
import ca.gosyer.util.system.filePicker
import ca.gosyer.util.system.fileSaver
@@ -205,14 +206,14 @@ fun SettingsBackupScreen(menuController: MenuController) {
}
Column {
Toolbar(stringResource("settings_backup_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_backup_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
PreferenceFile(
stringResource("backup_restore"),
stringResource("backup_restore_sub"),
stringResource(MR.strings.backup_restore),
stringResource(MR.strings.backup_restore_sub),
restoring,
restoringProgress,
restoreStatus
@@ -222,8 +223,8 @@ fun SettingsBackupScreen(menuController: MenuController) {
}
}
PreferenceFile(
stringResource("backup_create"),
stringResource("backup_create_sub"),
stringResource(MR.strings.backup_create),
stringResource(MR.strings.backup_create_sub),
creating,
creatingProgress,
creatingStatus,
@@ -249,7 +250,7 @@ private fun openMissingSourcesDialog(missingSources: List<String>, onPositiveCli
) {
LazyColumn {
item {
Text(stringResource("missing_sources"), style = MaterialTheme.typography.subtitle2)
Text(stringResource(MR.strings.missing_sources), style = MaterialTheme.typography.subtitle2)
}
items(missingSources) {
Text(it)

View File

@@ -19,14 +19,15 @@ 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.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
@Composable
fun SettingsBrowseScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_browse_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_browse_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {

View File

@@ -21,12 +21,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
@Composable
fun SettingsDownloadsScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_download_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_download_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {

View File

@@ -23,13 +23,14 @@ import androidx.compose.ui.unit.dp
import ca.gosyer.build.BuildResources
import ca.gosyer.data.ui.UiPreferences
import ca.gosyer.data.ui.model.StartScreen
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.SwitchPreference
import ca.gosyer.ui.base.resources.stringResource
import ca.gosyer.ui.base.vm.ViewModel
import ca.gosyer.ui.base.vm.viewModel
import dev.icerock.moko.resources.compose.stringResource
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
@@ -51,16 +52,16 @@ class SettingsGeneralViewModel @Inject constructor(
@Composable
fun getStartScreenChoices() = mapOf(
StartScreen.Library to stringResource("location_library"),
StartScreen.Updates to stringResource("location_updates"),
StartScreen.Sources to stringResource("location_sources"),
StartScreen.Extensions to stringResource("location_extensions")
StartScreen.Library to stringResource(MR.strings.location_library),
StartScreen.Updates to stringResource(MR.strings.location_updates),
StartScreen.Sources to stringResource(MR.strings.location_sources),
StartScreen.Extensions to stringResource(MR.strings.location_extensions)
)
@Composable
fun getLanguageChoices(): Map<String, String> = (
mapOf(
"" to stringResource("language_system_default", currentLocale.getDisplayName(currentLocale))
"" to stringResource(MR.strings.language_system_default, currentLocale.getDisplayName(currentLocale))
) + BuildResources.LANGUAGES
.associateWith { Locale.forLanguageTag(it).getDisplayName(currentLocale) }
)
@@ -69,7 +70,7 @@ class SettingsGeneralViewModel @Inject constructor(
@Composable
fun getDateChoices(): Map<String, String> {
return mapOf(
"" to stringResource("date_system_default"),
"" to stringResource(MR.strings.date_system_default),
"MM/dd/yy" to "MM/dd/yy",
"dd/MM/yy" to "dd/MM/yy",
"yyyy-MM-dd" to "yyyy-MM-dd"
@@ -91,21 +92,21 @@ class SettingsGeneralViewModel @Inject constructor(
fun SettingsGeneralScreen(menuController: MenuController) {
val vm = viewModel<SettingsGeneralViewModel>()
Column {
Toolbar(stringResource("settings_general_screen"), menuController, closable = true)
Toolbar(stringResource(MR.strings.settings_general_screen), menuController, closable = true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
ChoicePreference(
preference = vm.startScreen,
title = stringResource("start_screen"),
title = stringResource(MR.strings.start_screen),
choices = vm.getStartScreenChoices()
)
}
item {
SwitchPreference(
preference = vm.confirmExit,
title = stringResource("confirm_exit")
title = stringResource(MR.strings.confirm_exit)
)
}
item {
@@ -114,14 +115,14 @@ fun SettingsGeneralScreen(menuController: MenuController) {
item {
ChoicePreference(
preference = vm.language,
title = stringResource("language"),
title = stringResource(MR.strings.language),
choices = vm.getLanguageChoices(),
)
}
item {
ChoicePreference(
preference = vm.dateFormat,
title = stringResource("date_format"),
title = stringResource(MR.strings.date_format),
choices = vm.getDateChoices()
)
}

View File

@@ -26,7 +26,8 @@ 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 ca.gosyer.ui.base.resources.stringResource
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
@@ -60,19 +61,19 @@ fun SettingsLibraryScreen(menuController: MenuController) {
val vm = viewModel<SettingsLibraryViewModel>()
Column {
Toolbar(stringResource("settings_library_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_library_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
SwitchPreference(
preference = vm.showAllCategory,
title = stringResource("show_all_category")
title = stringResource(MR.strings.show_all_category)
)
}
item {
PreferenceRow(
stringResource("location_categories"),
stringResource(MR.strings.location_categories),
onClick = { openCategoriesMenu(vm::refreshCategoryCount) },
subtitle = vm.categories.collectAsState().value.toString()
)

View File

@@ -21,12 +21,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
@Composable
fun SettingsParentalControlsScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_parental_control_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_parental_control_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {

View File

@@ -28,7 +28,7 @@ import ca.gosyer.data.reader.ReaderPreferences
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.translation.XmlResourceBundle
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
@@ -36,9 +36,9 @@ import ca.gosyer.ui.base.prefs.ExpandablePreference
import ca.gosyer.ui.base.prefs.PreferenceMutableStateFlow
import ca.gosyer.ui.base.prefs.SwitchPreference
import ca.gosyer.ui.base.prefs.asStateIn
import ca.gosyer.ui.base.resources.stringResource
import ca.gosyer.ui.base.vm.ViewModel
import ca.gosyer.ui.base.vm.viewModel
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -47,7 +47,6 @@ import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
class SettingsReaderViewModel @Inject constructor(
private val resources: XmlResourceBundle,
readerPreferences: ReaderPreferences
) : ViewModel() {
val modes = readerPreferences.modes().asStateFlow()
@@ -68,10 +67,10 @@ class SettingsReaderViewModel @Inject constructor(
}.launchIn(scope)
}
fun getDirectionChoices() = Direction.values().associate { it to resources.getStringA(it.res) }
fun getDirectionChoices() = Direction.values().associateWith { it.res.localized() }
fun getPaddingChoices() = mapOf(
0 to resources.getStringA("page_padding_none"),
0 to MR.strings.page_padding_none.localized(),
8 to "8 Dp",
16 to "16 Dp",
32 to "32 Dp"
@@ -79,23 +78,23 @@ class SettingsReaderViewModel @Inject constructor(
fun getMaxSizeChoices(direction: Direction) = if (direction == Direction.Right || direction == Direction.Left) {
mapOf(
0 to resources.getStringA("max_size_unrestricted"),
0 to MR.strings.max_size_unrestricted.localized(),
700 to "700 Dp",
900 to "900 Dp",
1100 to "1100 Dp"
)
} else {
mapOf(
0 to resources.getStringA("max_size_unrestricted"),
0 to MR.strings.max_size_unrestricted.localized(),
500 to "500 Dp",
700 to "700 Dp",
900 to "900 Dp"
)
}
fun getImageScaleChoices() = ImageScale.values().associate { it to resources.getStringA(it.res) }
fun getImageScaleChoices() = ImageScale.values().associateWith { it.res.localized() }
fun getNavigationModeChoices() = NavigationMode.values().associate { it to resources.getStringA(it.res) }
fun getNavigationModeChoices() = NavigationMode.values().associateWith { it.res.localized() }
}
data class ReaderModePreference(
@@ -130,7 +129,7 @@ fun SettingsReaderScreen(menuController: MenuController) {
val vm = viewModel<SettingsReaderViewModel>()
val modeSettings by vm.modeSettings.collectAsState()
Column {
Toolbar(stringResource("settings_reader"), menuController, true)
Toolbar(stringResource(MR.strings.settings_reader), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
@@ -138,7 +137,7 @@ fun SettingsReaderScreen(menuController: MenuController) {
ChoicePreference(
vm.selectedMode,
vm.modes.collectAsState().value.associateWith { it },
stringResource("reader_mode")
stringResource(MR.strings.reader_mode)
)
}
item {
@@ -150,13 +149,13 @@ fun SettingsReaderScreen(menuController: MenuController) {
ChoicePreference(
it.direction,
vm.getDirectionChoices(),
stringResource("direction"),
stringResource(MR.strings.direction),
enabled = !it.defaultMode
)
SwitchPreference(
it.continuous,
stringResource("continuous"),
stringResource("continuous_sub"),
stringResource(MR.strings.continuous),
stringResource(MR.strings.continuous_sub),
enabled = !it.defaultMode
)
val continuous by it.continuous.collectAsState()
@@ -164,13 +163,13 @@ fun SettingsReaderScreen(menuController: MenuController) {
ChoicePreference(
it.padding,
vm.getPaddingChoices(),
stringResource("page_padding")
stringResource(MR.strings.page_padding)
)
val direction by it.direction.collectAsState()
val (title, subtitle) = if (direction == Direction.Up || direction == Direction.Down) {
stringResource("force_fit_width") to stringResource("force_fit_width_sub")
stringResource(MR.strings.force_fit_width) to stringResource(MR.strings.force_fit_width_sub)
} else {
stringResource("force_fit_height") to stringResource("force_fit_height_sub")
stringResource(MR.strings.force_fit_height) to stringResource(MR.strings.force_fit_height_sub)
}
SwitchPreference(
it.fitSize,
@@ -179,13 +178,13 @@ fun SettingsReaderScreen(menuController: MenuController) {
)
val maxSize by it.maxSize.collectAsState()
val (maxSizeTitle, maxSizeSubtitle) = if (direction == Direction.Up || direction == Direction.Down) {
stringResource("max_width") to stringResource(
"max_width_sub",
stringResource(MR.strings.max_width) to stringResource(
MR.strings.max_width_sub,
maxSize
)
} else {
stringResource("max_height") to stringResource(
"max_height_sub",
stringResource(MR.strings.max_height) to stringResource(
MR.strings.max_height_sub,
maxSize
)
}
@@ -199,13 +198,13 @@ fun SettingsReaderScreen(menuController: MenuController) {
ChoicePreference(
it.imageScale,
vm.getImageScaleChoices(),
stringResource("image_scale")
stringResource(MR.strings.image_scale)
)
}
ChoicePreference(
it.navigationMode,
vm.getNavigationModeChoices(),
stringResource("navigation_mode")
stringResource(MR.strings.navigation_mode)
)
}
}

View File

@@ -31,96 +31,97 @@ import androidx.compose.ui.unit.dp
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.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
import ca.gosyer.ui.main.Routes
@Composable
fun SettingsScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("location_settings"), closable = false)
Toolbar(stringResource(MR.strings.location_settings), closable = false)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
PreferenceRow(
title = stringResource("settings_general"),
title = stringResource(MR.strings.settings_general),
icon = Icons.Rounded.Tune,
onClick = { menuController.push(Routes.SettingsGeneral) }
)
}
item {
PreferenceRow(
title = stringResource("settings_appearance"),
title = stringResource(MR.strings.settings_appearance),
icon = Icons.Rounded.Palette,
onClick = { menuController.push(Routes.SettingsAppearance) }
)
}
item {
PreferenceRow(
title = stringResource("settings_server"),
title = stringResource(MR.strings.settings_server),
icon = Icons.Rounded.Computer,
onClick = { menuController.push(Routes.SettingsServer) }
)
}
item {
PreferenceRow(
title = stringResource("settings_library"),
title = stringResource(MR.strings.settings_library),
icon = Icons.Rounded.CollectionsBookmark,
onClick = { menuController.push(Routes.SettingsLibrary) }
)
}
item {
PreferenceRow(
title = stringResource("settings_reader"),
title = stringResource(MR.strings.settings_reader),
icon = Icons.Rounded.ChromeReaderMode,
onClick = { menuController.push(Routes.SettingsReader) }
)
}
/*item {
Pref(
title = stringResource("settings_download"),
title = stringResource(MR.strings.settings_download),
icon = Icons.Rounded.GetApp,
onClick = { navController.push(Route.SettingsDownloads) }
)
}
item {
Pref(
title = stringResource("settings_tracking"),
title = stringResource(MR.strings.settings_tracking),
icon = Icons.Rounded.Sync,
onClick = { navController.push(Route.SettingsTracking) }
)
}*/
item {
PreferenceRow(
title = stringResource("settings_browse"),
title = stringResource(MR.strings.settings_browse),
icon = Icons.Rounded.Explore,
onClick = { menuController.push(Routes.SettingsBrowse) }
)
}
item {
PreferenceRow(
title = stringResource("settings_backup"),
title = stringResource(MR.strings.settings_backup),
icon = Icons.Rounded.Backup,
onClick = { menuController.push(Routes.SettingsBackup) }
)
}
/*item {
Pref(
title = stringResource("settings_security"),
title = stringResource(MR.strings.settings_security),
icon = Icons.Rounded.Security,
onClick = { navController.push(Route.SettingsSecurity) }
)
}
item {
Pref(
title = stringResource("settings_parental_controls"),
title = stringResource(MR.strings.settings_parental_controls),
icon = Icons.Rounded.PeopleOutline,
onClick = { navController.push(Route.SettingsParentalControls) }
)
}*/
item {
PreferenceRow(
title = stringResource("settings_advanced"),
title = stringResource(MR.strings.settings_advanced),
icon = Icons.Rounded.Code,
onClick = { menuController.push(Routes.SettingsAdvanced) }
)

View File

@@ -21,12 +21,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
@Composable
fun SettingsSecurityScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_security_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_security_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {

View File

@@ -32,6 +32,7 @@ import ca.gosyer.data.server.ServerPreferences
import ca.gosyer.data.server.ServerService
import ca.gosyer.data.server.model.Auth
import ca.gosyer.data.server.model.Proxy
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
@@ -40,10 +41,10 @@ import ca.gosyer.ui.base.prefs.PreferenceRow
import ca.gosyer.ui.base.prefs.SwitchPreference
import ca.gosyer.ui.base.prefs.asStateIn
import ca.gosyer.ui.base.prefs.asStringStateIn
import ca.gosyer.ui.base.resources.stringResource
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
@@ -85,9 +86,9 @@ class SettingsServerViewModel @Inject constructor(
@Composable
fun getProxyChoices() = mapOf(
Proxy.NO_PROXY to stringResource("no_proxy"),
Proxy.HTTP_PROXY to stringResource("http_proxy"),
Proxy.SOCKS_PROXY to stringResource("socks_proxy")
Proxy.NO_PROXY to stringResource(MR.strings.no_proxy),
Proxy.HTTP_PROXY to stringResource(MR.strings.http_proxy),
Proxy.SOCKS_PROXY to stringResource(MR.strings.socks_proxy)
)
val httpHost = serverPreferences.proxyHttpHost().asStateIn(scope)
@@ -99,9 +100,9 @@ class SettingsServerViewModel @Inject constructor(
@Composable
fun getAuthChoices() = mapOf(
Auth.NONE to stringResource("no_auth"),
Auth.BASIC to stringResource("basic_auth"),
Auth.DIGEST to stringResource("digest_auth")
Auth.NONE to stringResource(MR.strings.no_auth),
Auth.BASIC to stringResource(MR.strings.basic_auth),
Auth.DIGEST to stringResource(MR.strings.digest_auth)
)
val authUsername = serverPreferences.authUsername().asStateIn(scope)
val authPassword = serverPreferences.authPassword().asStateIn(scope)
@@ -147,27 +148,27 @@ fun SettingsServerScreen(menuController: MenuController) {
}
}
Column {
Toolbar(stringResource("settings_server_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_server_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {
item {
SwitchPreference(preference = vm.host, title = stringResource("host_server"))
SwitchPreference(preference = vm.host, title = stringResource(MR.strings.host_server))
}
if (host) {
item {
PreferenceRow(
stringResource("host_settings"),
stringResource(MR.strings.host_settings),
Icons.Rounded.Info,
subtitle = stringResource("host_settings_sub")
subtitle = stringResource(MR.strings.host_settings_sub)
)
}
item {
val ip by vm.ip.collectAsState()
EditTextPreference(
preference = vm.ip,
title = stringResource("host_ip"),
subtitle = stringResource("host_ip_sub", ip),
title = stringResource(MR.strings.host_ip),
subtitle = stringResource(MR.strings.host_ip_sub, ip),
changeListener = vm::serverSettingChanged
)
}
@@ -175,15 +176,15 @@ fun SettingsServerScreen(menuController: MenuController) {
val port by vm.port.collectAsState()
EditTextPreference(
preference = vm.port,
title = stringResource("host_port"),
subtitle = stringResource("host_port_sub", port),
title = stringResource(MR.strings.host_port),
subtitle = stringResource(MR.strings.host_port_sub, port),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.socksProxyEnabled,
title = stringResource("host_socks_enabled"),
title = stringResource(MR.strings.host_socks_enabled),
changeListener = vm::serverSettingChanged
)
}
@@ -191,8 +192,8 @@ fun SettingsServerScreen(menuController: MenuController) {
val proxyHost by vm.socksProxyHost.collectAsState()
EditTextPreference(
preference = vm.socksProxyHost,
title = stringResource("host_socks_host"),
subtitle = stringResource("host_socks_host_sub", proxyHost),
title = stringResource(MR.strings.host_socks_host),
subtitle = stringResource(MR.strings.host_socks_host_sub, proxyHost),
changeListener = vm::serverSettingChanged
)
}
@@ -200,32 +201,32 @@ fun SettingsServerScreen(menuController: MenuController) {
val proxyPort by vm.socksProxyPort.collectAsState()
EditTextPreference(
preference = vm.socksProxyPort,
title = stringResource("host_socks_port"),
subtitle = stringResource("host_socks_port_sub", proxyPort),
title = stringResource(MR.strings.host_socks_port),
subtitle = stringResource(MR.strings.host_socks_port_sub, proxyPort),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.debugLogsEnabled,
title = stringResource("host_debug_logging"),
subtitle = stringResource("host_debug_logging_sub"),
title = stringResource(MR.strings.host_debug_logging),
subtitle = stringResource(MR.strings.host_debug_logging_sub),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.systemTrayEnabled,
title = stringResource("host_system_tray"),
subtitle = stringResource("host_system_tray_sub"),
title = stringResource(MR.strings.host_system_tray),
subtitle = stringResource(MR.strings.host_system_tray_sub),
changeListener = vm::serverSettingChanged
)
}
item {
SwitchPreference(
preference = vm.webUIEnabled,
title = stringResource("host_webui"),
subtitle = stringResource("host_webui_sub"),
title = stringResource(MR.strings.host_webui),
subtitle = stringResource(MR.strings.host_webui_sub),
changeListener = vm::serverSettingChanged
)
}
@@ -233,8 +234,8 @@ fun SettingsServerScreen(menuController: MenuController) {
val webUIEnabled by vm.webUIEnabled.collectAsState()
SwitchPreference(
preference = vm.openInBrowserEnabled,
title = stringResource("host_open_in_browser"),
subtitle = stringResource("host_open_in_browser_sub"),
title = stringResource(MR.strings.host_open_in_browser),
subtitle = stringResource(MR.strings.host_open_in_browser_sub),
changeListener = vm::serverSettingChanged,
enabled = webUIEnabled
)
@@ -242,15 +243,15 @@ fun SettingsServerScreen(menuController: MenuController) {
item {
SwitchPreference(
preference = vm.basicAuthEnabled,
title = stringResource("basic_auth"),
subtitle = stringResource("host_basic_auth_sub"),
title = stringResource(MR.strings.basic_auth),
subtitle = stringResource(MR.strings.host_basic_auth_sub),
changeListener = vm::serverSettingChanged
)
}
item {
EditTextPreference(
preference = vm.basicAuthUsername,
title = stringResource("host_basic_auth_username"),
title = stringResource(MR.strings.host_basic_auth_username),
changeListener = vm::serverSettingChanged,
enabled = basicAuthEnabled
)
@@ -258,7 +259,7 @@ fun SettingsServerScreen(menuController: MenuController) {
item {
EditTextPreference(
preference = vm.basicAuthPassword,
title = stringResource("host_basic_auth_password"),
title = stringResource(MR.strings.host_basic_auth_password),
changeListener = vm::serverSettingChanged,
visualTransformation = PasswordVisualTransformation(),
enabled = basicAuthEnabled
@@ -271,27 +272,27 @@ fun SettingsServerScreen(menuController: MenuController) {
item {
EditTextPreference(
vm.serverUrl,
stringResource("server_url"),
stringResource(MR.strings.server_url),
subtitle = vm.serverUrl.collectAsState().value
)
}
item {
EditTextPreference(
vm.serverPort,
stringResource("server_port"),
stringResource(MR.strings.server_port),
subtitle = vm.serverPort.collectAsState().value
)
}
item {
PreferenceRow(
stringResource("server_preference_warning"),
stringResource(MR.strings.server_preference_warning),
Icons.Rounded.Warning,
subtitle = stringResource("server_preference_warning_sub")
subtitle = stringResource(MR.strings.server_preference_warning_sub)
)
}
item {
ChoicePreference(vm.proxy, vm.getProxyChoices(), stringResource("server_proxy"))
ChoicePreference(vm.proxy, vm.getProxyChoices(), stringResource(MR.strings.server_proxy))
}
when (proxy) {
Proxy.NO_PROXY -> Unit
@@ -299,14 +300,14 @@ fun SettingsServerScreen(menuController: MenuController) {
item {
EditTextPreference(
vm.httpHost,
stringResource("http_proxy"),
stringResource(MR.strings.http_proxy),
vm.httpHost.collectAsState().value
)
}
item {
EditTextPreference(
vm.httpPort,
stringResource("http_port"),
stringResource(MR.strings.http_port),
vm.httpPort.collectAsState().value
)
}
@@ -315,30 +316,30 @@ fun SettingsServerScreen(menuController: MenuController) {
item {
EditTextPreference(
vm.socksHost,
stringResource("socks_proxy"),
stringResource(MR.strings.socks_proxy),
vm.socksHost.collectAsState().value
)
}
item {
EditTextPreference(
vm.socksPort,
stringResource("socks_port"),
stringResource(MR.strings.socks_port),
vm.socksPort.collectAsState().value
)
}
}
}
item {
ChoicePreference(vm.auth, vm.getAuthChoices(), stringResource("authentication"))
ChoicePreference(vm.auth, vm.getAuthChoices(), stringResource(MR.strings.authentication))
}
if (auth != Auth.NONE) {
item {
EditTextPreference(vm.authUsername, stringResource("auth_username"))
EditTextPreference(vm.authUsername, stringResource(MR.strings.auth_username))
}
item {
EditTextPreference(
vm.authPassword,
stringResource("auth_password"),
stringResource(MR.strings.auth_password),
visualTransformation = PasswordVisualTransformation()
)
}

View File

@@ -21,12 +21,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ca.gosyer.ui.base.components.MenuController
import ca.gosyer.ui.base.components.Toolbar
import ca.gosyer.ui.base.resources.stringResource
import dev.icerock.moko.resources.compose.stringResource
import ca.gosyer.i18n.MR
@Composable
fun SettingsTrackingScreen(menuController: MenuController) {
Column {
Toolbar(stringResource("settings_tracking_screen"), menuController, true)
Toolbar(stringResource(MR.strings.settings_tracking_screen), menuController, true)
Box {
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state) {

View File

@@ -42,7 +42,8 @@ import ca.gosyer.build.BuildConfig
import ca.gosyer.data.models.Source
import ca.gosyer.ui.base.components.KamelImage
import ca.gosyer.ui.base.components.combinedMouseClickable
import ca.gosyer.ui.base.resources.stringResource
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
@@ -122,7 +123,7 @@ fun SourcesSideMenu(
shape = RoundedCornerShape(4.dp),
elevation = 4.dp
) {
Text(source?.name ?: stringResource("sources_home"), modifier = Modifier.padding(10.dp))
Text(source?.name ?: stringResource(MR.strings.sources_home), modifier = Modifier.padding(10.dp))
}
},
modifier = Modifier.size(64.dp),
@@ -153,7 +154,7 @@ fun SourcesSideMenu(
)
}
} else {
Icon(Icons.Rounded.Home, stringResource("sources_home"), modifier = modifier)
Icon(Icons.Rounded.Home, stringResource(MR.strings.sources_home), modifier = modifier)
}
}
}

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