Further splitting the translation class into more methods to simplify recompositions
This commit is contained in:
+182
-142
@@ -49,33 +49,32 @@ fun TranslatableRichTextViewer(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit
|
||||
) {
|
||||
var translatedTextState by remember {
|
||||
mutableStateOf(ResultOrError(content, null, null, null))
|
||||
}
|
||||
|
||||
var showOriginal by remember { mutableStateOf(false) }
|
||||
var langSettingsPopupExpanded by remember { mutableStateOf(false) }
|
||||
|
||||
TranslateAndWatchLanguageChanges(content, accountViewModel) { result, newShowOriginal ->
|
||||
if (translatedTextState.result != result.result ||
|
||||
translatedTextState.sourceLang != result.sourceLang ||
|
||||
translatedTextState.targetLang != result.targetLang
|
||||
) {
|
||||
translatedTextState = result
|
||||
}
|
||||
|
||||
if (showOriginal != newShowOriginal) {
|
||||
showOriginal = newShowOriginal
|
||||
}
|
||||
}
|
||||
|
||||
val toBeViewed by remember(translatedTextState) {
|
||||
derivedStateOf {
|
||||
if (showOriginal) content else translatedTextState.result ?: content
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
var translatedTextState by remember {
|
||||
mutableStateOf(ResultOrError(content, null, null, null))
|
||||
}
|
||||
|
||||
var showOriginal by remember { mutableStateOf(false) }
|
||||
|
||||
TranslateAndWatchLanguageChanges(content, accountViewModel) { result, newShowOriginal ->
|
||||
if (translatedTextState.result != result.result ||
|
||||
translatedTextState.sourceLang != result.sourceLang ||
|
||||
translatedTextState.targetLang != result.targetLang
|
||||
) {
|
||||
translatedTextState = result
|
||||
}
|
||||
|
||||
if (showOriginal != newShowOriginal) {
|
||||
showOriginal = newShowOriginal
|
||||
}
|
||||
}
|
||||
|
||||
val toBeViewed by remember(translatedTextState) {
|
||||
derivedStateOf {
|
||||
if (showOriginal) content else translatedTextState.result ?: content
|
||||
}
|
||||
}
|
||||
|
||||
ExpandableRichTextViewer(
|
||||
toBeViewed,
|
||||
canPreview,
|
||||
@@ -86,69 +85,174 @@ fun TranslatableRichTextViewer(
|
||||
nav
|
||||
)
|
||||
|
||||
val target = translatedTextState.targetLang
|
||||
val source = translatedTextState.sourceLang
|
||||
|
||||
if (source != null && target != null && source != target) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 5.dp)
|
||||
if (translatedTextState.sourceLang != null &&
|
||||
translatedTextState.targetLang != null &&
|
||||
translatedTextState.sourceLang != translatedTextState.targetLang
|
||||
) {
|
||||
TranslationMessage(
|
||||
translatedTextState.sourceLang!!,
|
||||
translatedTextState.targetLang!!,
|
||||
accountViewModel
|
||||
) {
|
||||
val clickableTextStyle =
|
||||
SpanStyle(color = MaterialTheme.colors.primary.copy(alpha = 0.52f))
|
||||
showOriginal = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val annotatedTranslationString = buildAnnotatedString {
|
||||
withStyle(clickableTextStyle) {
|
||||
pushStringAnnotation("langSettings", true.toString())
|
||||
append(stringResource(R.string.translations_auto))
|
||||
}
|
||||
@Composable
|
||||
private fun TranslationMessage(
|
||||
source: String,
|
||||
target: String,
|
||||
accountViewModel: AccountViewModel,
|
||||
onChangeWhatToShow: (Boolean) -> Unit
|
||||
) {
|
||||
var langSettingsPopupExpanded by remember { mutableStateOf(false) }
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
append("-${stringResource(R.string.translations_translated_from)} ")
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 5.dp)
|
||||
) {
|
||||
val clickableTextStyle =
|
||||
SpanStyle(color = MaterialTheme.colors.primary.copy(alpha = 0.52f))
|
||||
|
||||
withStyle(clickableTextStyle) {
|
||||
pushStringAnnotation("showOriginal", true.toString())
|
||||
append(Locale(source).displayName)
|
||||
}
|
||||
val annotatedTranslationString = buildAnnotatedString {
|
||||
withStyle(clickableTextStyle) {
|
||||
pushStringAnnotation("langSettings", true.toString())
|
||||
append(stringResource(R.string.translations_auto))
|
||||
}
|
||||
|
||||
append(" ${stringResource(R.string.translations_to)} ")
|
||||
append("-${stringResource(R.string.translations_translated_from)} ")
|
||||
|
||||
withStyle(clickableTextStyle) {
|
||||
pushStringAnnotation("showOriginal", false.toString())
|
||||
append(Locale(target).displayName)
|
||||
withStyle(clickableTextStyle) {
|
||||
pushStringAnnotation("showOriginal", true.toString())
|
||||
append(Locale(source).displayName)
|
||||
}
|
||||
|
||||
append(" ${stringResource(R.string.translations_to)} ")
|
||||
|
||||
withStyle(clickableTextStyle) {
|
||||
pushStringAnnotation("showOriginal", false.toString())
|
||||
append(Locale(target).displayName)
|
||||
}
|
||||
}
|
||||
|
||||
ClickableText(
|
||||
text = annotatedTranslationString,
|
||||
style = LocalTextStyle.current.copy(
|
||||
color = MaterialTheme.colors.onSurface.copy(
|
||||
alpha = 0.32f
|
||||
)
|
||||
),
|
||||
overflow = TextOverflow.Visible,
|
||||
maxLines = 3
|
||||
) { spanOffset ->
|
||||
annotatedTranslationString.getStringAnnotations(spanOffset, spanOffset)
|
||||
.firstOrNull()
|
||||
?.also { span ->
|
||||
if (span.tag == "showOriginal") {
|
||||
onChangeWhatToShow(span.item.toBoolean())
|
||||
} else {
|
||||
langSettingsPopupExpanded = !langSettingsPopupExpanded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClickableText(
|
||||
text = annotatedTranslationString,
|
||||
style = LocalTextStyle.current.copy(color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)),
|
||||
overflow = TextOverflow.Visible,
|
||||
maxLines = 3
|
||||
) { spanOffset ->
|
||||
annotatedTranslationString.getStringAnnotations(spanOffset, spanOffset)
|
||||
.firstOrNull()
|
||||
?.also { span ->
|
||||
if (span.tag == "showOriginal") {
|
||||
showOriginal = span.item.toBoolean()
|
||||
} else {
|
||||
langSettingsPopupExpanded = !langSettingsPopupExpanded
|
||||
}
|
||||
}
|
||||
DropdownMenu(
|
||||
expanded = langSettingsPopupExpanded,
|
||||
onDismissRequest = { langSettingsPopupExpanded = false }
|
||||
) {
|
||||
DropdownMenuItem(onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.dontTranslateFrom(source)
|
||||
langSettingsPopupExpanded = false
|
||||
}
|
||||
}) {
|
||||
if (source in accountViewModel.account.dontTranslateFrom) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.size(24.dp))
|
||||
}
|
||||
|
||||
DropdownMenu(
|
||||
expanded = langSettingsPopupExpanded,
|
||||
onDismissRequest = { langSettingsPopupExpanded = false }
|
||||
) {
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(
|
||||
stringResource(
|
||||
R.string.translations_never_translate_from_lang,
|
||||
Locale(source).displayName
|
||||
)
|
||||
)
|
||||
}
|
||||
Divider()
|
||||
DropdownMenuItem(onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.prefer(source, target, source)
|
||||
langSettingsPopupExpanded = false
|
||||
}
|
||||
}) {
|
||||
if (accountViewModel.account.preferenceBetween(source, target) == source) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.size(24.dp))
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(
|
||||
stringResource(
|
||||
R.string.translations_show_in_lang_first,
|
||||
Locale(source).displayName
|
||||
)
|
||||
)
|
||||
}
|
||||
DropdownMenuItem(onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.prefer(source, target, target)
|
||||
langSettingsPopupExpanded = false
|
||||
}
|
||||
}) {
|
||||
if (accountViewModel.account.preferenceBetween(source, target) == target) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.size(24.dp))
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(
|
||||
stringResource(
|
||||
R.string.translations_show_in_lang_first,
|
||||
Locale(target).displayName
|
||||
)
|
||||
)
|
||||
}
|
||||
Divider()
|
||||
|
||||
val languageList =
|
||||
ConfigurationCompat.getLocales(Resources.getSystem().configuration)
|
||||
for (i in 0 until languageList.size()) {
|
||||
languageList.get(i)?.let { lang ->
|
||||
DropdownMenuItem(onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.dontTranslateFrom(source)
|
||||
accountViewModel.translateTo(lang)
|
||||
langSettingsPopupExpanded = false
|
||||
}
|
||||
}) {
|
||||
if (source in accountViewModel.account.dontTranslateFrom) {
|
||||
if (lang.language in accountViewModel.account.translateTo) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null,
|
||||
@@ -160,76 +264,12 @@ fun TranslatableRichTextViewer(
|
||||
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(stringResource(R.string.translations_never_translate_from_lang, Locale(source).displayName))
|
||||
}
|
||||
Divider()
|
||||
DropdownMenuItem(onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.prefer(source, target, source)
|
||||
langSettingsPopupExpanded = false
|
||||
}
|
||||
}) {
|
||||
if (accountViewModel.account.preferenceBetween(source, target) == source) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp)
|
||||
Text(
|
||||
stringResource(
|
||||
R.string.translations_always_translate_to_lang,
|
||||
lang.displayName
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.size(24.dp))
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(stringResource(R.string.translations_show_in_lang_first, Locale(source).displayName))
|
||||
}
|
||||
DropdownMenuItem(onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.prefer(source, target, target)
|
||||
langSettingsPopupExpanded = false
|
||||
}
|
||||
}) {
|
||||
if (accountViewModel.account.preferenceBetween(source, target) == target) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.size(24.dp))
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(stringResource(R.string.translations_show_in_lang_first, Locale(target).displayName))
|
||||
}
|
||||
Divider()
|
||||
|
||||
val languageList =
|
||||
ConfigurationCompat.getLocales(Resources.getSystem().configuration)
|
||||
for (i in 0 until languageList.size()) {
|
||||
languageList.get(i)?.let { lang ->
|
||||
DropdownMenuItem(onClick = {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
accountViewModel.translateTo(lang)
|
||||
langSettingsPopupExpanded = false
|
||||
}
|
||||
}) {
|
||||
if (lang.language in accountViewModel.account.translateTo) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
} else {
|
||||
Spacer(modifier = Modifier.size(24.dp))
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(stringResource(R.string.translations_always_translate_to_lang, lang.displayName))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user