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:
parent
d15fa402df
commit
317a21adc0
7 changed files with 54 additions and 25 deletions
|
|
@ -164,9 +164,9 @@ sealed class Preference {
|
||||||
override val title: String,
|
override val title: String,
|
||||||
val login: () -> Unit,
|
val login: () -> Unit,
|
||||||
val openSettings: () -> Unit,
|
val openSettings: () -> Unit,
|
||||||
|
override val subtitle: String? = null,
|
||||||
) : PreferenceItem<String>() {
|
) : PreferenceItem<String>() {
|
||||||
override val enabled: Boolean = true
|
override val enabled: Boolean = true
|
||||||
override val subtitle: String? = null
|
|
||||||
override val icon: ImageVector? = null
|
override val icon: ImageVector? = null
|
||||||
override val onValueChanged: suspend (newValue: String) -> Boolean = { true }
|
override val onValueChanged: suspend (newValue: String) -> Boolean = { true }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -176,13 +176,13 @@ internal fun PreferenceItem(
|
||||||
}
|
}
|
||||||
// AM (CONNECTIONS) -->
|
// AM (CONNECTIONS) -->
|
||||||
is Preference.PreferenceItem.ConnectionPreference -> {
|
is Preference.PreferenceItem.ConnectionPreference -> {
|
||||||
item.service.run {
|
val isLoggedIn by item.service.isLoggedInFlow.collectAsState(item.service.isLogged)
|
||||||
ConnectionPreferenceWidget(
|
ConnectionPreferenceWidget(
|
||||||
service = this,
|
service = item.service,
|
||||||
checked = isLogged,
|
checked = isLoggedIn,
|
||||||
onClick = { if (isLogged) item.openSettings() else item.login() },
|
onClick = { if (isLoggedIn) item.openSettings() else item.login() },
|
||||||
)
|
subtitle = item.subtitle,
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
// <-- AM (CONNECTIONS)
|
// <-- AM (CONNECTIONS)
|
||||||
is Preference.PreferenceItem.InfoPreference -> {
|
is Preference.PreferenceItem.InfoPreference -> {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -80,23 +81,21 @@ object SettingsConnectionScreen : SearchableSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isLoggedIn by connectionsManager.discord.isLoggedInFlow.collectAsState(connectionsManager.discord.isLogged)
|
||||||
|
|
||||||
return listOf(
|
return listOf(
|
||||||
Preference.PreferenceGroup(
|
Preference.PreferenceGroup(
|
||||||
title = stringResource(KMR.strings.special_services),
|
title = stringResource(KMR.strings.special_services),
|
||||||
preferenceItems = persistentListOf(
|
preferenceItems = persistentListOf(
|
||||||
Preference.PreferenceItem.ConnectionPreference(
|
Preference.PreferenceItem.ConnectionPreference(
|
||||||
title = stringResource(connectionsManager.discord.nameStrRes()),
|
title = stringResource(connectionsManager.discord.nameStrRes()),
|
||||||
|
subtitle = stringResource(KMR.strings.pref_discord_configuration).takeIf { isLoggedIn },
|
||||||
service = connectionsManager.discord,
|
service = connectionsManager.discord,
|
||||||
login = {
|
login = {
|
||||||
navigator.push(DiscordLoginScreen())
|
navigator.push(DiscordLoginScreen())
|
||||||
},
|
},
|
||||||
openSettings = { navigator.push(SettingsDiscordScreen) },
|
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(
|
Preference.PreferenceItem.InfoPreference(
|
||||||
stringResource(KMR.strings.connections_discord_info, stringResource(MR.strings.app_name)),
|
stringResource(KMR.strings.connections_discord_info, stringResource(MR.strings.app_name)),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@ package eu.kanade.presentation.more.settings.widget
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.sizeIn
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Done
|
import androidx.compose.material.icons.outlined.Done
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
|
@ -19,37 +21,54 @@ import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.presentation.connection.components.ConnectionLogoIcon
|
import eu.kanade.presentation.connection.components.ConnectionLogoIcon
|
||||||
import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted
|
import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted
|
||||||
|
import eu.kanade.presentation.more.settings.LocalPreferenceMinHeight
|
||||||
import eu.kanade.tachiyomi.data.connections.ConnectionsService
|
import eu.kanade.tachiyomi.data.connections.ConnectionsService
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("ModifierNotUsedAtRoot", "MagicNumber")
|
@Suppress("ModifierNotUsedAtRoot", "MagicNumber")
|
||||||
fun ConnectionPreferenceWidget(
|
fun ConnectionPreferenceWidget(
|
||||||
service: ConnectionsService,
|
service: ConnectionsService,
|
||||||
checked: Boolean,
|
checked: Boolean,
|
||||||
|
subtitle: String?,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val highlighted = LocalPreferenceHighlighted.current
|
val highlighted = LocalPreferenceHighlighted.current
|
||||||
|
val minHeight = LocalPreferenceMinHeight.current
|
||||||
Box(modifier = Modifier.highlightBackground(highlighted)) {
|
Box(modifier = Modifier.highlightBackground(highlighted)) {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
|
.sizeIn(minHeight = minHeight)
|
||||||
.clickable(enabled = onClick != null, onClick = { onClick?.invoke() })
|
.clickable(enabled = onClick != null, onClick = { onClick?.invoke() })
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = PrefsHorizontalPadding, vertical = 8.dp),
|
.padding(horizontal = PrefsHorizontalPadding),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
ConnectionLogoIcon(service)
|
ConnectionLogoIcon(service)
|
||||||
Text(
|
Column(
|
||||||
text = stringResource(service.nameStrRes()),
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = PrefsHorizontalPadding),
|
||||||
maxLines = 1,
|
) {
|
||||||
style = MaterialTheme.typography.titleLarge,
|
Text(
|
||||||
fontSize = TitleFontSize,
|
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) {
|
if (checked) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Outlined.Done,
|
imageVector = Icons.Outlined.Done,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import androidx.annotation.DrawableRes
|
||||||
import dev.icerock.moko.resources.StringResource
|
import dev.icerock.moko.resources.StringResource
|
||||||
import eu.kanade.domain.connections.service.ConnectionsPreferences
|
import eu.kanade.domain.connections.service.ConnectionsPreferences
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
|
@ -52,6 +54,15 @@ abstract class ConnectionsService(val id: Long) {
|
||||||
get() = getUsername().isNotEmpty() &&
|
get() = getUsername().isNotEmpty() &&
|
||||||
getPassword().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.
|
* Override this method in token-based services to retrieve the token.
|
||||||
* Default implementation returns an empty string.
|
* Default implementation returns an empty string.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import kotlinx.serialization.json.JsonElement
|
||||||
const val RICH_PRESENCE_TAG = "discord_rpc"
|
const val RICH_PRESENCE_TAG = "discord_rpc"
|
||||||
|
|
||||||
// Constant for application id
|
// 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
|
val DOWNLOAD_BUTTON_LABEL_RES = R.string.discord_download_button
|
||||||
const val DOWNLOAD_BUTTON_URL = "https://komikku-app.github.io/download/"
|
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
|
// Constants for standard Rich Presence image urls
|
||||||
private const val KOMIKKU_IMAGE_URL = "emojis/1401719615536500916.webp?quality=lossless"
|
private const val KOMIKKU_IMAGE_URL = "emojis/1365538288894738532.webp?quality=lossless"
|
||||||
private const val KOMIKKU_PREVIEW_IMAGE_URL = "emojis/1401732831314575401.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 val KOMIKKU_IMAGE = if (isPreviewBuildType) KOMIKKU_PREVIEW_IMAGE_URL else KOMIKKU_IMAGE_URL
|
||||||
private const val LIBRARY_IMAGE_URL = "emojis/1365262809050644591.webp?quality=lossless"
|
private const val LIBRARY_IMAGE_URL = "emojis/1365262809050644591.webp?quality=lossless"
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@
|
||||||
<string name="special_services">Special Services</string>
|
<string name="special_services">Special Services</string>
|
||||||
<string name="pref_category_connections">Connections</string>
|
<string name="pref_category_connections">Connections</string>
|
||||||
<string name="pref_connections_summary">Discord, more to come..</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">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="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>
|
<string name="pref_discord_rpc">Discord Rich Presence</string>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue