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
This commit is contained in:
Cuong-Tran 2025-10-13 14:38:27 +07:00 committed by GitHub
parent d15fa402df
commit 317a21adc0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 54 additions and 25 deletions

View file

@ -164,9 +164,9 @@ sealed class Preference {
override val title: String,
val login: () -> Unit,
val openSettings: () -> Unit,
override val subtitle: String? = null,
) : PreferenceItem<String>() {
override val enabled: Boolean = true
override val subtitle: String? = null
override val icon: ImageVector? = null
override val onValueChanged: suspend (newValue: String) -> Boolean = { true }
}

View file

@ -176,14 +176,14 @@ internal fun PreferenceItem(
}
// AM (CONNECTIONS) -->
is Preference.PreferenceItem.ConnectionPreference -> {
item.service.run {
val isLoggedIn by item.service.isLoggedInFlow.collectAsState(item.service.isLogged)
ConnectionPreferenceWidget(
service = this,
checked = isLogged,
onClick = { if (isLogged) item.openSettings() else item.login() },
service = item.service,
checked = isLoggedIn,
onClick = { if (isLoggedIn) item.openSettings() else item.login() },
subtitle = item.subtitle,
)
}
}
// <-- AM (CONNECTIONS)
is Preference.PreferenceItem.InfoPreference -> {
InfoWidget(text = item.title)

View file

@ -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)),
),

View file

@ -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),
.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,

View file

@ -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<Boolean> 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.

View file

@ -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"

View file

@ -181,7 +181,7 @@
<string name="special_services">Special Services</string>
<string name="pref_category_connections">Connections</string>
<string name="pref_connections_summary">Discord, more to come..</string>
<string name="pref_discord_configuration">Configure Discord RPC</string>
<string name="pref_discord_configuration">Open to configure Discord RPC</string>
<string name="connections_discord">Discord</string>
<string name="connections_discord_info">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</string>
<string name="pref_discord_rpc">Discord Rich Presence</string>