Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/src/main/java/dev/dimension/flare/ui/AppContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fun FlareApp(content: @Composable () -> Unit) {
LocalUriHandler provides uriHandler,
LocalAppearanceSettings provides appearanceSettings,
LocalComponentAppearance provides
remember(appearanceSettings, appSettings.aiConfig) {
remember(appearanceSettings, appSettings.translateConfig, appSettings.aiConfig.tldr) {
ComponentAppearance(
dynamicTheme = appearanceSettings.dynamicTheme,
avatarShape =
Expand All @@ -86,7 +86,7 @@ fun FlareApp(content: @Composable () -> Unit) {
compatLinkPreview = appearanceSettings.compatLinkPreview,
aiConfig =
ComponentAppearance.AiConfig(
translation = appSettings.aiConfig.translation,
translation = true,
tldr = appSettings.aiConfig.tldr,
),
fullWidthPost = appearanceSettings.fullWidthPost,
Expand Down

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@
<string name="settings_ai_config_tldr_description">对长篇文章启用 AI 摘要,仅在超过 500 个字符的帖子中可用</string>
<string name="settings_ai_config_translate_prompt">翻译提示</string>
<string name="settings_ai_config_tldr_prompt">摘要提示</string>
<string name="settings_ai_config_translate_provider">翻译服务提供商</string>
<string name="settings_ai_config_translate_provider_description">选择处理翻译的服务提供商</string>
<string name="settings_ai_config_translate_provider_ai">AI</string>
<string name="settings_ai_config_translate_provider_google">谷歌翻译</string>
<string name="settings_language_title">语言</string>
<string name="settings_language_description">更改应用程序的语言</string>
<string name="settings_rss_management_title">RSS 管理</string>
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,14 @@
<string name="settings_ai_config_translation_description">Replace Google Translate with AI translation, might take longer time</string>
<string name="settings_ai_config_enable_tldr">Enable AI Summarization</string>
<string name="settings_ai_config_tldr_description">Enable AI summarization for long posts, only available in post that longer than 500 characters</string>
<string name="settings_ai_config_enable_pre_translation">Enable pre-translation</string>
<string name="settings_ai_config_pre_translation_description">Translate and cache newly loaded timeline and profile content in the background. This can consume a large amount of tokens.</string>
<string name="settings_ai_config_translate_prompt">Translation Prompt</string>
<string name="settings_ai_config_tldr_prompt">Summary Prompt</string>
<string name="settings_ai_config_translate_provider">Translation Provider</string>
<string name="settings_ai_config_translate_provider_description">Choose which service handles translation</string>
<string name="settings_ai_config_translate_provider_ai">AI</string>
<string name="settings_ai_config_translate_provider_google">Google Translate</string>
<string name="settings_language_title">Language</string>
<string name="settings_language_description">Change the language of the app</string>
<string name="settings_rss_management_title">RSS Management</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@
<string name="reply_to">回复 %1$s</string>
<string name="status_detail_translate">翻译帖子</string>
<string name="status_detail_tldr">摘要帖子</string>
<string name="translation_badge_translated">已翻译</string>
<string name="translation_badge_translating">翻译中</string>
<string name="translation_badge_failed">翻译失败</string>
<string name="translation_retry">重试翻译</string>
<string name="translation_show_original">显示原文</string>
<string name="date_format_year_month_day">yyyy年MMMdd日</string>
<string name="date_format_month_day">MMMdd日</string>
<string name="date_format_full">yyyy年MMMdd日 HH:mm</string>
Expand Down
5 changes: 5 additions & 0 deletions compose-ui/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@
<string name="reply_to">Reply to %1$s</string>
<string name="status_detail_translate">Translate Post</string>
<string name="status_detail_tldr">Summary Post</string>
<string name="translation_badge_translated">Translated</string>
<string name="translation_badge_translating">Translating</string>
<string name="translation_badge_failed">Failed</string>
<string name="translation_retry">Retry translation</string>
<string name="translation_show_original">Show original</string>

<string name="date_format_year_month_day">dd MMM yy</string>
<string name="date_format_month_day">dd MMM</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.dimension.flare.ui.component

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
Expand Down Expand Up @@ -46,12 +47,13 @@ import dev.dimension.flare.compose.ui.profile_header_button_following
import dev.dimension.flare.compose.ui.profile_header_button_is_fans
import dev.dimension.flare.compose.ui.profile_header_button_requested
import dev.dimension.flare.model.MicroBlogKey
import dev.dimension.flare.ui.component.placeholder
import dev.dimension.flare.ui.component.platform.PlatformErrorButton
import dev.dimension.flare.ui.component.platform.PlatformFilledTonalButton
import dev.dimension.flare.ui.component.platform.PlatformOutlinedButton
import dev.dimension.flare.ui.component.platform.PlatformText
import dev.dimension.flare.ui.component.platform.isBigScreen
import dev.dimension.flare.ui.component.status.TranslationDisplayBadge
import dev.dimension.flare.ui.model.TranslationDisplayState
import dev.dimension.flare.ui.model.UiProfile
import dev.dimension.flare.ui.model.UiRelation
import dev.dimension.flare.ui.model.UiState
Expand Down Expand Up @@ -271,6 +273,11 @@ private fun ProfileHeaderSuccess(
)
}
}
AnimatedVisibility(user.translationDisplayState != TranslationDisplayState.Hidden) {
TranslationDisplayBadge(
state = user.translationDisplayState,
)
}
},
content = {
user.description?.let {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.dimension.flare.ui.component.status

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background
Expand Down Expand Up @@ -46,16 +47,15 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import compose.icons.FontAwesomeIcons
import compose.icons.fontawesomeicons.Solid
import compose.icons.fontawesomeicons.regular.Bookmark
import compose.icons.fontawesomeicons.solid.At
import compose.icons.fontawesomeicons.solid.Bookmark
import compose.icons.fontawesomeicons.solid.Ellipsis
import compose.icons.fontawesomeicons.solid.Globe
import compose.icons.fontawesomeicons.solid.Image
import compose.icons.fontawesomeicons.solid.Language
import compose.icons.fontawesomeicons.solid.Lock
import compose.icons.fontawesomeicons.solid.LockOpen
import compose.icons.fontawesomeicons.solid.Reply
import compose.icons.fontawesomeicons.solid.Retweet
import compose.icons.fontawesomeicons.solid.TriangleExclamation
import compose.icons.fontawesomeicons.solid.Tv
import dev.dimension.flare.compose.ui.Res
import dev.dimension.flare.compose.ui.bookmark_add
Expand Down Expand Up @@ -88,6 +88,8 @@ import dev.dimension.flare.compose.ui.share
import dev.dimension.flare.compose.ui.show_media
import dev.dimension.flare.compose.ui.status_detail_tldr
import dev.dimension.flare.compose.ui.status_detail_translate
import dev.dimension.flare.compose.ui.translation_retry
import dev.dimension.flare.compose.ui.translation_show_original
import dev.dimension.flare.compose.ui.unlike
import dev.dimension.flare.compose.ui.user_block
import dev.dimension.flare.compose.ui.user_block_with_parameter
Expand All @@ -112,6 +114,7 @@ import dev.dimension.flare.ui.component.RichText
import dev.dimension.flare.ui.component.placeholder
import dev.dimension.flare.ui.component.platform.PlatformCard
import dev.dimension.flare.ui.component.platform.PlatformCheckbox
import dev.dimension.flare.ui.component.platform.PlatformCircularProgressIndicator
import dev.dimension.flare.ui.component.platform.PlatformDropdownMenuDivider
import dev.dimension.flare.ui.component.platform.PlatformDropdownMenuItem
import dev.dimension.flare.ui.component.platform.PlatformDropdownMenuScope
Expand All @@ -122,6 +125,7 @@ import dev.dimension.flare.ui.component.platform.PlatformTextButton
import dev.dimension.flare.ui.component.platform.PlatformTextStyle
import dev.dimension.flare.ui.component.toImageVector
import dev.dimension.flare.ui.model.ClickContext
import dev.dimension.flare.ui.model.TranslationDisplayState
import dev.dimension.flare.ui.model.UiCard
import dev.dimension.flare.ui.model.UiMedia
import dev.dimension.flare.ui.model.UiPoll
Expand Down Expand Up @@ -208,6 +212,13 @@ public fun CommonStatusComponent(
tint = PlatformTheme.colorScheme.caption,
)
}
AnimatedVisibility(
visible = item.translationDisplayState != TranslationDisplayState.Hidden,
) {
TranslationDisplayBadge(
state = item.translationDisplayState,
)
}
if (appearanceSettings.showPlatformLogo) {
FAIcon(
imageVector = item.platformType.brandIcon,
Expand Down Expand Up @@ -309,6 +320,7 @@ public fun CommonStatusComponent(

if (isDetail && !item.content.isEmpty && appearanceSettings.showTranslateButton) {
TranslationComponent(
item = item,
statusKey = item.itemKey,
contentWarning = item.contentWarning,
rawContent = item.content.innerText,
Expand Down Expand Up @@ -625,8 +637,45 @@ private fun StatusReactionComponent(
}
}

@Composable
internal fun TranslationDisplayBadge(
state: TranslationDisplayState,
modifier: Modifier = Modifier,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
FAIcon(
FontAwesomeIcons.Solid.Language,
contentDescription = null,
tint = PlatformTheme.colorScheme.caption,
)
AnimatedContent(state) { state ->
when (state) {
TranslationDisplayState.Translating ->
PlatformCircularProgressIndicator(
modifier = Modifier.size(12.dp),
color = PlatformTheme.colorScheme.caption,
)

TranslationDisplayState.Translated -> Unit
TranslationDisplayState.Failed ->
FAIcon(
FontAwesomeIcons.Solid.TriangleExclamation,
contentDescription = null,
tint = PlatformTheme.colorScheme.caption,
modifier = Modifier.size(12.dp),
)
TranslationDisplayState.Hidden -> Unit
}
}
}
}

@Composable
private fun TranslationComponent(
item: UiTimelineV2.Post,
statusKey: String,
contentWarning: UiRichText?,
rawContent: String,
Expand Down Expand Up @@ -700,6 +749,7 @@ private fun TranslationComponent(
"translate_${contentWarning}_${rawContent}_${Locale.current.language}_${componentAppearance.aiConfig.translation}",
) {
statusTranslatePresenter(
item = item,
contentWarning = contentWarning,
content = content,
targetLanguage = Locale.current.language,
Expand Down Expand Up @@ -813,9 +863,13 @@ internal fun StatusActions(
when (action) {
is ActionMenu.Group -> {
StatusActionGroup(
icon = action.displayItem.icon?.toImageVector() ?: FontAwesomeIcons.Solid.Ellipsis,
icon =
action.displayItem.icon?.toImageVector()
?: FontAwesomeIcons.Solid.Ellipsis,
number = action.displayItem.count,
color = action.displayItem.color?.toComposeColor() ?: PlatformContentColor.current,
color =
action.displayItem.color?.toComposeColor()
?: PlatformContentColor.current,
withTextMinWidth = index != items.lastIndex,
) { closeMenu, isMenuShown ->
action.actions.fastForEach { subActions ->
Expand All @@ -834,7 +888,10 @@ internal fun StatusActions(

is ActionMenu.Item -> {
StatusActionButton(
icon = action.icon?.toImageVector() ?: FontAwesomeIcons.Solid.Ellipsis, // Fallback or handle null
icon =
action.icon?.toImageVector()
?: FontAwesomeIcons.Solid.Ellipsis,
// Fallback or handle null
number = action.count,
color = action.color?.toComposeColor() ?: PlatformContentColor.current,
withTextMinWidth = index != items.lastIndex,
Expand Down Expand Up @@ -931,6 +988,9 @@ private fun ActionMenu.Item.Text.asString(): String =
ActionMenu.Item.Text.Localized.Type.MuteWithHandleParameter -> Res.string.user_mute_with_parameter
ActionMenu.Item.Text.Localized.Type.AcceptFollowRequest -> Res.string.more
ActionMenu.Item.Text.Localized.Type.RejectFollowRequest -> Res.string.more
ActionMenu.Item.Text.Localized.Type.RetryTranslation -> Res.string.translation_retry
ActionMenu.Item.Text.Localized.Type.Translate -> Res.string.status_detail_translate
ActionMenu.Item.Text.Localized.Type.ShowOriginal -> Res.string.translation_show_original
}
stringResource(resource, *parameters.toTypedArray())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.dimension.flare.ui.component.status

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand All @@ -16,6 +17,7 @@ import dev.dimension.flare.ui.component.DateTimeText
import dev.dimension.flare.ui.component.NetworkImage
import dev.dimension.flare.ui.component.platform.PlatformText
import dev.dimension.flare.ui.model.ClickContext
import dev.dimension.flare.ui.model.TranslationDisplayState
import dev.dimension.flare.ui.model.UiTimelineV2
import dev.dimension.flare.ui.theme.PlatformTheme
import dev.dimension.flare.ui.theme.screenHorizontalPadding
Expand Down Expand Up @@ -56,6 +58,11 @@ internal fun FeedComponent(
modifier = Modifier.weight(1f),
maxLines = 1,
)
AnimatedVisibility(data.translationDisplayState != TranslationDisplayState.Hidden) {
TranslationDisplayBadge(
state = data.translationDisplayState,
)
}
data.actualCreatedAt?.let {
DateTimeText(
it,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,56 @@ package dev.dimension.flare.ui.component.status
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import dev.dimension.flare.ui.model.UiState
import dev.dimension.flare.ui.model.UiTimelineV2
import dev.dimension.flare.ui.presenter.invoke
import dev.dimension.flare.ui.presenter.server.AiTLDRPresenter
import dev.dimension.flare.ui.presenter.status.StatusTranslationPayload
import dev.dimension.flare.ui.presenter.status.TranslateCacheTarget
import dev.dimension.flare.ui.presenter.status.TranslatePresenter
import dev.dimension.flare.ui.render.UiRichText
import dev.dimension.flare.ui.render.toTranslatableText

@Composable
internal fun statusTranslatePresenter(
item: UiTimelineV2.Post,
contentWarning: UiRichText?,
content: UiRichText,
targetLanguage: String,
): TranslateResult {
val contentWarningState =
contentWarning?.takeIf { !it.isEmpty }?.let {
translateText(it, targetLanguage)
translateText(
text = it,
targetLanguage = targetLanguage,
cacheTarget =
TranslateCacheTarget(
accountType = item.accountType,
statusKey = item.statusKey,
payload =
StatusTranslationPayload(
content = content,
contentWarning = contentWarning,
),
field = TranslateCacheTarget.Field.ContentWarning,
),
)
}
val textState = translateText(content, targetLanguage)
val textState =
translateText(
text = content,
targetLanguage = targetLanguage,
cacheTarget =
TranslateCacheTarget(
accountType = item.accountType,
statusKey = item.statusKey,
payload =
StatusTranslationPayload(
content = content,
contentWarning = contentWarning,
),
field = TranslateCacheTarget.Field.Content,
),
)
return TranslateResult(
contentWarning = contentWarningState,
text = textState,
Expand All @@ -30,9 +63,10 @@ internal fun statusTranslatePresenter(
private fun translateText(
text: UiRichText,
targetLanguage: String,
cacheTarget: TranslateCacheTarget? = null,
) = run {
remember(text, targetLanguage) {
TranslatePresenter(text, targetLanguage)
remember(text, targetLanguage, cacheTarget) {
TranslatePresenter(text, targetLanguage, cacheTarget)
}.invoke()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal fun ProvideThemeSettings(content: @Composable () -> Unit) {
CompositionLocalProvider(
LocalAppearanceSettings provides appearanceSettings,
LocalComponentAppearance provides
remember(appearanceSettings, appSettings.aiConfig) {
remember(appearanceSettings, appSettings.translateConfig, appSettings.aiConfig.tldr) {
ComponentAppearance(
dynamicTheme = appearanceSettings.dynamicTheme,
avatarShape =
Expand All @@ -51,7 +51,7 @@ internal fun ProvideThemeSettings(content: @Composable () -> Unit) {
compatLinkPreview = appearanceSettings.compatLinkPreview,
aiConfig =
ComponentAppearance.AiConfig(
translation = appSettings.aiConfig.translation,
translation = true,
tldr = appSettings.aiConfig.tldr,
),
fullWidthPost = appearanceSettings.fullWidthPost,
Expand Down
Loading
Loading