From 317a21adc09ac09860cdd14139428e4f3ddb3cae Mon Sep 17 00:00:00 2001 From: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com> Date: Mon, 13 Oct 2025 14:38:27 +0700 Subject: [PATCH] chore(discord): Enhance Discord integration and update application ID (#1236) * fix(discord): Update Komikku image * feat(discord): Enhance Discord connection preferences with login state and improved UI * fix(discord): Update application ID for Discord Rich Presence --- .../presentation/more/settings/Preference.kt | 2 +- .../more/settings/PreferenceItem.kt | 14 ++++---- .../screen/SettingsConnectionScreen.kt | 9 +++-- .../widget/ConnectionPreferenceWidget.kt | 35 ++++++++++++++----- .../data/connections/ConnectionsService.kt | 11 ++++++ .../connections/discord/DiscordRPCModels.kt | 6 ++-- .../moko-resources/base/strings.xml | 2 +- 7 files changed, 54 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt b/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt index 95289ecb2..4841e0cac 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/Preference.kt @@ -164,9 +164,9 @@ sealed class Preference { override val title: String, val login: () -> Unit, val openSettings: () -> Unit, + override val subtitle: String? = null, ) : PreferenceItem() { override val enabled: Boolean = true - override val subtitle: String? = null override val icon: ImageVector? = null override val onValueChanged: suspend (newValue: String) -> Boolean = { true } } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt b/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt index 29e80c049..42a2bde58 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/PreferenceItem.kt @@ -176,13 +176,13 @@ internal fun PreferenceItem( } // AM (CONNECTIONS) --> is Preference.PreferenceItem.ConnectionPreference -> { - item.service.run { - ConnectionPreferenceWidget( - service = this, - checked = isLogged, - onClick = { if (isLogged) item.openSettings() else item.login() }, - ) - } + val isLoggedIn by item.service.isLoggedInFlow.collectAsState(item.service.isLogged) + ConnectionPreferenceWidget( + service = item.service, + checked = isLoggedIn, + onClick = { if (isLoggedIn) item.openSettings() else item.login() }, + subtitle = item.subtitle, + ) } // <-- AM (CONNECTIONS) is Preference.PreferenceItem.InfoPreference -> { diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsConnectionScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsConnectionScreen.kt index 85667c9c8..5e0c64fc4 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsConnectionScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsConnectionScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -80,23 +81,21 @@ object SettingsConnectionScreen : SearchableSettings { } } + val isLoggedIn by connectionsManager.discord.isLoggedInFlow.collectAsState(connectionsManager.discord.isLogged) + return listOf( Preference.PreferenceGroup( title = stringResource(KMR.strings.special_services), preferenceItems = persistentListOf( Preference.PreferenceItem.ConnectionPreference( title = stringResource(connectionsManager.discord.nameStrRes()), + subtitle = stringResource(KMR.strings.pref_discord_configuration).takeIf { isLoggedIn }, service = connectionsManager.discord, login = { navigator.push(DiscordLoginScreen()) }, openSettings = { navigator.push(SettingsDiscordScreen) }, ), - Preference.PreferenceItem.TextPreference( - title = stringResource(KMR.strings.pref_discord_configuration), - enabled = connectionsManager.discord.isLogged, - onClick = { navigator.push(SettingsDiscordScreen) }, - ), Preference.PreferenceItem.InfoPreference( stringResource(KMR.strings.connections_discord_info, stringResource(MR.strings.app_name)), ), diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/ConnectionPreferenceWidget.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/ConnectionPreferenceWidget.kt index 6fe3333d6..2307758b4 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/ConnectionPreferenceWidget.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/widget/ConnectionPreferenceWidget.kt @@ -3,10 +3,12 @@ package eu.kanade.presentation.more.settings.widget import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.sizeIn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Done import androidx.compose.material3.Icon @@ -19,37 +21,54 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import eu.kanade.presentation.connection.components.ConnectionLogoIcon import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted +import eu.kanade.presentation.more.settings.LocalPreferenceMinHeight import eu.kanade.tachiyomi.data.connections.ConnectionsService import tachiyomi.i18n.MR import tachiyomi.presentation.core.i18n.stringResource +import tachiyomi.presentation.core.util.secondaryItemAlpha @Composable @Suppress("ModifierNotUsedAtRoot", "MagicNumber") fun ConnectionPreferenceWidget( service: ConnectionsService, checked: Boolean, + subtitle: String?, modifier: Modifier = Modifier, onClick: (() -> Unit)? = null, ) { val highlighted = LocalPreferenceHighlighted.current + val minHeight = LocalPreferenceMinHeight.current Box(modifier = Modifier.highlightBackground(highlighted)) { Row( modifier = modifier + .sizeIn(minHeight = minHeight) .clickable(enabled = onClick != null, onClick = { onClick?.invoke() }) .fillMaxWidth() - .padding(horizontal = PrefsHorizontalPadding, vertical = 8.dp), + .padding(horizontal = PrefsHorizontalPadding), verticalAlignment = Alignment.CenterVertically, ) { ConnectionLogoIcon(service) - Text( - text = stringResource(service.nameStrRes()), + Column( modifier = Modifier .weight(1f) - .padding(horizontal = 16.dp), - maxLines = 1, - style = MaterialTheme.typography.titleLarge, - fontSize = TitleFontSize, - ) + .padding(horizontal = PrefsHorizontalPadding), + ) { + Text( + text = stringResource(service.nameStrRes()), + maxLines = 1, + style = MaterialTheme.typography.titleLarge, + fontSize = TitleFontSize, + ) + if (!subtitle.isNullOrBlank()) { + Text( + text = subtitle, + modifier = Modifier + .secondaryItemAlpha(), + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + ) + } + } if (checked) { Icon( imageVector = Icons.Outlined.Done, diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/connections/ConnectionsService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/connections/ConnectionsService.kt index c1ea32c6a..cbf97f561 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/connections/ConnectionsService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/connections/ConnectionsService.kt @@ -7,6 +7,8 @@ import androidx.annotation.DrawableRes import dev.icerock.moko.resources.StringResource import eu.kanade.domain.connections.service.ConnectionsPreferences import eu.kanade.tachiyomi.network.NetworkHelper +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine import okhttp3.OkHttpClient import uy.kohesive.injekt.injectLazy @@ -52,6 +54,15 @@ abstract class ConnectionsService(val id: Long) { get() = getUsername().isNotEmpty() && getPassword().isNotEmpty() + open val isLoggedInFlow: Flow by lazy { + combine( + connectionsPreferences.connectionsUsername(this).changes(), + connectionsPreferences.connectionsPassword(this).changes(), + ) { username, password -> + username.isNotEmpty() && password.isNotEmpty() + } + } + /** * Override this method in token-based services to retrieve the token. * Default implementation returns an empty string. diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/connections/discord/DiscordRPCModels.kt b/app/src/main/java/eu/kanade/tachiyomi/data/connections/discord/DiscordRPCModels.kt index d046a2e37..093c38ef9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/connections/discord/DiscordRPCModels.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/connections/discord/DiscordRPCModels.kt @@ -17,7 +17,7 @@ import kotlinx.serialization.json.JsonElement const val RICH_PRESENCE_TAG = "discord_rpc" // Constant for application id -internal const val RICH_PRESENCE_APPLICATION_ID = "1365208874440986685" +internal const val RICH_PRESENCE_APPLICATION_ID = "1424627741256585271" val DOWNLOAD_BUTTON_LABEL_RES = R.string.discord_download_button const val DOWNLOAD_BUTTON_URL = "https://komikku-app.github.io/download/" @@ -197,8 +197,8 @@ enum class DiscordScreen( } // Constants for standard Rich Presence image urls -private const val KOMIKKU_IMAGE_URL = "emojis/1401719615536500916.webp?quality=lossless" -private const val KOMIKKU_PREVIEW_IMAGE_URL = "emojis/1401732831314575401.webp?quality=lossless" +private const val KOMIKKU_IMAGE_URL = "emojis/1365538288894738532.webp?quality=lossless" +private const val KOMIKKU_PREVIEW_IMAGE_URL = "emojis/1365538288894738532.webp?quality=lossless" private val KOMIKKU_IMAGE = if (isPreviewBuildType) KOMIKKU_PREVIEW_IMAGE_URL else KOMIKKU_IMAGE_URL private const val LIBRARY_IMAGE_URL = "emojis/1365262809050644591.webp?quality=lossless" diff --git a/i18n-kmk/src/commonMain/moko-resources/base/strings.xml b/i18n-kmk/src/commonMain/moko-resources/base/strings.xml index 546a887e4..5a8cf2272 100644 --- a/i18n-kmk/src/commonMain/moko-resources/base/strings.xml +++ b/i18n-kmk/src/commonMain/moko-resources/base/strings.xml @@ -181,7 +181,7 @@ Special Services Connections Discord, more to come.. - Configure Discord RPC + Open to configure Discord RPC Discord This Discord Service works through token logging. Use at your own risk. Your token is stored locally and %s does not share it anywhere else Discord Rich Presence