diff --git a/app/autodiscovery/api/build.gradle b/app/autodiscovery/api/build.gradle index 7959cef84e4b46f435b7c4c8039caf904eb2768f..55914b0cc00c4b6fa9b1cff67914897bdd7b8ae7 100644 --- a/app/autodiscovery/api/build.gradle +++ b/app/autodiscovery/api/build.gradle @@ -1,30 +1,11 @@ -apply plugin: 'com.android.library' -apply plugin: 'org.jetbrains.kotlin.android' +apply plugin: 'java-library' +apply plugin: 'kotlin' -dependencies { - implementation project(":app:core") +java { + sourceCompatibility = javaVersion + targetCompatibility = javaVersion } -android { - compileSdkVersion buildConfig.compileSdk - buildToolsVersion buildConfig.buildTools - - defaultConfig { - minSdkVersion buildConfig.minSdk - targetSdkVersion buildConfig.robolectricSdk - } - - lintOptions { - abortOnError false - lintConfig file("$rootProject.projectDir/config/lint/lint.xml") - } - - compileOptions { - sourceCompatibility javaVersion - targetCompatibility javaVersion - } - - kotlinOptions { - jvmTarget = kotlinJvmVersion - } +dependencies { + api project(":mail:common") } diff --git a/app/autodiscovery/api/src/main/AndroidManifest.xml b/app/autodiscovery/api/src/main/AndroidManifest.xml deleted file mode 100644 index f94c1b149c6e6429e56f7f5a50e6830ffbd3fdfc..0000000000000000000000000000000000000000 --- a/app/autodiscovery/api/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/app/autodiscovery/providersxml/build.gradle b/app/autodiscovery/providersxml/build.gradle index 9cd4bae54b3a23ce6a27aa15b683892fd135ecc2..1ec0a36c0bdb26e4f5f1e9e2d71d129fd27b5ca1 100644 --- a/app/autodiscovery/providersxml/build.gradle +++ b/app/autodiscovery/providersxml/build.gradle @@ -16,6 +16,7 @@ dependencies { testImplementation "com.google.truth:truth:${versions.truth}" testImplementation "org.mockito:mockito-inline:${versions.mockito}" testImplementation "org.mockito.kotlin:mockito-kotlin:${versions.mockitoKotlin}" + testImplementation "io.insert-koin:koin-test:${versions.koin}" testImplementation "io.insert-koin:koin-test-junit4:${versions.koin}" } diff --git a/app/autodiscovery/srvrecords/build.gradle b/app/autodiscovery/srvrecords/build.gradle index 061b93041d30f6ec8468bb75d5455abd99ab523c..36a5976850f6e10665675d80e7fb26ccbe7a72b0 100644 --- a/app/autodiscovery/srvrecords/build.gradle +++ b/app/autodiscovery/srvrecords/build.gradle @@ -1,51 +1,18 @@ -apply plugin: 'com.android.library' -apply plugin: 'org.jetbrains.kotlin.android' +apply plugin: 'java-library' +apply plugin: 'kotlin' + +java { + sourceCompatibility = javaVersion + targetCompatibility = javaVersion +} dependencies { - implementation project(":app:core") - implementation project(":mail:common") - implementation project(":app:autodiscovery:api") + api project(":app:autodiscovery:api") - implementation "com.jakewharton.timber:timber:${versions.timber}" implementation "org.minidns:minidns-hla:${versions.minidns}" - testImplementation project(':app:testing') - testImplementation project(":backend:imap") - testImplementation "org.robolectric:robolectric:${versions.robolectric}" - testImplementation "androidx.test:core:${versions.androidxTestCore}" testImplementation "junit:junit:${versions.junit}" testImplementation "com.google.truth:truth:${versions.truth}" testImplementation "org.mockito:mockito-inline:${versions.mockito}" testImplementation "org.mockito.kotlin:mockito-kotlin:${versions.mockitoKotlin}" - testImplementation "io.insert-koin:koin-test-junit4:${versions.koin}" -} - -android { - compileSdkVersion buildConfig.compileSdk - buildToolsVersion buildConfig.buildTools - - defaultConfig { - minSdkVersion buildConfig.minSdk - targetSdkVersion buildConfig.robolectricSdk - } - - lintOptions { - abortOnError false - lintConfig file("$rootProject.projectDir/config/lint/lint.xml") - } - - compileOptions { - sourceCompatibility javaVersion - targetCompatibility javaVersion - } - - kotlinOptions { - jvmTarget = kotlinJvmVersion - } - - testOptions { - unitTests { - includeAndroidResources = true - } - } } diff --git a/app/autodiscovery/srvrecords/src/main/AndroidManifest.xml b/app/autodiscovery/srvrecords/src/main/AndroidManifest.xml deleted file mode 100644 index a18001ee090c7b07bb0a241e44047f68096f3204..0000000000000000000000000000000000000000 --- a/app/autodiscovery/srvrecords/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/app/autodiscovery/srvrecords/src/test/java/com/fsck/k9/autodiscovery/srvrecords/SrvServiceDiscoveryTest.kt b/app/autodiscovery/srvrecords/src/test/java/com/fsck/k9/autodiscovery/srvrecords/SrvServiceDiscoveryTest.kt index 387edb3ff6315415b2bca5cbf9a1a9be4e96a2f5..5123822d74784d1f60a902286ffda99a37de83bc 100644 --- a/app/autodiscovery/srvrecords/src/test/java/com/fsck/k9/autodiscovery/srvrecords/SrvServiceDiscoveryTest.kt +++ b/app/autodiscovery/srvrecords/src/test/java/com/fsck/k9/autodiscovery/srvrecords/SrvServiceDiscoveryTest.kt @@ -1,6 +1,5 @@ package com.fsck.k9.autodiscovery.srvrecords -import com.fsck.k9.RobolectricTest import com.fsck.k9.autodiscovery.api.DiscoveredServerSettings import com.fsck.k9.autodiscovery.api.DiscoveryResults import com.fsck.k9.autodiscovery.api.DiscoveryTarget @@ -12,7 +11,7 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.verifyNoMoreInteractions -class SrvServiceDiscoveryTest : RobolectricTest() { +class SrvServiceDiscoveryTest { @Test fun discover_whenNoMailServices_shouldReturnNoResults() { diff --git a/app/autodiscovery/thunderbird/build.gradle b/app/autodiscovery/thunderbird/build.gradle index 11007e72060ba3d86c8240547c03f612f0d33f3d..dc48d2c50f1b6808269bcffc252fc95629292080 100644 --- a/app/autodiscovery/thunderbird/build.gradle +++ b/app/autodiscovery/thunderbird/build.gradle @@ -1,51 +1,20 @@ -apply plugin: 'com.android.library' -apply plugin: 'org.jetbrains.kotlin.android' +apply plugin: 'java-library' +apply plugin: 'kotlin' + +java { + sourceCompatibility = javaVersion + targetCompatibility = javaVersion +} dependencies { - implementation project(":app:core") - implementation project(":mail:common") - implementation project(":app:autodiscovery:api") + api project(":app:autodiscovery:api") - implementation "com.jakewharton.timber:timber:${versions.timber}" + compileOnly 'com.github.cketti:xmlpull-extracted-from-android:1.0' implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}" - testImplementation project(':app:testing') - testImplementation project(":backend:imap") - testImplementation "org.robolectric:robolectric:${versions.robolectric}" - testImplementation "androidx.test:core:${versions.androidxTestCore}" testImplementation "junit:junit:${versions.junit}" testImplementation "com.google.truth:truth:${versions.truth}" testImplementation "org.mockito:mockito-inline:${versions.mockito}" testImplementation "org.mockito.kotlin:mockito-kotlin:${versions.mockitoKotlin}" - testImplementation "io.insert-koin:koin-test-junit4:${versions.koin}" -} - -android { - compileSdkVersion buildConfig.compileSdk - buildToolsVersion buildConfig.buildTools - - defaultConfig { - minSdkVersion buildConfig.minSdk - targetSdkVersion buildConfig.robolectricSdk - } - - lintOptions { - abortOnError false - lintConfig file("$rootProject.projectDir/config/lint/lint.xml") - } - - compileOptions { - sourceCompatibility javaVersion - targetCompatibility javaVersion - } - - kotlinOptions { - jvmTarget = kotlinJvmVersion - } - - testOptions { - unitTests { - includeAndroidResources = true - } - } + testImplementation 'com.github.cketti:kxml2-extracted-from-android:1.0' } diff --git a/app/autodiscovery/thunderbird/src/main/AndroidManifest.xml b/app/autodiscovery/thunderbird/src/main/AndroidManifest.xml deleted file mode 100644 index b3794dd016a08484904f24864cd35e799e27e15e..0000000000000000000000000000000000000000 --- a/app/autodiscovery/thunderbird/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/app/autodiscovery/thunderbird/src/test/java/com/fsck/k9/autodiscovery/thunderbird/ThunderbirdAutoconfigTest.kt b/app/autodiscovery/thunderbird/src/test/java/com/fsck/k9/autodiscovery/thunderbird/ThunderbirdAutoconfigTest.kt index 3ab8c970fd64be1e312118a9694795fd169e3916..4648f675605391b09c4e6d4c8c88b631b29a2974 100644 --- a/app/autodiscovery/thunderbird/src/test/java/com/fsck/k9/autodiscovery/thunderbird/ThunderbirdAutoconfigTest.kt +++ b/app/autodiscovery/thunderbird/src/test/java/com/fsck/k9/autodiscovery/thunderbird/ThunderbirdAutoconfigTest.kt @@ -1,6 +1,5 @@ package com.fsck.k9.autodiscovery.thunderbird -import com.fsck.k9.RobolectricTest import com.fsck.k9.autodiscovery.api.DiscoveredServerSettings import com.fsck.k9.autodiscovery.api.DiscoveryResults import com.fsck.k9.mail.AuthType @@ -8,7 +7,7 @@ import com.fsck.k9.mail.ConnectionSecurity import com.google.common.truth.Truth.assertThat import org.junit.Test -class ThunderbirdAutoconfigTest : RobolectricTest() { +class ThunderbirdAutoconfigTest { private val parser = ThunderbirdAutoconfigParser() @Test diff --git a/app/core/build.gradle b/app/core/build.gradle index c33b91510ef10003b3f50e787820f853a531d3fc..4434a06286788e36d83cae03d083a3a3ef11760f 100644 --- a/app/core/build.gradle +++ b/app/core/build.gradle @@ -37,6 +37,7 @@ dependencies { testImplementation "org.mockito.kotlin:mockito-kotlin:${versions.mockitoKotlin}" testImplementation "org.jdom:jdom2:2.0.6" testImplementation "io.insert-koin:koin-test:${versions.koin}" + testImplementation "io.insert-koin:koin-test-junit4:${versions.koin}" } android { diff --git a/app/core/src/main/java/com/fsck/k9/Preferences.kt b/app/core/src/main/java/com/fsck/k9/Preferences.kt index eca0f09fb1a7f1621f077ddef1d2eb4a94188ce7..4120025c893ce12826fbbaae503c25688a9482d0 100644 --- a/app/core/src/main/java/com/fsck/k9/Preferences.kt +++ b/app/core/src/main/java/com/fsck/k9/Preferences.kt @@ -3,7 +3,6 @@ package com.fsck.k9 import android.content.Context import androidx.annotation.GuardedBy import androidx.annotation.RestrictTo -import com.fsck.k9.helper.sendBlockingSilently import com.fsck.k9.mail.MessagingException import com.fsck.k9.mailstore.LocalStoreProvider import com.fsck.k9.preferences.AccountManager @@ -19,6 +18,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.callbackFlow @@ -135,7 +135,7 @@ class Preferences internal constructor( val listener = AccountsChangeListener { val account = getAccount(accountUuid) if (account != null) { - sendBlockingSilently(account) + trySendBlocking(account) } else { close() } @@ -155,7 +155,7 @@ class Preferences internal constructor( send(accounts) val listener = AccountsChangeListener { - sendBlockingSilently(accounts) + trySendBlocking(accounts) } addOnAccountsChangeListener(listener) diff --git a/app/core/src/main/java/com/fsck/k9/helper/CallbackFlowHelper.kt b/app/core/src/main/java/com/fsck/k9/helper/CallbackFlowHelper.kt deleted file mode 100644 index 85bc379665919d303cf04023fef1d6b22faad516..0000000000000000000000000000000000000000 --- a/app/core/src/main/java/com/fsck/k9/helper/CallbackFlowHelper.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.fsck.k9.helper - -import kotlinx.coroutines.channels.ClosedSendChannelException -import kotlinx.coroutines.channels.SendChannel -import kotlinx.coroutines.channels.onClosed -import kotlinx.coroutines.channels.onFailure -import kotlinx.coroutines.channels.onSuccess -import kotlinx.coroutines.channels.sendBlocking -import kotlinx.coroutines.channels.trySendBlocking - -/** - * Like [sendBlocking], but ignores [ClosedSendChannelException]. - */ -fun SendChannel.sendBlockingSilently(element: E) { - trySendBlocking(element) - .onSuccess { } - .onFailure { } - .onClosed { } -} diff --git a/app/core/src/main/java/com/fsck/k9/mailstore/FolderRepository.kt b/app/core/src/main/java/com/fsck/k9/mailstore/FolderRepository.kt index f40136d34cc92743470f5526862f172d02815d64..3fcd8f1e3a3ece180da860a31ab7dbfebdd08d9a 100644 --- a/app/core/src/main/java/com/fsck/k9/mailstore/FolderRepository.kt +++ b/app/core/src/main/java/com/fsck/k9/mailstore/FolderRepository.kt @@ -5,7 +5,6 @@ import com.fsck.k9.Account.FolderMode import com.fsck.k9.DI import com.fsck.k9.controller.MessagingController import com.fsck.k9.controller.SimpleMessagingListener -import com.fsck.k9.helper.sendBlockingSilently import com.fsck.k9.mail.FolderClass import com.fsck.k9.preferences.AccountManager import kotlinx.coroutines.CoroutineDispatcher @@ -13,6 +12,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.callbackFlow @@ -65,14 +65,14 @@ class FolderRepository( val folderStatusChangedListener = object : SimpleMessagingListener() { override fun folderStatusChanged(statusChangedAccount: Account, folderId: Long) { if (statusChangedAccount.uuid == account.uuid) { - sendBlockingSilently(getDisplayFolders(account, displayMode)) + trySendBlocking(getDisplayFolders(account, displayMode)) } } } messagingController.addListener(folderStatusChangedListener) val folderSettingsChangedListener = FolderSettingsChangedListener { - sendBlockingSilently(getDisplayFolders(account, displayMode)) + trySendBlocking(getDisplayFolders(account, displayMode)) } messageStore.addFolderSettingsChangedListener(folderSettingsChangedListener) @@ -173,7 +173,7 @@ class FolderRepository( send(getPushFolders(account, folderMode)) val listener = FolderSettingsChangedListener { - sendBlockingSilently(getPushFolders(account, folderMode)) + trySendBlocking(getPushFolders(account, folderMode)) } messageStore.addFolderSettingsChangedListener(listener) diff --git a/app/core/src/main/java/com/fsck/k9/mailstore/LocalFolder.java b/app/core/src/main/java/com/fsck/k9/mailstore/LocalFolder.java index 72441da924306714752ce6c6570af9120a3a253a..406b29bcf1676b28dfec0110022243f2c28a6721 100644 --- a/app/core/src/main/java/com/fsck/k9/mailstore/LocalFolder.java +++ b/app/core/src/main/java/com/fsck/k9/mailstore/LocalFolder.java @@ -925,6 +925,7 @@ public class LocalFolder { db.execSQL("DELETE FROM threads WHERE message_id IN " + "(SELECT id FROM messages WHERE folder_id = ?)", folderIdArg); db.execSQL("DELETE FROM messages WHERE folder_id = ?", folderIdArg); + db.execSQL("DELETE FROM folder_extra_values WHERE folder_id = ?", folderIdArg); setMoreMessages(MoreMessages.UNKNOWN); resetLastChecked(db); diff --git a/app/core/src/main/java/com/fsck/k9/message/TextBodyBuilder.java b/app/core/src/main/java/com/fsck/k9/message/TextBodyBuilder.java index 85aba6d7061705abcf58dbc6d86c7a7e528463b5..eb2235cb1bf75c9b2b43c486c226ede6ab66881a 100644 --- a/app/core/src/main/java/com/fsck/k9/message/TextBodyBuilder.java +++ b/app/core/src/main/java/com/fsck/k9/message/TextBodyBuilder.java @@ -188,7 +188,8 @@ class TextBodyBuilder { private String getSignatureHtml() { String signature = ""; if (!isEmpty(mSignature)) { - signature = "
" + textToHtmlFragment(mSignature) + "
"; + signature = "
" + + HtmlConverter.textToHtmlFragmentWithOriginalWhitespace(mSignature) + "
"; } return signature; } @@ -205,10 +206,7 @@ class TextBodyBuilder { return mQuotedTextHtml; } - /** - * protected for unit-test purposes - */ - protected String textToHtmlFragment(String text) { + private String textToHtmlFragment(String text) { return HtmlConverter.textToHtmlFragment(text); } diff --git a/app/core/src/main/java/com/fsck/k9/message/html/EmailTextToHtml.kt b/app/core/src/main/java/com/fsck/k9/message/html/EmailTextToHtml.kt index 51ac09c715aad31ae3929684e6a899005d19205e..c14b569fc41dbd77ad19c3bff6fa747a20804af1 100644 --- a/app/core/src/main/java/com/fsck/k9/message/html/EmailTextToHtml.kt +++ b/app/core/src/main/java/com/fsck/k9/message/html/EmailTextToHtml.kt @@ -11,7 +11,7 @@ class EmailTextToHtml private constructor(private val text: String) { sections.forEach { section -> appendBlockQuoteElement(section.quoteDepth) - TextToHtml.appendAsHtmlFragment(html, section) + TextToHtml.appendAsHtmlFragment(html, section, retainOriginalWhitespace = true) } appendBlockQuoteElement(quoteDepth = 0) diff --git a/app/core/src/main/java/com/fsck/k9/message/html/HtmlConverter.kt b/app/core/src/main/java/com/fsck/k9/message/html/HtmlConverter.kt index 4e0f356ef6da79550b518e9284e2c5ae80174a40..826cabc2b5d72fa6b521c5994c470463c42adc5e 100644 --- a/app/core/src/main/java/com/fsck/k9/message/html/HtmlConverter.kt +++ b/app/core/src/main/java/com/fsck/k9/message/html/HtmlConverter.kt @@ -47,6 +47,17 @@ object HtmlConverter { */ @JvmStatic fun textToHtmlFragment(text: String): String { - return TextToHtml.toHtmlFragment(text) + return TextToHtml.toHtmlFragment(text, retainOriginalWhitespace = false) + } + + /** + * Convert a plain text string into an HTML fragment. + * + * This does not convert consecutive spaces to a series of non-breaking spaces followed by a regular space. + * Only use this in combination with CSS to properly display the whitespace. + */ + @JvmStatic + fun textToHtmlFragmentWithOriginalWhitespace(text: String): String { + return TextToHtml.toHtmlFragment(text, retainOriginalWhitespace = true) } } diff --git a/app/core/src/main/java/com/fsck/k9/message/html/TextToHtml.kt b/app/core/src/main/java/com/fsck/k9/message/html/TextToHtml.kt index eff721397c0d6991a2e273bd2c5302d9b3c143c9..286c88c2d623022e45a542264d44af2aadd40234 100644 --- a/app/core/src/main/java/com/fsck/k9/message/html/TextToHtml.kt +++ b/app/core/src/main/java/com/fsck/k9/message/html/TextToHtml.kt @@ -2,7 +2,11 @@ package com.fsck.k9.message.html import java.util.ArrayDeque -class TextToHtml private constructor(private val text: CharSequence, private val html: StringBuilder) { +class TextToHtml private constructor( + private val text: CharSequence, + private val html: StringBuilder, + private val retainOriginalWhitespace: Boolean +) { fun appendAsHtmlFragment() { val modifications = HTML_MODIFIERS .flatMap { it.findModifications(text) } @@ -51,11 +55,49 @@ class TextToHtml private constructor(private val text: CharSequence, private val } private fun appendHtmlEncoded(startIndex: Int, endIndex: Int) { + if (retainOriginalWhitespace) { + appendHtmlEncodedWithOriginalWhitespace(startIndex, endIndex) + } else { + appendHtmlEncodedWithNonBreakingSpaces(startIndex, endIndex) + } + } + + private fun appendHtmlEncodedWithOriginalWhitespace(startIndex: Int, endIndex: Int) { for (i in startIndex until endIndex) { appendHtmlEncoded(text[i]) } } + private fun appendHtmlEncodedWithNonBreakingSpaces(startIndex: Int, endIndex: Int) { + var adjustedStartIndex = startIndex + if (startIndex < endIndex && text[startIndex] == SPACE) { + html.append(NON_BREAKING_SPACE) + adjustedStartIndex++ + } + + var spaces = 0 + for (i in adjustedStartIndex until endIndex) { + if (text[i] == SPACE) { + spaces++ + } else { + appendSpaces(spaces) + spaces = 0 + appendHtmlEncoded(text[i]) + } + } + + appendSpaces(spaces) + } + + private fun appendSpaces(count: Int) { + if (count <= 0) return + + repeat(count - 1) { + html.append(NON_BREAKING_SPACE) + } + html.append(SPACE) + } + internal fun appendHtml(text: String) { html.append(text) } @@ -84,18 +126,22 @@ class TextToHtml private constructor(private val text: CharSequence, private val companion object { private val HTML_MODIFIERS = listOf(DividerReplacer, UriLinkifier, SignatureWrapper) + + private const val SPACE = ' ' + private const val NON_BREAKING_SPACE = '\u00A0' + private const val HTML_NEWLINE = "
" private const val TEXT_TO_HTML_EXTRA_BUFFER_LENGTH = 512 @JvmStatic - fun appendAsHtmlFragment(html: StringBuilder, text: CharSequence) { - TextToHtml(text, html).appendAsHtmlFragment() + fun appendAsHtmlFragment(html: StringBuilder, text: CharSequence, retainOriginalWhitespace: Boolean) { + TextToHtml(text, html, retainOriginalWhitespace).appendAsHtmlFragment() } @JvmStatic - fun toHtmlFragment(text: CharSequence): String { + fun toHtmlFragment(text: CharSequence, retainOriginalWhitespace: Boolean): String { val html = StringBuilder(text.length + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH) - TextToHtml(text, html).appendAsHtmlFragment() + TextToHtml(text, html, retainOriginalWhitespace).appendAsHtmlFragment() return html.toString() } } diff --git a/app/core/src/test/java/com/fsck/k9/message/html/HtmlConverterTest.kt b/app/core/src/test/java/com/fsck/k9/message/html/HtmlConverterTest.kt index 178110da15971c3963a93e3ddd282e15c0b0e20c..e2c02528e4c61eefaf52ac8b7e0dd10771785705 100644 --- a/app/core/src/test/java/com/fsck/k9/message/html/HtmlConverterTest.kt +++ b/app/core/src/test/java/com/fsck/k9/message/html/HtmlConverterTest.kt @@ -400,6 +400,60 @@ class HtmlConverterTest { ) } + @Test + fun `textToHtmlFragment() with single space at the start of a line`() { + val text = " foo" + + val result = HtmlConverter.textToHtmlFragment(text) + + assertThat(result).isEqualTo("\u00A0foo") + } + + @Test + fun `textToHtmlFragment() with two spaces at the start of a line`() { + val text = " foo" + + val result = HtmlConverter.textToHtmlFragment(text) + + assertThat(result).isEqualTo("\u00A0 foo") + } + + @Test + fun `textToHtmlFragment() with consecutive spaces at the start of a line`() { + val text = " some words here" + + val result = HtmlConverter.textToHtmlFragment(text) + + assertThat(result).isEqualTo("\u00A0\u00A0\u00A0 some words here") + } + + @Test + fun `textToHtmlFragment() with consecutive spaces between words`() { + val text = "foo bar" + + val result = HtmlConverter.textToHtmlFragment(text) + + assertThat(result).isEqualTo("foo\u00A0 bar") + } + + @Test + fun `textToHtmlFragment() with single space at the end of a line`() { + val text = "foo \n" + + val result = HtmlConverter.textToHtmlFragment(text) + + assertThat(result).isEqualTo("foo
") + } + + @Test + fun `textToHtmlFragment() with consecutive spaces at the end of a line`() { + val text = "some words here \n" + + val result = HtmlConverter.textToHtmlFragment(text) + + assertThat(result).isEqualTo("some words here\u00A0\u00A0
") + } + @Test fun `htmlToText() should convert BR tags to line breaks`() { val input = diff --git a/app/k9mail/build.gradle b/app/k9mail/build.gradle index d594824ac1158dd0bd186eb4f9ab438684d3dbfd..d74107b3344dc60bde08a4f10827d3494ae60cb7 100644 --- a/app/k9mail/build.gradle +++ b/app/k9mail/build.gradle @@ -37,6 +37,7 @@ dependencies { testImplementation "com.google.truth:truth:${versions.truth}" testImplementation "org.mockito:mockito-inline:${versions.mockito}" testImplementation "org.mockito.kotlin:mockito-kotlin:${versions.mockitoKotlin}" + testImplementation "io.insert-koin:koin-test:${versions.koin}" testImplementation "io.insert-koin:koin-test-junit4:${versions.koin}" } @@ -48,8 +49,8 @@ android { applicationId "foundation.e.mail" testApplicationId "foundation.e.mail.tests" - versionCode 33000 - versionName '6.300' + versionCode 33001 + versionName '6.301' // Keep in sync with the resource string array 'supported_languages' resConfigs "in", "br", "ca", "cs", "cy", "da", "de", "et", "en", "en_GB", "es", "eo", "eu", "fr", "gd", "gl", diff --git a/app/storage/build.gradle b/app/storage/build.gradle index afbf61f7ca9443b5dd77669eb040a0b87b44422b..d4db393c3e066bd3b4166ecbcc57fc32b078171a 100644 --- a/app/storage/build.gradle +++ b/app/storage/build.gradle @@ -18,6 +18,7 @@ dependencies { testImplementation "com.google.truth:truth:${versions.truth}" testImplementation "org.mockito:mockito-inline:${versions.mockito}" testImplementation "org.mockito.kotlin:mockito-kotlin:${versions.mockitoKotlin}" + testImplementation "io.insert-koin:koin-test:${versions.koin}" testImplementation "io.insert-koin:koin-test-junit4:${versions.koin}" testImplementation "commons-io:commons-io:${versions.commonsIo}" } diff --git a/app/storage/src/main/java/com/fsck/k9/storage/messages/MoveMessageOperations.kt b/app/storage/src/main/java/com/fsck/k9/storage/messages/MoveMessageOperations.kt index a3f49ae381d7bb52e8026f9bce05b533c976aef6..62ae5124ed3f1d476f07173d9f55d90462841bad 100644 --- a/app/storage/src/main/java/com/fsck/k9/storage/messages/MoveMessageOperations.kt +++ b/app/storage/src/main/java/com/fsck/k9/storage/messages/MoveMessageOperations.kt @@ -23,11 +23,20 @@ internal class MoveMessageOperations( threadMessageOperations.createThreadEntryIfNecessary(database, destinationMessageId, threadInfo) convertOriginalMessageEntryToPlaceholderEntry(database, messageId) + moveFulltextEntry(database, messageId, destinationMessageId) destinationMessageId } } + private fun moveFulltextEntry(database: SQLiteDatabase, messageId: Long, destinationMessageId: Long) { + val values = ContentValues().apply { + put("docid", destinationMessageId) + } + + database.update("messages_fulltext", values, "docid = ?", arrayOf(messageId.toString())) + } + private fun createMessageEntry( database: SQLiteDatabase, messageId: Long, diff --git a/app/ui/base/src/main/java/com/fsck/k9/ui/base/loader/LoaderStateObserver.kt b/app/ui/base/src/main/java/com/fsck/k9/ui/base/loader/LoaderStateObserver.kt index 802aa0523ee09acb2cc415e87e7a27d58ec1c3bf..5f06f13075928dc8bb3e98ff700515eeec947ce0 100644 --- a/app/ui/base/src/main/java/com/fsck/k9/ui/base/loader/LoaderStateObserver.kt +++ b/app/ui/base/src/main/java/com/fsck/k9/ui/base/loader/LoaderStateObserver.kt @@ -33,6 +33,7 @@ private class LoaderStateObserver( override fun onChanged(state: LoaderState?) { when (state) { + null -> Unit is LoaderState.Loading -> loadingView.show() is LoaderState.Error -> errorView.show() is LoaderState.Data -> { diff --git a/app/ui/legacy/build.gradle b/app/ui/legacy/build.gradle index fdaeca5375596dc62808cda66b7d83823512cf98..0c594ea03df7d7c10967aa3fd9e5e68d3754f393 100644 --- a/app/ui/legacy/build.gradle +++ b/app/ui/legacy/build.gradle @@ -35,7 +35,7 @@ dependencies { implementation 'com.mikepenz:materialdrawer:8.4.5' implementation 'com.mikepenz:materialdrawer-iconics:8.4.5' implementation 'com.mikepenz:fontawesome-typeface:5.9.0.0-kotlin@aar' - implementation 'com.github.ByteHamster:SearchPreference:v2.1.0' + implementation 'com.github.ByteHamster:SearchPreference:v2.2.1' implementation "com.mikepenz:fastadapter:${versions.fastAdapter}" implementation "com.mikepenz:fastadapter-extensions-drag:${versions.fastAdapter}" implementation "com.mikepenz:fastadapter-extensions-utils:${versions.fastAdapter}" @@ -63,6 +63,7 @@ dependencies { testImplementation "com.google.truth:truth:${versions.truth}" testImplementation "org.mockito:mockito-inline:${versions.mockito}" testImplementation "org.mockito.kotlin:mockito-kotlin:${versions.mockitoKotlin}" + testImplementation "io.insert-koin:koin-test:${versions.koin}" testImplementation "io.insert-koin:koin-test-junit4:${versions.koin}" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.kotlinCoroutines}" testImplementation "app.cash.turbine:turbine:${versions.turbine}" @@ -89,9 +90,13 @@ android { debug { def useNewSetupUi = project.hasProperty('k9mail.useNewSetupUi') ? project.property('k9mail.useNewSetupUi') : "false" buildConfigField "boolean", "USE_NEW_SETUP_UI_FOR_ONBOARDING", useNewSetupUi + + manifestPlaceholders = ['appAuthRedirectScheme': 'FIXME: override this in your app project'] } release { buildConfigField "boolean", "USE_NEW_SETUP_UI_FOR_ONBOARDING", "false" + + manifestPlaceholders = ['appAuthRedirectScheme': 'FIXME: override this in your app project'] } } diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageList.kt b/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageList.kt index 07804ce0c7d236aadf27dcc7d746794acc34e199..8735a87ad1306cf3dda3bc14f5d111801d9d6818 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageList.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/activity/MessageList.kt @@ -147,7 +147,7 @@ open class MessageList : * filtered views, e.g. when only displaying the unread messages in a folder. */ private var noThreading = false - private var displayMode: DisplayMode? = null + private var displayMode: DisplayMode = DisplayMode.MESSAGE_LIST private var messageReference: MessageReference? = null /** @@ -320,7 +320,7 @@ open class MessageList : } if (savedInstanceState != null) { - val savedDisplayMode = savedInstanceState.getSerializable(STATE_DISPLAY_MODE) as DisplayMode? + val savedDisplayMode = savedInstanceState.getSerializable(STATE_DISPLAY_MODE) as DisplayMode if (savedDisplayMode != DisplayMode.SPLIT_VIEW) { displayMode = savedDisplayMode return diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewContainerFragment.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewContainerFragment.kt index 6c4e79a388273204c01c0a111ed2e7d23e560941..ee83695a9107f738202d211f14fe628a17be5a57 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewContainerFragment.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/messageview/MessageViewContainerFragment.kt @@ -44,13 +44,17 @@ class MessageViewContainerFragment : Fragment() { private val messageViewFragment: MessageViewFragment get() { check(isResumed) - val itemId = adapter.getItemId(messageReference) - - // ViewPager2/FragmentStateAdapter don't provide an easy way to get hold of the Fragment for the active - // page. So we're using an implementation detail (the fragment tag) to find the fragment. - return childFragmentManager.findFragmentByTag("f$itemId") as MessageViewFragment + return findMessageViewFragment() } + private fun findMessageViewFragment(): MessageViewFragment { + val itemId = adapter.getItemId(messageReference) + + // ViewPager2/FragmentStateAdapter don't provide an easy way to get hold of the Fragment for the active + // page. So we're using an implementation detail (the fragment tag) to find the fragment. + return childFragmentManager.findFragmentByTag("f$itemId") as MessageViewFragment + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -221,7 +225,7 @@ class MessageViewContainerFragment : Fragment() { } fun onPendingIntentResult(requestCode: Int, resultCode: Int, data: Intent?) { - messageViewFragment.onPendingIntentResult(requestCode, resultCode, data) + findMessageViewFragment().onPendingIntentResult(requestCode, resultCode, data) } private class MessageViewContainerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) { diff --git a/app/ui/legacy/src/main/res/raw/changelog_master.xml b/app/ui/legacy/src/main/res/raw/changelog_master.xml index 433c2511ca348f17358b3b96b78cfea7b83effe9..44d538b120dcb28dd8d85d21c8b78d3ca029e353 100644 --- a/app/ui/legacy/src/main/res/raw/changelog_master.xml +++ b/app/ui/legacy/src/main/res/raw/changelog_master.xml @@ -5,6 +5,13 @@ Locale-specific versions are kept in res/raw-/changelog.xml. --> + + Fixed crash when viewing a message and OpenKeychain needed to display its user interface, e.g. to ask for a password + When composing a message containing consecutive spaces convert them to non-breaking spaces in the generated HTML part of the message + Fixed bug where moving a message to another folder wouldn't update the apps search index + Fixed small bug where not all cached values were removed when using "clear local messages" + Updated translations + Added support for swiping between messages Fixed multiple bugs when there are notifications for more than 8 messages diff --git a/app/ui/legacy/src/main/res/values-ar/strings.xml b/app/ui/legacy/src/main/res/values-ar/strings.xml index 16638d9b174898cdb4e479ceb56844049db9279e..db9fa0b16d8c6b3ade02259540fbe1994293f217 100644 --- a/app/ui/legacy/src/main/res/values-ar/strings.xml +++ b/app/ui/legacy/src/main/res/values-ar/strings.xml @@ -592,7 +592,6 @@ احفظ أو إلغ الرسالة؟ هل تريد إلغاء الرسالة ؟ هل أنت متأكد من أنك تود إلغاء هذه الرسالة ؟ - حدّد النص للنسخ تأكيد الحذف أتريد حذف هذه الرسالة؟ نعم diff --git a/app/ui/legacy/src/main/res/values-be/strings.xml b/app/ui/legacy/src/main/res/values-be/strings.xml index d246f6a979e1a46f7b5b70c3a61bc49843599f30..371f91eb3002c8f552edd51e8db84bb4e298d3d7 100644 --- a/app/ui/legacy/src/main/res/values-be/strings.xml +++ b/app/ui/legacy/src/main/res/values-be/strings.xml @@ -658,7 +658,6 @@ Захаваць альбо адкінуць змены? Скасаваць ліст? Сапраўды хочаце скасаваць ліст? - Абраць тэкст для капіявання. Выдаліць лакальныя лісты? Гэта выдаліць усе лакальныя лісты з каталога. Лісты на серверы не крануцца. Выдаліць лісты diff --git a/app/ui/legacy/src/main/res/values-bg/strings.xml b/app/ui/legacy/src/main/res/values-bg/strings.xml index 95407ea386cc7485fec979f0739a141712b858b0..a693106dde4724da5d5e29a3044dd778fedf6d4f 100644 --- a/app/ui/legacy/src/main/res/values-bg/strings.xml +++ b/app/ui/legacy/src/main/res/values-bg/strings.xml @@ -654,7 +654,6 @@ Запази или Откажи промените? Изтриване на съобщението? Сигурен ли сте, че желаете да изтрието това съобщение? - Изберете текст за копиране. Изчисти локалните съобщения? Това ще премахне всички локални съобщения от папката. Няма да бъдат изтрити съобщения от сървара. Изчисти съобщения diff --git a/app/ui/legacy/src/main/res/values-br/strings.xml b/app/ui/legacy/src/main/res/values-br/strings.xml index 6c2b053ba70a7627fd37c7a0e433dd9b2ebb8dd3..83bdc2c38130974b6b4a3f54f70ad85dfb9c86d3 100644 --- a/app/ui/legacy/src/main/res/values-br/strings.xml +++ b/app/ui/legacy/src/main/res/values-br/strings.xml @@ -632,7 +632,6 @@ Enrollañ pe dilezel ar gemennadenn? Dilezel ar gemennadenn? Sur oc’h e fell deoc’h dilezel ar gemennadenn? - Diuzit an destenn da eilañ Kadarnat an dilamadur Fellout a ra deoc’h dilemel ar gemennadenn-mañ? diff --git a/app/ui/legacy/src/main/res/values-ca/strings.xml b/app/ui/legacy/src/main/res/values-ca/strings.xml index 06db7ef7dacb9f42d386955d9d0b77f49771a1ed..fc5d0102d5930894a213b0e632c449b27454ad7d 100644 --- a/app/ui/legacy/src/main/res/values-ca/strings.xml +++ b/app/ui/legacy/src/main/res/values-ca/strings.xml @@ -12,6 +12,8 @@ Llicència d\'Apache, versió 2.0 Projecte de codi obert Lloc web + Manual de l\'usuari + Obtingueu ajuda Fòrum d\'usuaris Fediverse Twitter @@ -141,7 +143,9 @@ Ha fallat l\'autenticació Ha fallat l\'autenticació de %s. Actualitzeu la configuració del servidor. + Error de notificació + S\'ha produït un error en intentar crear una notificació del sistema per a un missatge nou. El motiu més probable és que falti un so de notificació.\n\nToqueu per obrir la configuració de notificació. S\'està comprovant el correu: %s:%s S\'està comprovant el correu S\'està enviant correu: %s @@ -703,7 +707,6 @@ Voleu desar o descartar els canvis? Descarto el missatge? Segur que voleu descartar aquest missatge? - Seleccioneu el text a copiar. Voleu netejar els missatges locals? Això suprimirà tots els missatges locals de la carpeta. No se suprimirà cap missatge del servidor. Neteja els missatges diff --git a/app/ui/legacy/src/main/res/values-cs/strings.xml b/app/ui/legacy/src/main/res/values-cs/strings.xml index 25b33af7fa02c81ef72d196474cb6e48084d72bb..528c61989127705ddea407ff499bd1aefc8d35e5 100644 --- a/app/ui/legacy/src/main/res/values-cs/strings.xml +++ b/app/ui/legacy/src/main/res/values-cs/strings.xml @@ -716,7 +716,6 @@ Uložit nebo zahodit změny? Zahodit zprávu? Opravdu chcete tuto zprávu zahodit? - Vyberte text pro kopírování. Vymazat zprávy uložené lokálně? Toto ze složky odebere všechny lokálně uložené zprávy. Ze serveru nebudou vymazány žádné zprávy. Vyčistit zprávy diff --git a/app/ui/legacy/src/main/res/values-cy/strings.xml b/app/ui/legacy/src/main/res/values-cy/strings.xml index bfaf52376709b49211c727547149d670defa797a..3ff0de56b5c28ee3fca908a41293e9785bdb8853 100644 --- a/app/ui/legacy/src/main/res/values-cy/strings.xml +++ b/app/ui/legacy/src/main/res/values-cy/strings.xml @@ -708,7 +708,6 @@ Cadw neu Ddiddymu\'r newidiadau? Dileu\'r neges? Wyt ti\'n sicr dy fod am ddileu\'r neges hon? - Dewisa destun i\'w gopïo. Clirio negeseuon lleol? Bydd hyn yn tynnu pob neges leol o\'r ffolder. Ni chaiff negeseuon eu dileu o\'r gweinydd. Clirio negeseuon diff --git a/app/ui/legacy/src/main/res/values-da/strings.xml b/app/ui/legacy/src/main/res/values-da/strings.xml index c1efd24cc1a748b04e9459bf0bb09da8a4dafc11..52de27134569c8cb9b0feb7269214ecdc2afed56 100644 --- a/app/ui/legacy/src/main/res/values-da/strings.xml +++ b/app/ui/legacy/src/main/res/values-da/strings.xml @@ -683,7 +683,6 @@ Gem eller Kassér ændringer? Annuller meddelelse? Er du sikker på at du ønsker at annullere denne meddelelse? - Vælg tekst som skal kopieres. Ryd lokale beskeder Dette vil slette alle lokale beskeder fra mappen. Ingen beskeder slettes fra serveren. Rens beskeder diff --git a/app/ui/legacy/src/main/res/values-de/strings.xml b/app/ui/legacy/src/main/res/values-de/strings.xml index 83ad03820ab7c6d33247ecbe8c80bed90e59f506..80537ebcd854391bbb7ddbe53ae21d297067ffc4 100644 --- a/app/ui/legacy/src/main/res/values-de/strings.xml +++ b/app/ui/legacy/src/main/res/values-de/strings.xml @@ -732,7 +732,6 @@ Bitte senden Sie Fehlerberichte, Ideen für neue Funktionen und stellen Sie Frag Änderungen speichern oder verwerfen? Nachricht verwerfen? Sind Sie sicher, dass Sie die Nachricht verwerfen möchten? - Text auswählen, um ihn zu kopieren. Lokale Nachrichten löschen? Dadurch werden alle lokalen Nachrichten aus dem Ordner entfernt. Es werden keine Nachrichten vom Server gelöscht. Nachrichten löschen diff --git a/app/ui/legacy/src/main/res/values-el/strings.xml b/app/ui/legacy/src/main/res/values-el/strings.xml index 2ca0287c3c4efc9df72e965e985279b5d664bd95..fdcc6554cd697bbec5d542ad81d5814e63a6750e 100644 --- a/app/ui/legacy/src/main/res/values-el/strings.xml +++ b/app/ui/legacy/src/main/res/values-el/strings.xml @@ -675,7 +675,6 @@ Αποθήκευση ή Απόρριψη αλλαγών; Απόρριψη μηνύματος; Είστε σίγουροι ότι θέλετε να απορρίψετε αυτό το μήνυμα; - Επιλογή κειμένου για αντιγραφή Καθαρισμός τοπικών μηνυμάτων; Αυτό θα καταργήσει όλα τα τοπικά μηνύματα από το φάκελο. Δε θα διαγραφούν μηνύματα από τον εξυπηρετητή. Καθαρισμός μηνυμάτων diff --git a/app/ui/legacy/src/main/res/values-eo/strings.xml b/app/ui/legacy/src/main/res/values-eo/strings.xml index 17e6f6663ef269e1ce017b0de00cdd7df9ec0f64..8dcf3daa6d1ff07baa92e0f2f87ae7036b314b61 100644 --- a/app/ui/legacy/src/main/res/values-eo/strings.xml +++ b/app/ui/legacy/src/main/res/values-eo/strings.xml @@ -673,7 +673,6 @@ Ĉu konservi aŭ nuligi ŝanĝojn? Ĉu forigi mesaĝon? Ĉu vi certe volas forigi tiun ĉi mesaĝon? - Elektu tekston por kopii. Ĉu forviŝi lokajn mesaĝojn? Tio ĉi forigos ĉiujn lokajn mesaĝojn el la mesaĝujo. Neniuj mesaĝoj estos forigitaj el la servilo. Forviŝi mesaĝojn diff --git a/app/ui/legacy/src/main/res/values-es/strings.xml b/app/ui/legacy/src/main/res/values-es/strings.xml index ec13cbc93382961cedef5ffab483f7af928bd918..ac29513195091bef9bc108dcae0645c47d792458 100644 --- a/app/ui/legacy/src/main/res/values-es/strings.xml +++ b/app/ui/legacy/src/main/res/values-es/strings.xml @@ -425,7 +425,7 @@ Configurar clave de extremo a extremo Sin aplicación OpenPGP configurada Conectado a %s - Configurando... + Configurando… Almacenar todos los borradores cifrados Todos los borradores serán guardados con cifrado Cifrar borradores solamente si está disponible el cifrado @@ -698,7 +698,6 @@ ¿Guardar o descartar cambios? ¿Descartar mensaje? ¿Está seguro de descartar este mensaje? - Seleccionar texto a copiar. ¿Limpiar mensajes locales? Esto eliminará todos los mensajes locales de la carpeta. No se eliminarán mensajes del servidor. Limpiar mensajes @@ -981,7 +980,7 @@ Un mensaje de configuración Autocrypt comparte de manera segura su configuración con otros dispositivos. Enviar mensaje de configuración El mensaje se enviará a esta dirección: - Generando mensaje de configuración... + Generando mensaje de configuración… Enviando mensaje a: Para finalizar, abra el mensaje en su otro dispositivo e introduzca el código de configuración. Mostrar código de configuración @@ -999,7 +998,7 @@ Puede mantener este mensaje y usarlo como copia de seguridad de su clave secreta Permitir acceso a contactos Para poder proveer sugerencias de contactos y mostrar sus nombres, la app necesita acceso a éstos. Se produjo un error al cargar los datos - Iniciando... + Iniciando… Esperar hasta que se permita la sincronización en segundo plano Esperar hasta que la red esté disponible Toca aquí para leer más sobre el tema. diff --git a/app/ui/legacy/src/main/res/values-et/strings.xml b/app/ui/legacy/src/main/res/values-et/strings.xml index 8668149b9a219bcb18731acd8d4f395c8e6dd22a..0af97fa412ad4fad5583d7ea6884917873ec4e71 100644 --- a/app/ui/legacy/src/main/res/values-et/strings.xml +++ b/app/ui/legacy/src/main/res/values-et/strings.xml @@ -423,7 +423,7 @@ Seadista otspunktide võti OpenPGP rakendus seadistamata %s ühendatud - Seadistamine... + Seadistamine… Salvesta kõik mustandid krüpteeritult Kõik mustandid salvestatakse krüpteeritult Krüpteeri mustandid vaid siis, kui krüpteerimine on lubatud @@ -527,8 +527,6 @@ Korda vibreerimist ei ole kasutusel Uue meilisõnumi helin - Vilguta LEDi - Vilguta LEDi uue e-kirja saabumisel Sõnumi koostamise valikud Teavitustule värv ei ole kasutusel @@ -697,7 +695,6 @@ Salvestada või loobuda muudatustest? Loobud sõnumist? Oled kindel, et soovid sõnumist loobuda? - Vali kopeerimiseks tekst. Puhasta kohalikud kirjad Puhasta kirjad Kinnita kustutamine @@ -762,7 +759,7 @@ Väljuvaid kirju teenindava serveri salasõna Kasuta sama salasõna ka väljuvate kirjade serveri tarbeks Serveri nimi: %s - Näita lugemata sõnumite arvu... + Näita lugemata sõnumite arvu… Konto Konto, mille lugemata sõnumite arvu peaks näitama Koondsisendkaust @@ -815,8 +812,6 @@ Kaugotsing ebaõnnestus Otsi - Luba serverist otsimine - Lisaks seadmes olevatele sõnumitele otsi ka serveris olevatest sõnumitest Otsi serveris olevatest sõnumitest Serverist otsimiseks on vajalik võrguühendus. Muuda lugemisel värvi @@ -941,7 +936,7 @@ Selle kirja krüptimisel on kasutusel OpenPGP.\nKirjalugemsieks palun paigalda ja seadista sobilik OpenPGP rakendus. Ava sätted K-9 sõnumite nimekiri - Sõnumite laadimine... + Sõnumite laadimine… Krüpteerimine poe võimalik Mõned kirja saajad ei saa seda funktsionaalsust kasutada! Võimalda krüpteerimine diff --git a/app/ui/legacy/src/main/res/values-eu/strings.xml b/app/ui/legacy/src/main/res/values-eu/strings.xml index 084e693de8aa0cfe6d910c289becc5afd3a42a19..9b72d3ffb4480f7f8d8cd2142fa58eaafcf88a43 100644 --- a/app/ui/legacy/src/main/res/values-eu/strings.xml +++ b/app/ui/legacy/src/main/res/values-eu/strings.xml @@ -660,7 +660,6 @@ Gorde edo baztertu aldaketak? Baztertu mezua? Ziur mezu hau baztertu nahi duzula? - Hautatu kopiatzeko testua. Garbitu mezu lokalak? Honek tokiko mezu guztiak kenduko ditu karpetatik. Ez da mezurik ezabatuko zerbitzarian. Garbitu mezuak diff --git a/app/ui/legacy/src/main/res/values-fa/strings.xml b/app/ui/legacy/src/main/res/values-fa/strings.xml index c966ca96d1fca670995623d3aa1b92b9a1ad82e9..55453f3271731c87e19f678aa4cb4cab3ab28521 100644 --- a/app/ui/legacy/src/main/res/values-fa/strings.xml +++ b/app/ui/legacy/src/main/res/values-fa/strings.xml @@ -680,7 +680,6 @@ تغییرات حفظ شود یا دور ریخته شود؟ پیام از بین برود؟ آیا از دورانداختن این پیام مطمئن هستید؟ - متن را انتخاب کنید تا کپی شود. پیام‌ها از روی دستگاه پاک شود؟ این کار همهٔ پیام‌ها را از پوشهٔ روی دستگاه پاک می‌کند. هیچ پیامی از روی کارساز پاک نمی‌شود. پاک‌کردن پیام‌ها diff --git a/app/ui/legacy/src/main/res/values-fi/strings.xml b/app/ui/legacy/src/main/res/values-fi/strings.xml index 6b23917e43401ca16337864c7307d888d340efc2..8b93a933ec66b73987a593c67ef84a718656c1f5 100644 --- a/app/ui/legacy/src/main/res/values-fi/strings.xml +++ b/app/ui/legacy/src/main/res/values-fi/strings.xml @@ -735,7 +735,6 @@ Ilmoita virheistä, ota osaa sovelluskehitykseen ja esitä kysymyksiä osoittees Tallennetaanko vai hylätäänkö muutokset? Hylkää viesti? Haluatko varmasti hylätä tämän viestin? - Valitse kopioitava teksti. Poistetaanko paikalliset viestit? Tämä poistaa kaikki paikalliset viestit kansiosta. Viestejä ei poisteta palvelimelta. Poista viestit diff --git a/app/ui/legacy/src/main/res/values-fr/strings.xml b/app/ui/legacy/src/main/res/values-fr/strings.xml index 9bf2da248d616f8808a4ad587bea37a2961567b6..2e276d15a148c1e859af17935e23643bd3bc6bce 100644 --- a/app/ui/legacy/src/main/res/values-fr/strings.xml +++ b/app/ui/legacy/src/main/res/values-fr/strings.xml @@ -710,7 +710,6 @@ jusqu’à %d de plus Enregistrer ou abandonner les changements ? Abandonner le courriel ? Voulez-vous vraiment abandonner ce courriel ? - Sélectionner le texte à copier. Effacer les courriels locaux ? Tous les courriels locaux seront supprimés du dossier. Aucun courriel ne sera supprimé du serveur. Effacer les courriels diff --git a/app/ui/legacy/src/main/res/values-fy/strings.xml b/app/ui/legacy/src/main/res/values-fy/strings.xml index ad2c4723a2ccf948bfc8bf83d8db78ebbf311e3e..3f42c9df7880e0adf95c6c0a807c74389358f2d5 100644 --- a/app/ui/legacy/src/main/res/values-fy/strings.xml +++ b/app/ui/legacy/src/main/res/values-fy/strings.xml @@ -731,7 +731,6 @@ Graach flaterrapporten stjoere, bydragen foar nije funksjes en fragen stelle op Wizigingen bewarje of ferwerpe? Berjocht ôfbrekke? Binne jo wis dat jo dit berjocht fuortsmite wolle - Selektearje tekst om te kopiearjen. Lokale berjochten wiskje? Dit sil alle lokale berjochten út dizze map wiskje. Der wurde gjin berjochten fan de server wiske. Berjochten wiskje diff --git a/app/ui/legacy/src/main/res/values-gd/strings.xml b/app/ui/legacy/src/main/res/values-gd/strings.xml index f78c709f96a010b8dcd6acd0a94696109f82f2ed..a862afd95f4e07a3c54ad905d29875e8d00edaa1 100644 --- a/app/ui/legacy/src/main/res/values-gd/strings.xml +++ b/app/ui/legacy/src/main/res/values-gd/strings.xml @@ -668,7 +668,6 @@ A bheil thu airson an teachdaireachd seo a shàbhaladh no a thilgeil air falbh\? A bheil thu airson an teachdaireachd seo a thilgeil air falbh\? A bheil thu cinnteach gu bheil thu airson an teachdaireachd seo a thilgeil air falbh\? - Tagh teacsa airson lethbhreac a dhèanamh dheth. Dearbh an sguabadh às A bheil thu cinnteach gu bheil thu airson an teachdaireachd seo a sguabadh às\? diff --git a/app/ui/legacy/src/main/res/values-gl-rES/strings.xml b/app/ui/legacy/src/main/res/values-gl-rES/strings.xml index 7432041eaca1a64958df40c962acf8c70435373a..e42e3f0415d0caac25bd01ad5af28c9c9a35ef38 100644 --- a/app/ui/legacy/src/main/res/values-gl-rES/strings.xml +++ b/app/ui/legacy/src/main/res/values-gl-rES/strings.xml @@ -553,7 +553,6 @@ Gardar ou descartar esta mensaxe? Descartar mensaxe? Tes a certeza de querer descartar esta mensaxe? - Seleccionar texto para copiar. Confirmar borrado Queres eliminar esta mensaxe? diff --git a/app/ui/legacy/src/main/res/values-gl/strings.xml b/app/ui/legacy/src/main/res/values-gl/strings.xml index 34b8db923d4b97b3d0eec1c2e30ad248d34d468a..7286ada9af942833eb26c91de388bd4dc485063e 100644 --- a/app/ui/legacy/src/main/res/values-gl/strings.xml +++ b/app/ui/legacy/src/main/res/values-gl/strings.xml @@ -655,7 +655,6 @@ Gardar ou desbotar os cambios? Descartar mensaxe? Tes a certeza de querer descartar esta mensaxe? - Seleccionar texto a copiar. Borrar as mensaxes locais? Isto eliminará todas as mensaxes locais do cartafol. Non se eliminarán as mensaxes deste servidor. Borrar mensaxes diff --git a/app/ui/legacy/src/main/res/values-hr/strings.xml b/app/ui/legacy/src/main/res/values-hr/strings.xml index 4e3cb2f2ac3cb41464cc45bd57429a9ed0e1c1b6..63a54d043d5e968d4cafbdcdb62f4b8980e47200 100644 --- a/app/ui/legacy/src/main/res/values-hr/strings.xml +++ b/app/ui/legacy/src/main/res/values-hr/strings.xml @@ -651,7 +651,6 @@ Spremiti ili Odbaciti ovu poruku? Odbaciti poruku? Jeste li sigurni da želite odbaciti ovu poruku? - Odaberi tekst za kopiranje.. Očistiti lokalne poruke? Očisti poruke Potvrda brisanja diff --git a/app/ui/legacy/src/main/res/values-hu/strings.xml b/app/ui/legacy/src/main/res/values-hu/strings.xml index a2b6cb0ca92f580c01cccae724f0a9bbde1a43e9..870ecc59bdfb2c266f65f00f040d31085ad0479e 100644 --- a/app/ui/legacy/src/main/res/values-hu/strings.xml +++ b/app/ui/legacy/src/main/res/values-hu/strings.xml @@ -674,7 +674,6 @@ Menti vagy elveti a változtatásokat? Elveti az üzenet? Biztosan el szeretné vetni ezt az üzenetet? - Szöveg kijelölése a másoláshoz. Helyi üzenetek kiürítése Ez eltávolítja az összes helyi üzenetet mappából. Az üzenetek nem kerülnek törlésre a szerverről. Üzenetek kiürítése diff --git a/app/ui/legacy/src/main/res/values-in/strings.xml b/app/ui/legacy/src/main/res/values-in/strings.xml index d848046c5440d2b1cc8ca50cec9d1cdd9bb8830e..d46ce5ba414bdaf488f8844cd0602c0260a3484b 100644 --- a/app/ui/legacy/src/main/res/values-in/strings.xml +++ b/app/ui/legacy/src/main/res/values-in/strings.xml @@ -659,7 +659,6 @@ Simpan atau Buang pesan ini? Buang pesan? Anda yakin ingin membuang pesan ini? - Pilih teks yang akan disalin. Bersihkan pesan lokal? Ini akan menghapus semua pesan lokal dari folder. Tidak ada pesan yang akan dihapus dari server. Bersihkan pesan diff --git a/app/ui/legacy/src/main/res/values-is/strings.xml b/app/ui/legacy/src/main/res/values-is/strings.xml index a29cab387e2962c8b5cb3c2dc3785e6612e9bffd..e6310b5e397bf396b100328affad4af0d30d0b0a 100644 --- a/app/ui/legacy/src/main/res/values-is/strings.xml +++ b/app/ui/legacy/src/main/res/values-is/strings.xml @@ -673,7 +673,6 @@ Vista eða henda breytingum? Henda skilaboðum? Ertu viss um að þú viljir henda þessum skilaboðum? - Veldu texta til að afrita. Hreinsa staðvær skilaboð? Þetta mun fjarlægja öll staðvær skilaboð úr þessari möppu. Engum skilaboðum verður eytt af póstþjóninum. Hreinsa skilaboð diff --git a/app/ui/legacy/src/main/res/values-it/strings.xml b/app/ui/legacy/src/main/res/values-it/strings.xml index 0005e32b8607a21bbc531adde516c5a94684fb36..4d9cca2ef87f8ba7e75b87b5190f910168a55165 100644 --- a/app/ui/legacy/src/main/res/values-it/strings.xml +++ b/app/ui/legacy/src/main/res/values-it/strings.xml @@ -730,7 +730,6 @@ Invia segnalazioni di bug, contribuisci con nuove funzionalità e poni domande s Vuoi cancellare le modifiche\? Conferma l\'eliminazione Vuoi cancellare questo messaggio\? - Seleziona il testo da copiare. Vuoi cancellare i messaggi locali? Questo rimuoverà tutti i messaggi locali dalla cartella. Nessun messaggio sarà eliminato dal server. Cancella messaggi @@ -1049,7 +1048,6 @@ Puoi conservare questo messaggio e utilizza come una copia di sicurezza della tu Errore certificato Esportazione riuscita. I registri potrebbero contenere informazioni sensibili. Fai attenzione a chi li invii. Suono email inviata - XOauth2 (Gmail, Outlook) Ogni 5 minuti ANNULLA MODIFICA diff --git a/app/ui/legacy/src/main/res/values-iw/strings.xml b/app/ui/legacy/src/main/res/values-iw/strings.xml index 411a2cd98a48bcfd9c0a867e38a2881730966605..2032d717e1925092c4c4ec5bbf0d6b2b7acc1a8a 100644 --- a/app/ui/legacy/src/main/res/values-iw/strings.xml +++ b/app/ui/legacy/src/main/res/values-iw/strings.xml @@ -545,7 +545,6 @@ לשמור או להשליך הודעה זו? לשמור או לבטל שינויים? להשליך את ההודעה? - בחר טקסט כדי להעתיק. אשר מחיקה אתה בטוח שאתה רוצה למחוק את ההודעה הזאת? מחק diff --git a/app/ui/legacy/src/main/res/values-ja/strings.xml b/app/ui/legacy/src/main/res/values-ja/strings.xml index a2ff01fc771e066dffd81ffbf91d3f3b9c8648a5..ee1637df432905448d1153ec592af8f6d9a2e2a2 100644 --- a/app/ui/legacy/src/main/res/values-ja/strings.xml +++ b/app/ui/legacy/src/main/res/values-ja/strings.xml @@ -13,6 +13,7 @@ オープンソースプロジェクト ウェブサイト ユーザーマニュアル + 助けを得る ユーザーフォーラム Fediverse Twitter @@ -708,7 +709,6 @@ 変更を保存しますか? メッセージ破棄? このメッセージを破棄しますか? - 選択したテキストをコピーします ローカルのメッセージをクリアしますか? この操作はすべてのローカルメッセージをフォルダーから削除します。 サーバ上のメッセージは削除されません。 メッセージのクリア diff --git a/app/ui/legacy/src/main/res/values-ko/strings.xml b/app/ui/legacy/src/main/res/values-ko/strings.xml index 366aa390771b5752825fda6e42593a9f9a5d9b2a..80e2a1e45c3ce0b6023d8e08a926ec2d7578e31a 100644 --- a/app/ui/legacy/src/main/res/values-ko/strings.xml +++ b/app/ui/legacy/src/main/res/values-ko/strings.xml @@ -589,7 +589,6 @@ 이 메시지를 저장하거나 버리시겠습니까? 메시지 버림 메시지 작성을 취소하고 버리겠습니까? - 복사할 텍스트 선택 삭제 확인 이 메시지를 삭제하시겠습니까? diff --git a/app/ui/legacy/src/main/res/values-lt/strings.xml b/app/ui/legacy/src/main/res/values-lt/strings.xml index a97b97f6a6e42ae06f9f34c9793ac048d419628f..6f129f14658e1e07b482f9866041123af400f09b 100644 --- a/app/ui/legacy/src/main/res/values-lt/strings.xml +++ b/app/ui/legacy/src/main/res/values-lt/strings.xml @@ -705,7 +705,6 @@ Išsaugoti ar atmesti pakeitimus? Nepaisyti laiško? Ar tikrai norite nepaisyti šio pranešimo? - Pasirinkti tesktą kopijavimui. Išvalyti vietinius laiškus? Tai iš aplanko pašalins visus vietinius laiškus. Iš serverio laiškai nebus ištrinti. Išvalyti laiškus diff --git a/app/ui/legacy/src/main/res/values-lv/strings.xml b/app/ui/legacy/src/main/res/values-lv/strings.xml index cc1fd35434ca3da221e229cf655a90e8e4990ef9..17343c71c167bec6f13e25e743a5279b49c7fcda 100644 --- a/app/ui/legacy/src/main/res/values-lv/strings.xml +++ b/app/ui/legacy/src/main/res/values-lv/strings.xml @@ -679,7 +679,6 @@ pat %d vairāk Saglabāt vai atcelt izmaiņas? Izmest vēstuli? Vai tiešām izmest šo vēstuli? - Iezīmēt tekstu, lai kopētu. Izdzēst ierīcē esošās vēstules? Šādi no mapes tiks izdzēstas visas lejupielādētās vēstules. No servera vēstules netiks izdzēstas. Izdzēst vēstules diff --git a/app/ui/legacy/src/main/res/values-ml/strings.xml b/app/ui/legacy/src/main/res/values-ml/strings.xml index 1f4fc3664e5697f5ee552a291bea44ac47c8684e..fc8c070af06a64782aede1188b852119a0e1cba0 100644 --- a/app/ui/legacy/src/main/res/values-ml/strings.xml +++ b/app/ui/legacy/src/main/res/values-ml/strings.xml @@ -684,7 +684,6 @@ ഈ സന്ദേശം സംരക്ഷിക്കണോ അതോ നിരസിക്കണോ? സന്ദേശം നിരസിക്കണോ? ഈ സന്ദേശം നിരസിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ? - പകർത്താൻ വാചകം തിരഞ്ഞെടുക്കുക. പ്രാദേശിക സന്ദേശങ്ങൾ മായ്‌ക്കണോ? ഇത് എല്ലാ പ്രാദേശിക സന്ദേശങ്ങളും ഫോൾഡറിൽ നിന്ന് നീക്കംചെയ്യും. സെർവറിൽ നിന്ന് സന്ദേശങ്ങളൊന്നും ഇല്ലാതാക്കില്ല. സന്ദേശങ്ങൾ മായ്‌ക്കുക diff --git a/app/ui/legacy/src/main/res/values-nb/strings.xml b/app/ui/legacy/src/main/res/values-nb/strings.xml index 38d5f6241bccae2549e383dd919f6f65e41e4020..63ee87589a0fc10d5cc0470b882871eb0cb4c429 100644 --- a/app/ui/legacy/src/main/res/values-nb/strings.xml +++ b/app/ui/legacy/src/main/res/values-nb/strings.xml @@ -649,7 +649,6 @@ til %d flere Lagre eller Forkast denne meldingen? Forkast melding? Er du sikker på at du vil forkaste denne meldingen? - Velg teksten du vil kopiere. Fjern lokale meldinger? Dette vil fjerne alle lokale meldinger fra mappen. Ingen meldinger vil bli slettet fra tjener. Fjern meldinger diff --git a/app/ui/legacy/src/main/res/values-nl/strings.xml b/app/ui/legacy/src/main/res/values-nl/strings.xml index 0db826098fdcf24a01d8088c2a99446defddfa1f..1490e23ba7f58d9258c64ba7f2deb1afd88eb355 100644 --- a/app/ui/legacy/src/main/res/values-nl/strings.xml +++ b/app/ui/legacy/src/main/res/values-nl/strings.xml @@ -672,7 +672,6 @@ Wil je deze wijzigingen verwijderen\? Bevestig verwijderen\? Wil je dit bericht verwijderen\? - Selecteer tekst om te kopiëren. Lokale berichten wissen? Dit zal alle lokale berichten uit deze map wissen. Er worden geen berichten van de server gewist. Berichten wissen @@ -980,7 +979,6 @@ U kunt dit bericht bewaren als backup voor uw geheime sleutel. Als u dit wilt do Melding instellen Als je het niet nodig vindt om per direct meldingen te ontvangen van nieuwe berichten, dan kun je beter duw uitschakelen en in plaats daarvan kiezen voor peilen. Met peilen wordt er om de zoveel tijd gekeken of er nieuwe e-mails zijn binnengekomen. Daarvoor is het weergeven van een melding niet continu nodig. Duw uitschakelen - XOauth2 (Gmail, Outlook) Geluid afspelen wanneer een email succesvol verzonden is Geluid verzonden email Servicevoorwaarden diff --git a/app/ui/legacy/src/main/res/values-pl/strings.xml b/app/ui/legacy/src/main/res/values-pl/strings.xml index 469e4606e1c6a75c39c5934d9582a2e76facf8ad..c5b0db993269d4e4df80fea431c4f9d418551331 100644 --- a/app/ui/legacy/src/main/res/values-pl/strings.xml +++ b/app/ui/legacy/src/main/res/values-pl/strings.xml @@ -711,7 +711,6 @@ Zapisać czy odrzucić zmiany? Usunąć wiadomość? Czy na pewno chcesz usunąć tą wiadomość? - Wybierz tekst do skopiowania. Usunąć wiadomości lokalne? Wszystkie wiadomości lokalne z folderu zostaną usunięte. Wiadomości nie zostaną usunięte z serwera. Wyczyść wiadomości diff --git a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml index bcfabe2892a6c14f7f8e09dc38d556121e135a94..95125fd05dcbdf67d48f7a665907e7c4a25b4cea 100644 --- a/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rBR/strings.xml @@ -146,7 +146,9 @@ Falha na autenticação Falha na autenticação de %s. Atualize suas configurações de servidor. + Erro de notificação + Ocorreu um erro ao tentar criar uma notificação de sistema para uma nova mensagem. O provável motivo é a ausência de um som de notificação.\n\nToque para abrir as configurações de notificação. Verificando email: %s:%s Verificando email Enviando mensagem: %s @@ -711,7 +713,6 @@ Salvar ou descartar as alterações? Descartar a mensagem? Tem certeza que deseja descartar esta mensagem? - Selecione o texto a ser copiado. Limpar mensagens locais? Isso removerá todas as mensagens locais da pasta. Nenhuma mensagem será excluída no servidor. Limpar mensagens diff --git a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml index 6b0e93aa3d8fa5914fe748776c38b1d894c3ee81..578aaf4de83834b2b97d27de8b9385910e242ace 100644 --- a/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml +++ b/app/ui/legacy/src/main/res/values-pt-rPT/strings.xml @@ -644,7 +644,6 @@ Guardar ou rejeitar esta mensagem? Rejeitar mensagem? Tem a certeza que pretende rejeitar esta mensagem? - Selecione o texto para copiar. Limpar mensagens locais? Isto removerá todas as mensagens locais da pasta. Não serão apagadas mensagens do servidor. Limpar mensagens diff --git a/app/ui/legacy/src/main/res/values-ro/strings.xml b/app/ui/legacy/src/main/res/values-ro/strings.xml index b221b663feec1010ef02f7c5390e3e14eb130644..77c18a5565e6206b429d71c8267da569399255eb 100644 --- a/app/ui/legacy/src/main/res/values-ro/strings.xml +++ b/app/ui/legacy/src/main/res/values-ro/strings.xml @@ -702,7 +702,6 @@ Uneori datorită faptului că cineva încearcă să te atace pe tine sau serveru Salvați sau respingeți modificările? Renunți la mesaj? Sigur dorești să renunți la mesaj? - Selectează textul de copiat. Eliminare mesaje locale? Această acțiune va elimina toate mesejele locale din dosar. Niciun mesaj nu va fi șters de pe server. Elimină mesajele diff --git a/app/ui/legacy/src/main/res/values-ru/strings.xml b/app/ui/legacy/src/main/res/values-ru/strings.xml index 3654ceb179742bdc5e6c0190177dee1b111998a2..094cbb30fb0a147df2901e5c80b6f3ac75bc1f54 100644 --- a/app/ui/legacy/src/main/res/values-ru/strings.xml +++ b/app/ui/legacy/src/main/res/values-ru/strings.xml @@ -735,7 +735,6 @@ Mail — почтовый клиент для Android. Сохранить или отменить изменения? Удаление Отменить сообщение? - Выберите текст длительным нажатием Стереть локальные сообщения? Это удалит все локальные сообщения из папки.Сообщения не будут удалены с сервера. Стереть сообщения diff --git a/app/ui/legacy/src/main/res/values-sk/strings.xml b/app/ui/legacy/src/main/res/values-sk/strings.xml index ef4f63f78d8a848da9004767ea3a9dbffc81d561..22682ea14110d687c1ee0375ffdc0efe44d952f9 100644 --- a/app/ui/legacy/src/main/res/values-sk/strings.xml +++ b/app/ui/legacy/src/main/res/values-sk/strings.xml @@ -656,7 +656,6 @@ Uložiť alebo zahodiť túto správu? Zahodiť správu? Naozaj chcete zahodiť túto správu? - Vyberte text na kopírovanie. Zmazať lokálne uložené správy? Týmto odstránite všetky správy z priečinka. Na servi nebude žiadna spŕava zmazaná. Vyčistiť zprávy diff --git a/app/ui/legacy/src/main/res/values-sl/strings.xml b/app/ui/legacy/src/main/res/values-sl/strings.xml index b70e183390218d87fa496789dc108658c6189b0a..45df127258d0b2d42679c1e5c33190241fbead1f 100644 --- a/app/ui/legacy/src/main/res/values-sl/strings.xml +++ b/app/ui/legacy/src/main/res/values-sl/strings.xml @@ -12,6 +12,8 @@ Dovoljenje Apache, različica 2.0 Odprtokodni projekt Spletna stran + Navodila za uporabo + Poišči pomoč Uporabniški forum Fediverse Twitter @@ -147,7 +149,9 @@ dodatnih %d sporočil Overjanje je spodletelo Overjanje je spodletelo za račun %s. Posodobiti je treba nastavitve strežnika. + Napaka obveščanja + Med poskusom ustvarjanja sistemskega obvestila za novo sporočilo je prišlo do napake. Razlog je najverjetneje manjkajoči zvok obvestila.\n\nTapni, za odpreti nastavitve obvestil. Preverjanje pošte: %s:%s Preverjanje pošte Pošiljanje pošte: %s @@ -712,7 +716,6 @@ dodatnih %d sporočil Ali želite shraniti ali zavreči spremembe? Ali želite zavreči sporočilo? Ali ste prepričani, da želite zavreči to sporočilo? - Izberite besedilo za kopiranje. Ali želite počistiti krajevna sporočila? S tem bodo iz mape odstranjena vsa krajevna sporočila. Nobeno sporočilo ne bo izbrisano s strežnika. Počisti sporočila diff --git a/app/ui/legacy/src/main/res/values-sq/strings.xml b/app/ui/legacy/src/main/res/values-sq/strings.xml index 7316ab8711662a1e5b289ef4572ba081a9f86e5b..fc3e742de97ef53b6f975977d79178fb7765d9d1 100644 --- a/app/ui/legacy/src/main/res/values-sq/strings.xml +++ b/app/ui/legacy/src/main/res/values-sq/strings.xml @@ -712,7 +712,6 @@ Të ruhen apo të Hidhen tej ndryshimet? Të hidhet tej mesazhi? Jeni i sigurt se doni të hidhet tej ky mesazh? - Përzgjidhni tekst për kopjim. Të spastrohen mesazhe vendore? Kjo do të heqë nga dosja krejt mesazhet vendore. Prej shërbyesit s’do të fshihet ndonjë mesazh. Spastroji mesazhet diff --git a/app/ui/legacy/src/main/res/values-sr/strings.xml b/app/ui/legacy/src/main/res/values-sr/strings.xml index 0f390c0054380d7309a34f08e72db08cd4e1b375..bd9b52dd6444eff4ceea2aa7bed307d9b1f08159 100644 --- a/app/ui/legacy/src/main/res/values-sr/strings.xml +++ b/app/ui/legacy/src/main/res/values-sr/strings.xml @@ -655,7 +655,6 @@ Да сачувам или одбацим ову поруку? Одбацити поруку? Желите ли заиста да одбаците ову поруку? - Изаберите текст за копирање. Да очистим локалне поруке? Ово ће обрисати све локалне поруке из фасцикле. Ниједна порука са сервера неће бити обрисана. Очисти поруке diff --git a/app/ui/legacy/src/main/res/values-sv/strings.xml b/app/ui/legacy/src/main/res/values-sv/strings.xml index 8d28f4d94a83e9c57f19137e1146ed8ac9eb27fa..ecdf2d61787bafccd9efea9e2314c65b09d82727 100644 --- a/app/ui/legacy/src/main/res/values-sv/strings.xml +++ b/app/ui/legacy/src/main/res/values-sv/strings.xml @@ -713,7 +713,6 @@ Spara eller kassera ändringar? Kassera meddelandet? Är du säker på att du vill kassera detta meddelande? - Välj text att kopiera. Rensa lokala meddelanden? Detta tar bort alla lokala meddelanden från mappen. Inga meddelanden tas bort från servern. Rensa meddelanden diff --git a/app/ui/legacy/src/main/res/values-tr/strings.xml b/app/ui/legacy/src/main/res/values-tr/strings.xml index 239ee597629f6dd1e199e676a3efa0d7979faabb..c89903ca2cd4f22512f4d9148f090472f7b85f1e 100644 --- a/app/ui/legacy/src/main/res/values-tr/strings.xml +++ b/app/ui/legacy/src/main/res/values-tr/strings.xml @@ -694,7 +694,6 @@ Değişikliklerden vazgeç veya kaydet? İleti silinsin mi? Bu mesajı silmek istediğinizden emin misiniz? - Kopyalamak için metni seç. Yerel iletiler temizlensin mi? Bu işlem tüm yerel iletileri klasörden kaldıracak. İletiler sunucudan silinmeyecek. İletileri temizle diff --git a/app/ui/legacy/src/main/res/values-uk/strings.xml b/app/ui/legacy/src/main/res/values-uk/strings.xml index 59186a6522f4edcbe7d93b00cc214cdbcca5c6b1..71f52c6aea5d1e0599075f2e2e07a6b1eff82663 100644 --- a/app/ui/legacy/src/main/res/values-uk/strings.xml +++ b/app/ui/legacy/src/main/res/values-uk/strings.xml @@ -703,7 +703,6 @@ Зберегти чи Скасувати зміни? Скасувати повідомлення? Ви дійсно хочете скасувати це повідомлення? - Виберіть текст для копіювання. Очистити локальні повідомлення? Це видалить всі локальні повідомлення з теки. Жодне повідомлення не буде видалене з сервера. Очистити повідомлення diff --git a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml index 764be89ab4f10fa610c01e065188bdc44f299d59..1dfcb8640c641811b18e9700958fbfe436cfb62e 100644 --- a/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml +++ b/app/ui/legacy/src/main/res/values-zh-rCN/strings.xml @@ -709,7 +709,6 @@ 保存或取消更改? 丢弃该邮件? 确定丢弃该邮件? - 选择需要拷贝的文本。 清除本地消息? 这将从文件夹中删除所有本地邮件。 没有消息会从服务器中被删除。 清除消息 diff --git a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml index c1148319992d3ce5b2cb9ffb73e99bf1475e05f3..5f05d37b99a07a1139513ef9a028f2857bf65062 100644 --- a/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml +++ b/app/ui/legacy/src/main/res/values-zh-rTW/strings.xml @@ -702,7 +702,6 @@ 儲存還是捨棄變更? 捨棄郵件? 是否確定捨棄儲存目前的郵件? - 選擇需要複製的文字內容。 清除本地訊息? 這將從信件匣中刪除所有本地郵件。 沒有訊息會從伺服器中被刪除。 清除訊息 diff --git a/app/ui/legacy/src/test/java/com/fsck/k9/ui/settings/general/GeneralSettingsViewModelTest.kt b/app/ui/legacy/src/test/java/com/fsck/k9/ui/settings/general/GeneralSettingsViewModelTest.kt index 5037a828c172bb1410bdd89d88721da8a39a81e9..cb9b435c4c7ab0598fd776d668cd2200d7227185 100644 --- a/app/ui/legacy/src/test/java/com/fsck/k9/ui/settings/general/GeneralSettingsViewModelTest.kt +++ b/app/ui/legacy/src/test/java/com/fsck/k9/ui/settings/general/GeneralSettingsViewModelTest.kt @@ -12,12 +12,11 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.test.TestCoroutineDispatcher +import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.setMain -import kotlinx.coroutines.withTimeout import org.junit.After import org.junit.Before import org.junit.Test @@ -28,7 +27,7 @@ class GeneralSettingsViewModelTest { private val logFileWriter = TestLogFileWriter() private val contentUri = mock() private val viewModel = GeneralSettingsViewModel(logFileWriter) - private val testCoroutineDispatcher = TestCoroutineDispatcher() + private val testCoroutineDispatcher = StandardTestDispatcher() @Before fun setUp() { @@ -41,62 +40,60 @@ class GeneralSettingsViewModelTest { } @Test - fun `export logs without errors`() = runBlocking { + fun `export logs without errors`() = runTest { viewModel.uiState.test { viewModel.exportLogs(contentUri) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Idle) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Exporting) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Success) - testCoroutineDispatcher.advanceTimeBy(GeneralSettingsViewModel.SNACKBAR_DURATION) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Idle) + testCoroutineDispatcher.scheduler.advanceUntilIdle() assertThat(cancelAndConsumeRemainingEvents()).isEmpty() } } @Test - fun `export logs with consumer changing while LogFileWriter_writeLogTo is running`() = runBlocking { - withTimeout(timeMillis = 1000L) { - logFileWriter.shouldWait() - - val mutex = Mutex(locked = true) + fun `export logs with consumer changing while LogFileWriter_writeLogTo is running`() = runTest { + logFileWriter.shouldWait() + + val mutex = Mutex(locked = true) + + // The first consumer + val job = launch(CoroutineName("ConsumerOne")) { + var first = true + val states = viewModel.uiState.onEach { + if (first) { + first = false + mutex.unlock() + } + }.take(2).toList() + + assertThat(states[0]).isEqualTo(GeneralSettingsUiState.Idle) + assertThat(states[1]).isEqualTo(GeneralSettingsUiState.Exporting) + } - // The first consumer - val job = launch(CoroutineName("ConsumerOne")) { - var first = true - val states = viewModel.uiState.onEach { - if (first) { - first = false - mutex.unlock() - } - }.take(2).toList() + // Wait until the "ConsumerOne" coroutine has collected the initial UI state + mutex.lock() - assertThat(states[0]).isEqualTo(GeneralSettingsUiState.Idle) - assertThat(states[1]).isEqualTo(GeneralSettingsUiState.Exporting) - } + viewModel.exportLogs(contentUri) - // Wait until the "ConsumerOne" coroutine has collected the initial UI state - mutex.lock() + // Wait until the "ConsumerOne" coroutine has finished collecting items + job.join() - viewModel.exportLogs(contentUri) - - // Wait until the "ConsumerOne" coroutine has finished collecting items - job.join() - - // The second consumer - viewModel.uiState.test { - assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Exporting) - logFileWriter.resume() - assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Success) - testCoroutineDispatcher.advanceTimeBy(GeneralSettingsViewModel.SNACKBAR_DURATION) - assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Idle) - assertThat(cancelAndConsumeRemainingEvents()).isEmpty() - } + // The second consumer + viewModel.uiState.test { + assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Exporting) + logFileWriter.resume() + assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Success) + assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Idle) + testCoroutineDispatcher.scheduler.advanceUntilIdle() + assertThat(cancelAndConsumeRemainingEvents()).isEmpty() } } @Test - fun `export logs with IOException`() = runBlocking { + fun `export logs with IOException`() = runTest { logFileWriter.exception = IOException() viewModel.uiState.test { @@ -105,14 +102,14 @@ class GeneralSettingsViewModelTest { assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Idle) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Exporting) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Failure) - testCoroutineDispatcher.advanceTimeBy(GeneralSettingsViewModel.SNACKBAR_DURATION) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Idle) + testCoroutineDispatcher.scheduler.advanceUntilIdle() assertThat(cancelAndConsumeRemainingEvents()).isEmpty() } } @Test - fun `export logs with IllegalStateException`() = runBlocking { + fun `export logs with IllegalStateException`() = runTest { logFileWriter.exception = IllegalStateException() viewModel.uiState.test { @@ -121,8 +118,8 @@ class GeneralSettingsViewModelTest { assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Idle) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Exporting) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Failure) - testCoroutineDispatcher.advanceTimeBy(GeneralSettingsViewModel.SNACKBAR_DURATION) assertThat(awaitItem()).isEqualTo(GeneralSettingsUiState.Idle) + testCoroutineDispatcher.scheduler.advanceUntilIdle() assertThat(cancelAndConsumeRemainingEvents()).isEmpty() } } diff --git a/app/ui/setup/build.gradle b/app/ui/setup/build.gradle index 42c10c8337fcc512aa49a390966f803e25e2c892..a4279c21e0b1a09906d5ddd45e407ba1a931ae34 100644 --- a/app/ui/setup/build.gradle +++ b/app/ui/setup/build.gradle @@ -22,6 +22,7 @@ dependencies { testImplementation "com.google.truth:truth:${versions.truth}" testImplementation "org.mockito:mockito-core:${versions.mockito}" testImplementation "org.mockito.kotlin:mockito-kotlin:${versions.mockitoKotlin}" + testImplementation "io.insert-koin:koin-test:${versions.koin}" testImplementation "io.insert-koin:koin-test-junit4:${versions.koin}" } diff --git a/build.gradle b/build.gradle index d4832439c848ee65fceb19cfa4f89360d0adcc35..1b7a67dea0ee635df29151d5bd2c7a1410bfc18e 100644 --- a/build.gradle +++ b/build.gradle @@ -11,47 +11,47 @@ buildscript { ] versions = [ - 'kotlin': '1.6.10', - 'kotlinCoroutines': '1.6.0', + 'kotlin': '1.7.10', + 'kotlinCoroutines': '1.6.4', 'jetbrainsAnnotations': '23.0.0', - 'androidxAppCompat': '1.4.1', - 'androidxActivity': '1.4.0', + 'androidxAppCompat': '1.4.2', + 'androidxActivity': '1.5.1', 'androidxRecyclerView': '1.2.1', - 'androidxLifecycle': '2.4.1', - 'androidxAnnotation': '1.3.0', + 'androidxLifecycle': '2.5.1', + 'androidxAnnotation': '1.4.0', 'androidxBiometric': '1.1.0', - 'androidxNavigation': '2.4.1', - 'androidxConstraintLayout': '2.1.3', + 'androidxNavigation': '2.5.1', + 'androidxConstraintLayout': '2.1.4', 'androidxWorkManager': '2.7.1', - 'androidxFragment': '1.4.1', + 'androidxFragment': '1.5.1', 'androidxLocalBroadcastManager': '1.1.0', - 'androidxCore': '1.7.0', + 'androidxCore': '1.8.0', 'androidxCardView': '1.0.0', 'androidxPreference': '1.2.0', 'androidxTestCore': '1.4.0', - 'materialComponents': '1.5.0', + 'materialComponents': '1.6.1', 'fastAdapter': '5.6.0', 'preferencesFix': '1.1.0', - 'okio': '3.0.0', + 'okio': '3.2.0', 'moshi': '1.13.0', 'timber': '5.0.1', - 'koin': '3.1.5', + 'koin': '3.2.0', 'commonsIo': '2.6', 'mime4j': '0.8.6', - 'okhttp': '4.9.3', + 'okhttp': '4.10.0', 'minidns': '1.0.3', - 'glide': '4.13.1', - 'jsoup': '1.14.3', + 'glide': '4.13.2', + 'jsoup': '1.15.2', 'retrofit': '2.9.0', 'androidxTestRunner': '1.4.0', 'junit': '4.13.2', - 'robolectric': '4.7.3', - 'mockito': '4.3.1', + 'robolectric': '4.8.1', + 'mockito': '4.6.1', 'mockitoKotlin': '4.0.0', 'truth': '1.1.3', - 'turbine': '0.7.0', + 'turbine': '0.9.0', 'ktlint': '0.40.0', - 'leakcanary': '2.8.1' + 'leakcanary': '2.9.1' ] javaVersion = JavaVersion.VERSION_11 @@ -66,7 +66,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' + classpath 'com.android.tools.build:gradle:7.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" classpath "org.jlleitschuh.gradle:ktlint-gradle:10.0.0" } diff --git a/fastlane/metadata/android/en-US/changelogs/33001.txt b/fastlane/metadata/android/en-US/changelogs/33001.txt new file mode 100644 index 0000000000000000000000000000000000000000..feae1067c2b2c09e9e547ff0dfecc8576eb0a2e2 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/33001.txt @@ -0,0 +1,5 @@ +- Fixed crash when viewing a message and OpenKeychain needed to display its user interface, e.g. to ask for a password +- When composing a message containing consecutive spaces convert them to non-breaking spaces in the generated HTML part of the message +- Fixed bug where moving a message to another folder wouldn't update the apps search index +- Fixed small bug where not all cached values were removed when using "clear local messages" +- Updated translations diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..249e5832f090a2944b7473328c07c9755baa3196 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b1159fc54f39b3b208f767fd65a460b6016e04ad..2ec77e51a9c9fdad7b06dcd6b4bf75a36b92f6d9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787337ffb79f0e3cf8b1e9f00f680a959de1..a69d9cb6c20655813e44515156e7253a2a239138 100755 --- a/gradlew +++ b/gradlew @@ -205,6 +205,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f93825db68fb0c0b5150917f340eaa5d02..53a6b238d414d91c30c5644c82393d27416fbbe6 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/app/core/src/main/java/com/fsck/k9/helper/EmailHelper.kt b/mail/common/src/main/java/com/fsck/k9/helper/EmailHelper.kt similarity index 100% rename from app/core/src/main/java/com/fsck/k9/helper/EmailHelper.kt rename to mail/common/src/main/java/com/fsck/k9/helper/EmailHelper.kt