From 04b7ce47a2c5745d1981d07319ef0d069e239401 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Tue, 25 Jun 2024 13:39:14 +0200 Subject: [PATCH] fix: Correctly handle setting / editing a status' language (#780) Previous code set the initial status text, and then set up the callbacks which meant that the status' length was initially 0, even when editing a status. This meant that, e.g., editing a status to change its language would erroneously report the status body was empty. It also meant that editing a status and changing just the language would not prompt to save or discard the changes if moving back. Fix this. First, only set the status content after the callbacks that compute the status length. Second, provide a function that sets the status' language, and update the close confirmation state when the language changes. Modify isDirty() to compare the original and current language when determining if the status is dirty. Fixes #701 --- .../components/compose/ComposeActivity.kt | 18 +++++++-------- .../components/compose/ComposeViewModel.kt | 22 ++++++++++++++----- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/app/pachli/components/compose/ComposeActivity.kt b/app/src/main/java/app/pachli/components/compose/ComposeActivity.kt index 9584e6574..8ae61e7a8 100644 --- a/app/src/main/java/app/pachli/components/compose/ComposeActivity.kt +++ b/app/src/main/java/app/pachli/components/compose/ComposeActivity.kt @@ -413,6 +413,13 @@ class ComposeActivity : ) binding.composeEditField.setTokenizer(ComposeTokenizer()) + val mentionColour = binding.composeEditField.linkTextColors.defaultColor + highlightSpans(binding.composeEditField.text, mentionColour) + binding.composeEditField.doAfterTextChanged { editable -> + highlightSpans(editable!!, mentionColour) + viewModel.onContentChanged(editable) + } + binding.composeEditField.setText(startingText) when (composeOptions?.initialCursorPosition ?: InitialCursorPosition.END) { @@ -422,13 +429,6 @@ class ComposeActivity : ) } - val mentionColour = binding.composeEditField.linkTextColors.defaultColor - highlightSpans(binding.composeEditField.text, mentionColour) - binding.composeEditField.doAfterTextChanged { editable -> - highlightSpans(editable!!, mentionColour) - viewModel.onContentChanged(editable) - } - // work around Android platform bug -> https://issuetracker.google.com/issues/67102093 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O || Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1 @@ -594,7 +594,7 @@ class ComposeActivity : private fun setupLanguageSpinner(initialLanguages: List) { binding.composePostLanguageButton.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) { - viewModel.postLanguage = (parent.adapter.getItem(position) as Locale).modernLanguageCode + viewModel.onLanguageChanged((parent.adapter.getItem(position) as Locale).modernLanguageCode) } override fun onNothingSelected(parent: AdapterView<*>) { @@ -927,7 +927,7 @@ class ComposeActivity : @VisibleForTesting val selectedLanguage: String? - get() = viewModel.postLanguage + get() = viewModel.language private fun updateVisibleCharactersLeft(textLength: Int) { val remainingLength = maximumTootCharacters - textLength diff --git a/app/src/main/java/app/pachli/components/compose/ComposeViewModel.kt b/app/src/main/java/app/pachli/components/compose/ComposeViewModel.kt index 15636a713..e602a14d4 100644 --- a/app/src/main/java/app/pachli/components/compose/ComposeViewModel.kt +++ b/app/src/main/java/app/pachli/components/compose/ComposeViewModel.kt @@ -89,7 +89,11 @@ class ComposeViewModel @Inject constructor( /** The initial content warning for this status, before any edits */ private var initialContentWarning: String = "" - internal var postLanguage: String? = null + /** The initial language for this status, before any changes */ + private var initialLanguage: String? = null + + /** The current language for this status. */ + internal var language: String? = null /** If editing a draft then the ID of the draft, otherwise 0 */ private var draftId: Int = 0 @@ -279,6 +283,12 @@ class ComposeViewModel @Inject constructor( _statusVisibility.value = newVisibility } + /** Call this to change the status' language */ + fun onLanguageChanged(newLanguage: String) { + language = newLanguage + updateCloseConfirmation() + } + @VisibleForTesting fun updateStatusLength() { _statusLength.value = statusLength(content, effectiveContentWarning, instanceInfo.value.charactersReservedPerUrl) @@ -317,8 +327,9 @@ class ComposeViewModel @Inject constructor( val contentWarningChanged = effectiveContentWarning != initialContentWarning val mediaChanged = media.value.isNotEmpty() val pollChanged = poll.value != null + val languageChanged = initialLanguage != language - return modifiedInitialState || contentChanged || contentWarningChanged || mediaChanged || pollChanged || scheduledTimeChanged + return modifiedInitialState || contentChanged || contentWarningChanged || mediaChanged || pollChanged || languageChanged || scheduledTimeChanged } private fun isEmpty(content: CharSequence, contentWarning: CharSequence): Boolean { @@ -375,7 +386,7 @@ class ComposeViewModel @Inject constructor( failedToSend = false, failedToSendAlert = false, scheduledAt = scheduledAt.value, - language = postLanguage, + language = language, statusId = originalStatusId, ) } @@ -418,7 +429,7 @@ class ComposeViewModel @Inject constructor( draftId = draftId, idempotencyKey = randomAlphanumericString(16), retries = 0, - language = postLanguage, + language = language, statusId = originalStatusId, ) @@ -538,7 +549,8 @@ class ComposeViewModel @Inject constructor( scheduledTootId = composeOptions?.scheduledTootId originalStatusId = composeOptions?.statusId initialContent = composeOptions?.content ?: "" - postLanguage = composeOptions?.language + initialLanguage = composeOptions?.language + language = initialLanguage val tootVisibility = composeOptions?.visibility ?: Status.Visibility.UNKNOWN if (tootVisibility != Status.Visibility.UNKNOWN) {