From 2d1dcd34c0a9e8a2bbaec84c5fd749630205b402 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Fri, 5 May 2023 09:29:57 +0100 Subject: [PATCH 001/234] Add mentions to rich text editor --- dependencies.gradle | 3 +- dependencies_groups.gradle | 2 + vector/build.gradle | 1 + .../java/im/vector/app/core/utils/TestSpan.kt | 2 +- .../home/room/detail/AutoCompleter.kt | 72 +++++-- .../home/room/detail/TimelineViewModel.kt | 3 + .../composer/MessageComposerFragment.kt | 12 +- .../detail/composer/RichTextComposerLayout.kt | 22 +- .../composer/mentions/PillDisplayHandler.kt | 78 +++++++ .../app/features/html/EventHtmlRenderer.kt | 2 +- .../app/features/html/HtmlCodeHandlers.kt | 4 +- .../mentions/PillDisplayHandlerTest.kt | 198 ++++++++++++++++++ 12 files changed, 375 insertions(+), 24 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt create mode 100644 vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt diff --git a/dependencies.gradle b/dependencies.gradle index 5f4df15860..9fbaf5608d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -101,7 +101,7 @@ ext.libs = [ ], element : [ 'opusencoder' : "io.element.android:opusencoder:1.1.0", - 'wysiwyg' : "io.element.android:wysiwyg:1.2.2" + 'wysiwyg' : "io.element.android:wysiwyg:2.2.0" ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", @@ -172,6 +172,7 @@ ext.libs = [ 'kluent' : "org.amshove.kluent:kluent-android:1.73", 'timberJunitRule' : "net.lachlanmckee:timber-junit-rule:1.0.1", 'junit' : "junit:junit:4.13.2", + 'robolectric' : "org.robolectric:robolectric:4.9", ] ] diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 6292b5d231..66d07f258b 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -189,6 +189,7 @@ ext.groups = [ 'org.codehaus.groovy', 'org.codehaus.mojo', 'org.codehaus.woodstox', + 'org.conscrypt', 'org.eclipse.ee4j', 'org.ec4j.core', 'org.freemarker', @@ -221,6 +222,7 @@ ext.groups = [ 'org.ow2.asm', 'org.ow2.asm', 'org.reactivestreams', + 'org.robolectric', 'org.slf4j', 'org.sonatype.oss', 'org.testng', diff --git a/vector/build.gradle b/vector/build.gradle index 05a23bf0df..a5f368ff9d 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -299,6 +299,7 @@ dependencies { testImplementation libs.tests.kluent testImplementation libs.mockk.mockk testImplementation libs.androidx.coreTesting + testImplementation libs.tests.robolectric // Plant Timber tree for test testImplementation libs.tests.timberJunitRule testImplementation libs.airbnb.mavericksTesting diff --git a/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt b/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt index ebbe565642..fe6f6cb987 100644 --- a/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt +++ b/vector/src/androidTest/java/im/vector/app/core/utils/TestSpan.kt @@ -23,7 +23,7 @@ import android.text.Spanned import android.text.style.StrikethroughSpan import androidx.core.text.getSpans import im.vector.app.features.html.HtmlCodeSpan -import io.element.android.wysiwyg.spans.InlineCodeSpan +import io.element.android.wysiwyg.view.spans.InlineCodeSpan import io.mockk.justRun import io.mockk.mockk import io.mockk.slot diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt index 51e1fb06f2..2a5113ef6c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt @@ -40,23 +40,31 @@ import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.html.PillImageSpan import im.vector.app.features.themes.ThemeUtils +import io.element.android.wysiwyg.EditorEditText +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.permalinks.PermalinkService import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.toEveryoneInRoomMatrixItem import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.api.util.toRoomAliasMatrixItem +import timber.log.Timber class AutoCompleter @AssistedInject constructor( @Assisted val roomId: String, @Assisted val isInThreadTimeline: Boolean, + private val session: Session, private val avatarRenderer: AvatarRenderer, private val commandAutocompletePolicy: CommandAutocompletePolicy, autocompleteCommandPresenterFactory: AutocompleteCommandPresenter.Factory, private val autocompleteMemberPresenterFactory: AutocompleteMemberPresenter.Factory, private val autocompleteRoomPresenter: AutocompleteRoomPresenter, - private val autocompleteEmojiPresenter: AutocompleteEmojiPresenter + private val autocompleteEmojiPresenter: AutocompleteEmojiPresenter, ) { + private val permalinkService: PermalinkService + get() = session.permalinkService() + private lateinit var autocompleteMemberPresenter: AutocompleteMemberPresenter @AssistedFactory @@ -99,6 +107,9 @@ class AutoCompleter @AssistedInject constructor( } private fun setupCommands(backgroundDrawable: Drawable, editText: EditText) { + // Rich text editor is not yet supported + if (editText is EditorEditText) return + Autocomplete.on(editText) .with(commandAutocompletePolicy) .with(autocompleteCommandPresenter) @@ -128,17 +139,15 @@ class AutoCompleter @AssistedInject constructor( .with(backgroundDrawable) .with(object : AutocompleteCallback { override fun onPopupItemClicked(editable: Editable, item: AutocompleteMemberItem): Boolean { - return when (item) { - is AutocompleteMemberItem.Header -> false // do nothing header is not clickable - is AutocompleteMemberItem.RoomMember -> { - insertMatrixItem(editText, editable, TRIGGER_AUTO_COMPLETE_MEMBERS, item.roomMemberSummary.toMatrixItem()) - true - } - is AutocompleteMemberItem.Everyone -> { - insertMatrixItem(editText, editable, TRIGGER_AUTO_COMPLETE_MEMBERS, item.roomSummary.toEveryoneInRoomMatrixItem()) - true - } - } + val matrixItem = when (item) { + is AutocompleteMemberItem.Header -> null // do nothing header is not clickable + is AutocompleteMemberItem.RoomMember -> item.roomMemberSummary.toMatrixItem() + is AutocompleteMemberItem.Everyone -> item.roomSummary.toEveryoneInRoomMatrixItem() + } ?: return false + + insertMatrixItem(editText, editable, TRIGGER_AUTO_COMPLETE_MEMBERS, matrixItem) + + return true } override fun onPopupVisibilityChanged(shown: Boolean) { @@ -166,6 +175,9 @@ class AutoCompleter @AssistedInject constructor( } private fun setupEmojis(backgroundDrawable: Drawable, editText: EditText) { + // Rich text editor is not yet supported + if (editText is EditorEditText) return + Autocomplete.on(editText) .with(CharPolicy(TRIGGER_AUTO_COMPLETE_EMOJIS, false)) .with(autocompleteEmojiPresenter) @@ -197,7 +209,41 @@ class AutoCompleter @AssistedInject constructor( .build() } - private fun insertMatrixItem(editText: EditText, editable: Editable, firstChar: Char, matrixItem: MatrixItem) { + private fun insertMatrixItem(editText: EditText, editable: Editable, firstChar: Char, matrixItem: MatrixItem) = + if (editText is EditorEditText) { + insertMatrixItemIntoRichTextEditor(editText, matrixItem) + } else { + insertMatrixItemIntoEditable(editText, editable, firstChar, matrixItem) + } + + private fun insertMatrixItemIntoRichTextEditor(editorEditText: EditorEditText, matrixItem: MatrixItem) { + if (matrixItem is MatrixItem.EveryoneInRoomItem) { + editorEditText.replaceTextSuggestion(matrixItem.displayName) + return + } + + val permalink = permalinkService.createPermalink(matrixItem.id) + + if (permalink == null) { + Timber.e(NullPointerException("Cannot autocomplete as permalink is null")) + return + } + + val linkText = when (matrixItem) { + is MatrixItem.RoomAliasItem, + is MatrixItem.RoomItem, + is MatrixItem.SpaceItem -> + matrixItem.id + is MatrixItem.EveryoneInRoomItem, + is MatrixItem.UserItem, + is MatrixItem.EventItem -> + matrixItem.getBestName() + } + + editorEditText.setLinkSuggestion(url = permalink, text = linkText) + } + + private fun insertMatrixItemIntoEditable(editText: EditText, editable: Editable, firstChar: Char, matrixItem: MatrixItem) { // Detect last firstChar and remove it var startIndex = editable.lastIndexOf(firstChar) if (startIndex == -1) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 746396d1e1..3793ed18d2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -765,6 +765,9 @@ class TimelineViewModel @AssistedInject constructor( return room?.membershipService()?.getRoomMember(userId) } + fun getRoom(roomId: String): RoomSummary? = + session.roomService().getRoomSummary(roomId) + private fun handleComposerFocusChange(action: RoomDetailAction.ComposerFocusChange) { if (room == null) return // Ensure outbound session keys diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt index d9459d259a..9dda413af7 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt @@ -83,6 +83,7 @@ import im.vector.app.features.home.room.detail.TimelineViewModel import im.vector.app.features.home.room.detail.composer.link.SetLinkFragment import im.vector.app.features.home.room.detail.composer.link.SetLinkSharedAction import im.vector.app.features.home.room.detail.composer.link.SetLinkSharedActionViewModel +import im.vector.app.features.home.room.detail.composer.mentions.PillDisplayHandler import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActionViewModel import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet @@ -315,9 +316,7 @@ class MessageComposerFragment : VectorBaseFragment(), A val composerEditText = composer.editText composerEditText.setHint(R.string.room_message_placeholder) - if (!vectorPreferences.isRichTextEditorEnabled()) { - autoCompleter.setup(composerEditText) - } + autoCompleter.setup(composerEditText) observerUserTyping() @@ -404,6 +403,13 @@ class MessageComposerFragment : VectorBaseFragment(), A SetLinkFragment.show(isTextSupported, initialLink, childFragmentManager) } } + (composer as? RichTextComposerLayout)?.pillDisplayHandler = PillDisplayHandler( + roomId = roomId, + getRoom = timelineViewModel::getRoom, + getMember = timelineViewModel::getMember, + ) { matrixItem: MatrixItem -> + PillImageSpan(glideRequests, avatarRenderer, requireContext(), matrixItem) + } } private fun sendTextMessage(text: CharSequence, formattedText: String? = null) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt index a821458939..ac64d18737 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt @@ -49,10 +49,14 @@ import im.vector.app.core.utils.DimensionConverter import im.vector.app.databinding.ComposerRichTextLayoutBinding import im.vector.app.databinding.ViewRichTextMenuButtonBinding import im.vector.app.features.home.room.detail.composer.images.UriContentListener +import im.vector.app.features.home.room.detail.composer.mentions.PillDisplayHandler import io.element.android.wysiwyg.EditorEditText -import io.element.android.wysiwyg.inputhandlers.models.InlineFormat -import io.element.android.wysiwyg.inputhandlers.models.LinkAction +import io.element.android.wysiwyg.display.KeywordDisplayHandler +import io.element.android.wysiwyg.display.LinkDisplayHandler +import io.element.android.wysiwyg.display.TextDisplay import io.element.android.wysiwyg.utils.RustErrorCollector +import io.element.android.wysiwyg.view.models.InlineFormat +import io.element.android.wysiwyg.view.models.LinkAction import uniffi.wysiwyg_composer.ActionState import uniffi.wysiwyg_composer.ComposerAction @@ -102,6 +106,8 @@ internal class RichTextComposerLayout @JvmOverloads constructor( override val attachmentButton: ImageButton get() = views.attachmentButton + var pillDisplayHandler: PillDisplayHandler? = null + // Border of the EditText private val borderShapeDrawable: MaterialShapeDrawable by lazy { MaterialShapeDrawable().apply { @@ -227,6 +233,16 @@ internal class RichTextComposerLayout @JvmOverloads constructor( views.composerEditTextOuterBorder.background = borderShapeDrawable setupRichTextMenu() + views.richTextComposerEditText.linkDisplayHandler = LinkDisplayHandler { text, url -> + pillDisplayHandler?.resolveLinkDisplay(text, url) ?: TextDisplay.Plain + } + views.richTextComposerEditText.keywordDisplayHandler = object : KeywordDisplayHandler { + override val keywords: List + get() = pillDisplayHandler?.keywords.orEmpty() + + override fun resolveKeywordDisplay(text: String): TextDisplay = + pillDisplayHandler?.resolveKeywordDisplay(text) ?: TextDisplay.Plain + } updateTextFieldBorder(isFullScreen) } @@ -269,7 +285,7 @@ internal class RichTextComposerLayout @JvmOverloads constructor( views.richTextComposerEditText.getLinkAction()?.let { when (it) { LinkAction.InsertLink -> callback?.onSetLink(isTextSupported = true, initialLink = null) - is LinkAction.SetLink -> callback?.onSetLink(isTextSupported = false, initialLink = it.currentLink) + is LinkAction.SetLink -> callback?.onSetLink(isTextSupported = false, initialLink = it.currentUrl) } } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt new file mode 100644 index 0000000000..b657257b85 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.detail.composer.mentions + +import android.text.style.ReplacementSpan +import io.element.android.wysiwyg.display.KeywordDisplayHandler +import io.element.android.wysiwyg.display.LinkDisplayHandler +import io.element.android.wysiwyg.display.TextDisplay +import org.matrix.android.sdk.api.session.permalinks.PermalinkData +import org.matrix.android.sdk.api.session.permalinks.PermalinkParser +import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary +import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.util.MatrixItem +import org.matrix.android.sdk.api.util.toEveryoneInRoomMatrixItem +import org.matrix.android.sdk.api.util.toMatrixItem + +/** + * A rich text editor [LinkDisplayHandler] and [KeywordDisplayHandler] + * that helps with replacing user and room links with pills. + */ +internal class PillDisplayHandler( + private val roomId: String, + private val getRoom: (roomId: String) -> RoomSummary?, + private val getMember: (userId: String) -> RoomMemberSummary?, + private val replacementSpanFactory: (matrixItem: MatrixItem) -> ReplacementSpan, +) : LinkDisplayHandler, KeywordDisplayHandler { + override fun resolveLinkDisplay(text: String, url: String): TextDisplay { + val matrixItem = when (val permalink = PermalinkParser.parse(url)) { + is PermalinkData.UserLink -> { + val userId = permalink.userId + when (val roomMember = getMember(userId)) { + null -> MatrixItem.UserItem(userId, userId, null) + else -> roomMember.toMatrixItem() + } + } + is PermalinkData.RoomLink -> { + val roomId = permalink.roomIdOrAlias + val room = getRoom(roomId) + when { + room == null -> MatrixItem.RoomItem(roomId, roomId, null) + text == MatrixItem.NOTIFY_EVERYONE -> room.toEveryoneInRoomMatrixItem() + else -> room.toMatrixItem() + } + } + else -> + return TextDisplay.Plain + } + val replacement = replacementSpanFactory.invoke(matrixItem) + return TextDisplay.Custom(customSpan = replacement) + } + + override val keywords: List + get() = listOf(MatrixItem.NOTIFY_EVERYONE) + + override fun resolveKeywordDisplay(text: String): TextDisplay = + when (text) { + MatrixItem.NOTIFY_EVERYONE -> { + val matrixItem = getRoom(roomId)?.toEveryoneInRoomMatrixItem() + ?: MatrixItem.EveryoneInRoomItem(roomId) + TextDisplay.Custom(replacementSpanFactory.invoke(matrixItem)) + } + else -> TextDisplay.Plain + } +} diff --git a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt index cb3f12d867..5874474965 100644 --- a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt @@ -43,7 +43,7 @@ import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.ColorProvider import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences -import io.element.android.wysiwyg.spans.InlineCodeSpan +import io.element.android.wysiwyg.view.spans.InlineCodeSpan import io.noties.markwon.AbstractMarkwonPlugin import io.noties.markwon.Markwon import io.noties.markwon.MarkwonPlugin diff --git a/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt b/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt index 3175996ba1..7ffd9ceb84 100644 --- a/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt +++ b/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt @@ -18,8 +18,8 @@ package im.vector.app.features.html import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences -import io.element.android.wysiwyg.spans.CodeBlockSpan -import io.element.android.wysiwyg.spans.InlineCodeSpan +import io.element.android.wysiwyg.view.spans.CodeBlockSpan +import io.element.android.wysiwyg.view.spans.InlineCodeSpan import io.noties.markwon.MarkwonVisitor import io.noties.markwon.SpannableBuilder import io.noties.markwon.core.MarkwonTheme diff --git a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt new file mode 100644 index 0000000000..6529cf162e --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.detail.composer.mentions + +import android.graphics.Canvas +import android.graphics.Paint +import android.text.style.ReplacementSpan +import io.element.android.wysiwyg.display.TextDisplay +import io.mockk.every +import io.mockk.mockk +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary +import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.util.MatrixItem +import org.matrix.android.sdk.api.util.MatrixItem.Companion.NOTIFY_EVERYONE +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +internal class PillDisplayHandlerTest { + private val mockGetMember = mockk<(userId: String) -> RoomMemberSummary?>() + private val mockGetRoom = mockk<(roomId: String) -> RoomSummary?>() + private val fakeReplacementSpanFactory = { matrixItem: MatrixItem -> MatrixItemHolderSpan(matrixItem) } + + private companion object { + const val ROOM_ID = "!thisroom:matrix.org" + const val NON_MATRIX_URL = "https://example.com" + const val UNKNOWN_MATRIX_ROOM_ID = "!unknown:matrix.org" + const val UNKNOWN_MATRIX_ROOM_URL = "https://matrix.to/#/$UNKNOWN_MATRIX_ROOM_ID" + const val KNOWN_MATRIX_ROOM_ID = "!known:matrix.org" + const val KNOWN_MATRIX_ROOM_URL = "https://matrix.to/#/$KNOWN_MATRIX_ROOM_ID" + const val KNOWN_MATRIX_ROOM_AVATAR = "https://example.com/avatar.png" + const val KNOWN_MATRIX_ROOM_NAME = "known room" + const val UNKNOWN_MATRIX_USER_ID = "@unknown:matrix.org" + const val UNKNOWN_MATRIX_USER_URL = "https://matrix.to/#/$UNKNOWN_MATRIX_USER_ID" + const val KNOWN_MATRIX_USER_ID = "@known:matrix.org" + const val KNOWN_MATRIX_USER_URL = "https://matrix.to/#/$KNOWN_MATRIX_USER_ID" + const val KNOWN_MATRIX_USER_AVATAR = "https://example.com/avatar.png" + const val KNOWN_MATRIX_USER_NAME = "known user" + } + + @Before + fun setUp() { + every { mockGetMember(UNKNOWN_MATRIX_USER_ID) } returns null + every { mockGetMember(KNOWN_MATRIX_USER_ID) } returns createFakeRoomMember(KNOWN_MATRIX_USER_NAME, KNOWN_MATRIX_USER_ID, KNOWN_MATRIX_USER_AVATAR) + every { mockGetRoom(UNKNOWN_MATRIX_ROOM_ID) } returns null + every { mockGetRoom(KNOWN_MATRIX_ROOM_ID) } returns createFakeRoom(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR) + every { mockGetRoom(ROOM_ID) } returns createFakeRoom(ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR) + } + + @Test + fun `when resolve non-matrix link, then it returns plain text`() { + val subject = createSubject() + + val result = subject.resolveLinkDisplay("text", NON_MATRIX_URL) + + assertEquals(TextDisplay.Plain, result) + } + + @Test + fun `when resolve unknown user link, then it returns generic custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveLinkDisplay("text", UNKNOWN_MATRIX_USER_URL) + .getMatrixItem() + + assertEquals(MatrixItem.UserItem(UNKNOWN_MATRIX_USER_ID, UNKNOWN_MATRIX_USER_ID, null), matrixItem) + } + + @Test + fun `when resolve known user link, then it returns named custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_USER_URL) + .getMatrixItem() + + assertEquals(MatrixItem.UserItem(KNOWN_MATRIX_USER_ID, KNOWN_MATRIX_USER_NAME, KNOWN_MATRIX_USER_AVATAR), matrixItem) + } + + @Test + fun `when resolve unknown room link, then it returns generic custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveLinkDisplay("text", UNKNOWN_MATRIX_ROOM_URL) + .getMatrixItem() + + assertEquals(MatrixItem.RoomItem(UNKNOWN_MATRIX_ROOM_ID, UNKNOWN_MATRIX_ROOM_ID, null), matrixItem) + } + + @Test + fun `when resolve known room link, then it returns named custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_ROOM_URL) + .getMatrixItem() + + assertEquals(MatrixItem.RoomItem(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem) + } + + @Test + fun `when resolve @room link, then it returns room notification custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveLinkDisplay("@room", KNOWN_MATRIX_ROOM_URL) + .getMatrixItem() + + assertEquals(MatrixItem.EveryoneInRoomItem(KNOWN_MATRIX_ROOM_ID, NOTIFY_EVERYONE, KNOWN_MATRIX_ROOM_AVATAR, KNOWN_MATRIX_ROOM_NAME), matrixItem) + } + + @Test + fun `when resolve @room keyword, then it returns room notification custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveKeywordDisplay("@room") + .getMatrixItem() + + assertEquals(MatrixItem.EveryoneInRoomItem(ROOM_ID, NOTIFY_EVERYONE, KNOWN_MATRIX_ROOM_AVATAR, KNOWN_MATRIX_ROOM_NAME), matrixItem) + } + + @Test + fun `given cannot get current room, when resolve @room keyword, then it returns room notification custom pill`() { + val subject = createSubject() + every { mockGetRoom(ROOM_ID) } returns null + + val matrixItem = subject.resolveKeywordDisplay("@room") + .getMatrixItem() + + assertEquals(MatrixItem.EveryoneInRoomItem(ROOM_ID, NOTIFY_EVERYONE, null, null), matrixItem) + } + + @Test + fun `when get keywords, then it returns @room`() { + val subject = createSubject() + + assertEquals(listOf("@room"), subject.keywords) + } + + private fun TextDisplay.getMatrixItem(): MatrixItem? { + val customSpan = this as? TextDisplay.Custom + assertNotNull("The URL did not resolve to a custom link display method", customSpan) + + val matrixItemHolderSpan = customSpan!!.customSpan as MatrixItemHolderSpan + return matrixItemHolderSpan.matrixItem + } + + private fun createSubject(): PillDisplayHandler = PillDisplayHandler( + roomId = ROOM_ID, + getRoom = mockGetRoom, + getMember = mockGetMember, + replacementSpanFactory = fakeReplacementSpanFactory + ) + + private fun createFakeRoomMember(displayName: String, userId: String, avatarUrl: String): RoomMemberSummary = RoomMemberSummary( + membership = Membership.JOIN, + userId = userId, + displayName = displayName, + avatarUrl = avatarUrl, + ) + + private fun createFakeRoom(roomId: String, roomName: String, avatarUrl: String): RoomSummary = RoomSummary( + roomId = roomId, + displayName = roomName, + avatarUrl = avatarUrl, + encryptionEventTs = null, + typingUsers = emptyList(), + isEncrypted = false + ) + + data class MatrixItemHolderSpan( + val matrixItem: MatrixItem + ) : ReplacementSpan() { + override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) { + // Do nothing + } + + override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int { + return 0 + } + } +} From 29d8845792df5c53c7b099ae3f7d9c26baeecea2 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Wed, 17 May 2023 11:59:20 +0100 Subject: [PATCH 002/234] Add slash commands to rich text editor --- .../features/home/room/detail/AutoCompleter.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt index 2a5113ef6c..3c6228caeb 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt @@ -107,9 +107,6 @@ class AutoCompleter @AssistedInject constructor( } private fun setupCommands(backgroundDrawable: Drawable, editText: EditText) { - // Rich text editor is not yet supported - if (editText is EditorEditText) return - Autocomplete.on(editText) .with(commandAutocompletePolicy) .with(autocompleteCommandPresenter) @@ -117,10 +114,14 @@ class AutoCompleter @AssistedInject constructor( .with(backgroundDrawable) .with(object : AutocompleteCallback { override fun onPopupItemClicked(editable: Editable, item: Command): Boolean { - editable.clear() - editable - .append(item.command) - .append(" ") + if (editText is EditorEditText) { + editText.replaceTextSuggestion(item.command) + } else { + editable.clear() + editable + .append(item.command) + .append(" ") + } return true } From 24614bbbae2ac8e171505305e94bebcaf111291f Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Wed, 17 May 2023 12:04:53 +0100 Subject: [PATCH 003/234] Add changelog --- changelog.d/8440.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/8440.feature diff --git a/changelog.d/8440.feature b/changelog.d/8440.feature new file mode 100644 index 0000000000..19c9d919eb --- /dev/null +++ b/changelog.d/8440.feature @@ -0,0 +1 @@ +[Rich text editor] Add mentions and slash commands \ No newline at end of file From 3157a35b74a5f56206da856e22cd67d66ed92da8 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Thu, 18 May 2023 11:05:04 +0100 Subject: [PATCH 004/234] Add autocomplete to plain text composer --- .../home/room/detail/AutoCompleter.kt | 20 ++++++++--- .../composer/MessageComposerFragment.kt | 35 +++++++++++++------ .../detail/composer/RichTextComposerLayout.kt | 5 +++ 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt index 3c6228caeb..568f4cf9e7 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt @@ -87,6 +87,7 @@ class AutoCompleter @AssistedInject constructor( } private lateinit var glideRequests: GlideRequests + private val autocompletes: MutableSet> = hashSetOf() fun setup(editText: EditText) { this.editText = editText @@ -98,16 +99,27 @@ class AutoCompleter @AssistedInject constructor( setupRooms(backgroundDrawable, editText) } + fun setEnabled(isEnabled: Boolean) = + autocompletes.forEach { + if (!isEnabled) { it.dismissPopup() } + it.setEnabled(isEnabled) + } + fun clear() { this.editText = null autocompleteEmojiPresenter.clear() autocompleteRoomPresenter.clear() autocompleteCommandPresenter.clear() autocompleteMemberPresenter.clear() + autocompletes.forEach { + it.setEnabled(false) + it.dismissPopup() + } + autocompletes.clear() } private fun setupCommands(backgroundDrawable: Drawable, editText: EditText) { - Autocomplete.on(editText) + autocompletes += Autocomplete.on(editText) .with(commandAutocompletePolicy) .with(autocompleteCommandPresenter) .with(ELEVATION_DP) @@ -133,7 +145,7 @@ class AutoCompleter @AssistedInject constructor( private fun setupMembers(backgroundDrawable: ColorDrawable, editText: EditText) { autocompleteMemberPresenter = autocompleteMemberPresenterFactory.create(roomId) - Autocomplete.on(editText) + autocompletes += Autocomplete.on(editText) .with(CharPolicy(TRIGGER_AUTO_COMPLETE_MEMBERS, true)) .with(autocompleteMemberPresenter) .with(ELEVATION_DP) @@ -158,7 +170,7 @@ class AutoCompleter @AssistedInject constructor( } private fun setupRooms(backgroundDrawable: ColorDrawable, editText: EditText) { - Autocomplete.on(editText) + autocompletes += Autocomplete.on(editText) .with(CharPolicy(TRIGGER_AUTO_COMPLETE_ROOMS, true)) .with(autocompleteRoomPresenter) .with(ELEVATION_DP) @@ -179,7 +191,7 @@ class AutoCompleter @AssistedInject constructor( // Rich text editor is not yet supported if (editText is EditorEditText) return - Autocomplete.on(editText) + autocompletes += Autocomplete.on(editText) .with(CharPolicy(TRIGGER_AUTO_COMPLETE_EMOJIS, false)) .with(autocompleteEmojiPresenter) .with(ELEVATION_DP) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt index 9dda413af7..a7fc72d2d4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt @@ -125,9 +125,7 @@ class MessageComposerFragment : VectorBaseFragment(), A private val roomId: String get() = withState(timelineViewModel) { it.roomId } - private val autoCompleter: AutoCompleter by lazy { - autoCompleterFactory.create(roomId, isThreadTimeLine()) - } + private val autoCompleters: MutableMap = hashMapOf() private val emojiPopup: EmojiPopup by lifecycleAwareLazy { createEmojiPopup() @@ -262,9 +260,8 @@ class MessageComposerFragment : VectorBaseFragment(), A override fun onDestroyView() { super.onDestroyView() - if (!vectorPreferences.isRichTextEditorEnabled()) { - autoCompleter.clear() - } + autoCompleters.values.forEach(AutoCompleter::clear) + autoCompleters.clear() messageComposerViewModel.endAllVoiceActions() } @@ -275,7 +272,12 @@ class MessageComposerFragment : VectorBaseFragment(), A (composer as? View)?.isVisible = messageComposerState.isComposerVisible composer.sendButton.isInvisible = !messageComposerState.isSendButtonVisible - (composer as? RichTextComposerLayout)?.isTextFormattingEnabled = attachmentState.isTextFormattingEnabled + (composer as? RichTextComposerLayout)?.also { + val isTextFormattingEnabled = attachmentState.isTextFormattingEnabled + it.isTextFormattingEnabled = isTextFormattingEnabled + autoCompleters[it.richTextEditText]?.setEnabled(isTextFormattingEnabled) + autoCompleters[it.plainTextEditText]?.setEnabled(!isTextFormattingEnabled) + } } private fun setupBottomSheet() { @@ -316,7 +318,12 @@ class MessageComposerFragment : VectorBaseFragment(), A val composerEditText = composer.editText composerEditText.setHint(R.string.room_message_placeholder) - autoCompleter.setup(composerEditText) + (composer as? RichTextComposerLayout)?.let { + initAutoCompleter(it.richTextEditText) + initAutoCompleter(it.plainTextEditText) + } ?: run { + initAutoCompleter(composer.editText) + } observerUserTyping() @@ -412,6 +419,14 @@ class MessageComposerFragment : VectorBaseFragment(), A } } + private fun initAutoCompleter(editText: EditText) { + if (autoCompleters.containsKey(editText)) return + + autoCompleters[editText] = + autoCompleterFactory.create(roomId, isThreadTimeLine()) + .also { it.setup(editText) } + } + private fun sendTextMessage(text: CharSequence, formattedText: String? = null) { if (lockSendButton) { Timber.w("Send button is locked") @@ -441,12 +456,12 @@ class MessageComposerFragment : VectorBaseFragment(), A } private fun renderRegularMode(content: CharSequence) { - autoCompleter.exitSpecialMode() + autoCompleters.values.forEach(AutoCompleter::exitSpecialMode) composer.renderComposerMode(MessageComposerMode.Normal(content)) } private fun renderSpecialMode(mode: MessageComposerMode.Special) { - autoCompleter.enterSpecialMode() + autoCompleters.values.forEach(AutoCompleter::enterSpecialMode) composer.renderComposerMode(mode) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt index ac64d18737..c028498405 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt @@ -106,6 +106,11 @@ internal class RichTextComposerLayout @JvmOverloads constructor( override val attachmentButton: ImageButton get() = views.attachmentButton + val richTextEditText: EditText get() = + views.richTextComposerEditText + val plainTextEditText: EditText get() = + views.plainTextComposerEditText + var pillDisplayHandler: PillDisplayHandler? = null // Border of the EditText From 6752c69c228053dc752a3c002251ce7e2633b296 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 15 May 2023 05:25:37 +0000 Subject: [PATCH 005/234] Translated using Weblate (Czech) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- library/ui-strings/src/main/res/values-cs/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index 25b877648a..93a43c42c7 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -3009,4 +3009,5 @@ Zásady přijatelného používání Přejít k obnovení Verze šifrování + %1$s změnil(a) své zobrazované jméno na %2$s \ No newline at end of file From 1659675d3b86f705330f13bd99da2375aa1f4b2f Mon Sep 17 00:00:00 2001 From: Vri Date: Sun, 14 May 2023 14:30:59 +0000 Subject: [PATCH 006/234] Translated using Weblate (German) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- library/ui-strings/src/main/res/values-de/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-de/strings.xml b/library/ui-strings/src/main/res/values-de/strings.xml index 65dd4157ea..75b3b4c65c 100644 --- a/library/ui-strings/src/main/res/values-de/strings.xml +++ b/library/ui-strings/src/main/res/values-de/strings.xml @@ -11,7 +11,7 @@ %1$s hat %2$s gebannt %1$s hat die Einladung für %2$s zurückgezogen %1$s hat das Profilbild geändert - %1$s hat den Anzeigenamen geändert in %2$s + %1$s hat den Anzeigenamen zu %2$s geändert %1$s hat den Anzeigenamen von %2$s auf %3$s geändert %1$s hat den Anzeigenamen gelöscht (war %2$s) %1$s hat das Raumthema geändert auf: %2$s @@ -2948,4 +2948,5 @@ Mit Sicherheitsschlüssel oder -phrase verifizieren … Nutzungsbedingungen Verschlüsselungsversion + %1$s hat den Anzeigenamen zu %2$s geändert \ No newline at end of file From a7130f63eade7cbd2a615bd38652716f9dac4f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Mon, 15 May 2023 18:53:11 +0000 Subject: [PATCH 007/234] Translated using Weblate (Estonian) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- library/ui-strings/src/main/res/values-et/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-et/strings.xml b/library/ui-strings/src/main/res/values-et/strings.xml index ff6fe32a25..1628f801dc 100644 --- a/library/ui-strings/src/main/res/values-et/strings.xml +++ b/library/ui-strings/src/main/res/values-et/strings.xml @@ -2949,4 +2949,5 @@ Sõnum Sõnum kasutajalt %s Krüptoteekide versioon + %1$s muutis oma uueks kuvatavaks nimeks %2$s \ No newline at end of file From a3bbe0bd8ce766e8e66958f5c73d79f23e3af1a1 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Sun, 14 May 2023 19:01:58 +0000 Subject: [PATCH 008/234] Translated using Weblate (Persian) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/ --- library/ui-strings/src/main/res/values-fa/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-fa/strings.xml b/library/ui-strings/src/main/res/values-fa/strings.xml index 9e971ce69b..636628c811 100644 --- a/library/ui-strings/src/main/res/values-fa/strings.xml +++ b/library/ui-strings/src/main/res/values-fa/strings.xml @@ -2949,4 +2949,5 @@ سیاست استفادهٔ پذیرفتنی ادامه برای بازنشانی نگارش Crypto + %1$s نام نمایشیش را به %2$s تغییر داد \ No newline at end of file From c98598eed1a4fd0b3bc3b97b9a25252f317b9d76 Mon Sep 17 00:00:00 2001 From: Glandos Date: Mon, 15 May 2023 08:07:22 +0000 Subject: [PATCH 009/234] Translated using Weblate (French) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- library/ui-strings/src/main/res/values-fr/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-fr/strings.xml b/library/ui-strings/src/main/res/values-fr/strings.xml index e48d308ce7..e26be0b036 100644 --- a/library/ui-strings/src/main/res/values-fr/strings.xml +++ b/library/ui-strings/src/main/res/values-fr/strings.xml @@ -2949,4 +2949,5 @@ Politique d’utilisation acceptable Version de cryptographie Faire la réinitialisation + %1$s a modifié son nom d’affichage en %2$s \ No newline at end of file From fe37d63149f50c91352cb2d05b9ca0d8bd4612fc Mon Sep 17 00:00:00 2001 From: Linerly Date: Sun, 14 May 2023 13:17:12 +0000 Subject: [PATCH 010/234] Translated using Weblate (Indonesian) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- library/ui-strings/src/main/res/values-in/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-in/strings.xml b/library/ui-strings/src/main/res/values-in/strings.xml index c32cf40e85..2ed4293850 100644 --- a/library/ui-strings/src/main/res/values-in/strings.xml +++ b/library/ui-strings/src/main/res/values-in/strings.xml @@ -2891,4 +2891,5 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Kebijakan Penggunaan Wajar Versi kripto Lanjutkan mengatur ulang + %1$s mengubah nama tampilannya ke %2$s \ No newline at end of file From 872fef6d22f402cc644d4541a043d35e2deef159 Mon Sep 17 00:00:00 2001 From: random Date: Mon, 15 May 2023 08:06:21 +0000 Subject: [PATCH 011/234] Translated using Weblate (Italian) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- library/ui-strings/src/main/res/values-it/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-it/strings.xml b/library/ui-strings/src/main/res/values-it/strings.xml index 54ad5f5dd9..8c13bdc3a2 100644 --- a/library/ui-strings/src/main/res/values-it/strings.xml +++ b/library/ui-strings/src/main/res/values-it/strings.xml @@ -2940,4 +2940,5 @@ Politica di utilizzo accettabile Procedi con la reimpostazione Versione crittografia + %1$s ha cambiato il nome visualizzato in %2$s \ No newline at end of file From d79df5a0cb90640eb1f05fcd34e4307ddaf74473 Mon Sep 17 00:00:00 2001 From: raspin0 Date: Tue, 16 May 2023 20:45:31 +0000 Subject: [PATCH 012/234] Translated using Weblate (Polish) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- .../src/main/res/values-pl/strings.xml | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/library/ui-strings/src/main/res/values-pl/strings.xml b/library/ui-strings/src/main/res/values-pl/strings.xml index 603265bd26..b96f2345db 100644 --- a/library/ui-strings/src/main/res/values-pl/strings.xml +++ b/library/ui-strings/src/main/res/values-pl/strings.xml @@ -377,7 +377,7 @@ %1$s w %2$s Czy na pewno chcesz usunąć widżet z tego pokoju? Nie można utworzyć widżetu. - Nie udało się wysłać prośby. + Nie udało się wysłać żądania. Poziom uprawnień musi być liczbą dodatnią. Nie jesteś w tym pokoju. Nie masz uprawnień, aby zrobić to w tym pokoju. @@ -391,7 +391,7 @@ Błąd polecenia Nierozpoznane polecenie: %s Głośne - Strona startowa + Strona główna Pokoje Zaproszeni Dezaktywuj konto @@ -609,7 +609,7 @@ Importowanie kluczy… Odblokuj Historię Wprowadź klucz odzyskiwania - Kopia Przywrócona %s ! + Kopia przywrócona %s! dodano jeden nowy klucz do tej sesji. dodano %d nowe klucze do tej sesji. @@ -661,7 +661,7 @@ Pomoc i o aplikacji Wszystkie wiadomości (hałaśliwy) Wszystkie wiadomości - Tylko wspomnienia + Tylko wzmianki Wycisz Ustawienia Nie ignorujesz żadnych użytkowników @@ -801,9 +801,9 @@ Użyj kopii zapasowej klucza aby odblokować historię zaszyfrowanych wiadomości użyj klucza odzyskiwania Użyj Klucza Odzyskiwania aby odblokować historię zaszyfrowanych wiadomości - Kopia zapasowa nie może zostać zdeszyfrowana za pomocą tego hasła: proszę upewnij się, czy wprowadzone hasło jest poprawne. + Kopia zapasowa nie mogła zostać rozszyfrowana za pomocą tego Hasła: upewnij się, że wprowadzono prawidłowe Hasło bezpieczeństwa. Przywracanie kopii zapasowej: - Kopia zapasowa nie może zostać zdeszyfrowana za pomocą tego klucza odzyskiwania: proszę upewnij się, czy wprowadzony klucz odzyskiwania jest poprawny. + Kopia zapasowa nie mogła zostać rozszyfrowana za pomocą tego Klucza: upewnij się, że wprowadzono prawidłowy Klucz bezpieczeństwa. Kopia zapasowa klucza nie jest aktywna dla tej sesji. Twoje klucze nie są będą zapisywane w kopii zapasowej od tej sesji. Kopia zapasowa posiada sygnaturę od nieznanej sesji z ID %s. @@ -1127,7 +1127,7 @@ %d aktywnych sesji %d aktywnych sesji - Zweryfikuj te urządzenie + Weryfikuj inne urządzenie Otwórz obecną sesję i użyj jej do zweryfikowania obecnej, przyznając jej dostęp do zaszyfrowanych wiadomości. Zweryfkuj Zweryfikowano @@ -1240,7 +1240,7 @@ Wpisz frazę bezpieczeństwa którą znasz tylko ty, będzie wykorzystywana do zabezpieczania sekretów na twoim serwerze. Przechowuj swój Klucz Bezpieczeństwa w chronionym miejscu takim jak menadżer haseł lub sejf. Zapisz Klucz Bezpieczeństwa - Użyj Frazy Bezpieczeństwa + Użyj hasła bezpieczeństwa Użyj klucza bezpieczeństwa Zabezpiecza przed utratą dostępu do zaszyfrowanych wiadomości poprzez zapisanie kluczy szyfrujących na twoim serwerze. Włącz aparat @@ -1384,7 +1384,7 @@ Niektóre znaki nie są dozwolone Podaj adres pokoju Ten adres jest już w użyciu - Możesz aktywować tę opcję jeżeli pokój będzie wykorzystywany jedynie do współpracy z wewnętrznymi zespołami na Twoim serwerze domowym. Ta opcja nie może być zmieniona później. + Możesz aktywować tę opcję, jeżeli pokój będzie wykorzystywany jedynie do współpracy z wewnętrznymi zespołami na Twoim serwerze domowym. Nie będzie można zmienić tej opcji. Zablokuj wszystkich nie będących członkami %s przed dołączeniem do tego pokoju Ukryj zaawansowane Pokaż zaawansowane @@ -1545,13 +1545,13 @@ Konfigurowanie odzyskiwania. Nie zweryfikujesz %1$s (%2$s) jeżeli przerwiesz w tym momencie. Zacznij ponownie w ich profilu użytkownika. ROZUMIEM - Fraza Bezpieczeństwa - Ustaw Frazę Bezpieczeństwa + Hasło bezpieczeństwa + Ustaw hasło bezpieczeństwa Wybierz nazwę użytkownika. Potwierdź swoją tożsamość poprzez zweryfikowanie tego logowania aby uzyskać dostęp do zaszyfrowanych wiadomości. Potwierdź swoją tożsamość poprzez zweryfikowanie tego logowania przy pomocy którejś z pozostałych sesji w celu przyznania dostępu do zaszyfrowanych wiadomości. - Interaktywna weryfikacja z wykorzystaniem emotikon - Zweryfikuj logowanie + Zweryfikuj interaktywnie za pomocą emoji + Weryfikuj logowanie Zweryfikuj nowe logowanie do swojego konta: %1$s Zaszyfrowano przez urządzenie niezweryfikowane Niezaszyfrowane @@ -1564,7 +1564,7 @@ Zaczniesz ponownie od zera, bez historii, bez wiadomości, bez zaufanych urządzeń bądź użytkowników Jeżeli zresetujesz wszystko Wykonaj tę akcję wyłącznie wówczas gdy nie masz żadnego innego urządzenia na którym możesz zweryfikować bieżące urządzenie. - Zresetuj wszystko + Resetuj wszystko Zapomniałeś(-łaś) albo straciłeś wszystkie opcje odzyskiwania\? Zresetuj wszystko Nie udało się uzyskać dostępu do bezpiecznego magazynu Sprawdzanie klucza kopii zapasowej @@ -1818,7 +1818,7 @@ Uprawnienia pokoju Odblokowanie użytkownika pozwoli mu na ponowne dołączenie do tej przestrzeni. Zablokowanie użytkownika usunie go z tego miejsca i uniemożliwi ponowne dołączenie. - Ten pokój jest prywatny. Nie będziesz w stanie dołączyć bez zaproszenia. + Ten pokój nie jest publiczny. Nie będziesz w stanie dołączyć bez zaproszenia. Zakańczanie połączenia… Brak odpowiedzi Użytkownik, do którego zadzwoniłeś jest zajęty. @@ -1947,15 +1947,15 @@ Wszystkie pokoje, w których jesteś będą pokazywane na ekranie domowym. Pokaż wszystkie pokoje w ekranie domowym Zarządzaj pokojami oraz przestrzeniami - Oznacz jako nie sugerowana - Oznacz jako sugerowana + Oznacz jako nie sugerowane + Oznacz jako sugerowane Sugerowane Zarządzaj pokojami Szukasz kogoś , kto nie jest w %s\? %s Cię zaprasza Zostałeś zaproszony Przestrzenie są nową metodą na grupowanie razem wielu pokoi i osób. - Dodaj przestrzeń do jakiejkolwiek przestrzeni którą zarządzasz. + Dodaj przestrzeń do jakiejkolwiek przestrzeni, którą zarządzasz. Dodaj istniejące przestrzenie Dodaj istniejące pokoje Dodaj istniejące pokoje i przestrzenie @@ -1974,7 +1974,7 @@ Dołącz pomimo to Dołącz do przestrzeni Utwórz przestrzeń - Na razie pomiń + Pomiń na razie Dołącz do mojej przestrzeni %1$s %2$s Nie będą częścią %s Tylko do tego pokoju @@ -1983,13 +1983,13 @@ Udostępnij link Zaproś przez nazwę użytkownika lub email Zaproś przez email - Aktualnie jesteś tu tylko ty. %s będzie jeszcze lepszą przestrzenią, gdy dołączą do niej inni. + Aktualnie jesteś tu tylko Ty. %s będzie jeszcze lepsze, gdy dołączą inni. Zaproś do %s Zaproś osoby Zaproś osoby do Twojej przestrzeni Opis Tworzenie przestrzeni… - Losowy + Losowe Ogólny Kim są Twoi znajomi \? Stworzymy dla nich pokoje. Możesz też dodać następne w późniejszym etapie. @@ -2000,9 +2000,9 @@ Prywatna Otwarta dla każdego, najlepsza dla społeczności Publiczna - Prywatna przestrzeń dla Ciebie i Twoich znajomych - Ja i moi znajomi - Prywatna przestrzeń do organizacji Twoich pokojów + Prywatna przestrzeń dla Ciebie i Twoich kolegów z drużyny + Ja i moi koledzy z drużyny + Prywatna przestrzeń do organizacji Twoich pokoi Tylko ja Upewnij się, że odpowiednie osoby mają dostęp do %s. Z kim pracujesz\? @@ -2069,7 +2069,7 @@ Przekaż opinię Nie udało się przesłać opinii (%s) Dziękujemy, Twoja opinia została wysłana - Pozwalam na kontakt ze mną w razie dodatkowych pytań + Możesz się ze mną skontaktować, jeśli masz jakiekolwiek pytania Używasz przestrzeni w wersji beta. Ta opinia pomoże nam w tworzeniu kolejnych wersji. Twoja platforma i nazwa użytkownika zostaną odnotowane, abyśmy mogli w pełni wykorzystać Twoje sugestie. Prześlij opinię o przestrzeniach Stwórz nową przestrzeń @@ -2089,7 +2089,7 @@ Twój serwer Wersja pokoju Inne przestrzenie lub pokoje, których możesz nie znać - Przestrzeń, o której wiesz, że zawiera ten pokój + Przestrzeń, którą znasz, że zawiera ten pokój Zdecyduj kto może odnaleźć i dołączyć do tego pokoju. Dotknij, aby edytować przestrzenie Wybierz przestrzenie @@ -2110,7 +2110,7 @@ Usuń nagranie Opinia użytkownika Synchronizacja klucza samopodpisującego (Self Signing key) - Weryfikacja ręczna poprzez tekst + Zweryfikuj ręcznie za pomocą tekstu lub innego klienta Matrix z krzyżową weryfikacją nowych sesji logowania Nie masz uprawnień do zmiany poziomu pokoju Oczekiwanie na historię szyfrowania @@ -2210,7 +2210,7 @@ Rozmowa głosowa zakończona • %1$s Oddzwoń Nie udało się skonfigurować logowania krzyżowego - Aktualizacja spowoduje utworzenie pokoju w nowej wersji. Wszystkie obecne wiadomości zostaną w zarchiwizowanym pokoju. + Aktualizacja spowoduje utworzenie pokoju w nowej wersji. Wszystkie bieżące wiadomości zostaną zarchiwizowane w tym pokoju. Nagrywanie wiadomości głosowej Zatrzymaj nagrywanie Wstrzymaj wiadomość głosową @@ -2242,7 +2242,7 @@ Dodaj do danej przestrzeni Stwórz przestrzeń Edytuj treść - Poznaj stan pokoju + Przeglądaj stan pokoju Narzędzia deweloperskie Nieobecny Pokój publiczny @@ -2295,7 +2295,7 @@ Nie udostępniamy informacji podmiotom trzecim Nie zbieramy i nie profilujemy danych użytkownika tutaj - Pomóż nam znaleźć błędy i ulepszyć ${app_name} poprzez udostępnianie anonimowych danych użytkowania. Aby lepiej zrozumieć jak użytkownicy wykorzystują wiele urządzeń wygenerujemy losowy identyfikator dzielony pomiędzy Twoimi urządzeniami. + Pomóż nam zidentyfikować problemy i ulepszyć ${app_name}, udostępniając anonimowe dane o użytkowaniu. Aby zrozumieć, w jaki sposób użytkownicy korzystają z wielu urządzeń, wygenerujemy losowy identyfikator dzielony pomiędzy Twoimi urządzeniami. \n \nWięcej informacji %s. Pomóż usprawnić ${app_name} @@ -2311,7 +2311,7 @@ Posiadam już konto Bezpieczna komunikacja. Masz wszystko pod kontrolą. - Przejmij swoje konwersacje. + Bądź właścicielem swoich konwersacji. By odkryć istniejące kontakty, musisz najpierw przesłać swoje dane kontaktowe (adresy e-mail i numer telefonu) do serwera tożsamości. Przed wysłaniem Twoje dane zostaną zaszyfrowane w celu zachowania prywatności. Uzyskaj pomoc w korzystaniu z ${app_name} Nie masz uprawnień by dołączyć do tego pokoju @@ -2350,7 +2350,7 @@ Uwaga: aplikacja zostanie uruchomiona ponownie Włącz wiadomości w wątkach Upewnij się, że odpowiednie osoby mają dostęp do firmy %s. Więcej osób możesz zaprosić później. - Wyślij niestandardowe zdarzenie stanowe + Wyślij własne wydarzenie stanu Wyślij zdarzenie stanowe Zdarzenia stanowe Zawartość zdarzenia @@ -2583,7 +2583,7 @@ min Pokoje w przestrzeni Dalej - Dostawca + Metoda Znaleziono %d dostawcę. Znaleziono %d dostawców. @@ -2632,7 +2632,7 @@ Kod został wysłany do %s Potwierdź swój numer telefonu Wyloguj wszystkie urządzenia - Zresetuj hasło + Resetuj hasło Upewnij się, że ma 8 lub więcej znaków. Wybierz nowe hasło Nowe hasło @@ -2670,7 +2670,7 @@ MSC3061: Współdzielenie kluczy pokoju dla wcześniejszych wiadomości Ten kod QR wygląda na niepoprawny. Spróbuj zweryfikować przy użyciu innej metody. Dostęp do wcześniejszych zaszyfrowanych wiadomości nie będzie możliwy. Zresetuj bezpieczną kopię zapasową wiadomości oraz klucze weryfikacyjne by zacząć od nowa. - Nie udało się zweryfikować tego urządzenia + Nie można zweryfikować tego urządzenia Zapoznaj się z warunkami i zasadami serwera %s Jaki jest adres twojego serwera\? Miejsce na twoje konwersacje @@ -3040,7 +3040,7 @@ Sprawdź, by upewnić się że Twoje konto jest bezpieczne Zaszyfrowano za pomocą usuniętego urządzenia Akceptowalna polityka użytkowania - Jak tylko zaproszeni użytkownicy dołączą do ${app_name}, będziesz mógł czatować w pokoju zaszyfrowanym end-to-end + Jak tylko zaproszeni użytkownicy dołączą do ${app_name}, będziesz mógł czatować w pokoju szyfrowanym end-to-end Czekanie aż użytkownicy dołączą do ${app_name} Żądanie weryfikacji nie zostało znalezione. Mogło zostać anulowane lub obsłużone przez inną sesję. Wznów @@ -3048,7 +3048,7 @@ Zdobądź najnowszą wersję (uwaga: mogą wystąpić problemy z logowaniem) Nightly build Zweryfikuj swoją tożsamość, aby uzyskać dostęp do wiadomości zaszyfrowanych i udowodnić swoją tożsamość innym. - Zweryfikuj za pomocą innego urządzenia + Weryfikuj innym urządzeniem Weryfikuję z Klucza bezpieczeństwa lub Frazy… Rozpoczął transmisje głosową Możesz zaprosić tylko jeden e-mail jednocześnie @@ -3068,4 +3068,5 @@ %1$d zaznaczono %1$d zaznaczono + %1$s zmienił swoją wyświetlaną nazwę na %2$s \ No newline at end of file From 6412c2a7cea1b9d811c717f19e83273fe8bbd918 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Sun, 14 May 2023 16:59:49 +0000 Subject: [PATCH 013/234] Translated using Weblate (Slovak) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sk/ --- library/ui-strings/src/main/res/values-sk/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-sk/strings.xml b/library/ui-strings/src/main/res/values-sk/strings.xml index 6f95e6428b..ee058b56fd 100644 --- a/library/ui-strings/src/main/res/values-sk/strings.xml +++ b/library/ui-strings/src/main/res/values-sk/strings.xml @@ -3009,4 +3009,5 @@ Zásady prijateľného používania Pokračovať v obnovení Krypto verzia + %1$s zmenil/a svoje zobrazované meno na %2$s \ No newline at end of file From 16f8f01cdbffa540102e3e6077c59741ff731bb4 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Mon, 15 May 2023 08:55:54 +0000 Subject: [PATCH 014/234] Translated using Weblate (Albanian) Currently translated at 99.3% (2612 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sq/ --- library/ui-strings/src/main/res/values-sq/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-sq/strings.xml b/library/ui-strings/src/main/res/values-sq/strings.xml index 39a67b3b72..02cacc124c 100644 --- a/library/ui-strings/src/main/res/values-sq/strings.xml +++ b/library/ui-strings/src/main/res/values-sq/strings.xml @@ -2935,4 +2935,5 @@ Rregulla të Pranueshme Përdorimi Vazhdo me rikthimin te parazgjedhjet Version kriptografie + %1$s ndërroi emrin e vet në ekran në %2$s \ No newline at end of file From d5c98414a45c1e5a6c3842dd2284d2127cd5363f Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Sun, 14 May 2023 16:57:15 +0000 Subject: [PATCH 015/234] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- library/ui-strings/src/main/res/values-uk/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-uk/strings.xml b/library/ui-strings/src/main/res/values-uk/strings.xml index 0ba658abd7..54943c001f 100644 --- a/library/ui-strings/src/main/res/values-uk/strings.xml +++ b/library/ui-strings/src/main/res/values-uk/strings.xml @@ -3069,4 +3069,5 @@ Політика прийнятного користування Перейти до скидання Криптоверсія + %1$s змінює своє ім\'я на %2$s \ No newline at end of file From 3e8eeac533fe6a92e8d8b5f3a89d33ae357bb07b Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Mon, 15 May 2023 02:38:52 +0000 Subject: [PATCH 016/234] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2628 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- library/ui-strings/src/main/res/values-zh-rTW/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml index 2b0a6c2d5b..a1bfa92235 100644 --- a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml @@ -2889,4 +2889,5 @@ 可接受的使用政策 繼續重設 加密版本 + %1$s 變更了他們的顯示名稱為 %2$s \ No newline at end of file From 0e9b62a43a4d3ca8cde7a55b85f4ee563d99ad89 Mon Sep 17 00:00:00 2001 From: someone1611 Date: Wed, 17 May 2023 10:13:08 +0000 Subject: [PATCH 017/234] Translated using Weblate (Vietnamese) Currently translated at 83.0% (2182 of 2628 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- .../src/main/res/values-vi/strings.xml | 126 +++++++++++++++--- 1 file changed, 108 insertions(+), 18 deletions(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 34cbdd6afc..062889596b 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -669,7 +669,7 @@ Phòng chat của bạn được hiển thị ở đây. Bạn có thể tạo mới phòng chat hoặc tham gia các phòng cộng đồng hiện có. Chọn một máy chủ Hãy bắt đầu - Mở rộng và hiệu chỉnh trải nghiệm của bạn + Mở rộng và tùy chỉnh trải nghiệm của bạn Giữ cho hội thoải riêng tư với bảo mật đầu cuối Chat với một người hoặc chat nhóm Đây là hội thoại của bạn. Bạn sở hữu nó. @@ -754,7 +754,7 @@ Cấu hình máy chủ định danh Ngắt kết nối máy chủ định danh Máy chủ định danh - Sử dụng Bot, cầu nối, widget hoặc sticker + Sử dụng Bot, cầu nối, widget hoặc gói sticker Được khám phá bởi người khác Điều khoản Dịch vụ Xem lịch sử chỉnh sửa @@ -789,7 +789,7 @@ Nén dữ liệu mặc định Media Chọn quốc gia - Quản lý email và số điện thoại liên kết với tài khoản Matrix + Quản lý địa chỉ thư điện tử và số điện thoại liên kết với tài khoản Matrix Email và số điện thoại Hiện tất cả tin nhắn từ %s\? Mật khẩu của bạn vừa được cập nhật @@ -911,7 +911,7 @@ Tiếp Email (tùy chọn) Email - Thêm địa chỉ email để phục hồi tài khoản. Sau này bạn có thể tùy chọn cho phép người khác tìm mình qua email. + Thêm địa chỉ thư điện tử để có thể phục hồi tài khoản. Sau này bạn có thể tùy chọn cho phép người khác tìm mình qua thông tin này. Thêm địa chỉ email Mật khẩu chưa được thay đổi. \n @@ -925,7 +925,7 @@ Nhấp vào đường dẫn để xác nhận mật khẩu mới. Sau khi bạn nhâp vào đường dẫn, hãy nhấp vào bên dưới. Email xác thực đã được gửi tới %1$s. Kiểm tra mailbox - Email này không gắn với tài khoản nào + Địa chỉ thư điện tử này không được liên kết với tài khoản nào Tiếp tục Đổi mật khẩu sẽ đặt lại tất cả khóa bảo mật trên tất cả phiên của bạn, làm cho lịch sử chat mã hóa không đọc được. Vui lòng Sao lưu Khóa hoặc xuất khẩu tất cả khóa bảo mật các phòng từ một phiên đăng nhập khác trước khi đặt lại mật khẩu. Cảnh báo! @@ -934,7 +934,7 @@ Tiếp Email xác thực thông tin đã được gửi tới bạn để xác nhận đặt lại mật khẩu mới. Đặt lại mật khẩu ở %1$s - Địa chỉ email này không có trong hệ thống. + Địa chỉ thư điện tử này không được liên kết với tài khoản nào. Địa chỉ Địa chỉ Dịch vụ Element Matrix Xóa lịch sử @@ -985,7 +985,7 @@ Đảm bảo rằng bạn nhấp vào đường link trong email được gửi tới bạn. Loại bỏ %s\? Số điện thoại - Không có địa chỉ email nào trong tài khoản của bạn + Không có địa chỉ thư điện tử nào trong tài khoản của bạn Địa chỉ email Hiển thị thông tin ứng dụng trong thiết lập hệ thống. Thông tin ứng dụng @@ -1116,7 +1116,7 @@ Chạy thử Chuẩn đoán khắc phục sự cố Bật thông báo qua email cho %s - Để được nhận thông báo qua email, hãy liên kết một địa chỉ mail với tài khoản Matrix của bạn + Để được nhận thông báo qua thư điện tử, hãy liên kết một địa chỉ thư điện tử với tài khoản Matrix của bạn Thông báo qua email Nâng cấp không gian Thay đổi tên không gian @@ -1797,19 +1797,19 @@ Không thể kết nối với máy chủ xác thực Nhập URL máy chủ xác thực Bạn có đồng ý gửi thông tin này không\? - Để khám phá các liên hệ hiện có, bạn cần gửi thông tin liên hệ (email và số điện thoại) đến máy chủ nhận dạng của mình. Chúng tôi băm dữ liệu của bạn trước khi gửi cho quyền riêng tư. - Gửi email và số điện thoại đến %s + Để khám phá các liên hệ hiện có, bạn cần gửi thông tin liên hệ (địa chỉ thư điện tử và số điện thoại) đến máy chủ định danh của mình. Chúng tôi băm dữ liệu của bạn trước khi gửi để đảm bảo quyền riêng tư. + Gửi địa chỉ thư điện tử và số điện thoại đến %s Đồng ý Thu hồi sự đồng ý của tôi Các liên hệ của bạn là riêng tư. Để khám phá người dùng từ danh bạ của bạn, chúng tôi cần sự cho phép của bạn để gửi thông tin liên hệ đến máy chủ xác thực của bạn. - Bạn đã đồng ý gửi email và số điện thoại đến máy chủ xác thực này để khám phá những người dùng khác từ danh bạ của bạn. + Bạn đã đồng ý gửi địa chỉ thư điện tử và số điện thoại đến máy chủ định danh này để khám phá những người dùng khác từ danh bạ của bạn. Gửi email và số điện thoại - Chúng tôi đã gửi cho bạn một email xác nhận đến %s, trước tiên vui lòng kiểm tra email của bạn và nhấp vào liên kết xác nhận - Chúng tôi đã gửi cho bạn một email xác nhận đến %s, kiểm tra email của bạn và nhấp vào liên kết xác nhận + Chúng tôi đã gửi một thư đến %s, trước tiên vui lòng kiểm tra hòm thư của bạn và nhấp vào liên kết xác nhận + Chúng tôi đã gửi một thư đến %s, kiểm tra hòm thư của bạn và nhấp vào liên kết xác nhận Số điện thoại có thể khám phá Ngắt kết nối khỏi máy chủ xác thực của bạn sẽ có nghĩa là bạn sẽ không thể khám phá bởi những người dùng khác và bạn sẽ không thể mời người khác qua email hoặc điện thoại. Tùy chọn Khám phá sẽ xuất hiện khi bạn đã thêm số điện thoại. - app_id: + Định danh ứng dụng (ID): Không có cổng Push đã đăng ký Không có quy tắc Push nào được xác định Quy tắc Push @@ -1842,7 +1842,7 @@ Vui lòng chờ… Thay đổi mạng Thay đổi - Không có mạng. Vui lòng kiểm tra kết nối Internet. + Không có mạng. Kiểm tra kết nối Internet. Tạo Space mới Tạo phòng mới Sự kiện bị hỏng, không thể hiển thị @@ -2206,7 +2206,7 @@ Không phải bây giờ Kích hoạt Nghe thông báo - Tùy chọn Khám phá sẽ xuất hiện sau khi bạn đã thêm email. + Tùy chọn Khám phá sẽ xuất hiện sau khi bạn đã thêm địa chỉ thư điện tử. Địa chỉ email có thể khám phá Hiện tại bạn không sử dụng máy chủ xác thực. Để khám phá và có thể khám phá bởi các liên hệ hiện có mà bạn biết, hãy cấu hình một danh bạ dưới đây. Không có chính sách được cung cấp bởi máy chủ xác thực @@ -2253,8 +2253,8 @@ Âm thanh & Hình ảnh Format: Url: - session_name: - app_display_name: + Tên hiển thị của phiên: + Tên hiển thị của ứng dụng: push_key: Gửi video với kích thước gốc @@ -2320,4 +2320,94 @@ %d thay đổi về danh sách truy cập + Mã hóa bị thiết đặt sai. + Đã chia sẻ vị trí + Không mở được liên kết: cộng đồng đã được thay bằng spaces + Quét mã QR + Tôi đã có tài khoản + Tạo tài khoản + Bỏ qua bước này + Lưu và tiếp tục + Vào cài đặt mỗi khi cần cập nhật hồ sơ + Trông rất tuyệt! + Thêm ảnh hồ sơ + Bạn có thể đổi lại sau + Tên hiển thị + Chọn tên hiển thị + Tên người dùng / Thư điện tử / Số điện thoại + Bạn có phải con người\? + Làm theo chỉ dẫn gửi tới %s + Đặt lại mật khẩu + Quên mật khẩu + Gửi lại thư + Không nhận được thư\? + Làm theo chỉ dẫn gửi tới %s + Xác nhận địa chỉ thư điện tử + Gửi lại mã + Một mã đã được gửi tới %s + Xác nhận số điện thoại + Đăng xuất mọi thiết bị + Đặt lại mật khẩu + Đặt mật khẩu chữa ít nhất 8 ký tự. + Chọn mật khẩu mới + Mật khẩu mới + Kiểm tra hòm thư. + Mã xác nhận + Số điện thoại + Nhập số điện thoại + Địa chỉ thư điện tử + Nhập địa chỉ thư điện tử + Sửa + Hay + Nơi các cuộc trò chuyện được đặt + Nơi các cuộc trò chuyện được đặt + Phải chứa ít nhất 8 ký tự + Tạo tài khoản + Tài khoản %s đã được tạo + Chúc mừng! + Về trang chủ + Cá nhân hóa hồ sơ + Kết nối tới máy chủ + Bỏ qua câu hỏi + Cộng đồng + Nhóm + Bạn bè và gia đình + Nhắn tin bảo mật. + Gửi phản hồi + Đã bật: + Thẻ hồ sơ: + Định danh của phiên: + Đi + Đang cập nhật dữ liệu của bạn… + Mọi người + Yêu thích + Chưa đọc + Tất cả + Xem trong phòng + Đang trả lời %s + Sửa + Sao lưu có con dấu hợp lệ từ người dùng này. + Lệnh \"%s\" không được hỗ trợ ở chủ đề. + Xin lỗi, phòng này không được tìm thấy +\nHãy thử lại.%s + Dùng của hệ thống + Chọn thủ công + Thiết đặt tự động + Chọn cỡ chữ + Bạn đã bật chỉ mã hóa với các phiên đã xác thực trong tất cả các phòng ở Cài đặt bảo mật. + Trong phòng có các thiết bị chưa được xác thực, chúng sẽ không thể giải mã tin nhắn mà bạn gửi. + Không gửi tin nhắn được mã hóa cho các phiên chưa xác thực trong phòng này. + Thông tin tài khoản của bạn được quản lý riêng rẽ tại %1$s. + Tài khoản + Tự động phát các ảnh động + Phiên bản thuật toán + Cấp quyền + + %1$s và %2$d người khác + + %1$s và %2$s + Mẹo: Nhấn giữ một tin nhắn và dùng “%s”. + Space là một cách mới để nhóm các phòng và mọi người. Tạo một space để bắt đầu. + Chưa có space nào. + %1$s đã đổi tên hiển thị thành %2$s \ No newline at end of file From bf244f68056b9d0d9b151bedc317e718216cfc6d Mon Sep 17 00:00:00 2001 From: Zet Date: Sat, 20 May 2023 13:55:55 +0000 Subject: [PATCH 018/234] Translated using Weblate (Arabic) Currently translated at 39.3% (1034 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ar/ --- .../src/main/res/values-ar/strings.xml | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/library/ui-strings/src/main/res/values-ar/strings.xml b/library/ui-strings/src/main/res/values-ar/strings.xml index 1df5a29451..3e1869b0c8 100644 --- a/library/ui-strings/src/main/res/values-ar/strings.xml +++ b/library/ui-strings/src/main/res/values-ar/strings.xml @@ -1162,12 +1162,12 @@ كلمة السر الجديدة التالي - صفر - واحد - اثنان - قليلة - كثيرة - اخرى + لم تحدد + واحد محدد + اثنان محددان + %1$d محددة + %1$d محددة + %1$d محددة صفر @@ -1210,4 +1210,12 @@ د سا أنهى %1$s البث الصوتي. + أظهر كل الغرف في دليل الغرف. حتى الغرف ذات المحتوى الحساس. + هنا ستجد الطلبات والدعوات. + لا جديد. + الدعوات + الفضاءات هي طريقة جديدة لتنظيم الغرف والأفراد.أنشئ فضاءً للبدأ. + بدون فضاءات. + تفضيلات التخطيط + غير %1$s اسمه العلني إلى %2$s \ No newline at end of file From 0edea016b1db48c55c309bea79b3235a682b467d Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 22 May 2023 19:32:07 +0000 Subject: [PATCH 019/234] Translated using Weblate (Czech) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- library/ui-strings/src/main/res/values-cs/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index 93a43c42c7..38c78a712a 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -3010,4 +3010,7 @@ Přejít k obnovení Verze šifrování %1$s změnil(a) své zobrazované jméno na %2$s + Profilový obrázek uživatele %1$s + Avatar místnosti %1$s + Avatar prostoru %1$s \ No newline at end of file From 72b2b591e338aebc4eae529bfa027dd0a2999fe5 Mon Sep 17 00:00:00 2001 From: Vri Date: Sat, 20 May 2023 10:47:45 +0000 Subject: [PATCH 020/234] Translated using Weblate (German) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- library/ui-strings/src/main/res/values-de/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-de/strings.xml b/library/ui-strings/src/main/res/values-de/strings.xml index 75b3b4c65c..faf5a0d896 100644 --- a/library/ui-strings/src/main/res/values-de/strings.xml +++ b/library/ui-strings/src/main/res/values-de/strings.xml @@ -2949,4 +2949,7 @@ Nutzungsbedingungen Verschlüsselungsversion %1$s hat den Anzeigenamen zu %2$s geändert + Benutzer-Profilbild von %1$s + Raum-Avatar von %1$s + Space-Avatar von %1$s \ No newline at end of file From 19ba773df90dc04625626ce276122902871acf44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sun, 21 May 2023 20:07:07 +0000 Subject: [PATCH 021/234] Translated using Weblate (Estonian) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- library/ui-strings/src/main/res/values-et/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-et/strings.xml b/library/ui-strings/src/main/res/values-et/strings.xml index 1628f801dc..66a799c5f9 100644 --- a/library/ui-strings/src/main/res/values-et/strings.xml +++ b/library/ui-strings/src/main/res/values-et/strings.xml @@ -2950,4 +2950,7 @@ Sõnum kasutajalt %s Krüptoteekide versioon %1$s muutis oma uueks kuvatavaks nimeks %2$s + Kasutaja %1$s tunnuspilt + %1$s jututoa tunnuspilt + %1$s kogukonna tunnuspilt \ No newline at end of file From 541690605fd9d1d3d474384b5ef0358217448231 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Sat, 20 May 2023 12:28:47 +0000 Subject: [PATCH 022/234] Translated using Weblate (Persian) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/ --- .../src/main/res/values-fa/strings.xml | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/library/ui-strings/src/main/res/values-fa/strings.xml b/library/ui-strings/src/main/res/values-fa/strings.xml index 636628c811..90f049e18f 100644 --- a/library/ui-strings/src/main/res/values-fa/strings.xml +++ b/library/ui-strings/src/main/res/values-fa/strings.xml @@ -10,7 +10,7 @@ %1$s، انسداد %2$s را رفع کرد %1$s، %2$s را مسدود کرد %1$s دعوت %2$s را نپذیرفت - %1$s تصویرش را عوض کرد + %1$s چهرکش را عوض کرد %1$s نام نمایشی خود را به %2$s تنظیم کرد %1$s نام نمایشیش را از %2$s به %3$s تغییر داد %1$s نام نمایشیش (%2$s) را پاک کرد @@ -26,7 +26,7 @@ همهٔ اعضای اتاق. هرکسی. %s این اتاق را ارتقا داد. - (تصویر هم عوض شد) + (چهرک نیز تغییر کرد) %1$s نام اتاق را پاک کرد %1$s موضوع اتاق را پاک کرد %1$s دعوتی برای پیوستن %2$s به اتاق فرستاد @@ -94,13 +94,13 @@ تحریم %1$s را برداشتید %1$s را تحریم کردید دعوت %1$s را پس‌گرفتید - آواتارتان را عوض کردید + چهرکتان را عوض کردید نام نمایشیتان را به %1$s تغییر دادید نام نمایشیتان را از %1$s به %2$s تغییر دادید نام نمایشیتان را برداشتید (%1$s بود) موضوع را به %1$s تغییر دادید - %1$s آواتار اتاق را تغییر داد - آواتار اتاق را تغییر دادید + %1$s چهرک اتاق را تغییر داد + چهرک اتاق را تغییر دادید نام اتاق را به %1$s تغییر دادید تماس تصویری گرفتید. تماس صوتی گرفتید. @@ -112,8 +112,8 @@ این اتاق را ارتقا دادید. نام اتاق را برداشتید موضوع اتاق را برداشتید - %1$s آواتار اتاق را برداشت - آواتار اتاق را برداشتید + %1$s چهرک اتاق را برداشت + چهرک اتاق را برداشتید برای %1$s دعوت پیوستن به اتاق فرستادید دعوت پیوستن %1$s به اتاق را پس گرفتید دعوت برای %1$s را پذیرفتید @@ -1065,7 +1065,7 @@ بازنشاندن از نشانی اصلی ارتباط با مدیر خدمتتان اکنون بازبینی شود - آواتار + چهرک دلیل: %1$s به دست %2$s از %1$s تحریم شدید به دست %2$s از %1$s اخراج شدید @@ -1185,7 +1185,7 @@ پیش‌نمایش محتوای چندرسانه‌ای قبل از ارسال لرزیدن گوشی در هنگام ذکر یک کاربر شامل تغییرات نام نمایشی و چهرک. - نمایش پیام‌های مربوط به حساب کاربری + نمایش رویدادهای حساب دعوت‌ها، برداشتن‌ها و انسدادها تأثیر نمی‌پذیرند. نمایش پیام‌های پیوستن و ترک اتاق پیش‌نمایشی از آدرس‌های URL در پیام‌ها نمایش داده شود. @@ -1691,7 +1691,7 @@ نمی‌توانید به خودتان پیام دهید! هم‌رسانی با متن جست‌وجوی آشنایان روی ماتریکس - تنظیم آواتار + تنظیم چهرک برای تأیید عبارت امنیتیتان، دوباره واردش کنید. عبارت امنیتی تنظیم یک عبارت امنیتی @@ -1794,7 +1794,7 @@ برداشتن پیام‌های دیگران آگاه کردن همه دستکاری ابزارک‌ها - تغییر آواتار اتاق + تغییر چهرک اتاق تغییر نشانی اصلی اتاق به کار انداختن رمزنگاری اتاق تغییر نمایانی تاریخچه @@ -2950,4 +2950,7 @@ ادامه برای بازنشانی نگارش Crypto %1$s نام نمایشیش را به %2$s تغییر داد + نگارهٔ نمایهٔ کاربر %1$s + چهرک اتاق %1$s + چهرک فضای %1$s \ No newline at end of file From 8fc5d73f750695659061bdcc60ea3abf4fdd3d18 Mon Sep 17 00:00:00 2001 From: Tuomas Hietala Date: Wed, 24 May 2023 12:05:35 +0000 Subject: [PATCH 023/234] Translated using Weblate (Finnish) Currently translated at 84.0% (2212 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fi/ --- .../src/main/res/values-fi/strings.xml | 101 +++++++++++++++--- 1 file changed, 89 insertions(+), 12 deletions(-) diff --git a/library/ui-strings/src/main/res/values-fi/strings.xml b/library/ui-strings/src/main/res/values-fi/strings.xml index 96408da021..74018e87d1 100644 --- a/library/ui-strings/src/main/res/values-fi/strings.xml +++ b/library/ui-strings/src/main/res/values-fi/strings.xml @@ -12,7 +12,7 @@ %1$s veti takaisin kutsun käyttäjälle %2$s %1$s vaihtoi profiilikuvaansa %1$s asetti näyttönimekseen %2$s - %1$s muutti näyttönimensä nimestä %2$s nimeen %3$s + %1$s vaihtoi näyttönimensä nimestä %2$s nimeen %3$s %1$s poisti näyttönimensä (%2$s) %1$s vaihtoi aiheeksi: %2$s %1$s vaihtoi huoneen nimeksi %2$s @@ -150,7 +150,7 @@ Aloitit videopuhelun. Vaihdoit huoneen nimeksi: %1$s Vaihdoit huoneen profiilikuvaa - %1$s muutti huoneen profiilikuvaa + %1$s vaihtoi huoneen profiilikuvaa Vaihdoit aiheen: %1$s Poistit nimimerkkisi (se oli %1$s) Vaihdoit nimimerkkisi %1$s nimeen %2$s @@ -424,10 +424,10 @@ Viesti sisältää käyttäjänimeni Näytä aikaleimat 12 tunnin muodossa Analytiikka - Haluatko varmasti poistaa pienoissovelluksen tästä huoneesta\? + Haluatko varmasti poistaa sovelman tästä huoneesta\? Sovelmaa ei voitu luoda. Pyynnön lähetys epäonnistui. - Oikeustason täytyy olla positiivinen luku. + Oikeustason täytyy olla positiivinen kokonaisluku. Et ole tässä huoneessa. Sinulla ei ole oikeutta suorittaa toimintoa tässä huoneessa. room_id puuttuu pyynnöstä. @@ -930,13 +930,13 @@ Sovelma Lataa sovelma Sovelman lisäsi: - Sovelman käyttö saattaa asettaa keksejä ja jakaa tietoa kohteen %s kanssa: + Sovelman käyttö saattaa asettaa evästeitä ja jakaa tietoa kohteen %s kanssa: Sovelman käyttö saattaa jakaa tietoa kohteen %s kanssa: Sovelman lataus epäonnistui. \n%s Lataa sovelma uudelleen Avaa selaimessa - Kumoa minun pääsy + Kumoa minun pääsyni Näyttönimesi Profiilikuvasi osoite Käyttäjätunnisteesi @@ -946,9 +946,9 @@ Tämä sovelma haluaa käyttää seuraavia resursseja: Salli Estä kaikki - Käytä kameraa - Käytä mikrofonia - Lue DRM-suojattua mediaa + Käyttää kameraa + Käyttää mikrofonia + Lukea DRM-suojattua mediaa Huomiotta Muuta Tuo osapuolten välisen salauksen avaimet tiedostosta ”%1$s”. @@ -1252,7 +1252,7 @@ Haluatko varmasti poistaa tämän tapahtuman\? Huomaa, että jos poistat huoneen nimen tai aiheen muutostapahtuman, se voi perua muutoksen. Anna syy Käyttäjä poistanut tapahtuman, syynä: %1$s - Tapahtuma moderoitu huoneen ylläpitäjän toimesta, syynä: %1$s + Huoneen ylläpitäjä moderoi tapahtuman, syy: %1$s Avaimet ovat jo ajan tasalla! ${app_name} Android Avainpyynnöt @@ -1403,7 +1403,7 @@ Jos poistat käyttäjän porttikiellon, hän voi liittyä huoneeseen uudelleen. Tämä poistaa käyttäjän huoneesta, mutta hän voi liittyä uudelleen. \n -\nJos haluat estää häntä uudelleen liittymästä, anna hänelle porttikielto. +\nJos haluat estää häntä liittymästä uudelleen, anna hänelle porttikielto. Syy porttikielolle Syy poistolle Poista käyttäjä @@ -1461,7 +1461,7 @@ Järjestelmän oletus Matrix ID Poistettu viesti - Aktivoi sovelma + Aktiiviset sovelmat Poista esto Estä käyttäjä Tai @@ -2429,4 +2429,81 @@ Yhdistä Kumoa kutsu Kotipalvelin ei hyväksy pelkistä numeroista koostuvaa käyttäjänimeä. + Viesti huoneessa + Viesti huoneessa %s + Viesti + Viesti käyttäjältä %s + Kysely + päätti kyselyn. + loi kyselyn. + lähetti tarran. + lähetti videon. + lähetti kuvan. + lähetti ääniviestin. + lähetti äänitiedoston. + lähetti tiedoston. + Muokkaa linkkiä + Luo linkki + Linkki + Teksti + Koko näytön tila päälle/pois + Koodilohko päälle/pois + Lainaus päälle/pois + Aseta linkki + Käytä alleviivaus-muotoilua + Käytä yliviivaus-muotoilua + Käytä kursivointi-muotoilua + Käytä lihavointi-muotoilua + Varmista, että tiedät tämän koodin alkuperän. Laitteet linkittämällä annat täyden pääsyn tiliisi. + Vahvista + Yritä uudelleen + Kirjaudutaan + Yhdistetään laitteeseen + Avaa sovellus toisella laitteellasi + Kotipalvelin ei tue QR-koodilla kirjautumista. + QR-koodi on virheellinen. + Toisen laitteen on oltava kirjattu sisään. + Toinen laite on jo kirjattu sisään. + Pyyntö epäonnistui. + Yhteyden muodostaminen ei onnistunut + Turvallinen yhteys muodostettu + Kirjaudu QR-koodilla + Monikäyttöinen ja turvallinen viestisovellus tiimeille, kavereille ja organisaatioille. Aloita luomalla keskustelu tai liittymällä olemassa olevaan huoneeseen. + ${app_name} toivottaa sinut tervetulleeksi, +\n%s. + Sovellus + Muuta menetelmää kuin taustasynkronointi ei löytynyt. + Tekstin muotoilu + Zoomaa nykyiseen sijaintiin + Näytä kysely aikajanalla + Kelaa 30 sekuntia eteenpäin + Kelaa 30 sekuntia taaksepäin + Osa tuloksista voi olla piilotettu, koska ne ovat yksityisiä ja vaativat kutsun. + Vain kutsulla, paras vaihtoehto itsellesi tai tiimeille + Luotettu-luottamustaso + Varoitus-luottamustaso + Palautusavaimen tallennuspaikka: + %s, jotta ihmiset tietävät, mistä huoneessa on kyse. + Odotetaan käyttäjien liittymistä sovellukseen ${app_name} + Kyselyhistoria + kertakirjautuminen + Kirjaudu käyttäen palvelua %s + Rekisteröidy käyttäen palvelua %s + Olet antanut suostumuksen sähköpostiosoitteiden ja puhelinnumeroiden lähettämiseen identiteettipalvelimelle yhteystiedoissasi olevien käyttäjien löytämiseksi. + Sähköposti lähetettiin osoitteeseen %s, tarkista sähköpostisi ja napsauta vahvistuslinkkiä + Siirry + Suojaudu salattuihin viesteihin ja tietoihin pääsyn menettämiseltä varmuuskopioimalla salausavaimesi palvelimellesi. + Suojaudu salattuihin viesteihin ja tietoihin pääsyn menettämiseltä varmuuskopioimalla salausavaimesi palvelimellesi. + Suojaudu salattuihin viesteihin ja tietoihin pääsyn menettämiseltä + Käyttäjän %1$s profiilikuva + Avaa kehittäjätyökalujen ruutu + Tili + Kryptografian versio + Ilmoitusasetusten päivittämisessä tapahtui virhe. Yritä uudelleen. + Salaus on määritetty virheellisesti, joten et voi lähettää viestejä. Avaa asetukset napsauttamalla. + Salaus on määritetty virheellisesti, joten et voi lähettää viestejä. Ota yhteyttä ylläpitäjään salauksen palauttamiseksi toimintakuntoon. + ${app_name} tarvitsee luvan ilmoitusten näyttämiseen. Ilmoituksia voi saada viesteistä, kutsuista ym. +\n +\nAnna käyttöoikeus seuraavissa ponnahdusikkunoissa, jotta näet ilmoituksia. + %1$s vaihtoi näyttänimekseen %2$s \ No newline at end of file From 1996df2f93ce0d5e64a086d0da46039f4e433369 Mon Sep 17 00:00:00 2001 From: Glandos Date: Sun, 21 May 2023 13:01:16 +0000 Subject: [PATCH 024/234] Translated using Weblate (French) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- library/ui-strings/src/main/res/values-fr/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-fr/strings.xml b/library/ui-strings/src/main/res/values-fr/strings.xml index e26be0b036..f47bd8e3e2 100644 --- a/library/ui-strings/src/main/res/values-fr/strings.xml +++ b/library/ui-strings/src/main/res/values-fr/strings.xml @@ -2950,4 +2950,7 @@ Version de cryptographie Faire la réinitialisation %1$s a modifié son nom d’affichage en %2$s + Image de profile de l’utilisateur %1$s + Avatar du salon %1$s + Avatar de l’espace %1$s \ No newline at end of file From 36db0ac8d6e64b9a7520de14e471c23b27da2ee1 Mon Sep 17 00:00:00 2001 From: Linerly Date: Sat, 20 May 2023 22:41:18 +0000 Subject: [PATCH 025/234] Translated using Weblate (Indonesian) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- library/ui-strings/src/main/res/values-in/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-in/strings.xml b/library/ui-strings/src/main/res/values-in/strings.xml index 2ed4293850..ae973ef7f5 100644 --- a/library/ui-strings/src/main/res/values-in/strings.xml +++ b/library/ui-strings/src/main/res/values-in/strings.xml @@ -2892,4 +2892,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Versi kripto Lanjutkan mengatur ulang %1$s mengubah nama tampilannya ke %2$s + Foto profil pengguna %1$s + Avatar ruangan %1$s + Avatar space %1$s \ No newline at end of file From baccb84efbd3d6e8d52241cb4ce5989894e68186 Mon Sep 17 00:00:00 2001 From: raspin0 Date: Tue, 23 May 2023 10:25:38 +0000 Subject: [PATCH 026/234] Translated using Weblate (Polish) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- library/ui-strings/src/main/res/values-pl/strings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-pl/strings.xml b/library/ui-strings/src/main/res/values-pl/strings.xml index b96f2345db..9bf1592b38 100644 --- a/library/ui-strings/src/main/res/values-pl/strings.xml +++ b/library/ui-strings/src/main/res/values-pl/strings.xml @@ -1127,7 +1127,7 @@ %d aktywnych sesji %d aktywnych sesji - Weryfikuj inne urządzenie + Weryfikuj to urządzenie Otwórz obecną sesję i użyj jej do zweryfikowania obecnej, przyznając jej dostęp do zaszyfrowanych wiadomości. Zweryfkuj Zweryfikowano @@ -3069,4 +3069,7 @@ %1$d zaznaczono %1$s zmienił swoją wyświetlaną nazwę na %2$s + Zdjęcie profilowe użytkownika %1$s + Awatar pokoju %1$s + Awatar przestrzeni %1$s \ No newline at end of file From 17a3ea3148b96ff7571248e9d98860f1fa8b6cd5 Mon Sep 17 00:00:00 2001 From: Bruno Date: Mon, 22 May 2023 11:18:14 +0000 Subject: [PATCH 027/234] Translated using Weblate (Portuguese (Brazil)) Currently translated at 98.2% (2584 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- .../src/main/res/values-pt-rBR/strings.xml | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml index f6a2c94553..31de3efe09 100644 --- a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml +++ b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml @@ -1045,7 +1045,7 @@ Visualizar Histórico de Edição Termos de Serviço Ser descobertável por outras(os) - Usar Bots, bridges, widgets e pacotes de stickers + Usar bots, bridges, widgets e pacotes de stickers Servidor de identidade Desconectar servidor de identidade Configurar servidor de identidade @@ -1352,7 +1352,7 @@ \nA confirmação vai ser salvada localmente e compartilhada numa versão futura do app. Envia a dada mensagem colorida como um arco-íris Envia o dado emote colorido como um arco-íris - Timeline + Linha do tempo Editor de mensagem Habilitar encriptação ponta-a-ponta… Habilitar encriptação\? @@ -2527,7 +2527,7 @@ Você precisa ter as permissões certas a fim de compartilhar localização ao vivo nesta sala. Você não tem permissão para compartilhar localização ao vivo Resultados vão ser visíveis quando a sondagem estiver terminada - Quando convidando numa sala encriptada que está compartilhando histórico, histórico encriptada vai estar visível. + Ao convidar alguém para uma uma sala criptografada que compartilha o histórico de texto, ele será visível mesmo sendo criptografado. MSC3061: Compartilhando chaves de sala para mensagens passadas Envie sua primeira mensagem para convidar %s a fazer chat Mensagens neste chat vão ser encriptadas ponta-a-ponta. @@ -2808,7 +2808,7 @@ A requisição falhou. Seja capaz de gravar e enviar broadcast de voz em timeline de sala. Broadcast de voz - Buffering… + Pré-carregando… Pausar broadcast de voz Tocar ou retomar broadcast de voz Parar gravação de broadcast de voz @@ -2884,4 +2884,16 @@ Tem certeza que você quer parar seu broadcast ao vivo\? Isto vai terminar o broadcast e a gravação completa vai estar disponível na sala. Parar de fazer broadcasting ao vivo\? Sim, Parar - + Avatar da sala %1$s + Avatar do espaço %1$s + Os detalhes da sua conta são gerenciados separadamente em %1$s. + Conta + Termos de Uso Aceitável + Um erro ocorreu ao atualizar suas preferências de notificação. Por favor, tente novamente. + Seu servidorcasa ainda não suporta threads. + Continuar com o reset + %1$s mudou seu nome de exibição para %2$s + Incapaz de reproduzir esse broadcast de voz. + Incapaz de decriptar esse broadcast de voz. + Erro de conexão - Gravação pausada + \ No newline at end of file From 671f846f5393ba7b3a2b52e69a229718fbee1606 Mon Sep 17 00:00:00 2001 From: Daimar Stein Date: Mon, 22 May 2023 11:15:36 +0000 Subject: [PATCH 028/234] Translated using Weblate (Portuguese (Brazil)) Currently translated at 98.2% (2584 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- library/ui-strings/src/main/res/values-pt-rBR/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml index 31de3efe09..7d1db41989 100644 --- a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml +++ b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml @@ -2292,8 +2292,8 @@ Jurídicos Este servidor não provê nenhuma política. Bibliotecas de terceiros - A política de seu servidor de identidade - A política de seu servidorcasa + A política do seu servidor de identidade + A política do seu servidor local Política de ${app_name} Nós não gravaremos nem criaremos um perfil dos dados de sua conta Ajude-nos a identificar problemas e melhorar ${app_name} ao compartilhar dados de uso anônimos. Para entender como pessoas usam seus múltiplos dispositivos, nós vamos gerar um identificador aleatório, compartilhado por seus dispositivos. From d409a33f92fcee68c5277f802aa23c8cc88e775f Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Sat, 20 May 2023 21:35:04 +0000 Subject: [PATCH 029/234] Translated using Weblate (Slovak) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sk/ --- library/ui-strings/src/main/res/values-sk/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sk/strings.xml b/library/ui-strings/src/main/res/values-sk/strings.xml index ee058b56fd..d0008ee88f 100644 --- a/library/ui-strings/src/main/res/values-sk/strings.xml +++ b/library/ui-strings/src/main/res/values-sk/strings.xml @@ -3010,4 +3010,7 @@ Pokračovať v obnovení Krypto verzia %1$s zmenil/a svoje zobrazované meno na %2$s + Profilový obrázok používateľa %1$s + Obrázok miestnosti %1$s + Obrázok priestoru %1$s \ No newline at end of file From 3848982c07754dd24b62e5943f92a4d652561f4f Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Sun, 21 May 2023 09:29:29 +0000 Subject: [PATCH 030/234] Translated using Weblate (Albanian) Currently translated at 99.3% (2615 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sq/ --- library/ui-strings/src/main/res/values-sq/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sq/strings.xml b/library/ui-strings/src/main/res/values-sq/strings.xml index 02cacc124c..a3ac79958b 100644 --- a/library/ui-strings/src/main/res/values-sq/strings.xml +++ b/library/ui-strings/src/main/res/values-sq/strings.xml @@ -2936,4 +2936,7 @@ Vazhdo me rikthimin te parazgjedhjet Version kriptografie %1$s ndërroi emrin e vet në ekran në %2$s + Foto profili i përdoruesit %1$s + Avatar i dhomës %1$s + Avatar i hapësirës %1$s \ No newline at end of file From 0391f77623a573e35e3e70f0564fda85b834ae3a Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Tue, 23 May 2023 19:14:37 +0000 Subject: [PATCH 031/234] Translated using Weblate (Swedish) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sv/ --- library/ui-strings/src/main/res/values-sv/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sv/strings.xml b/library/ui-strings/src/main/res/values-sv/strings.xml index 744c4c4e0f..726aa5f733 100644 --- a/library/ui-strings/src/main/res/values-sv/strings.xml +++ b/library/ui-strings/src/main/res/values-sv/strings.xml @@ -2949,4 +2949,8 @@ Kryptoversion Ett fel uppstod när du uppdaterade dina aviseringsinställningar. Var god försök igen. Fortsätt till återställning + Profilbild för användaren %1$s + Avatar för rummet %1$s + Avatar för utrymmet %1$s + %1$s bytte sitt visningsnamn till %2$s \ No newline at end of file From 09c70c99fa1d3c9917b00e10481c652bf24c2dc7 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Sat, 20 May 2023 10:48:00 +0000 Subject: [PATCH 032/234] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- library/ui-strings/src/main/res/values-uk/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-uk/strings.xml b/library/ui-strings/src/main/res/values-uk/strings.xml index 54943c001f..bf7d21feda 100644 --- a/library/ui-strings/src/main/res/values-uk/strings.xml +++ b/library/ui-strings/src/main/res/values-uk/strings.xml @@ -3070,4 +3070,7 @@ Перейти до скидання Криптоверсія %1$s змінює своє ім\'я на %2$s + Зображення профілю користувача %1$s + Аватар кімнати %1$s + Аватар простору %1$s \ No newline at end of file From d5794441d628884744b4e76d3312e2c65ab15474 Mon Sep 17 00:00:00 2001 From: phardyle Date: Tue, 23 May 2023 15:01:12 +0000 Subject: [PATCH 033/234] Translated using Weblate (Chinese (Simplified)) Currently translated at 97.8% (2574 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hans/ --- library/ui-strings/src/main/res/values-zh-rCN/strings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml index 52d5e5f17a..63c7c2a5a7 100644 --- a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml @@ -652,7 +652,7 @@ 设置响铃通知 设置电话通知 设置静音通知 - 选择指示灯颜色,震动,铃声… + 选择LED颜色、震动、铃声…… 加密密钥管理 恢复已加密消息 管理密钥备份 @@ -2822,4 +2822,7 @@ 结束了投票。 你的访问令牌提供对你账户的完全访问权限。勿与任何人分享它。 访问令牌 + 继续重设 + %1$s更改了其显示名称为%2$s + 账户 \ No newline at end of file From 900828f57ddfeea8021961656bb4a8afb38f3e9e Mon Sep 17 00:00:00 2001 From: ang yong en Date: Tue, 23 May 2023 04:30:08 +0000 Subject: [PATCH 034/234] Translated using Weblate (Chinese (Simplified)) Currently translated at 97.8% (2574 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hans/ --- library/ui-strings/src/main/res/values-zh-rCN/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml index 63c7c2a5a7..b0c008d4ae 100644 --- a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml @@ -2825,4 +2825,5 @@ 继续重设 %1$s更改了其显示名称为%2$s 账户 + 是的,停止 \ No newline at end of file From 7e748f28e899ea527dec83bda864294e9b2980ab Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Mon, 22 May 2023 01:35:59 +0000 Subject: [PATCH 035/234] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2631 of 2631 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- library/ui-strings/src/main/res/values-zh-rTW/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml index a1bfa92235..3bb22bd283 100644 --- a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml @@ -2890,4 +2890,7 @@ 繼續重設 加密版本 %1$s 變更了他們的顯示名稱為 %2$s + 使用者 %1$s 的個人資料照片 + 聊天室 %1$s 的大頭貼 + 聊天空間 %1$s 的大頭貼 \ No newline at end of file From d78d07b42a2e30939737df41abca7e8c562fdfb1 Mon Sep 17 00:00:00 2001 From: Vri Date: Sat, 20 May 2023 10:49:33 +0000 Subject: [PATCH 036/234] Translated using Weblate (German) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/de/ --- fastlane/metadata/android/de-DE/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/40106000.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/40106000.txt b/fastlane/metadata/android/de-DE/changelogs/40106000.txt new file mode 100644 index 0000000000..80ee810eec --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Element Android nutzt nun das Crypto-Rust-SDK. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases From d6302d3b9b0fc085a2d762edb2ad924b367aa83d Mon Sep 17 00:00:00 2001 From: Glandos Date: Sun, 21 May 2023 13:00:46 +0000 Subject: [PATCH 037/234] Translated using Weblate (French) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fr/ --- fastlane/metadata/android/fr-FR/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40106000.txt diff --git a/fastlane/metadata/android/fr-FR/changelogs/40106000.txt b/fastlane/metadata/android/fr-FR/changelogs/40106000.txt new file mode 100644 index 0000000000..7e04ed8f3c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Element Android utilise désormais le SDK cryptographique en Rust. +Intégralité des changements : https://github.com/vector-im/element-android/releases From cffd6e80d01761093cb0ba08eab834a0159e66e4 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Sat, 20 May 2023 21:33:29 +0000 Subject: [PATCH 038/234] Translated using Weblate (Slovak) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sk/ --- fastlane/metadata/android/sk/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sk/changelogs/40106000.txt diff --git a/fastlane/metadata/android/sk/changelogs/40106000.txt b/fastlane/metadata/android/sk/changelogs/40106000.txt new file mode 100644 index 0000000000..bb76d77ad5 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Element Android teraz používa Crypto Rust SDK. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases From 580f979c051f98538a74d233872cae9673642005 Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Tue, 23 May 2023 19:13:11 +0000 Subject: [PATCH 039/234] Translated using Weblate (Swedish) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sv/ --- fastlane/metadata/android/sv-SE/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sv-SE/changelogs/40106000.txt diff --git a/fastlane/metadata/android/sv-SE/changelogs/40106000.txt b/fastlane/metadata/android/sv-SE/changelogs/40106000.txt new file mode 100644 index 0000000000..073379ea5a --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Element Android använder ny Rust-krypto-SDK:t +Full ändringslogg: https://github.com/vector-im/element-android/releases From 8447e06b212970c6b24a6ab3fb4f95668188af75 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Sat, 20 May 2023 10:52:56 +0000 Subject: [PATCH 040/234] Translated using Weblate (Ukrainian) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/uk/ --- fastlane/metadata/android/uk/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/40106000.txt diff --git a/fastlane/metadata/android/uk/changelogs/40106000.txt b/fastlane/metadata/android/uk/changelogs/40106000.txt new file mode 100644 index 0000000000..0066e0c597 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Element Android тепер використовує Crypto Rust SDK. +Перелік усіх змін: https://github.com/vector-im/element-android/releases From b1b784de9fb687d01eaf853678ef84ef3b32864e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sun, 21 May 2023 20:06:18 +0000 Subject: [PATCH 041/234] Translated using Weblate (Estonian) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/et/ --- fastlane/metadata/android/et/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/et/changelogs/40106000.txt diff --git a/fastlane/metadata/android/et/changelogs/40106000.txt b/fastlane/metadata/android/et/changelogs/40106000.txt new file mode 100644 index 0000000000..233a4a0cdd --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: Element Android krüptoteekideks on nüüd Crypto Rust SDK. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases From 8eee238220188aa0b6fcbc6f51ebd5c30e566f53 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Sat, 20 May 2023 12:20:14 +0000 Subject: [PATCH 042/234] Translated using Weblate (Persian) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fa/ --- fastlane/metadata/android/fa/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/fa/changelogs/40106000.txt diff --git a/fastlane/metadata/android/fa/changelogs/40106000.txt b/fastlane/metadata/android/fa/changelogs/40106000.txt new file mode 100644 index 0000000000..1482b03042 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40106000.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: المنت اندروید اکنون از SDK راست Crypto استفاده می‌کند. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases From 1058f4b91d93f3cfac9d2eb1bce72a8c3c17897d Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Sun, 21 May 2023 15:15:29 +0000 Subject: [PATCH 043/234] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/zh_Hant/ --- fastlane/metadata/android/zh-TW/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40106000.txt diff --git a/fastlane/metadata/android/zh-TW/changelogs/40106000.txt b/fastlane/metadata/android/zh-TW/changelogs/40106000.txt new file mode 100644 index 0000000000..0ee6434a8d --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40106000.txt @@ -0,0 +1,2 @@ +此版本的主要變更:現在起,Element Android 使用 Crypto Rust SDK。 +完整異動:https://github.com/vector-im/element-android/releases From 7cff46d2713794de038366716bab00dfd7f64dc6 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 22 May 2023 19:33:05 +0000 Subject: [PATCH 044/234] Translated using Weblate (Czech) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/cs/ --- fastlane/metadata/android/cs-CZ/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40106000.txt diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40106000.txt b/fastlane/metadata/android/cs-CZ/changelogs/40106000.txt new file mode 100644 index 0000000000..797d2af0ae --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Element Android nyní používá Crypto Rust SDK. +Úplný seznam změn: https://github.com/vector-im/element-android/releases From 390377480c7bdce824a359026df38c98a9d56b53 Mon Sep 17 00:00:00 2001 From: Linerly Date: Sat, 20 May 2023 22:40:22 +0000 Subject: [PATCH 045/234] Translated using Weblate (Indonesian) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/id/ --- fastlane/metadata/android/id/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/id/changelogs/40106000.txt diff --git a/fastlane/metadata/android/id/changelogs/40106000.txt b/fastlane/metadata/android/id/changelogs/40106000.txt new file mode 100644 index 0000000000..b69e7fc7b9 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Element Android sekarang menggunakan SDK Kripto Rust. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases From d26d7f124b7b7a3c2501ca46b1f19e215ccdc291 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Sun, 21 May 2023 09:30:41 +0000 Subject: [PATCH 046/234] Translated using Weblate (Albanian) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sq/ --- fastlane/metadata/android/sq/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sq/changelogs/40106000.txt diff --git a/fastlane/metadata/android/sq/changelogs/40106000.txt b/fastlane/metadata/android/sq/changelogs/40106000.txt new file mode 100644 index 0000000000..5b8003c310 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Element Android tani përdor Crypto Rust SDK. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases From 287bff473d91cdb8034c21d222435e86859247d6 Mon Sep 17 00:00:00 2001 From: raspin0 Date: Sat, 20 May 2023 16:08:33 +0000 Subject: [PATCH 047/234] Translated using Weblate (Polish) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/pl/ --- fastlane/metadata/android/pl-PL/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40106000.txt diff --git a/fastlane/metadata/android/pl-PL/changelogs/40106000.txt b/fastlane/metadata/android/pl-PL/changelogs/40106000.txt new file mode 100644 index 0000000000..903bf9c419 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Element Android teraz korzysta z Crypto Rust SDK. +Pełna lista zmian:https://github.com/vector-im/element-android/releases From 37429c277b8b7496ba2e90c3c2b50426e389a9c9 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Fri, 26 May 2023 11:57:18 +0100 Subject: [PATCH 048/234] Show correct details when a poll is ended. Previously, the "end poll" timeline item always showed the title and options from the start event, regardless of whether any edits had been made. Now we show the latest edit, if available, falling back to the original otherwise. --- changelog.d/8471.bugfix | 1 + .../home/room/detail/timeline/factory/MessageItemFactory.kt | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelog.d/8471.bugfix diff --git a/changelog.d/8471.bugfix b/changelog.d/8471.bugfix new file mode 100644 index 0000000000..ff0b0f5493 --- /dev/null +++ b/changelog.d/8471.bugfix @@ -0,0 +1 @@ +The correct title and options are now displayed When a poll that was edited is ended. diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 09b91cc4f1..85e4db4091 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -286,7 +286,10 @@ class MessageItemFactory @Inject constructor( } else { null } - val pollContent = pollStartEvent?.root?.getClearContent()?.toModel() + + val editedContent = pollStartEvent?.annotations?.editSummary?.latestEdit?.getClearContent()?.toModel()?.newContent + val latestContent = editedContent ?: pollStartEvent?.root?.getClearContent() + val pollContent = latestContent?.toModel() return if (pollContent == null) { val title = stringProvider.getString(R.string.message_reply_to_ended_poll_preview).toEpoxyCharSequence() From 94812211401cf1a84065647cf08fb58f53ca0456 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Fri, 26 May 2023 09:19:38 +0000 Subject: [PATCH 049/234] Translated using Weblate (Czech) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- library/ui-strings/src/main/res/values-cs/strings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index 38c78a712a..188207dceb 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -306,7 +306,7 @@ Nesprávné uživatelské jméno nebo heslo Zdá se, že toto není platná e-mailová adresa Tato e-mailová adresa je již zadána. - Zapomenuté heslo? + Zapomněli jste heslo\? Tento domovský server by se rád přesvědčil, že nejste robot E-mailovou adresu se nepodařilo ověřit. Přesvědčte se, že jste klepli na zaslaný odkaz Prosím, zadejte platné URL @@ -3013,4 +3013,7 @@ Profilový obrázek uživatele %1$s Avatar místnosti %1$s Avatar prostoru %1$s + Nejnovější aktualizace vylepšila zabezpečené zasílání zpráv. Znovu ověřte své zařízení. + Dokud tento uživatel této relaci nedůvěřuje, jsou zprávy odesílané do ní a z ní označeny varováním. + Aplikace aktualizována \ No newline at end of file From 882fb58a7d4e780a2d269f83dd06210198a5f36d Mon Sep 17 00:00:00 2001 From: Vri Date: Thu, 25 May 2023 18:14:38 +0000 Subject: [PATCH 050/234] Translated using Weblate (German) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- library/ui-strings/src/main/res/values-de/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-de/strings.xml b/library/ui-strings/src/main/res/values-de/strings.xml index faf5a0d896..08407f3bdd 100644 --- a/library/ui-strings/src/main/res/values-de/strings.xml +++ b/library/ui-strings/src/main/res/values-de/strings.xml @@ -2952,4 +2952,7 @@ Benutzer-Profilbild von %1$s Raum-Avatar von %1$s Space-Avatar von %1$s + Verschlüsselte Kommunikation wurde mit der neuesten Aktualisierung verbessert. Bitte verifiziere deine Geräte erneut. + Solange der Benutzer dieser Sitzung nicht vertraut, werden Nachrichten mit Warnungen versehen. + App aktualisiert \ No newline at end of file From 13bdd10a6945231dd7ff92673d81af655b728078 Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Thu, 25 May 2023 04:31:11 +0000 Subject: [PATCH 051/234] Translated using Weblate (Persian) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/ --- library/ui-strings/src/main/res/values-fa/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-fa/strings.xml b/library/ui-strings/src/main/res/values-fa/strings.xml index 90f049e18f..6467330e38 100644 --- a/library/ui-strings/src/main/res/values-fa/strings.xml +++ b/library/ui-strings/src/main/res/values-fa/strings.xml @@ -2953,4 +2953,7 @@ نگارهٔ نمایهٔ کاربر %1$s چهرک اتاق %1$s چهرک فضای %1$s + پیام‌رسانی امن با جدیدترین به‌روز رسانی بهبود یافته است. لطفاً افزاره‌تان را دوباره تأیید کنید. + تا کاربر این نشست را تأیید کند، پیام‌های فرستاده و گرفته‌اش با هشدار برچسب می‌خورند. + کاره به‌روز شد \ No newline at end of file From ac235fa1db717c2b6ee41a0c6fba4fc8b456602e Mon Sep 17 00:00:00 2001 From: Glandos Date: Thu, 25 May 2023 07:22:02 +0000 Subject: [PATCH 052/234] Translated using Weblate (French) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- library/ui-strings/src/main/res/values-fr/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-fr/strings.xml b/library/ui-strings/src/main/res/values-fr/strings.xml index f47bd8e3e2..32cbbca34c 100644 --- a/library/ui-strings/src/main/res/values-fr/strings.xml +++ b/library/ui-strings/src/main/res/values-fr/strings.xml @@ -2953,4 +2953,7 @@ Image de profile de l’utilisateur %1$s Avatar du salon %1$s Avatar de l’espace %1$s + La messagerie sécurisée a été améliorée avec la dernière mise-à-jour. Veuillez re-vérifier votre appareil. + Jusqu’à ce que cet utilisateur fasse confiance à cette session, les messages sur cette session sont étiquetés avec des avertissements. + Application mise-à-jour \ No newline at end of file From 1fd2f78f4d476d14e6f4afd40a1e2db777f5e89d Mon Sep 17 00:00:00 2001 From: Linerly Date: Thu, 25 May 2023 22:42:58 +0000 Subject: [PATCH 053/234] Translated using Weblate (Indonesian) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- library/ui-strings/src/main/res/values-in/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-in/strings.xml b/library/ui-strings/src/main/res/values-in/strings.xml index ae973ef7f5..02bf8e0200 100644 --- a/library/ui-strings/src/main/res/values-in/strings.xml +++ b/library/ui-strings/src/main/res/values-in/strings.xml @@ -2895,4 +2895,7 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Foto profil pengguna %1$s Avatar ruangan %1$s Avatar space %1$s + Perpesanan aman telah ditingkatkan dengan pembaruan terkini. Silakan verifikasi ulang perangkat Anda. + Sampai pengguna ini mempercayai sesi ini, pesan yang dikirim dan diterima akan ditandai dengan peringatan. + Aplikasi diperbarui \ No newline at end of file From 72956bda646a0bc340f82f9bcc8f89ba0e59c8ff Mon Sep 17 00:00:00 2001 From: random Date: Fri, 26 May 2023 07:50:55 +0000 Subject: [PATCH 054/234] Translated using Weblate (Italian) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- library/ui-strings/src/main/res/values-it/strings.xml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/ui-strings/src/main/res/values-it/strings.xml b/library/ui-strings/src/main/res/values-it/strings.xml index 8c13bdc3a2..67fcde35d6 100644 --- a/library/ui-strings/src/main/res/values-it/strings.xml +++ b/library/ui-strings/src/main/res/values-it/strings.xml @@ -1451,7 +1451,7 @@ MEDIA In questa stanza non ci sono file multimediali FILE - %1$s alle %2$s + %1$s: %2$s In questa stanza non ci sono file Accedi con il tuo ID utente Accedi con il tuo ID utente @@ -2287,7 +2287,7 @@ Questo server non presenta alcuna informativa. Librerie di terze parti L\'informativa del tuo server d\'identità - L\'informativa del tuo homeserver + Informativa del tuo homeserver Informativa di ${app_name} Puoi disattivarlo in qualsiasi momento nelle impostazioni Non condividiamo informazioni con terze parti @@ -2941,4 +2941,10 @@ Procedi con la reimpostazione Versione crittografia %1$s ha cambiato il nome visualizzato in %2$s + La messaggistica sicura è stata migliorata con l\'aggiornamento più recente. Ri-verifica il tuo dispositivo. + Finché l\'utente si fida di questa sessione, i messaggi inviati da e verso essa sono contrassegnati da avvisi. + App aggiornata + Immagine del profilo dell\'utente %1$s + Avatar della stanza %1$s + Avatar dello spazio %1$s \ No newline at end of file From 8ecd03d5844376da4cd79699a15a7398bfa7ea9e Mon Sep 17 00:00:00 2001 From: raspin0 Date: Thu, 25 May 2023 11:00:39 +0000 Subject: [PATCH 055/234] Translated using Weblate (Polish) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- library/ui-strings/src/main/res/values-pl/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-pl/strings.xml b/library/ui-strings/src/main/res/values-pl/strings.xml index 9bf1592b38..75eb84c18d 100644 --- a/library/ui-strings/src/main/res/values-pl/strings.xml +++ b/library/ui-strings/src/main/res/values-pl/strings.xml @@ -3072,4 +3072,7 @@ Zdjęcie profilowe użytkownika %1$s Awatar pokoju %1$s Awatar przestrzeni %1$s + Bezpieczne wysyłanie wiadomości zostało usprawnione z najnowszą aktualizacją. Zweryfikuj swoje urządzenie ponownie. + Dopóki ten użytkownik nie zweryfikuje tej sesji, wysłane wiadomości będą zawierać ostrzeżenie. + Zaktualizowano aplikację \ No newline at end of file From c039d62e5ec40f90f32c818d6762c7afb4b70f5c Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Thu, 25 May 2023 01:13:23 +0000 Subject: [PATCH 056/234] Translated using Weblate (Slovak) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sk/ --- library/ui-strings/src/main/res/values-sk/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sk/strings.xml b/library/ui-strings/src/main/res/values-sk/strings.xml index d0008ee88f..2103006ba7 100644 --- a/library/ui-strings/src/main/res/values-sk/strings.xml +++ b/library/ui-strings/src/main/res/values-sk/strings.xml @@ -3013,4 +3013,7 @@ Profilový obrázok používateľa %1$s Obrázok miestnosti %1$s Obrázok priestoru %1$s + Najnovšou aktualizáciou sa zlepšilo bezpečné zasielanie správ. Overte prosím znova svoje zariadenie. + Pokiaľ tento používateľ tejto relácii nedôveruje, správy odoslané do nej a z nej sú označené varovaním. + Aplikácia bola aktualizovaná \ No newline at end of file From 64c47a6e6ce479b628d5e97981d562d841d8aba2 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Thu, 25 May 2023 08:51:20 +0000 Subject: [PATCH 057/234] Translated using Weblate (Albanian) Currently translated at 99.4% (2619 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sq/ --- library/ui-strings/src/main/res/values-sq/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sq/strings.xml b/library/ui-strings/src/main/res/values-sq/strings.xml index a3ac79958b..5ce061a7cb 100644 --- a/library/ui-strings/src/main/res/values-sq/strings.xml +++ b/library/ui-strings/src/main/res/values-sq/strings.xml @@ -2939,4 +2939,8 @@ Foto profili i përdoruesit %1$s Avatar i dhomës %1$s Avatar i hapësirës %1$s + Shkëmbimi i siguruar i mesazheve është përmirësuar me përditësimin më të ri. Ju lutemi, riverifikoni pajisjen tuaj. + Rimerre + Deri kur ky përdorues të besojë këtë sesion, mesazhet dërguar për të dhe nga ai etiketohem me sinjalizime. + Aplikacioni u përditësua \ No newline at end of file From 36a2e6e11c1e8d2dc76622a6125782ce56725bca Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Wed, 24 May 2023 21:01:09 +0000 Subject: [PATCH 058/234] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- library/ui-strings/src/main/res/values-uk/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-uk/strings.xml b/library/ui-strings/src/main/res/values-uk/strings.xml index bf7d21feda..4f6dbbf65a 100644 --- a/library/ui-strings/src/main/res/values-uk/strings.xml +++ b/library/ui-strings/src/main/res/values-uk/strings.xml @@ -3073,4 +3073,7 @@ Зображення профілю користувача %1$s Аватар кімнати %1$s Аватар простору %1$s + В останньому оновленні було вдосконалено захищений обмін повідомленнями. Перевірте свій пристрій ще раз. + Поки користувач не довіряє цьому сеансу, повідомлення, надіслані до нього та від нього, позначаються попередженнями. + Застосунок оновлено \ No newline at end of file From e7584d37bb581575a2efc8f35e65c8ab659bc953 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Thu, 25 May 2023 02:07:43 +0000 Subject: [PATCH 059/234] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- library/ui-strings/src/main/res/values-zh-rTW/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml index 3bb22bd283..8083e112b4 100644 --- a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml @@ -2893,4 +2893,7 @@ 使用者 %1$s 的個人資料照片 聊天室 %1$s 的大頭貼 聊天空間 %1$s 的大頭貼 + 最新更新改善了安全訊息傳遞。請重新驗證您的裝置。 + 在該使用者信任該工作階段之前,發送到該工作階段與從該工作階段傳送的訊息都帶有警告標籤。 + 應用程式已更新 \ No newline at end of file From 03165825377529d9690623a33676917c147568e5 Mon Sep 17 00:00:00 2001 From: random Date: Thu, 25 May 2023 12:14:10 +0000 Subject: [PATCH 060/234] Translated using Weblate (Italian) Currently translated at 100.0% (98 of 98 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/it/ --- fastlane/metadata/android/it-IT/changelogs/40106000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/40106000.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/40106000.txt b/fastlane/metadata/android/it-IT/changelogs/40106000.txt new file mode 100644 index 0000000000..2e8ef554e1 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: Element Android ora utilizza l'SDK Rust Crypto. +Cronologia completa: https://github.com/vector-im/element-android/releases From ac705151e9027e1a38d2250f7c1995ae8ba69461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sat, 27 May 2023 07:18:50 +0000 Subject: [PATCH 061/234] Translated using Weblate (Estonian) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- library/ui-strings/src/main/res/values-et/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-et/strings.xml b/library/ui-strings/src/main/res/values-et/strings.xml index 66a799c5f9..25ef48029a 100644 --- a/library/ui-strings/src/main/res/values-et/strings.xml +++ b/library/ui-strings/src/main/res/values-et/strings.xml @@ -2953,4 +2953,7 @@ Kasutaja %1$s tunnuspilt %1$s jututoa tunnuspilt %1$s kogukonna tunnuspilt + Turvalisele sõnumivahetusele on lisandunud palju täiendusi. Palun verifitseeri oma seade uuesti. + Seni kuni nimetatud kasutaja usaldab seda sessiooni, kõik siit ja siia saadetud sõnumid on märgistatud hoiatusega. + Rakendus on uuendatud \ No newline at end of file From 0736c9ede5e4b65f3838b3747732a70a38a7939b Mon Sep 17 00:00:00 2001 From: Vri Date: Fri, 26 May 2023 13:58:38 +0000 Subject: [PATCH 062/234] Translated using Weblate (German) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/de/ --- fastlane/metadata/android/de-DE/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/40106010.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/40106010.txt b/fastlane/metadata/android/de-DE/changelogs/40106010.txt new file mode 100644 index 0000000000..80ee810eec --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Element Android nutzt nun das Crypto-Rust-SDK. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases From 9c9fecc97d726da9d0fa376653da7df843aacacf Mon Sep 17 00:00:00 2001 From: Glandos Date: Sat, 27 May 2023 10:08:33 +0000 Subject: [PATCH 063/234] Translated using Weblate (French) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fr/ --- fastlane/metadata/android/fr-FR/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40106010.txt diff --git a/fastlane/metadata/android/fr-FR/changelogs/40106010.txt b/fastlane/metadata/android/fr-FR/changelogs/40106010.txt new file mode 100644 index 0000000000..7e04ed8f3c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Element Android utilise désormais le SDK cryptographique en Rust. +Intégralité des changements : https://github.com/vector-im/element-android/releases From d1f82ab2b9875ebba0bb5747496f0f554c10bdc0 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Sat, 27 May 2023 08:36:24 +0000 Subject: [PATCH 064/234] Translated using Weblate (Slovak) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sk/ --- fastlane/metadata/android/sk/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sk/changelogs/40106010.txt diff --git a/fastlane/metadata/android/sk/changelogs/40106010.txt b/fastlane/metadata/android/sk/changelogs/40106010.txt new file mode 100644 index 0000000000..bb76d77ad5 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Element Android teraz používa Crypto Rust SDK. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases From 09580af844f893560ba1b75514c74c58bf1e456e Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Fri, 26 May 2023 19:33:52 +0000 Subject: [PATCH 065/234] Translated using Weblate (Ukrainian) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/uk/ --- fastlane/metadata/android/uk/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/40106010.txt diff --git a/fastlane/metadata/android/uk/changelogs/40106010.txt b/fastlane/metadata/android/uk/changelogs/40106010.txt new file mode 100644 index 0000000000..0066e0c597 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Element Android тепер використовує Crypto Rust SDK. +Перелік усіх змін: https://github.com/vector-im/element-android/releases From d7b621f9d85117f3646560ab2d40e8127d59576c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sat, 27 May 2023 07:19:21 +0000 Subject: [PATCH 066/234] Translated using Weblate (Estonian) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/et/ --- fastlane/metadata/android/et/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/et/changelogs/40106010.txt diff --git a/fastlane/metadata/android/et/changelogs/40106010.txt b/fastlane/metadata/android/et/changelogs/40106010.txt new file mode 100644 index 0000000000..233a4a0cdd --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: Element Android krüptoteekideks on nüüd Crypto Rust SDK. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases From ba15aa11f28b9ce0c4965af5388b9c712d1d21b9 Mon Sep 17 00:00:00 2001 From: random Date: Sat, 27 May 2023 16:34:33 +0000 Subject: [PATCH 067/234] Translated using Weblate (Italian) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/it/ --- fastlane/metadata/android/it-IT/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/40106010.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/40106010.txt b/fastlane/metadata/android/it-IT/changelogs/40106010.txt new file mode 100644 index 0000000000..2e8ef554e1 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: Element Android ora utilizza l'SDK Rust Crypto. +Cronologia completa: https://github.com/vector-im/element-android/releases From f5eb78612f24d5accef3406728068ce626c74ead Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Fri, 26 May 2023 15:49:36 +0000 Subject: [PATCH 068/234] Translated using Weblate (Persian) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fa/ --- fastlane/metadata/android/fa/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/fa/changelogs/40106010.txt diff --git a/fastlane/metadata/android/fa/changelogs/40106010.txt b/fastlane/metadata/android/fa/changelogs/40106010.txt new file mode 100644 index 0000000000..1482b03042 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40106010.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: المنت اندروید اکنون از SDK راست Crypto استفاده می‌کند. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases From c53ec382e59023689acbdd7fd6ad98bbf0a4f385 Mon Sep 17 00:00:00 2001 From: Linerly Date: Fri, 26 May 2023 13:23:56 +0000 Subject: [PATCH 069/234] Translated using Weblate (Indonesian) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/id/ --- fastlane/metadata/android/id/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/id/changelogs/40106010.txt diff --git a/fastlane/metadata/android/id/changelogs/40106010.txt b/fastlane/metadata/android/id/changelogs/40106010.txt new file mode 100644 index 0000000000..b69e7fc7b9 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Element Android sekarang menggunakan SDK Kripto Rust. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases From 9409f47bcbdea39bdfbc23a94c2f5c4581007842 Mon Sep 17 00:00:00 2001 From: raspin0 Date: Fri, 26 May 2023 20:12:43 +0000 Subject: [PATCH 070/234] Translated using Weblate (Polish) Currently translated at 98.9% (98 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/pl/ --- fastlane/metadata/android/pl-PL/changelogs/40106000.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/metadata/android/pl-PL/changelogs/40106000.txt b/fastlane/metadata/android/pl-PL/changelogs/40106000.txt index 903bf9c419..c91b48c168 100644 --- a/fastlane/metadata/android/pl-PL/changelogs/40106000.txt +++ b/fastlane/metadata/android/pl-PL/changelogs/40106000.txt @@ -1,2 +1,2 @@ Główne zmiany w tej wersji: Element Android teraz korzysta z Crypto Rust SDK. -Pełna lista zmian:https://github.com/vector-im/element-android/releases +Pełna lista zmian: https://github.com/vector-im/element-android/releases From 3292a07d3a11185a37074574462be48352cfd52a Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Tue, 30 May 2023 18:59:13 +0000 Subject: [PATCH 071/234] Translated using Weblate (Swedish) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sv/ --- library/ui-strings/src/main/res/values-sv/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sv/strings.xml b/library/ui-strings/src/main/res/values-sv/strings.xml index 726aa5f733..52cf1b1b25 100644 --- a/library/ui-strings/src/main/res/values-sv/strings.xml +++ b/library/ui-strings/src/main/res/values-sv/strings.xml @@ -2953,4 +2953,7 @@ Avatar för rummet %1$s Avatar för utrymmet %1$s %1$s bytte sitt visningsnamn till %2$s + Säker meddelandehantering har förbättrats med den senaste uppdateringen. Vänligen verifiera din enhet igen. + Tills den här användaren litar på den här sessionen märks meddelanden som skickas till och från den med varningar. + App uppdaterad \ No newline at end of file From f92f87ce08019b6f573ee97f0daa7448c8d92281 Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Tue, 30 May 2023 19:00:07 +0000 Subject: [PATCH 072/234] Translated using Weblate (Swedish) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sv/ --- fastlane/metadata/android/sv-SE/changelogs/40106000.txt | 2 +- fastlane/metadata/android/sv-SE/changelogs/40106010.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 fastlane/metadata/android/sv-SE/changelogs/40106010.txt diff --git a/fastlane/metadata/android/sv-SE/changelogs/40106000.txt b/fastlane/metadata/android/sv-SE/changelogs/40106000.txt index 073379ea5a..215691cf4b 100644 --- a/fastlane/metadata/android/sv-SE/changelogs/40106000.txt +++ b/fastlane/metadata/android/sv-SE/changelogs/40106000.txt @@ -1,2 +1,2 @@ -Huvudsakliga ändringar i den här versionen: Element Android använder ny Rust-krypto-SDK:t +Huvudsakliga ändringar i den här versionen: Element Android använder nu Rust-krypto-SDK:t Full ändringslogg: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sv-SE/changelogs/40106010.txt b/fastlane/metadata/android/sv-SE/changelogs/40106010.txt new file mode 100644 index 0000000000..215691cf4b --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Element Android använder nu Rust-krypto-SDK:t +Full ändringslogg: https://github.com/vector-im/element-android/releases From 957e89bbfd28e45a4f480789858cdf17bb7113f0 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Mon, 29 May 2023 02:13:28 +0000 Subject: [PATCH 073/234] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/zh_Hant/ --- fastlane/metadata/android/zh-TW/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40106010.txt diff --git a/fastlane/metadata/android/zh-TW/changelogs/40106010.txt b/fastlane/metadata/android/zh-TW/changelogs/40106010.txt new file mode 100644 index 0000000000..0ee6434a8d --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40106010.txt @@ -0,0 +1,2 @@ +此版本的主要變更:現在起,Element Android 使用 Crypto Rust SDK。 +完整異動:https://github.com/vector-im/element-android/releases From ae4c3b078b1b5a20e47b40e5f346db80fe446e08 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 29 May 2023 11:32:04 +0000 Subject: [PATCH 074/234] Translated using Weblate (Czech) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/cs/ --- fastlane/metadata/android/cs-CZ/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40106010.txt diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40106010.txt b/fastlane/metadata/android/cs-CZ/changelogs/40106010.txt new file mode 100644 index 0000000000..797d2af0ae --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Element Android nyní používá Crypto Rust SDK. +Úplný seznam změn: https://github.com/vector-im/element-android/releases From 4371ba48cbda226616ff61ae92c173b388245f7f Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Tue, 30 May 2023 09:17:11 +0000 Subject: [PATCH 075/234] Translated using Weblate (Albanian) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sq/ --- fastlane/metadata/android/sq/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sq/changelogs/40106010.txt diff --git a/fastlane/metadata/android/sq/changelogs/40106010.txt b/fastlane/metadata/android/sq/changelogs/40106010.txt new file mode 100644 index 0000000000..0c2470c653 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Element Android tanimë përdor SDK Rust Fshehtëzimesh. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases From e976ddde34fdcee25664b40be26802b01cb03e5a Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Thu, 1 Jun 2023 18:42:09 +0000 Subject: [PATCH 076/234] Translated using Weblate (Czech) Currently translated at 100.0% (2634 of 2634 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- library/ui-strings/src/main/res/values-cs/strings.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index 188207dceb..6e43b2d487 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -278,8 +278,8 @@ Žádné výsledky Místnosti Odeslat záznamy - Odeslat záznamy zřícení - Odeslat screenshot + Odeslat záznamy o selhání + Odeslat snímek obrazovky Ohlásit chybu Zde popište svůj problém Za účelem diagnostiky problémů budou logy tohoto klienta odeslány s touto zprávou o chybě. Tato zpráva o chybě včetně logů a snímku obrazovky nebude veřejně viditelná. Pokud byste raději poslali pouze text výše, prosím odznačte: @@ -317,7 +317,7 @@ Přijmout Chyba Systémová upozornění - Prosím, popište chybu. Co jste provedli\? Jaké bylo očekávané chování\? Co se ve skutečnosti stalo\? + Popište prosím chybu. Co jste udělali\? Co jste očekávali, že se stane\? Co se ve skutečnosti stalo\? Pokud je to možné, prosím, napište popis anglicky. Třesením oznámit chybu Odeslat hlasovou zprávu @@ -2942,8 +2942,8 @@ Nastavit odkaz Přístupový token umožňuje plný přístup k účtu. Nikomu ho nesdělujte. Přístupový token - Přepnout na odrážky - Přepnout na číslovaný seznam + Přepnout seznam s odrážkami + Přepnout číslovaný seznam V této místnosti nejsou žádné předchozí hlasování Předchozí hlasování V této místnosti nejsou žádné aktivní hlasování From 0965050ec976fd8f74c691c759187c69289b0a1a Mon Sep 17 00:00:00 2001 From: raspin0 Date: Thu, 1 Jun 2023 08:27:05 +0000 Subject: [PATCH 077/234] Translated using Weblate (Polish) Currently translated at 100.0% (99 of 99 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/pl/ --- fastlane/metadata/android/pl-PL/changelogs/40106010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40106010.txt diff --git a/fastlane/metadata/android/pl-PL/changelogs/40106010.txt b/fastlane/metadata/android/pl-PL/changelogs/40106010.txt new file mode 100644 index 0000000000..c91b48c168 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Element Android teraz korzysta z Crypto Rust SDK. +Pełna lista zmian: https://github.com/vector-im/element-android/releases From 3c08fb637a03b27f55d124c6aa39207e13b102fd Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 2 Jun 2023 18:05:49 +0200 Subject: [PATCH 078/234] version++ --- matrix-sdk-android/build.gradle | 2 +- vector-app/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 420b24ab5a..e8d0b190c0 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -63,7 +63,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.6.2\"" + buildConfigField "String", "SDK_VERSION", "\"1.6.4\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 9a2506391e..8221497e74 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -37,7 +37,7 @@ ext.versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -ext.versionPatch = 2 +ext.versionPatch = 4 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From 5a745722097e0a01c793b80762234ce5f9611a48 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Fri, 2 Jun 2023 10:56:58 +0000 Subject: [PATCH 079/234] Translated using Weblate (Czech) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- .../ui-strings/src/main/res/values-cs/strings.xml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index 6e43b2d487..09f944ba7e 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -4,7 +4,7 @@ %1$s pozval(a) %2$s %1$s vás pozval(a) %1$s vstoupil(a) do místnosti - Uživatel %1$s opustil místnost + %1$s opustil(a) místnost %1$s odmítl(a) pozvání %1$s odebral(a) %2$s %1$s zrušil(a) vykázání %2$s @@ -28,7 +28,7 @@ (profilový obrázek byl také změněn) %1$s odstranili název místnosti %1$s odstranili téma místnosti - %1$s do této místnosti pozvali %2$s + %1$s do této místnosti pozval(a) %2$s %1$s přijali pozvání pro %2$s ** Nelze dešifrovat: %s ** Odesílatelovo zařízení nám neposlalo klíče pro tuto zprávu. @@ -40,7 +40,7 @@ %1$s a %2$s Prázdná místnost %s aktualizoval(a) tuto místnost. - %1$s zrušili pozvánku do místnosti pro %2$s + %1$s zrušil(a) pozvánku do místnosti pro %2$s Úvodní synchronizace: \nImportuji účet… Úvodní synchronizace: @@ -91,8 +91,8 @@ Odstranili jste téma místnosti %1$s odstranili obrázek místnosti Odstranili jste obrázek místnosti - Poslali jste %1$s pozvání ke vstupu do místnosti - Zrušili jste pozvánku ke vstupu do místnosti pro %1$s + Poslali jste %1$s pozvání do místnosti + Zrušili jste pozvánku do místnosti pro %1$s Přijali jste pozvání pro %1$s %1$s přidali widget %2$s Přidali jste widget %1$s @@ -177,7 +177,7 @@ Zpřístupnili jste budoucí zprávy pro %1$s %1$s zpřístupnil(a) budoucí zprávy pro %2$s Odešli jste z místnosti - Uživatel %1$s odešel z místnosti + %1$s opustil(a) místnost Vstoupili jste %1$s vstoupil(a) Založili jste diskusi @@ -3016,4 +3016,6 @@ Nejnovější aktualizace vylepšila zabezpečené zasílání zpráv. Znovu ověřte své zařízení. Dokud tento uživatel této relaci nedůvěřuje, jsou zprávy odesílané do ní a z ní označeny varováním. Aplikace aktualizována + Přesto se odhlásit + Nelze se spojit s domovským serverem. Pokud se přesto odhlásíte, nebude toto zařízení vymazáno ze seznamu zařízení, můžete jej odstranit pomocí jiného klienta. \ No newline at end of file From bb703f3935f02b1605da75074e21dd0a289b12f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Fri, 2 Jun 2023 10:03:59 +0000 Subject: [PATCH 080/234] Translated using Weblate (Estonian) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- library/ui-strings/src/main/res/values-et/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-et/strings.xml b/library/ui-strings/src/main/res/values-et/strings.xml index 25ef48029a..21ad8c2fd6 100644 --- a/library/ui-strings/src/main/res/values-et/strings.xml +++ b/library/ui-strings/src/main/res/values-et/strings.xml @@ -2956,4 +2956,6 @@ Turvalisele sõnumivahetusele on lisandunud palju täiendusi. Palun verifitseeri oma seade uuesti. Seni kuni nimetatud kasutaja usaldab seda sessiooni, kõik siit ja siia saadetud sõnumid on märgistatud hoiatusega. Rakendus on uuendatud + Jah, ikkagi logi välja + Ühendus koduserveriga puudub. Kui sa jätkad ja logid võrgust välja, siis seda seadet ei kustutata sinu seadmete loendist ning saad seda hiljem mõnest muust Matrixi kliendist teha. \ No newline at end of file From 29d1d5e4b777f4b6fc154cf4abb3eaf1f9a8a58b Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Fri, 2 Jun 2023 12:54:09 +0000 Subject: [PATCH 081/234] Translated using Weblate (Persian) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/ --- library/ui-strings/src/main/res/values-fa/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-fa/strings.xml b/library/ui-strings/src/main/res/values-fa/strings.xml index 6467330e38..fb5fd92f6b 100644 --- a/library/ui-strings/src/main/res/values-fa/strings.xml +++ b/library/ui-strings/src/main/res/values-fa/strings.xml @@ -2956,4 +2956,6 @@ پیام‌رسانی امن با جدیدترین به‌روز رسانی بهبود یافته است. لطفاً افزاره‌تان را دوباره تأیید کنید. تا کاربر این نشست را تأیید کند، پیام‌های فرستاده و گرفته‌اش با هشدار برچسب می‌خورند. کاره به‌روز شد + خروج به هر صورت + نمی‌توان به کارساز خانگی رسید. اگر همچنان خارج شوید این افزاره از سیاههٔ افزاره‌هایتان پاک نخواهد شد و باید از کارخواهس دیگر برش دارید. \ No newline at end of file From 4965be9961c0c6f77f52fd341498a3a2884618bb Mon Sep 17 00:00:00 2001 From: Glandos Date: Sat, 3 Jun 2023 09:28:09 +0000 Subject: [PATCH 082/234] Translated using Weblate (French) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/ --- library/ui-strings/src/main/res/values-fr/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-fr/strings.xml b/library/ui-strings/src/main/res/values-fr/strings.xml index 32cbbca34c..bf813ea8f1 100644 --- a/library/ui-strings/src/main/res/values-fr/strings.xml +++ b/library/ui-strings/src/main/res/values-fr/strings.xml @@ -2956,4 +2956,6 @@ La messagerie sécurisée a été améliorée avec la dernière mise-à-jour. Veuillez re-vérifier votre appareil. Jusqu’à ce que cet utilisateur fasse confiance à cette session, les messages sur cette session sont étiquetés avec des avertissements. Application mise-à-jour + Se déconnecter malgré tout + Impossible de joindre le serveur d’accueil. Si vous vous déconnectez malgré tout, cet appareil ne sera pas effacé de la liste de vos appareils, vous pourrez l’enlever en utilisant un autre client. \ No newline at end of file From 9007fafdf23a7dbb36602b6445f688ee8f880734 Mon Sep 17 00:00:00 2001 From: raspin0 Date: Fri, 2 Jun 2023 18:35:14 +0000 Subject: [PATCH 083/234] Translated using Weblate (Polish) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/ --- library/ui-strings/src/main/res/values-pl/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-pl/strings.xml b/library/ui-strings/src/main/res/values-pl/strings.xml index 75eb84c18d..31ab6c475d 100644 --- a/library/ui-strings/src/main/res/values-pl/strings.xml +++ b/library/ui-strings/src/main/res/values-pl/strings.xml @@ -3075,4 +3075,6 @@ Bezpieczne wysyłanie wiadomości zostało usprawnione z najnowszą aktualizacją. Zweryfikuj swoje urządzenie ponownie. Dopóki ten użytkownik nie zweryfikuje tej sesji, wysłane wiadomości będą zawierać ostrzeżenie. Zaktualizowano aplikację + Wyloguj mimo to + Nie można skontaktować się z serwerem domowym. Jeśli mimo to się wylogujesz, urządzenie nie zostanie usunięte z listy urządzeń. Usuń je za pomocą innego klienta. \ No newline at end of file From 840ca30d8ad8f3fdc66b6c11f6d97bcb253077dc Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Fri, 2 Jun 2023 20:30:56 +0000 Subject: [PATCH 084/234] Translated using Weblate (Slovak) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sk/ --- library/ui-strings/src/main/res/values-sk/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sk/strings.xml b/library/ui-strings/src/main/res/values-sk/strings.xml index 2103006ba7..7536c44cb7 100644 --- a/library/ui-strings/src/main/res/values-sk/strings.xml +++ b/library/ui-strings/src/main/res/values-sk/strings.xml @@ -3016,4 +3016,6 @@ Najnovšou aktualizáciou sa zlepšilo bezpečné zasielanie správ. Overte prosím znova svoje zariadenie. Pokiaľ tento používateľ tejto relácii nedôveruje, správy odoslané do nej a z nej sú označené varovaním. Aplikácia bola aktualizovaná + Aj tak sa odhlásiť + Nie je možné sa spojiť s domovským serverom. Ak sa aj tak odhlásite, toto zariadenie nebude vymazané zo zoznamu zariadení, môžete ho odstrániť pomocou iného klienta. \ No newline at end of file From 6c353d96a501e75f14b70d2cea133ca5527456cd Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Fri, 2 Jun 2023 11:38:02 +0000 Subject: [PATCH 085/234] Translated using Weblate (Albanian) Currently translated at 99.4% (2621 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sq/ --- library/ui-strings/src/main/res/values-sq/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sq/strings.xml b/library/ui-strings/src/main/res/values-sq/strings.xml index 5ce061a7cb..f79d418453 100644 --- a/library/ui-strings/src/main/res/values-sq/strings.xml +++ b/library/ui-strings/src/main/res/values-sq/strings.xml @@ -2943,4 +2943,6 @@ Rimerre Deri kur ky përdorues të besojë këtë sesion, mesazhet dërguar për të dhe nga ai etiketohem me sinjalizime. Aplikacioni u përditësua + Dil, sido qoftë + S’kapet dot shërbyesi Home. Nëse keni dalë, sido qoftë, kjo pajisje s’do të fshihet te lista e pajisjeve tuaja, mund të doni ta hiqni duke përdorur klient tjetër. \ No newline at end of file From 47da9c4534532ab60731010eaa37991cfa9804df Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Fri, 2 Jun 2023 17:28:19 +0000 Subject: [PATCH 086/234] Translated using Weblate (Ukrainian) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/ --- library/ui-strings/src/main/res/values-uk/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-uk/strings.xml b/library/ui-strings/src/main/res/values-uk/strings.xml index 4f6dbbf65a..a621db40b6 100644 --- a/library/ui-strings/src/main/res/values-uk/strings.xml +++ b/library/ui-strings/src/main/res/values-uk/strings.xml @@ -3076,4 +3076,6 @@ В останньому оновленні було вдосконалено захищений обмін повідомленнями. Перевірте свій пристрій ще раз. Поки користувач не довіряє цьому сеансу, повідомлення, надіслані до нього та від нього, позначаються попередженнями. Застосунок оновлено + Усе одно вийти + Не вдалося зв\'язатися з домашнім сервером. Якщо ви все одно вийдете з системи, цей пристрій не буде видалено з вашого списку пристроїв, можливо, ви захочете видалити його за допомогою іншого клієнта. \ No newline at end of file From 824f3802b2e02090ec0fe91563adb8fcc44cd3d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 08:27:17 +0000 Subject: [PATCH 087/234] Bump io.realm:realm-gradle-plugin from 10.15.1 to 10.16.0 (#8499) Bumps [io.realm:realm-gradle-plugin](https://github.com/realm/realm-java) from 10.15.1 to 10.16.0. - [Changelog](https://github.com/realm/realm-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/realm/realm-java/compare/v10.15.1...v10.16.0) --- updated-dependencies: - dependency-name: io.realm:realm-gradle-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- matrix-sdk-android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index e8d0b190c0..7420fba45e 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -17,7 +17,7 @@ buildscript { } } dependencies { - classpath "io.realm:realm-gradle-plugin:10.15.1" + classpath "io.realm:realm-gradle-plugin:10.16.0" } } From 07e06957ef14f90b47b7009cae42888408eb700f Mon Sep 17 00:00:00 2001 From: Yoan Pintas Date: Mon, 5 Jun 2023 22:02:11 +0200 Subject: [PATCH 088/234] Prompt the user when the invited MatrixId is not recognized (#8483) --- changelog.d/8468.bugfix | 1 + .../ui-strings/src/main/res/values/strings.xml | 4 ++++ .../createdirect/CreateDirectRoomActivity.kt | 15 ++++++++++++++- .../features/invite/InviteUsersToRoomActivity.kt | 15 ++++++++++++++- .../features/userdirectory/PendingSelection.kt | 2 +- .../features/userdirectory/UserListViewModel.kt | 4 ++++ .../features/userdirectory/UserListViewState.kt | 1 + 7 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 changelog.d/8468.bugfix diff --git a/changelog.d/8468.bugfix b/changelog.d/8468.bugfix new file mode 100644 index 0000000000..f250d48dc6 --- /dev/null +++ b/changelog.d/8468.bugfix @@ -0,0 +1 @@ +Prompt the user when the invited MatrixId is not recognized diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index ee7d2fea12..9f842a5741 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -1729,6 +1729,8 @@ "Public" "Anyone will be able to join this room" "The room has been created, but some invitations have not been sent for the following reason:\n\n%s" + Unable to find profiles for the Matrix IDs listed below. Would you like to start a chat anyway?\n\n%s + Start chat anyway "An error occurred getting trust info" "An error occurred getting keys backup data" @@ -2744,6 +2746,8 @@ Invitations sent to %1$s and %2$d more We could not invite users. Please check the users you want to invite and try again. + Unable to find profiles for the Matrix IDs listed below. Would you like to invite them anyway?\n\n%s + Invite anyway Scan a QR code Share my code diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt index fbddf815c6..faf4374d93 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt @@ -48,6 +48,7 @@ import im.vector.app.features.qrcode.QrCodeScannerEvents import im.vector.app.features.qrcode.QrCodeScannerFragment import im.vector.app.features.qrcode.QrCodeScannerViewModel import im.vector.app.features.qrcode.QrScannerArgs +import im.vector.app.features.userdirectory.PendingSelection import im.vector.app.features.userdirectory.UserListFragment import im.vector.app.features.userdirectory.UserListFragmentArgs import im.vector.app.features.userdirectory.UserListSharedAction @@ -160,7 +161,19 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { } private fun handleOnMenuItemSubmitClick(action: UserListSharedAction.OnMenuItemSubmitClick) { - viewModel.handle(CreateDirectRoomAction.PrepareRoomWithSelectedUsers(action.selections)) + val unknownUsers = action.selections.filter { it is PendingSelection.UserPendingSelection && it.isUnknownUser } + if (unknownUsers.isEmpty()) { + viewModel.handle(CreateDirectRoomAction.PrepareRoomWithSelectedUsers(action.selections)) + } else { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.dialog_title_confirmation) + .setMessage(getString(R.string.create_room_unknown_users_dialog_content, unknownUsers.joinToString("\n • ", " • ") { it.getMxId() })) + .setPositiveButton(R.string.create_room_unknown_users_dialog_submit) { _, _ -> + viewModel.handle(CreateDirectRoomAction.PrepareRoomWithSelectedUsers(action.selections)) + } + .setNegativeButton(R.string.action_cancel, null) + .show() + } } private fun renderCreateAndInviteState(state: Async) { diff --git a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt index 7f514d2ad2..c000efaef2 100644 --- a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt @@ -37,6 +37,7 @@ import im.vector.app.core.utils.onPermissionDeniedSnackbar import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.core.utils.toast import im.vector.app.features.contactsbook.ContactsBookFragment +import im.vector.app.features.userdirectory.PendingSelection import im.vector.app.features.userdirectory.UserListFragment import im.vector.app.features.userdirectory.UserListFragmentArgs import im.vector.app.features.userdirectory.UserListSharedAction @@ -94,7 +95,19 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() { } private fun handleOnMenuItemSubmitClick(action: UserListSharedAction.OnMenuItemSubmitClick) { - viewModel.handle(InviteUsersToRoomAction.InviteSelectedUsers(action.selections)) + val unknownUsers = action.selections.filter { it is PendingSelection.UserPendingSelection && it.isUnknownUser } + if (unknownUsers.isEmpty()) { + viewModel.handle(InviteUsersToRoomAction.InviteSelectedUsers(action.selections)) + } else { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.dialog_title_confirmation) + .setMessage(getString(R.string.invite_unknown_users_dialog_content, unknownUsers.joinToString("\n • ", " • ") { it.getMxId() })) + .setPositiveButton(R.string.invite_unknown_users_dialog_submit) { _, _ -> + viewModel.handle(InviteUsersToRoomAction.InviteSelectedUsers(action.selections)) + } + .setNegativeButton(R.string.action_cancel, null) + .show() + } } private fun openPhoneBook() { diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/PendingSelection.kt b/vector/src/main/java/im/vector/app/features/userdirectory/PendingSelection.kt index 643aa30995..7838b76452 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/PendingSelection.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/PendingSelection.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.api.util.toMatrixItem sealed class PendingSelection { - data class UserPendingSelection(val user: User) : PendingSelection() + data class UserPendingSelection(val user: User, var isUnknownUser: Boolean = false) : PendingSelection() data class ThreePidPendingSelection(val threePid: ThreePid) : PendingSelection() fun getBestName(): String { diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt index ae28ff020d..96875d73a5 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewModel.kt @@ -260,6 +260,7 @@ class UserListViewModel @AssistedInject constructor( .sortedBy { it.toMatrixItem().firstLetterOfDisplayName() } val userProfile = if (MatrixPatterns.isUserId(search)) { val user = tryOrNull { session.profileService().getProfileAsUser(search) } + setState { copy(unknownUserId = search.takeIf { user == null }) } User( userId = search, displayName = user?.displayName, @@ -284,6 +285,9 @@ class UserListViewModel @AssistedInject constructor( (action.pendingSelection is PendingSelection.UserPendingSelection && state.pendingSelections.last() is PendingSelection.UserPendingSelection) if (canSelectUser) { + if (action.pendingSelection is PendingSelection.UserPendingSelection) { + action.pendingSelection.isUnknownUser = action.pendingSelection.getMxId() == state.unknownUserId + } val selections = state.pendingSelections.toggle(action.pendingSelection, singleElement = state.singleSelection) setState { copy(pendingSelections = selections) } } diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt index ec932a2a57..27fa11bf54 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListViewState.kt @@ -30,6 +30,7 @@ data class UserListViewState( val matchingEmail: Async = Uninitialized, val filteredMappedContacts: List = emptyList(), val pendingSelections: Set = emptySet(), + val unknownUserId: String? = null, val searchTerm: String = "", val singleSelection: Boolean, val single3pidSelection: Boolean, From a70fba9f6aacee3fb41c1e42ae20c10af6484cb2 Mon Sep 17 00:00:00 2001 From: Vri Date: Sat, 3 Jun 2023 12:16:34 +0000 Subject: [PATCH 089/234] Translated using Weblate (German) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- library/ui-strings/src/main/res/values-de/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-de/strings.xml b/library/ui-strings/src/main/res/values-de/strings.xml index 08407f3bdd..334a1f45be 100644 --- a/library/ui-strings/src/main/res/values-de/strings.xml +++ b/library/ui-strings/src/main/res/values-de/strings.xml @@ -2955,4 +2955,6 @@ Verschlüsselte Kommunikation wurde mit der neuesten Aktualisierung verbessert. Bitte verifiziere deine Geräte erneut. Solange der Benutzer dieser Sitzung nicht vertraut, werden Nachrichten mit Warnungen versehen. App aktualisiert + Dein Heim-Server ist nicht erreichbar. Falls du dich dennoch abmeldest, wird dieses Gerät nicht von deiner Geräteliste entfernt, also müsstest du dies mit einer anderen Sitzung selbst machen. + Dennoch abmelden \ No newline at end of file From 06d30c3df26fce94544ee5516d88e0500fe2925b Mon Sep 17 00:00:00 2001 From: Linerly Date: Mon, 5 Jun 2023 06:24:33 +0000 Subject: [PATCH 090/234] Translated using Weblate (Indonesian) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/id/ --- library/ui-strings/src/main/res/values-in/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-in/strings.xml b/library/ui-strings/src/main/res/values-in/strings.xml index 02bf8e0200..c584ca793a 100644 --- a/library/ui-strings/src/main/res/values-in/strings.xml +++ b/library/ui-strings/src/main/res/values-in/strings.xml @@ -2898,4 +2898,6 @@ Di masa mendatang proses verifikasi ini akan dimutakhirkan. Perpesanan aman telah ditingkatkan dengan pembaruan terkini. Silakan verifikasi ulang perangkat Anda. Sampai pengguna ini mempercayai sesi ini, pesan yang dikirim dan diterima akan ditandai dengan peringatan. Aplikasi diperbarui + Tidak dapat mencapai homeserver. Jika Anda tetap keluar, perangkat ini tidak akan dihapus dari daftar perangkat. Anda dapat menghapusnya menggunakan klien lain. + Tetap keluar \ No newline at end of file From cc08bfd5001838ef516f9b3471604b1597349121 Mon Sep 17 00:00:00 2001 From: random Date: Mon, 5 Jun 2023 14:41:25 +0000 Subject: [PATCH 091/234] Translated using Weblate (Italian) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- library/ui-strings/src/main/res/values-it/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-it/strings.xml b/library/ui-strings/src/main/res/values-it/strings.xml index 67fcde35d6..0df7d9d6b0 100644 --- a/library/ui-strings/src/main/res/values-it/strings.xml +++ b/library/ui-strings/src/main/res/values-it/strings.xml @@ -2947,4 +2947,6 @@ Immagine del profilo dell\'utente %1$s Avatar della stanza %1$s Avatar dello spazio %1$s + Disconnetti comunque + Impossibile contattare l\'homeserver. Se ti disconnetti comunque, questo dispositivo non verrà cancellato dalla tua lista, meglio se lo rimuovi da un altro client. \ No newline at end of file From e4bff7555798fd1e046f9ca0572c425489d65133 Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Sat, 3 Jun 2023 19:12:00 +0000 Subject: [PATCH 092/234] Translated using Weblate (Swedish) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sv/ --- library/ui-strings/src/main/res/values-sv/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sv/strings.xml b/library/ui-strings/src/main/res/values-sv/strings.xml index 52cf1b1b25..3ec7b60778 100644 --- a/library/ui-strings/src/main/res/values-sv/strings.xml +++ b/library/ui-strings/src/main/res/values-sv/strings.xml @@ -2956,4 +2956,6 @@ Säker meddelandehantering har förbättrats med den senaste uppdateringen. Vänligen verifiera din enhet igen. Tills den här användaren litar på den här sessionen märks meddelanden som skickas till och från den med varningar. App uppdaterad + Kan inte nå hemservern. Om du ändå loggar ut kommer den här enheten inte att raderas från din enhetslista, du kanske vill ta bort den med en annan klient. + Logga ut ändå \ No newline at end of file From 8c63e872b998efff465ddfd3e7a96fcff0e95191 Mon Sep 17 00:00:00 2001 From: phardyle Date: Sat, 3 Jun 2023 13:08:57 +0000 Subject: [PATCH 093/234] Translated using Weblate (Chinese (Simplified)) Currently translated at 98.4% (2594 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hans/ --- .../src/main/res/values-zh-rCN/strings.xml | 114 ++++++++++-------- 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml index b0c008d4ae..33168cdc75 100644 --- a/library/ui-strings/src/main/res/values-zh-rCN/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rCN/strings.xml @@ -210,7 +210,7 @@ 请描述你遇到的问题。你做了什么?你期望发生什么?实际上发生了什么? 在这里描述你的问题 进度(%s%%) - 主服务器 URL + 家服务器 URL 登录 提交 错误的用户名和/或密码 @@ -256,7 +256,7 @@ 开始语音通话 开始视频通话 拍摄照片或视频 - 此主服务器想确认你不是机器人 + 此家服务器想确认你不是机器人 电子邮件地址验证失败:请确保你已点击邮件中的链接 原始 通话正在连接…… @@ -368,7 +368,7 @@ 公开名称 最近一次上线 %1$s @ %2$s - 主服务器 + 家服务器 身份服务器 实验室 通过和你其它会话里的用户设置对比以下内容来确认: @@ -501,7 +501,7 @@ \n \n要添加一些吗? 缺少一个必需参数。 - 要想继续使用主服务器 %1$s 你必须阅读并同意其服务条款。 + 要想继续使用家服务器 %1$s 你必须阅读并同意其服务条款。 现在阅读 下载 发送语音消息 @@ -535,13 +535,13 @@ 联系你的服务管理员 本服务器其中一项资源已超出限制,部分用户将无法登录 本服务器其中一项资源已超出限制。 - " 此主服务器已达到其每月活跃用户限制,因此<b>某些用户将无法登录</b>。" - 此主服务器已达到其每月活跃用户限制。 + " 此家服务器已达到其每月活跃用户限制,因此<b>某些用户将无法登录</b>。" + 此家服务器已达到其每月活跃用户限制。 请 %s 以继续使用本服务。 请 %s 以增加此限制的额度。 接受 错误 - 请审阅并接受此主服务器的政策: + 请审阅并接受此家服务器的政策: 通话 为来电使用 ${app_name} 的默认铃声 来电铃声 @@ -580,15 +580,15 @@ FCM令牌获取失败: \n%1$s 注册令牌 - FCM令牌已成功注册至主服务器。 - 未能将FCM令牌注册到主服务器: + FCM令牌已成功注册至家服务器。 + 未能将FCM令牌注册到家服务器: \n %1$s 启动系统相机而非自定义的相机屏幕。 开机时启动 启用开机时启动 检查后台限制 电池优化 - 当主服务器支持此功能时,在聊天中预览链接。 + 当家服务器支持此功能时,在聊天中预览链接。 发送正在输入通知 让房间中的其他用户知道你正在输入。 Markdown 格式化 @@ -669,7 +669,7 @@ (高级) 手动导出密钥 使用口令词组保护你的备份。 - 我们将会在主服务器上为你的密钥保存一份加密拷贝。设置一个口令词组来保护你的备份的安全。 + 我们将会在家服务器上为你的密钥保存一份加密拷贝。设置一个口令词组来保护你的备份的安全。 \n \n为了最大的安全性,此口令词组应当与你的账户密码不同。 设置口令词组 @@ -829,7 +829,7 @@ 断开连接 拒绝 这不是有效的 Matrix 服务器地址 - 无法在此 URL 找到主服务器,请检查 + 无法在此 URL 找到家服务器,请检查 播放 忽略 复制 @@ -837,7 +837,7 @@ 通知 ${app_name} 呼叫失败 无法建立实时连接。 -\n请让你的主服务器的管理员配置一个 TURN 服务器,以便呼叫能够可靠地工作。 +\n请让你的家服务器的管理员配置一个 TURN 服务器,以便呼叫能够可靠地工作。 选择声音设备 电话 扬声器 @@ -928,13 +928,13 @@ 读取受 DRM 保护的媒体 若要继续请接受服务条款。 恢复密钥已保存。 - 你的主服务器上已存在备份 + 你的家服务器上已存在备份 你似乎已在另一个会话中设置密钥备份。你想要将其替换为正在创建的吗? 安全备份 保护加密消息及数据的访问权 设置安全备份 你未使用身份服务器 - 你似乎正在试图连接到另一个主服务器。你想要登出吗? + 你似乎正在试图连接到另一个家服务器。你想要登出吗? 你已经跟上了! 你没有未读消息 你的私聊消息将显示在此处。点击右下角的 + 开始一些对话。 @@ -1008,7 +1008,7 @@ 同意身份服务器 (%s) 服务条款使你可以通过电子邮件地址或电话号码被发现。 启用详细日志。 详细日志将通过在你发送愤怒摇动(RageShake)时提供更多日志来帮助开发人员。即使启用,应用程序也不会记录消息内容或任何其他私人数据。 - 接收你的主服务器条款和条件后请重试。 + 接收你的家服务器条款和条件后请重试。 服务器似乎响应时间太长,这可能是由于连接不良或服务器错误引起的。请稍后再试。 发送附件 打开导航菜单 @@ -1098,7 +1098,7 @@ 输入 Modular Element 或你想使用的服务器地址 输入你想使用的服务器的地址 载入页面时出错:%1$s (%2$d) - 应用无法登录到此主服务器。主服务器支持以下登录类型:%1$s。 + 应用无法登录到此家服务器。家服务器支持以下登录类型:%1$s。 \n \n你想要通过网页客户端登录吗? 抱歉,此服务器不接受新账户。 @@ -1155,24 +1155,24 @@ 你的账户尚未创建。是否中止注册过程? 选择 matrix.org 选择 Element Matrix Services - 选择自定义主服务器 + 选择自定义家服务器 请进行人机验证 接受条款以继续 请检查你的电子邮件 我们向 %1$s 发送了电子邮件。 \n请点击其中包含的链接继续账户创建。 输入的验证码不正确。请检查。 - 过时的主服务器 + 过时的家服务器 发送了太多请求。你可以在 %1$d 秒后重试… 使用 Matrix ID 登录 使用 Matrix ID 登录 - 如果你在主服务器上设置了账户,在下方使用你的 Matrix ID(例 @user:domain.com)和密码。 + 如果你在家服务器上设置了账户,在下方使用你的 Matrix ID(例 @user:domain.com)和密码。 Matrix ID 如果你不知道你的密码,返回并重置。 这不是有效的用户标识符。预期格式:\'@user:homeserver.org\' - 无法找到有效的主服务器。请检查你的标识符 + 无法找到有效的家服务器。请检查你的标识符 你已登出 这可能由于多种原因: \n @@ -1184,7 +1184,7 @@ 重新登录 你已登出 登录 - 你的主服务器 (%1$s) 管理员将你从你的账户 %2$s (%3$s) 登出。 + 你的家服务器 (%1$s) 管理员将你从你的账户 %2$s (%3$s) 登出。 登录以恢复仅存储在此设备上的加密密钥。 你需要使用它们在任何设备上阅读所有安全消息。 登录 密码 @@ -1225,8 +1225,8 @@ 不安全 以下其中一项可能会受到威胁: \n -\n - 你的主服务器 -\n - 你验证的用户连接到的主服务器 +\n - 你的家服务器 +\n - 你验证的用户连接到的家服务器 \n - 你或其他用户的网络连接 \n - 你或其他用户的设备 视频。 @@ -1347,7 +1347,7 @@ 确认移除 你确定要移除(删除)此事件吗?注意,如果删除房间名称或话题的更改,更改会被撤销。 附加理由 - 编辑理由 + 删除理由 事件被用户删除,理由:%1$s ${app_name} Android 密钥请求 @@ -1363,7 +1363,7 @@ 以下其中一项可能有风险: \n \n- 你的密码 -\n- 你的主服务器 +\n- 你的家服务器 \n- 此设备或其它设备 \n- 设备使用的网络连接 \n @@ -1396,7 +1396,7 @@ 输入关键字以查找反应。 已读 跳至已读回执 - 事件被房间管理员调整,理由:%1$s + 事件被房间管理员删除,理由:%1$s 密钥已是最新! 保存到优盘或者备份盘 复制到你的个人云存储 @@ -1487,13 +1487,13 @@ 打开 %s 条款 是否从身份服务器 %s 断开? 身份服务器已过期。${app_name} 仅支持 API V2。 - 无法执行此操作。主服务器已过期。 + 无法执行此操作。家服务器已过时。 请先配置身份服务器。 请先在设置中接受身份服务器的条款。 为了你的隐私,${app_name}仅支持发送经过哈希处理的用户电子邮件的和电话号码。 关联失败。 当前与此标识符没有关联。 - 你的主服务器(%1$s)建议使用 %2$s 作为你的身份服务器 + 你的家服务器(%1$s)建议使用 %2$s 作为你的身份服务器 使用 %1$s 或者,你可以输入任何其它身份服务器网址 输入身份服务器 URL @@ -1632,7 +1632,7 @@ \n \n你的消息受加密保护,并且只有你和消息接收者拥有唯一解密密钥。 此处的消息未经端到端加密。 - 此主服务器正在运行旧版本。 请让你的主服务器管理员升级。 你可以继续,但某些功能可能无法正常工作。 + 此家服务器正在运行旧版本。 请让你的家服务器管理员升级。 你可以继续,但某些功能可能无法正常工作。 你将此房间设为仅邀请。 %1$s 仅发出此邀请。 在加密房间显示完整历史 @@ -1690,7 +1690,7 @@ 一些字符不被允许 请提供一个房间地址 此地址已被使用 - 若房间仅用于与你的主服务器上的内部团队协作,则你可以启用此选项。此选项之后无法更改。 + 若房间仅用于与你的家服务器上的内部团队协作,则你可以启用此选项。此选项之后无法更改。 阻止任何不属于%s的人加入此房间 隐藏高级 显示高级 @@ -1726,7 +1726,7 @@ 发布此地址 添加本地地址 此房间没有本地地址 - 为此房间设置地址以便用户通过你的主服务器(%1$s)找到此房间 + 为此房间设置地址以便用户通过你的家服务器(%1$s)找到此房间 本地地址 新的发布的地址(例如 #alias:server) 尚无其它已发布地址。 @@ -1858,8 +1858,8 @@ 有些房间可能被隐藏,因为其为私有房间,你需要得到邀请。 \n你没有权限添加房间。 此空间没有房间 - 请联系你的主服务器管理员以取得进一步资讯 - 看来你的主服务器尚未支持空间 + 请联系你的家服务器管理员以取得进一步资讯 + 看来你的家服务器尚未支持空间 想要使用实验功能? \n你可以将现有的空间添加到其它空间中。 管理房间和空间 @@ -1882,7 +1882,7 @@ 你认识的 %d 个人已加入 此别名当前无法被访问。 -\n请稍后再试,或询问房间管理员你身份有权访问。 +\n请稍后再试,或询问房间管理员你是否有权访问。 依然加入 加入空间 创建空间 @@ -1954,7 +1954,7 @@ 发送原始大小的视频 限制未知。 - 你的主服务器能接受大小最大为 %s 的附件(文件、媒体等)。 + 你的家服务器能接受大小最大为 %s 的附件(文件、媒体等)。 服务器文件上传限制 此文件过大,无法上传。 搜索名称 @@ -2028,7 +2028,7 @@ 查看和管理这个空间的地址。 空间地址 升级到推荐的房间版本 - 这个房间运行房间版本 %s,此主服务器已将其标记为不稳定。 + 这个房间运行房间版本 %s,此家服务器已将其标记为不稳定。 你需要权限才能升级房间 自动更新空间父级 自动邀请用户 @@ -2048,7 +2048,7 @@ 通过比较表情符号来验证 使用此设备扫描 使用其它设备扫码或切换并使用本设备扫码 - 主服务器 API 网址 + 家服务器API URL 缺少权限 要执行此操作,请从系统设置中授予相机权限。 缺少执行此操作的某些权限,请从系统设置中授予权限。 @@ -2200,8 +2200,8 @@ 离开 离线 在线 - 选择主服务器 - 无法访问 URL %s 上的主服务器。请检查你的链接或手动选择一个主服务器。 + 选择家服务器 + 无法访问 URL %s 上的家服务器。请检查你的链接或手动选择一个家服务器。 侦听通知 需要至少 %1$s 个选项 @@ -2252,7 +2252,7 @@ 第三方库 你的身份服务器政策 我们记录任何账户数据或绘制任何账户数据的画像 - 你的主服务器政策 + 你的家服务器政策 ${app_name} 政策 你可以随时在设置中关闭它 我们与第三方共享信息 @@ -2419,7 +2419,7 @@ 选择保存你的对话的位置,给予你控制权和独立性。通过 Matrix 连接。 安全且独立的通信,为你提供和在家中面对面对话同样等级的隐私。 安全传送消息。 - 向主服务器注册端点token失败: + 向家服务器注册端点token失败: \n%1$s 消息列有助于使你的对话保持话题并易于跟踪。%s 创建消息列将刷新应用程序。对于某些账户,这可能需要更长的时间。 重启应用以使更改生效。 @@ -2444,7 +2444,7 @@ 无法启用生物特征识别。 生物特征识别被禁用,因为最近添加了新的生物特征识别方法。 你可以在“设置”中再次启用它。 - 主服务器不接收仅有数字的用户名。 + 家服务器不接收仅有数字的用户名。 发送你的第一条消息邀请%s聊天 加密配置错误 此聊天中的消息会端到端加密。 @@ -2504,9 +2504,9 @@ \n \n注意,此操作会重启应用并可能需要一些时间。 自动播放动画图片 - 端点成功注册到主服务器。 + 端点成功注册到家服务器。 端点注册 - 你的主服务器当前不支持消息列,因此此功能可能不可靠。某些消息列的消息可能无法可靠地使用。 %s 你仍然要启用消息列吗? + 你的家服务器当前不支持消息列,因此此功能可能不可靠。某些消息列的消息可能无法可靠地使用。 %s 你仍然要启用消息列吗? Threads接近Beta了 🎉 来自消息列 实用提示:长按消息并使用“%s”。 @@ -2544,7 +2544,7 @@ %1$s 和 %2$s 电子邮件未验证,请检查你的收件箱 无法加载地图 -\n此主服务器可能没有设置好显示地图。 +\n此家服务器可能没有设置显示地图。 打开设置 全部聊天 为获得最佳安全性,请验证你的会话,并从任何你不认识或不再使用的会话登出。 @@ -2712,7 +2712,7 @@ 选择“显示QR码” 转到设置 -> 安全和隐私 在你的其它设备上打开应用程序 - 主服务器不支持QR码登录。 + 家服务器不支持QR码登录。 登录已在另一台设备上取消。 该QR码无效。 另一台设备必须登录。 @@ -2826,4 +2826,24 @@ %1$s更改了其显示名称为%2$s 账户 是的,停止 + 无法连接家服务器。若仍登出,此设备将不会从设备列表擦除,你或许想用另一个客户端移除它。 + 无论如何都要登出 + 你的家服务器还不支持列出消息列。 + 空间%1$s的头像 + 房间%1$s的头像 + 用户%1$s的用户资料图片 + 可接受的使用政策 + 正在等待用户加入${app_name} + 正从安全密钥或短语验证…… + 投票历史 + 应用已更新 + 验证你的身份以访问加密消息并向他人证明你的身份。 + 发送至和发送自此会话的消息带有警告标签,直至此用户信任此会话。 + 更新你的通知偏好时出错。请再试一次。 + 你的账户详细信息于%1$s单独管理。 + 加密版本 + 用另一设备验证 + 你一次仅能邀请一个电子邮件 + 开始语音广播 + 继续 \ No newline at end of file From f7dd492adc2e5e4eed520530e339430982b5b680 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Mon, 5 Jun 2023 01:52:15 +0000 Subject: [PATCH 094/234] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- library/ui-strings/src/main/res/values-zh-rTW/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml index 8083e112b4..8a82ee8a96 100644 --- a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml @@ -2896,4 +2896,6 @@ 最新更新改善了安全訊息傳遞。請重新驗證您的裝置。 在該使用者信任該工作階段之前,發送到該工作階段與從該工作階段傳送的訊息都帶有警告標籤。 應用程式已更新 + 無法連線至家伺服器。若您仍要登出,此裝置將不會從您的裝置清單中移除,您可能需要使用其他客戶端來移除。 + 仍要登出 \ No newline at end of file From a8d8176d97487db780c49c217629b122baa89016 Mon Sep 17 00:00:00 2001 From: phardyle Date: Sun, 4 Jun 2023 03:18:08 +0000 Subject: [PATCH 095/234] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/ --- library/ui-strings/src/main/res/values-zh-rTW/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml index 8a82ee8a96..8c51b44395 100644 --- a/library/ui-strings/src/main/res/values-zh-rTW/strings.xml +++ b/library/ui-strings/src/main/res/values-zh-rTW/strings.xml @@ -1301,9 +1301,9 @@ 確認移除 您確定要刪除此事件嗎?注意,如果您刪除聊天室名稱或主題的變更事件,該變更將被取消。 包含理由 - 修改原因 + 刪除原因 使用者刪除事件,理由:%1$s - 聊天室管理員管理了事件,理由:%1$s + 聊天室管理員刪除了事件,理由:%1$s 金鑰已為最新! ${app_name} Android 金鑰請求 From 551d559be180c2e2b196841a69b5760c353f3239 Mon Sep 17 00:00:00 2001 From: Vri Date: Sat, 3 Jun 2023 12:07:29 +0000 Subject: [PATCH 096/234] Translated using Weblate (German) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/de/ --- fastlane/metadata/android/de-DE/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/de-DE/changelogs/40106020.txt diff --git a/fastlane/metadata/android/de-DE/changelogs/40106020.txt b/fastlane/metadata/android/de-DE/changelogs/40106020.txt new file mode 100644 index 0000000000..80ee810eec --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Die wichtigsten Änderungen in dieser Version: Element Android nutzt nun das Crypto-Rust-SDK. +Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases From 65175106da8e4d6e91a215c4733c21742d5ee6cf Mon Sep 17 00:00:00 2001 From: Glandos Date: Sun, 4 Jun 2023 14:56:10 +0000 Subject: [PATCH 097/234] Translated using Weblate (French) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fr/ --- fastlane/metadata/android/fr-FR/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/fr-FR/changelogs/40106020.txt diff --git a/fastlane/metadata/android/fr-FR/changelogs/40106020.txt b/fastlane/metadata/android/fr-FR/changelogs/40106020.txt new file mode 100644 index 0000000000..7e04ed8f3c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Element Android utilise désormais le SDK cryptographique en Rust. +Intégralité des changements : https://github.com/vector-im/element-android/releases From e35ec86930784075ba178ffdef27c995667f05c0 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Sat, 3 Jun 2023 21:39:31 +0000 Subject: [PATCH 098/234] Translated using Weblate (Slovak) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sk/ --- fastlane/metadata/android/sk/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sk/changelogs/40106020.txt diff --git a/fastlane/metadata/android/sk/changelogs/40106020.txt b/fastlane/metadata/android/sk/changelogs/40106020.txt new file mode 100644 index 0000000000..bb76d77ad5 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Element Android teraz používa Crypto Rust SDK. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases From acdaec42c3e351630e7a759bf98c095b676a366e Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Sat, 3 Jun 2023 19:11:25 +0000 Subject: [PATCH 099/234] Translated using Weblate (Swedish) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sv/ --- fastlane/metadata/android/sv-SE/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sv-SE/changelogs/40106020.txt diff --git a/fastlane/metadata/android/sv-SE/changelogs/40106020.txt b/fastlane/metadata/android/sv-SE/changelogs/40106020.txt new file mode 100644 index 0000000000..215691cf4b --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Element Android använder nu Rust-krypto-SDK:t +Full ändringslogg: https://github.com/vector-im/element-android/releases From 93a93c5295439fb4dc16a15b1c866d0f24a1e506 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Sun, 4 Jun 2023 22:19:59 +0000 Subject: [PATCH 100/234] Translated using Weblate (Ukrainian) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/uk/ --- fastlane/metadata/android/uk/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/uk/changelogs/40106020.txt diff --git a/fastlane/metadata/android/uk/changelogs/40106020.txt b/fastlane/metadata/android/uk/changelogs/40106020.txt new file mode 100644 index 0000000000..0066e0c597 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Element Android тепер використовує Crypto Rust SDK. +Перелік усіх змін: https://github.com/vector-im/element-android/releases From bb5a65cb60d49d55b4c3bbb90719b237ab202441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Mon, 5 Jun 2023 06:49:32 +0000 Subject: [PATCH 101/234] Translated using Weblate (Estonian) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/et/ --- fastlane/metadata/android/et/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/et/changelogs/40106020.txt diff --git a/fastlane/metadata/android/et/changelogs/40106020.txt b/fastlane/metadata/android/et/changelogs/40106020.txt new file mode 100644 index 0000000000..233a4a0cdd --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: Element Android krüptoteekideks on nüüd Crypto Rust SDK. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases From b5f1941ae4595a8937b013e021d5a0bc86ed987a Mon Sep 17 00:00:00 2001 From: random Date: Mon, 5 Jun 2023 14:41:45 +0000 Subject: [PATCH 102/234] Translated using Weblate (Italian) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/it/ --- fastlane/metadata/android/it-IT/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/it-IT/changelogs/40106020.txt diff --git a/fastlane/metadata/android/it-IT/changelogs/40106020.txt b/fastlane/metadata/android/it-IT/changelogs/40106020.txt new file mode 100644 index 0000000000..2e8ef554e1 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: Element Android ora utilizza l'SDK Rust Crypto. +Cronologia completa: https://github.com/vector-im/element-android/releases From fabde93481c22c9d2ca6e5d74f3d70a4ba61cddc Mon Sep 17 00:00:00 2001 From: Danial Behzadi Date: Sat, 3 Jun 2023 19:54:46 +0000 Subject: [PATCH 103/234] Translated using Weblate (Persian) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/fa/ --- fastlane/metadata/android/fa/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/fa/changelogs/40106020.txt diff --git a/fastlane/metadata/android/fa/changelogs/40106020.txt b/fastlane/metadata/android/fa/changelogs/40106020.txt new file mode 100644 index 0000000000..1482b03042 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40106020.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: المنت اندروید اکنون از SDK راست Crypto استفاده می‌کند. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases From ebb05484a53adaaeb95515a158511f2d0b808724 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Sun, 4 Jun 2023 15:30:17 +0000 Subject: [PATCH 104/234] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/zh_Hant/ --- fastlane/metadata/android/zh-TW/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/zh-TW/changelogs/40106020.txt diff --git a/fastlane/metadata/android/zh-TW/changelogs/40106020.txt b/fastlane/metadata/android/zh-TW/changelogs/40106020.txt new file mode 100644 index 0000000000..0ee6434a8d --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40106020.txt @@ -0,0 +1,2 @@ +此版本的主要變更:現在起,Element Android 使用 Crypto Rust SDK。 +完整異動:https://github.com/vector-im/element-android/releases From 961ea9a8e0e48e048d7c29726791d462bd353063 Mon Sep 17 00:00:00 2001 From: Someone Date: Sun, 4 Jun 2023 03:49:09 +0000 Subject: [PATCH 105/234] Translated using Weblate (Vietnamese) Currently translated at 56.0% (56 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/vi/ --- fastlane/metadata/android/vi/changelogs/40103020.txt | 4 ++-- fastlane/metadata/android/vi/changelogs/40103030.txt | 4 ++-- fastlane/metadata/android/vi/changelogs/40103040.txt | 4 ++-- fastlane/metadata/android/vi/changelogs/40103050.txt | 2 ++ fastlane/metadata/android/vi/changelogs/40103060.txt | 2 ++ fastlane/metadata/android/vi/changelogs/40105080.txt | 2 ++ fastlane/metadata/android/vi/changelogs/40105100.txt | 2 ++ fastlane/metadata/android/vi/changelogs/40105110.txt | 2 ++ fastlane/metadata/android/vi/changelogs/40105120.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105130.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105140.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105160.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105180.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105200.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105220.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105240.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105250.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105260.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105280.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105300.txt | 2 +- fastlane/metadata/android/vi/changelogs/40105320.txt | 2 +- fastlane/metadata/android/vi/changelogs/40106000.txt | 2 ++ fastlane/metadata/android/vi/changelogs/40106010.txt | 2 ++ fastlane/metadata/android/vi/changelogs/40106020.txt | 2 ++ 24 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 fastlane/metadata/android/vi/changelogs/40103050.txt create mode 100644 fastlane/metadata/android/vi/changelogs/40103060.txt create mode 100644 fastlane/metadata/android/vi/changelogs/40105080.txt create mode 100644 fastlane/metadata/android/vi/changelogs/40105100.txt create mode 100644 fastlane/metadata/android/vi/changelogs/40105110.txt create mode 100644 fastlane/metadata/android/vi/changelogs/40106000.txt create mode 100644 fastlane/metadata/android/vi/changelogs/40106010.txt create mode 100644 fastlane/metadata/android/vi/changelogs/40106020.txt diff --git a/fastlane/metadata/android/vi/changelogs/40103020.txt b/fastlane/metadata/android/vi/changelogs/40103020.txt index 33a81f4a5d..d2eafcb2c6 100644 --- a/fastlane/metadata/android/vi/changelogs/40103020.txt +++ b/fastlane/metadata/android/vi/changelogs/40103020.txt @@ -1,2 +1,2 @@ -Những thay đổi chính trong phiên bản này: Thêm hỗ trợ Android Auto. Sửa rất nhiều lỗi! -Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.2 +Thay đổi chính trong phiên bản này: Hỗ trợ Android Auto. Sửa rất nhiều lỗi! +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases/tag/v1.3.2 diff --git a/fastlane/metadata/android/vi/changelogs/40103030.txt b/fastlane/metadata/android/vi/changelogs/40103030.txt index a36a3bb46d..91bab8d655 100644 --- a/fastlane/metadata/android/vi/changelogs/40103030.txt +++ b/fastlane/metadata/android/vi/changelogs/40103030.txt @@ -1,2 +1,2 @@ -Những thay đổi chính trong phiên bản này: Hiển thị (các) chính sách máy chủ xác thực trong phần cài đặt. Tạm thời bỏ hỗ trợ Android Auto. -Log thay đổi đầy đủ: https://github.com/vector-im/element-android/releases/tag/v1.3.3 +Thay đổi chính trong phiên bản này: Hiển thị (các) chính sách máy chủ định danh trong phần cài đặt. Tạm thời bỏ hỗ trợ Android Auto. +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases/tag/v1.3.3 diff --git a/fastlane/metadata/android/vi/changelogs/40103040.txt b/fastlane/metadata/android/vi/changelogs/40103040.txt index a1f6a8b22e..f6217c143b 100644 --- a/fastlane/metadata/android/vi/changelogs/40103040.txt +++ b/fastlane/metadata/android/vi/changelogs/40103040.txt @@ -1,2 +1,2 @@ -Những thay đổi chính trong phiên bản này: Thêm hỗ trợ hiển thị, cho phòng Tin nhắn Trực tiếp (lưu ý: hiển thị bị vô hiệu hóa trên matrix.org. Hỗ trợ Android Auto trở lại. -Nhật ký thay đổi: https://github.com/vector-im/element-android/releases/tag/v1.3.4 +Thay đổi chính trong phiên bản này: Hỗ trợ trạng thái, cho các phòng nhắn tin trực tiếp (ghi chú: trạng thái bị vô hiệu trên matrix.org). Hỗ trợ Android Auto trở lại. +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases/tag/v1.3.4 diff --git a/fastlane/metadata/android/vi/changelogs/40103050.txt b/fastlane/metadata/android/vi/changelogs/40103050.txt new file mode 100644 index 0000000000..64f0b89929 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40103050.txt @@ -0,0 +1,2 @@ +Thay đổi chính trong phiên bản này: Hỗ trợ trạng thái, cho các phòng nhắn tin trực tiếp (ghi chú: trạng thái bị vô hiệu trên matrix.org). Hỗ trợ Android Auto trở lại. +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases/tag/v1.3.5 diff --git a/fastlane/metadata/android/vi/changelogs/40103060.txt b/fastlane/metadata/android/vi/changelogs/40103060.txt new file mode 100644 index 0000000000..7ee925059e --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40103060.txt @@ -0,0 +1,2 @@ +Thay đổi chính trong phiên bản này: Hỗ trợ trạng thái, cho các phòng nhắn tin trực tiếp (ghi chú: trạng thái bị vô hiệu trên matrix.org). Hỗ trợ Android Auto trở lại. +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases/tag/v1.3.6 diff --git a/fastlane/metadata/android/vi/changelogs/40105080.txt b/fastlane/metadata/android/vi/changelogs/40105080.txt new file mode 100644 index 0000000000..b2f91aeb98 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40105080.txt @@ -0,0 +1,2 @@ +Thay đổi chính trong phiên bản này: Sửa lỗi và cải thiện. +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105100.txt b/fastlane/metadata/android/vi/changelogs/40105100.txt new file mode 100644 index 0000000000..caba6b7927 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40105100.txt @@ -0,0 +1,2 @@ +Thay đổi chính trong phiên bản này: Triển khai chế độ toàn màn hình mới cho trình soạn thảo văn bản phong phú và sửa lỗi. +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105110.txt b/fastlane/metadata/android/vi/changelogs/40105110.txt new file mode 100644 index 0000000000..caba6b7927 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40105110.txt @@ -0,0 +1,2 @@ +Thay đổi chính trong phiên bản này: Triển khai chế độ toàn màn hình mới cho trình soạn thảo văn bản phong phú và sửa lỗi. +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105120.txt b/fastlane/metadata/android/vi/changelogs/40105120.txt index 803f1d99bd..ef2d600e1e 100644 --- a/fastlane/metadata/android/vi/changelogs/40105120.txt +++ b/fastlane/metadata/android/vi/changelogs/40105120.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Chức năng chủ đề được bật theo mặc định. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105130.txt b/fastlane/metadata/android/vi/changelogs/40105130.txt index 803f1d99bd..ef2d600e1e 100644 --- a/fastlane/metadata/android/vi/changelogs/40105130.txt +++ b/fastlane/metadata/android/vi/changelogs/40105130.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Chức năng chủ đề được bật theo mặc định. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105140.txt b/fastlane/metadata/android/vi/changelogs/40105140.txt index 803f1d99bd..ef2d600e1e 100644 --- a/fastlane/metadata/android/vi/changelogs/40105140.txt +++ b/fastlane/metadata/android/vi/changelogs/40105140.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Chức năng chủ đề được bật theo mặc định. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105160.txt b/fastlane/metadata/android/vi/changelogs/40105160.txt index 803f1d99bd..ef2d600e1e 100644 --- a/fastlane/metadata/android/vi/changelogs/40105160.txt +++ b/fastlane/metadata/android/vi/changelogs/40105160.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Chức năng chủ đề được bật theo mặc định. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105180.txt b/fastlane/metadata/android/vi/changelogs/40105180.txt index 803f1d99bd..ef2d600e1e 100644 --- a/fastlane/metadata/android/vi/changelogs/40105180.txt +++ b/fastlane/metadata/android/vi/changelogs/40105180.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Chức năng chủ đề được bật theo mặc định. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105200.txt b/fastlane/metadata/android/vi/changelogs/40105200.txt index 4ec1289898..eda4b66d50 100644 --- a/fastlane/metadata/android/vi/changelogs/40105200.txt +++ b/fastlane/metadata/android/vi/changelogs/40105200.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Hầu hết là sửa lỗi. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105220.txt b/fastlane/metadata/android/vi/changelogs/40105220.txt index ab503fd458..881cf0601f 100644 --- a/fastlane/metadata/android/vi/changelogs/40105220.txt +++ b/fastlane/metadata/android/vi/changelogs/40105220.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Hầu hết là cải thiện chức năng phát thanh. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105240.txt b/fastlane/metadata/android/vi/changelogs/40105240.txt index 8ea7cb0c54..302e0ed184 100644 --- a/fastlane/metadata/android/vi/changelogs/40105240.txt +++ b/fastlane/metadata/android/vi/changelogs/40105240.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Hầu hết là sửa lỗi, cụ thể là sửa lỗi khiến cho tin nhắn không xuất hiện trên dòng thời gian. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105250.txt b/fastlane/metadata/android/vi/changelogs/40105250.txt index 8ea7cb0c54..302e0ed184 100644 --- a/fastlane/metadata/android/vi/changelogs/40105250.txt +++ b/fastlane/metadata/android/vi/changelogs/40105250.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Hầu hết là sửa lỗi, cụ thể là sửa lỗi khiến cho tin nhắn không xuất hiện trên dòng thời gian. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105260.txt b/fastlane/metadata/android/vi/changelogs/40105260.txt index e9ca191393..124a0f504c 100644 --- a/fastlane/metadata/android/vi/changelogs/40105260.txt +++ b/fastlane/metadata/android/vi/changelogs/40105260.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Chủ yếu là sửa lỗi. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105280.txt b/fastlane/metadata/android/vi/changelogs/40105280.txt index e9ca191393..124a0f504c 100644 --- a/fastlane/metadata/android/vi/changelogs/40105280.txt +++ b/fastlane/metadata/android/vi/changelogs/40105280.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Chủ yếu là sửa lỗi. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105300.txt b/fastlane/metadata/android/vi/changelogs/40105300.txt index 374a609262..617b41c00b 100644 --- a/fastlane/metadata/android/vi/changelogs/40105300.txt +++ b/fastlane/metadata/android/vi/changelogs/40105300.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Liên kết cố định tới các phòng, spaces, người dùng và tin nhắn giờ được hiển thị hình viên thuốc. Chúng tôi cũng đã sửa một số vấn đề với những nhãn dãn (sticker) tùy chỉnh và thanh đánh dấu đã đọc bị kẹt ở quá khứ. -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40105320.txt b/fastlane/metadata/android/vi/changelogs/40105320.txt index 57963d522b..d66fe4802d 100644 --- a/fastlane/metadata/android/vi/changelogs/40105320.txt +++ b/fastlane/metadata/android/vi/changelogs/40105320.txt @@ -1,2 +1,2 @@ Thay đổi chính trong phiên bản này: Chủ yếu là sửa lỗi -Toàn bộ nhật ký thay đổi: https://github.com/vector-im/element-android/releases +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40106000.txt b/fastlane/metadata/android/vi/changelogs/40106000.txt new file mode 100644 index 0000000000..08b7503d74 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40106000.txt @@ -0,0 +1,2 @@ +Thay đổi chính trong phiên bản này: Element Android giờ dùng công cụ phát triển phần mềm Rust cho mã hóa +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40106010.txt b/fastlane/metadata/android/vi/changelogs/40106010.txt new file mode 100644 index 0000000000..08b7503d74 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40106010.txt @@ -0,0 +1,2 @@ +Thay đổi chính trong phiên bản này: Element Android giờ dùng công cụ phát triển phần mềm Rust cho mã hóa +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/vi/changelogs/40106020.txt b/fastlane/metadata/android/vi/changelogs/40106020.txt new file mode 100644 index 0000000000..08b7503d74 --- /dev/null +++ b/fastlane/metadata/android/vi/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Thay đổi chính trong phiên bản này: Element Android giờ dùng công cụ phát triển phần mềm Rust cho mã hóa +Toàn bộ nhật ký sửa đổi: https://github.com/vector-im/element-android/releases From 8cd716b87e8530050d6cfc207f235609cf7939a9 Mon Sep 17 00:00:00 2001 From: Someone Date: Sun, 4 Jun 2023 03:52:37 +0000 Subject: [PATCH 106/234] Translated using Weblate (Vietnamese) Currently translated at 84.4% (2225 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- .../src/main/res/values-vi/strings.xml | 54 +++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 062889596b..504318c160 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -1,5 +1,5 @@ - + Lắc điện thoại để báo cáo lỗi Có vẻ bạn đang lắc điện thoại một cách tức giận. Bạn có muốn mở màn hình báo cáo lỗi không\? Miêu tả vấn đề của bạn ở đây @@ -1203,7 +1203,7 @@ Câu hỏi hoặc chủ đề thăm dò ý kiến Tạo Cuộc thăm dò ý kiến %s trong Cài đặt để nhận lời mời trực tiếp trong ${app_name}. - Liên kết email này với tài khoản của bạn + Liên kết địa chỉ thư điện tử này với tài khoản của bạn Lời mời này đến Space này đã được gửi đến %s không được liên kết với tài khoản của bạn Lời mời này đến phòng này đã được gửi đến %s không được liên kết với tài khoản của bạn Xin lưu ý nâng cấp sẽ tạo ra một phiên bản mới của căn phòng. Tất cả các tin nhắn hiện tại sẽ ở trong phòng lưu trữ này. @@ -1431,7 +1431,7 @@ Sự đồng ý của người dùng chưa được cung cấp. Không có mối liên hệ hiện tại với mã định danh này. Sự kết hợp đã thất bại. - Đối với quyền riêng tư của bạn, ${app_name} chỉ hỗ trợ gửi email và số điện thoại của người dùng băm. + Để đảm bảo quyền riêng tư cho bạn, ${app_name} chỉ hỗ trợ gửi địa chỉ thư điện tử và số điện thoại của người dùng khi đã được băm. Trước tiên, vui lòng chấp nhận các điều khoản của máy chủ nhận dạng trong cài đặt. Trước tiên, vui lòng cấu hình máy chủ nhận dạng. Hoạt động này là không thể. Homeerver đã lỗi thời. @@ -2011,7 +2011,7 @@ Mã QR Đặt lại khóa Khởi tạo xác thực chéo - Cho đến khi người dùng này tin tưởng phiên này, tin nhắn được gửi đến và đi từ nó được dán nhãn cảnh báo. Ngoài ra, bạn có thể xác minh thủ công. + Cho đến khi người dùng này tin tưởng phiên này, tin nhắn được gửi đến nó và từ nó đều mang nhãn cảnh báo. Ngoài ra, bạn có thể xác minh thủ công. %1$s (%2$s) đã đăng nhập bằng phiên mới: Phiên này được tin cậy để nhắn tin an toàn vì %1$s (%2$s) đã xác minh: Không tin cậy @@ -2410,4 +2410,50 @@ Space là một cách mới để nhóm các phòng và mọi người. Tạo một space để bắt đầu. Chưa có space nào. %1$s đã đổi tên hiển thị thành %2$s + Cứ đăng xuất + Không thể kết nối tới máy chủ nhà. Nếu bạn cứ đăng xuất, thiết bị này sẽ không được xóa khỏi danh sách thiết bị của bạn, bạn có thể muốn xóa nó bằng thiết bị khác. + Giao tiếp độc lập và bảo mật cho bạn mức độ riêng tư ngang với trò chuyện trực tiếp trong nhà. + Được mã hóa đầu cuối và không yêu cầu số điện thoại. Không quảng cáo hay khai thác dữ liệu. + Rời tất cả + Đặt lại các khóa xác thực không thể được hoàn tác. Sau khi đặt lại, bạn không thể truy cập vào các tin nhắn đã được mã hóa cũ, và tất cả bạn bè đã xác thực bạn trước đó sẽ thấy các cảnh báo cho đến khi nào bạn xác thực lại với họ. + Hiện thông tin hồ sơ mới nhất (ảnh đại diện và tên hiển thị) cho tất cả các tin nhắn. + Đăng xuất khỏi mọi phiên khác + Các phiên chưa được xác thực là các phiên đã đăng nhập bằng thông tin của bạn nhưng chưa được xác thực chéo. +\n +\nBạn cần đặc biệt chắc chắn là bạn nhận ra các phiên này vì chúng có thể đang sử dụng trái phép tài khoản của bạn. + Những người dùng khác trong tin nhắn trực tiếp và các phòng bạn tham gia có thể xem danh sách các phiên của bạn. +\n +\nNhư vậy giúp họ chắc chắn họ đang thực sự nói chuyện với bạn, nhưng vì thế mà họ cũng có thể thấy tên phiên bạn nhập ở đây. + Bật trình soạn thảo văn bản phong phú + Thử trình soạn thảo văn bản phong phú (sẽ có chế độ văn bản thuần) + Đây là nơi chứa các yêu cầu và lời mời mới. + Ảnh đại diện cho space %1$s + Ảnh đại diện cho phòng %1$s + Ảnh đại diện cho người dùng %1$s + Mở màn hình công cụ cho nhà phát triển + Thư viện ảnh + Đăng ký điểm cuối + Có một lỗi đã xảy ra. Kiểm tra kết nối mạng và thử lại. + Đang thử nghiệm + Địa chỉ máy chủ của bạn là gì\? Đó như là nhà của tất cả dữ liệu của bạn + Gửi ảnh và phim + Hiện tất cả (%1$d) + ${app_name} cũng là nơi tốt cho nơi làm việc. Được tin cậy bởi những tổ chức bảo mật nhất thế giới. + Tùy chọn bố cục + Mọi phiên + Sử dụng bố cục mới + Điểm cuối đã được đăng ký với máy chủ nhà. + Vị trí + Dịch vụ của Google + Hệ thống sẽ tự động gửi nhật ký khi nào xảy ra lỗi giải mã tin nhắn + + Đăng xuất khỏi %1$d phiên + + Các phiên đã được xác thực là phiên mà bạn đăng nhập bằng mật khẩu hay xác thực danh tính bằng một phiên khác +\n +\nNghĩa là bạn đã có tất cả các khóa cần thiết để mở khóa các tin nhắn đã được mã hóa và xác nhận với những người khác là bạn tin cậy phiên này. + Hiển thị và kiểm soát các phiên của bạn tốt hơn. + Ứng dụng nhắn tin bảo mật tất cả-trong-một cho nhóm, bạn bè và tổ chức. Tạo một cuộc trò chuyện, hay tham gia vào một phòng, để bắt đầu. + Chọn nơi lưu trữ các cuộc trò chuyện của bạn, cho bạn quyền kiểm soát và độc lập. Kết nối qua giao thức Matrix. + Chỉ tiếp tục nếu bạn chắc chắn là bạn đã mất tất cả các thiết bị và khóa bảo mật. \ No newline at end of file From 6e300872acc53f5c76a1b0418be69ff193eb65ba Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 5 Jun 2023 07:21:00 +0000 Subject: [PATCH 107/234] Translated using Weblate (Czech) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/cs/ --- fastlane/metadata/android/cs-CZ/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/cs-CZ/changelogs/40106020.txt diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40106020.txt b/fastlane/metadata/android/cs-CZ/changelogs/40106020.txt new file mode 100644 index 0000000000..797d2af0ae --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Element Android nyní používá Crypto Rust SDK. +Úplný seznam změn: https://github.com/vector-im/element-android/releases From ec9c3fa6f7c8c0fba198843c276eb007db1716aa Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Sun, 4 Jun 2023 08:31:11 +0000 Subject: [PATCH 108/234] Translated using Weblate (Albanian) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/sq/ --- fastlane/metadata/android/sq/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/sq/changelogs/40106020.txt diff --git a/fastlane/metadata/android/sq/changelogs/40106020.txt b/fastlane/metadata/android/sq/changelogs/40106020.txt new file mode 100644 index 0000000000..0cb7a00683 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Element Android tanimë përdor SDK Rust për Kripto. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases From 45d75ecc6d363827eabec4e9b44cc3cf6652cb2b Mon Sep 17 00:00:00 2001 From: raspin0 Date: Tue, 6 Jun 2023 19:53:35 +0000 Subject: [PATCH 109/234] Translated using Weblate (Polish) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/pl/ --- fastlane/metadata/android/pl-PL/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/pl-PL/changelogs/40106020.txt diff --git a/fastlane/metadata/android/pl-PL/changelogs/40106020.txt b/fastlane/metadata/android/pl-PL/changelogs/40106020.txt new file mode 100644 index 0000000000..c91b48c168 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Element Android teraz korzysta z Crypto Rust SDK. +Pełna lista zmian: https://github.com/vector-im/element-android/releases From 2d21d3f6ced87e32b6ee5efd7c3664c1c8c5d36b Mon Sep 17 00:00:00 2001 From: Linerly Date: Thu, 8 Jun 2023 02:41:46 +0000 Subject: [PATCH 110/234] Translated using Weblate (Indonesian) Currently translated at 100.0% (100 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/id/ --- fastlane/metadata/android/id/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/id/changelogs/40106020.txt diff --git a/fastlane/metadata/android/id/changelogs/40106020.txt b/fastlane/metadata/android/id/changelogs/40106020.txt new file mode 100644 index 0000000000..b69e7fc7b9 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Element Android sekarang menggunakan SDK Kripto Rust. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases From 6b2331dcbfc72a5a77c0792922d87ad9bdfdef70 Mon Sep 17 00:00:00 2001 From: valere Date: Thu, 8 Jun 2023 14:18:34 +0200 Subject: [PATCH 111/234] Deactivation test broken by latest synapse --- .../android/sdk/account/DeactivateAccountTest.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt index bb5618b816..61bd1b42ea 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt @@ -64,9 +64,15 @@ class DeactivateAccountTest : InstrumentedTest { // Test the error assertTrue( + "Unexpected deactivated error $throwable", throwable is Failure.ServerError && - throwable.error.code == MatrixError.M_USER_DEACTIVATED && - throwable.error.message == "This account has been deactivated" + ( + (throwable.error.code == MatrixError.M_USER_DEACTIVATED && + throwable.error.message == "This account has been deactivated") || + // Workaround for a breaking change on synapse to fix CI + // https://github.com/matrix-org/synapse/issues/15747 + throwable.error.code == MatrixError.M_FORBIDDEN + ) ) // Try to create an account with the deactivate account user id, it will fail (M_USER_IN_USE) From a311b21d7cb4c1a3614cc8ba63e6ffe067202bf7 Mon Sep 17 00:00:00 2001 From: Paul Marc Date: Thu, 8 Jun 2023 11:25:32 +0000 Subject: [PATCH 112/234] Translated using Weblate (Arabic) Currently translated at 39.2% (1036 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ar/ --- library/ui-strings/src/main/res/values-ar/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-ar/strings.xml b/library/ui-strings/src/main/res/values-ar/strings.xml index 3e1869b0c8..14c322330d 100644 --- a/library/ui-strings/src/main/res/values-ar/strings.xml +++ b/library/ui-strings/src/main/res/values-ar/strings.xml @@ -1218,4 +1218,6 @@ بدون فضاءات. تفضيلات التخطيط غير %1$s اسمه العلني إلى %2$s + إغلاق %s العناصر الفرعية + توسيع %s العناصر الفرعية \ No newline at end of file From 836fc71ebc84a7ac2ab8c6daa634f09fcb48d953 Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 03:27:52 +0000 Subject: [PATCH 113/234] Translated using Weblate (Vietnamese) Currently translated at 84.5% (2229 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 504318c160..50acf88582 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -1963,8 +1963,8 @@ Nhập %s của bạn để tiếp tục. Chìa khóa tin nhắn Cụm mật khẩu phục hồi - Xác minh bị hủy bỏ - Xác minh đã bị hủy bỏ. Bạn có thể bắt đầu xác minh lại. + Xác thực đã bị hủy bỏ + Xác thực đã bị hủy bỏ. Bạn có thể bắt đầu xác thực lại. Một trong những điều sau đây có thể bị xâm phạm: \n \n- Mật khẩu của bạn @@ -2411,7 +2411,7 @@ Chưa có space nào. %1$s đã đổi tên hiển thị thành %2$s Cứ đăng xuất - Không thể kết nối tới máy chủ nhà. Nếu bạn cứ đăng xuất, thiết bị này sẽ không được xóa khỏi danh sách thiết bị của bạn, bạn có thể muốn xóa nó bằng thiết bị khác. + Không thể kết nối tới máy chủ nhà. Nếu bạn cứ đăng xuất, thiết bị này sẽ không được xóa khỏi danh sách, bạn có thể muốn xóa nó bằng thiết bị khác. Giao tiếp độc lập và bảo mật cho bạn mức độ riêng tư ngang với trò chuyện trực tiếp trong nhà. Được mã hóa đầu cuối và không yêu cầu số điện thoại. Không quảng cáo hay khai thác dữ liệu. Rời tất cả @@ -2456,4 +2456,6 @@ Ứng dụng nhắn tin bảo mật tất cả-trong-một cho nhóm, bạn bè và tổ chức. Tạo một cuộc trò chuyện, hay tham gia vào một phòng, để bắt đầu. Chọn nơi lưu trữ các cuộc trò chuyện của bạn, cho bạn quyền kiểm soát và độc lập. Kết nối qua giao thức Matrix. Chỉ tiếp tục nếu bạn chắc chắn là bạn đã mất tất cả các thiết bị và khóa bảo mật. + Đóng %s mục + Mở %s mục \ No newline at end of file From e6bf8a981d30ac227e53efff153a43707ebd8d9a Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Fri, 9 Jun 2023 06:29:42 +0000 Subject: [PATCH 114/234] Translated using Weblate (Czech) Currently translated at 100.0% (2640 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- library/ui-strings/src/main/res/values-cs/strings.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index 09f944ba7e..5007940e48 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -1635,7 +1635,7 @@ Role Otevřít chat Umlčet mikrofon - Zrušit umlčení mikrofonu + Zrušit ztlumení mikrofonu Zastavit fotoaparát Spustit fotoaparát Bezpečná záloha @@ -3018,4 +3018,12 @@ Aplikace aktualizována Přesto se odhlásit Nelze se spojit s domovským serverem. Pokud se přesto odhlásíte, nebude toto zařízení vymazáno ze seznamu zařízení, můžete jej odstranit pomocí jiného klienta. + Přesto zahájit chat + Přesto pozvat + Nelze najít profily pro níže uvedené Matrix identifikátory. Chcete přesto zahájit chat\? +\n +\n%s + Nelze najít profily pro níže uvedené Matrix identifikátory. Chcete je přesto pozvat\? +\n +\n%s \ No newline at end of file From b840ff1d25423d60f597dbbeaf6e9439ab680287 Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 07:04:50 +0000 Subject: [PATCH 115/234] Translated using Weblate (Vietnamese) Currently translated at 84.5% (2230 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 50acf88582..ef4fafdab1 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2458,4 +2458,5 @@ Chỉ tiếp tục nếu bạn chắc chắn là bạn đã mất tất cả các thiết bị và khóa bảo mật. Đóng %s mục Mở %s mục + Bạn chỉ có thể mời một địa chỉ thư điện tử một lần \ No newline at end of file From 33ef138d4bc73f32a23e344eb6dcb08bb948c776 Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 07:06:10 +0000 Subject: [PATCH 116/234] Translated using Weblate (Vietnamese) Currently translated at 85.4% (2253 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- .../src/main/res/values-vi/strings.xml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index ef4fafdab1..cec75a90eb 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2459,4 +2459,28 @@ Đóng %s mục Mở %s mục Bạn chỉ có thể mời một địa chỉ thư điện tử một lần + Mở danh sách space + Chọn máy chủ của bạn + Bạn nắm quyền kiểm soát. + Muốn chạy một máy chủ của mình\? + %s cần xác nhận tài khoản của bạn + Đi thôi + Bạn sẽ trò chuyện với ai nhiều nhất\? + Chưa chắc chắn\? %s + URL Máy chủ + Đến lúc để thêm khuôn mặt vào tên + Nhắn tin với đồng đội. + Đã chia sẻ vị trí hiện tại + Tạo một cuộc trò chuyện hay phòng mới + Phát thanh + Những người khác có thể tìm thấy bạn %s + Chính sách máy chủ + %s sẽ gửi bạn một liên kết xác nhận + Làm chủ cuộc trò chuyện. + %s cần xác nhận tài khoản của bạn + Chào mừng trở lại! + Địa chỉ máy chủ của bạn là gì\? + Chúng tôi sẽ giúp bạn kết nối + Tìm để tham gia một máy chủ sẵn có\? + Đã bắt đầu phát thanh \ No newline at end of file From 5e00d474d9fae26170592a740c26f56260f014c1 Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 07:06:10 +0000 Subject: [PATCH 117/234] Translated using Weblate (Vietnamese) Currently translated at 85.5% (2254 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index cec75a90eb..e1cb6a9882 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2483,4 +2483,5 @@ Chúng tôi sẽ giúp bạn kết nối Tìm để tham gia một máy chủ sẵn có\? Đã bắt đầu phát thanh + Xác thực bằng khóa bảo mật hay chuỗi từ bảo mật \ No newline at end of file From 4903c246610c9924f09ffd4553285d6fafea1a0e Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 07:11:56 +0000 Subject: [PATCH 118/234] Translated using Weblate (Vietnamese) Currently translated at 85.5% (2254 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index e1cb6a9882..2764211a94 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2483,5 +2483,5 @@ Chúng tôi sẽ giúp bạn kết nối Tìm để tham gia một máy chủ sẵn có\? Đã bắt đầu phát thanh - Xác thực bằng khóa bảo mật hay chuỗi từ bảo mật + Xác thực bằng khóa bảo mật hay chuỗi từ bảo mật… \ No newline at end of file From 0ca5caee85ae355314b94a6ecba81946ce627c9a Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 07:12:14 +0000 Subject: [PATCH 119/234] Translated using Weblate (Vietnamese) Currently translated at 85.5% (2255 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 2764211a94..2225fa9f28 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2484,4 +2484,5 @@ Tìm để tham gia một máy chủ sẵn có\? Đã bắt đầu phát thanh Xác thực bằng khóa bảo mật hay chuỗi từ bảo mật… + Vui lòng liên hệ một quản trị viên để khôi phục mã hóa về trạng thái hợp lệ. \ No newline at end of file From 2a7b92d48fa5a5ced1fe0fe46087677a9d08c17b Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 07:12:19 +0000 Subject: [PATCH 120/234] Translated using Weblate (Vietnamese) Currently translated at 85.5% (2256 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 2225fa9f28..4ca7456efb 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2485,4 +2485,5 @@ Đã bắt đầu phát thanh Xác thực bằng khóa bảo mật hay chuỗi từ bảo mật… Vui lòng liên hệ một quản trị viên để khôi phục mã hóa về trạng thái hợp lệ. + Khôi phục mã hóa \ No newline at end of file From 0e7ca50588b2cfbf6a48227ccd82faaf14176b4f Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 07:16:06 +0000 Subject: [PATCH 121/234] Translated using Weblate (Vietnamese) Currently translated at 85.9% (2265 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 4ca7456efb..b8e17dfc89 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2486,4 +2486,13 @@ Xác thực bằng khóa bảo mật hay chuỗi từ bảo mật… Vui lòng liên hệ một quản trị viên để khôi phục mã hóa về trạng thái hợp lệ. Khôi phục mã hóa + Bản dựng mỗi ngày + Xác thực với thiết bị khác + Lịch sử bỏ phiếu + Các phiên + Bạn không thể truy cập vào các tin nhắn được mã hóa. Đặt lại sao lưu tin nhắn bảo mật và các khóa xác thực để bắt đầu lại. + Không thể xác thực thiết bị này + Ứng dụng được cập nhật + Trước khi người dùng này tin tưởng phiên này, các tin nhắn gửi đến phiên và từ phiên đều mang nhãn cảnh báo. + Xác thực danh tính để truy cập vào các tin nhắn được mã hóa và chứng minh danh tính của bạn với những người khác. \ No newline at end of file From 38330a7b67ee27b1d5da54cc9b42ec008ae9937e Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 9 Jun 2023 09:29:01 +0100 Subject: [PATCH 122/234] Update RTE library to support pasting of images. --- changelog.d/8270.bugfix | 1 + dependencies.gradle | 2 +- .../home/room/detail/composer/RichTextComposerLayout.kt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelog.d/8270.bugfix diff --git a/changelog.d/8270.bugfix b/changelog.d/8270.bugfix new file mode 100644 index 0000000000..e2d3056de4 --- /dev/null +++ b/changelog.d/8270.bugfix @@ -0,0 +1 @@ +Update rich text editor library to support pasting of images. diff --git a/dependencies.gradle b/dependencies.gradle index f4d32c4894..78d842a7a5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -101,7 +101,7 @@ ext.libs = [ ], element : [ 'opusencoder' : "io.element.android:opusencoder:1.1.0", - 'wysiwyg' : "io.element.android:wysiwyg:2.2.1" + 'wysiwyg' : "io.element.android:wysiwyg:2.2.2" ], squareup : [ 'moshi' : "com.squareup.moshi:moshi:$moshi", diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt index 49e8f0cdc6..baba98ed8b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt @@ -88,7 +88,7 @@ internal class RichTextComposerLayout @JvmOverloads constructor( override val text: Editable? get() = editText.text override val formattedText: String? - get() = (editText as? EditorEditText)?.getHtmlOutput() + get() = (editText as? EditorEditText)?.getContentAsMessageHtml() override val editText: EditText get() = if (isTextFormattingEnabled) { views.richTextComposerEditText From 69ecdba1751893e01fceaa0390e7f399ad6785ef Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 9 Jun 2023 07:40:51 +0000 Subject: [PATCH 123/234] Translated using Weblate (Vietnamese) Currently translated at 85.9% (2266 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index b8e17dfc89..cc6e185e1c 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2486,7 +2486,7 @@ Xác thực bằng khóa bảo mật hay chuỗi từ bảo mật… Vui lòng liên hệ một quản trị viên để khôi phục mã hóa về trạng thái hợp lệ. Khôi phục mã hóa - Bản dựng mỗi ngày + Bản dựng hằng ngày Xác thực với thiết bị khác Lịch sử bỏ phiếu Các phiên @@ -2495,4 +2495,6 @@ Ứng dụng được cập nhật Trước khi người dùng này tin tưởng phiên này, các tin nhắn gửi đến phiên và từ phiên đều mang nhãn cảnh báo. Xác thực danh tính để truy cập vào các tin nhắn được mã hóa và chứng minh danh tính của bạn với những người khác. + Tải bản dựng mới nhất (ghi chú: bạn có thể gặp vấn đề khi đăng nhập) + \ No newline at end of file From ba3e7f63ff0cf6a7b07577d047f6f7241798212f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 9 Jun 2023 15:40:53 +0200 Subject: [PATCH 124/234] Only upgrade our libraries to limit the number of open PRs by Dependabot (#8518) --- .github/dependabot.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b6746c77d3..597f78f541 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,7 @@ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: @@ -13,7 +13,7 @@ updates: reviewers: - "vector-im/element-android-reviewers" ignore: - - dependency-name: "*github-script*" + - dependency-name: "*" # Updates for Gradle dependencies used in the app - package-ecosystem: gradle directory: "/" @@ -22,5 +22,6 @@ updates: open-pull-requests-limit: 200 reviewers: - "vector-im/element-android-reviewers" - ignore: - - dependency-name: com.google.zxing:core + allow: + - dependency-name: "io.element.android:wysiwyg" + - dependency-name: "org.matrix.rustcomponents:crypto-android" From f3db4a857af48ecc6ffe3f8782e80f6d06ef29ce Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 9 Jun 2023 14:58:17 +0100 Subject: [PATCH 125/234] always use getText().insert for adding pills --- .../detail/composer/MessageComposerFragment.kt | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt index a7fc72d2d4..6a3ca0f1c0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt @@ -808,15 +808,14 @@ class MessageComposerFragment : VectorBaseFragment(), A ) append(if (startToCompose) ": " else " ") } - if (startToCompose) { - if (displayName.startsWith("/")) { - // Ensure displayName will not be interpreted as a Slash command - composer.editText.append("\\") - } - composer.editText.append(pill) - } else { - composer.editText.text?.insert(composer.editText.selectionStart, pill) - } + if (startToCompose && displayName.startsWith("/")) { + // Ensure displayName will not be interpreted as a Slash command + composer.editText.append("\\") + } + // Always use EditText.getText().insert for adding pills as TextView.append doesn't appear + // to upgrade to BufferType.Spannable as hinted at in the docs: + // https://developer.android.com/reference/android/widget/TextView#append(java.lang.CharSequence) + composer.editText.text.insert(composer.editText.selectionStart, pill) } focusComposerAndShowKeyboard() } From cfa0f95799237faf707cfb4d3b188fe7322b484f Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 9 Jun 2023 16:02:09 +0100 Subject: [PATCH 126/234] Add PillDisplayHandler tests for custom domains. --- .../mentions/PillDisplayHandlerTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt index 6529cf162e..61347e67fb 100644 --- a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt +++ b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt @@ -55,6 +55,8 @@ internal class PillDisplayHandlerTest { const val KNOWN_MATRIX_USER_URL = "https://matrix.to/#/$KNOWN_MATRIX_USER_ID" const val KNOWN_MATRIX_USER_AVATAR = "https://example.com/avatar.png" const val KNOWN_MATRIX_USER_NAME = "known user" + const val CUSTOM_DOMAIN_MATRIX_ROOM_URL = "https://customdomain/#/room/$KNOWN_MATRIX_ROOM_ID" + const val CUSTOM_DOMAIN_MATRIX_USER_URL = "https://customdomain.com/#/user/$KNOWN_MATRIX_USER_ID" } @Before @@ -153,6 +155,26 @@ internal class PillDisplayHandlerTest { assertEquals(listOf("@room"), subject.keywords) } + @Test + fun `when resolve known user for custom domain link, then it returns named custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveLinkDisplay("text", CUSTOM_DOMAIN_MATRIX_USER_URL) + .getMatrixItem() + + assertEquals(MatrixItem.UserItem(KNOWN_MATRIX_USER_ID, KNOWN_MATRIX_USER_NAME, KNOWN_MATRIX_USER_AVATAR), matrixItem) + } + + @Test + fun `when resolve known room for custom domain link, then it returns named custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveLinkDisplay("text", CUSTOM_DOMAIN_MATRIX_ROOM_URL) + .getMatrixItem() + + assertEquals(MatrixItem.RoomItem(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem) + } + private fun TextDisplay.getMatrixItem(): MatrixItem? { val customSpan = this as? TextDisplay.Custom assertNotNull("The URL did not resolve to a custom link display method", customSpan) From 3b887fdf4ec8d82f5b35f06cb0743bae2e8273dc Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 9 Jun 2023 18:12:52 +0100 Subject: [PATCH 127/234] Test room alias links and fix bug found with PillDisplayHander not handling them --- .../composer/mentions/PillDisplayHandler.kt | 2 ++ .../mentions/PillDisplayHandlerTest.kt | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt index b657257b85..c2b71ea15b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandler.kt @@ -27,6 +27,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.toEveryoneInRoomMatrixItem import org.matrix.android.sdk.api.util.toMatrixItem +import org.matrix.android.sdk.api.util.toRoomAliasMatrixItem /** * A rich text editor [LinkDisplayHandler] and [KeywordDisplayHandler] @@ -53,6 +54,7 @@ internal class PillDisplayHandler( when { room == null -> MatrixItem.RoomItem(roomId, roomId, null) text == MatrixItem.NOTIFY_EVERYONE -> room.toEveryoneInRoomMatrixItem() + permalink.isRoomAlias -> room.toRoomAliasMatrixItem() else -> room.toMatrixItem() } } diff --git a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt index 61347e67fb..ee24b7a7fc 100644 --- a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt +++ b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt @@ -57,7 +57,10 @@ internal class PillDisplayHandlerTest { const val KNOWN_MATRIX_USER_NAME = "known user" const val CUSTOM_DOMAIN_MATRIX_ROOM_URL = "https://customdomain/#/room/$KNOWN_MATRIX_ROOM_ID" const val CUSTOM_DOMAIN_MATRIX_USER_URL = "https://customdomain.com/#/user/$KNOWN_MATRIX_USER_ID" + const val KNOWN_MATRIX_ROOM_ALIAS = "#known-alias:matrix.org" + const val KNOWN_MATRIX_ROOM_ALIAS_URL = "https://matrix.to/#/$KNOWN_MATRIX_ROOM_ALIAS" } + https://matrix.to/#/#rich-text-editor:matrix.org @Before fun setUp() { @@ -66,6 +69,7 @@ internal class PillDisplayHandlerTest { every { mockGetRoom(UNKNOWN_MATRIX_ROOM_ID) } returns null every { mockGetRoom(KNOWN_MATRIX_ROOM_ID) } returns createFakeRoom(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR) every { mockGetRoom(ROOM_ID) } returns createFakeRoom(ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR) + every { mockGetRoom(KNOWN_MATRIX_ROOM_ALIAS) } returns createFakeRoomWithAlias(KNOWN_MATRIX_ROOM_ALIAS, KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR) } @Test @@ -175,6 +179,16 @@ internal class PillDisplayHandlerTest { assertEquals(MatrixItem.RoomItem(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem) } + @Test + fun `when resolve known room with alias link, then it returns named custom pill`() { + val subject = createSubject() + + val matrixItem = subject.resolveLinkDisplay("text", KNOWN_MATRIX_ROOM_ALIAS_URL) + .getMatrixItem() + + assertEquals(MatrixItem.RoomAliasItem(KNOWN_MATRIX_ROOM_ALIAS, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR), matrixItem) + } + private fun TextDisplay.getMatrixItem(): MatrixItem? { val customSpan = this as? TextDisplay.Custom assertNotNull("The URL did not resolve to a custom link display method", customSpan) @@ -206,6 +220,16 @@ internal class PillDisplayHandlerTest { isEncrypted = false ) + private fun createFakeRoomWithAlias(roomAlias: String, roomId: String, roomName: String, avatarUrl: String): RoomSummary = RoomSummary( + roomId = roomId, + displayName = roomName, + avatarUrl = avatarUrl, + encryptionEventTs = null, + typingUsers = emptyList(), + isEncrypted = false, + canonicalAlias = roomAlias + ) + data class MatrixItemHolderSpan( val matrixItem: MatrixItem ) : ReplacementSpan() { From cb64175c2bfcb394849d4a061ac979c061bf25b7 Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 9 Jun 2023 19:43:26 +0100 Subject: [PATCH 128/234] Fix line length and typo. --- .../detail/composer/mentions/PillDisplayHandlerTest.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt index ee24b7a7fc..57c7aee420 100644 --- a/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt +++ b/vector/src/test/java/im/vector/app/features/home/room/detail/composer/mentions/PillDisplayHandlerTest.kt @@ -60,7 +60,6 @@ internal class PillDisplayHandlerTest { const val KNOWN_MATRIX_ROOM_ALIAS = "#known-alias:matrix.org" const val KNOWN_MATRIX_ROOM_ALIAS_URL = "https://matrix.to/#/$KNOWN_MATRIX_ROOM_ALIAS" } - https://matrix.to/#/#rich-text-editor:matrix.org @Before fun setUp() { @@ -69,7 +68,12 @@ internal class PillDisplayHandlerTest { every { mockGetRoom(UNKNOWN_MATRIX_ROOM_ID) } returns null every { mockGetRoom(KNOWN_MATRIX_ROOM_ID) } returns createFakeRoom(KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR) every { mockGetRoom(ROOM_ID) } returns createFakeRoom(ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR) - every { mockGetRoom(KNOWN_MATRIX_ROOM_ALIAS) } returns createFakeRoomWithAlias(KNOWN_MATRIX_ROOM_ALIAS, KNOWN_MATRIX_ROOM_ID, KNOWN_MATRIX_ROOM_NAME, KNOWN_MATRIX_ROOM_AVATAR) + every { mockGetRoom(KNOWN_MATRIX_ROOM_ALIAS) } returns createFakeRoomWithAlias( + KNOWN_MATRIX_ROOM_ALIAS, + KNOWN_MATRIX_ROOM_ID, + KNOWN_MATRIX_ROOM_NAME, + KNOWN_MATRIX_ROOM_AVATAR + ) } @Test From d30c6018e40e380af511494ad86a8d6dc7cd5c89 Mon Sep 17 00:00:00 2001 From: Oleg Date: Sun, 11 Jun 2023 09:30:33 +0000 Subject: [PATCH 129/234] Translated using Weblate (Russian) Currently translated at 99.6% (2628 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- .../src/main/res/values-ru/strings.xml | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/library/ui-strings/src/main/res/values-ru/strings.xml b/library/ui-strings/src/main/res/values-ru/strings.xml index bf329b89ec..b48e72cbba 100644 --- a/library/ui-strings/src/main/res/values-ru/strings.xml +++ b/library/ui-strings/src/main/res/values-ru/strings.xml @@ -3024,4 +3024,35 @@ Голосовая трансляция начата Ваш домашний сервер не поддерживает список обсуждений. Остановить + Всё равно выйти + Подтвердить сброс + Аватар пространства %1$s + Аватар комнаты %1$s + Сообщение от %s + Сообщение в %s + Сообщение в комнате + Комната/Пространство + Аккаунт + Аватар профиля пользователя %1$s + Продолжайте, только если вы уверены, что ваш ключ утерян, а доступ к другим активным устройствам отсустствует. + Пока пользователь не верифицировал эту сессию, отправленные и полученные сообщения отмечаются предупреждениями. + Запрос на верификацию отправлен. Откройте приложение на одном из активных устройств и подтвердите эту сессию. + Можно пригласить один email за раз + Приложение обновлено + Верификация секретной фразы или ключа… + Подтвердите ваш сеанс для доступа к зашифрованным сообщениям и верификации для других пользователей. + Не удается подключиться к серверу. Если вы подтвердите выход сейчас, это устройство не будет удалено из списка активных сеансов. Удалить этот сеанс можно будет с другого устройства. + Ожидание подключения пользователей к ${app_name} + При изменении настроек уведомлений произошла ошибка. Попробуйте ещё раз. + Когда приглашенные пользователи присоединятся к ${app_name}, вы сможете писать им с использованием сквозного шифрования + Сброс ваших ключей верификации не может быть отменен. После сброса, вы не будете иметь доступа к старым зашифрованным сообщениям, а все ваши контакты, верифицировавшие вас ранее, увидят предупреждение о повторной верификации. + Зашифрованно неактивным устройством + Защищенный обмен сообщениями был обновлен. Пожалуйста, повторно верифицируйте ваше устройство. + Не удается расшифровать голосовое сообщение. + Обзор опроса во времени + Сообщение + Подтвердить с помощью активного устройства + Возобновить + %1$s изменил отображаемое имя на %2$s + Запрос на верификацию не найден. Возможно, он был отменен или обработан другим сеансом. \ No newline at end of file From bbc1ed9e6246c9803b849289165c97a011dbbf61 Mon Sep 17 00:00:00 2001 From: Oleg Date: Sun, 11 Jun 2023 09:48:51 +0000 Subject: [PATCH 130/234] Translated using Weblate (Russian) Currently translated at 91.0% (91 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/ru/ --- fastlane/metadata/android/ru-RU/changelogs/40106020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/ru-RU/changelogs/40106020.txt diff --git a/fastlane/metadata/android/ru-RU/changelogs/40106020.txt b/fastlane/metadata/android/ru-RU/changelogs/40106020.txt new file mode 100644 index 0000000000..11550d3bb1 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/40106020.txt @@ -0,0 +1,2 @@ +Главные изменения этой версии: Element для Android теперь использует Crypto Rust SDK. +Полный список изменений: https://github.com/vector-im/element-android/releases From 6fe0002bd3812ec6cfb15c23a283f1640bc3e661 Mon Sep 17 00:00:00 2001 From: valere Date: Wed, 7 Jun 2023 19:20:24 +0200 Subject: [PATCH 131/234] Clean room shield update logic --- .../android/sdk/common/CommonTestHelper.kt | 17 +++ .../sdk/internal/crypto/RoomShieldTest.kt | 133 ++++++++++++++++++ .../DefaultCrossSigningService.kt | 6 +- .../crypto/crosssigning/UpdateTrustWorker.kt | 112 ++++++++------- .../sync/handler/ShieldSummaryUpdater.kt | 56 ++++++++ .../crypto/CryptoSessionInfoProvider.kt | 30 +++- .../UpdateTrustWorkerDataRepository.kt | 9 +- .../room/summary/RoomSummaryUpdater.kt | 23 ++- .../SyncResponsePostTreatmentAggregator.kt | 3 +- ...cResponsePostTreatmentAggregatorHandler.kt | 11 +- .../network/OutgoingRequestsProcessor.kt | 18 +-- .../sync/handler/ShieldSummaryUpdater.kt | 60 ++++++++ 12 files changed, 379 insertions(+), 99 deletions(-) create mode 100644 matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/RoomShieldTest.kt create mode 100644 matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/session/sync/handler/ShieldSummaryUpdater.kt create mode 100644 matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/session/sync/handler/ShieldSummaryUpdater.kt diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index 4053d1c1c4..983e00b9ea 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -99,6 +99,23 @@ class CommonTestHelper internal constructor(context: Context, val cryptoConfig: } } } + + @OptIn(ExperimentalCoroutinesApi::class) + internal fun runLongCryptoTest(context: Context, cryptoConfig: MXCryptoConfig? = null, autoSignoutOnClose: Boolean = true, block: suspend CoroutineScope.(CryptoTestHelper, CommonTestHelper) -> Unit) { + val testHelper = CommonTestHelper(context, cryptoConfig) + val cryptoTestHelper = CryptoTestHelper(testHelper) + return runTest(dispatchTimeoutMs = TestConstants.timeOutMillis * 4) { + try { + withContext(Dispatchers.Default) { + block(cryptoTestHelper, testHelper) + } + } finally { + if (autoSignoutOnClose) { + testHelper.cleanUpOpenedSessions() + } + } + } + } } internal val matrix: TestMatrix diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/RoomShieldTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/RoomShieldTest.kt new file mode 100644 index 0000000000..8e2284d588 --- /dev/null +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/RoomShieldTest.kt @@ -0,0 +1,133 @@ +/* + * Copyright 2023 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.crypto + +import android.util.Log +import androidx.lifecycle.Observer +import androidx.test.filters.LargeTest +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.runners.MethodSorters +import org.matrix.android.sdk.InstrumentedTest +import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.getRoom +import org.matrix.android.sdk.api.session.room.model.RoomSummary +import org.matrix.android.sdk.api.util.Optional +import org.matrix.android.sdk.common.CommonTestHelper +import org.matrix.android.sdk.common.SessionTestParams +import org.matrix.android.sdk.common.TestConstants +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +@RunWith(JUnit4::class) +@FixMethodOrder(MethodSorters.JVM) +@LargeTest +class RoomShieldTest : InstrumentedTest { + + @Test + fun testShieldNoVerification() = CommonTestHelper.runCryptoTest(context()) { cryptoTestHelper, _ -> + val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() + + val roomId = testData.roomId + + cryptoTestHelper.initializeCrossSigning(testData.firstSession) + cryptoTestHelper.initializeCrossSigning(testData.secondSession!!) + + // Test are flaky unless I use liveData observer on main thread + // Just calling getRoomSummary() with retryWithBackOff keeps an outdated version of the value + testData.firstSession.assertRoomShieldIs(roomId, RoomEncryptionTrustLevel.Default) + testData.secondSession!!.assertRoomShieldIs(roomId, RoomEncryptionTrustLevel.Default) + } + + @Test + fun testShieldInOneOne() = CommonTestHelper.runLongCryptoTest(context()) { cryptoTestHelper, testHelper -> + val testData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom() + + val roomId = testData.roomId + + Log.v("#E2E TEST", "Initialize cross signing...") + cryptoTestHelper.initializeCrossSigning(testData.firstSession) + cryptoTestHelper.initializeCrossSigning(testData.secondSession!!) + Log.v("#E2E TEST", "... Initialized.") + + // let alive and bob verify + Log.v("#E2E TEST", "Alice and Bob verify each others...") + cryptoTestHelper.verifySASCrossSign(testData.firstSession, testData.secondSession!!, testData.roomId) + + // Add a new session for bob + // This session will be unverified for now + + Log.v("#E2E TEST", "Log in a new bob device...") + val bobSecondSession = testHelper.logIntoAccount(testData.secondSession!!.myUserId, SessionTestParams(true)) + + Log.v("#E2E TEST", "Bob session logged in ${bobSecondSession.myUserId.take(6)}") + + Log.v("#E2E TEST", "Assert room shields...") + testData.firstSession.assertRoomShieldIs(roomId, RoomEncryptionTrustLevel.Warning) + // in 1:1 we ignore our own status + testData.secondSession!!.assertRoomShieldIs(roomId, RoomEncryptionTrustLevel.Trusted) + + // Adding another user should make bob consider his devices now and see same shield as alice + Log.v("#E2E TEST", "Create Sam account") + val samSession = testHelper.createAccount(TestConstants.USER_SAM, SessionTestParams(withInitialSync = true)) + + // Let alice invite sam + Log.v("#E2E TEST", "Let alice invite sam") + testData.firstSession.getRoom(roomId)!!.membershipService().invite(samSession.myUserId) + testHelper.waitForAndAcceptInviteInRoom(samSession, roomId) + + Log.v("#E2E TEST", "Assert room shields...") + testData.firstSession.assertRoomShieldIs(roomId, RoomEncryptionTrustLevel.Warning) + testData.secondSession!!.assertRoomShieldIs(roomId, RoomEncryptionTrustLevel.Warning) + + // Now let's bob verify his session + + Log.v("#E2E TEST", "Bob verifies his new session") + cryptoTestHelper.verifyNewSession(testData.secondSession!!, bobSecondSession) + + testData.firstSession.assertRoomShieldIs(roomId, RoomEncryptionTrustLevel.Trusted) + testData.secondSession!!.assertRoomShieldIs(roomId, RoomEncryptionTrustLevel.Trusted) + } + + @OptIn(DelicateCoroutinesApi::class) + private suspend fun Session.assertRoomShieldIs(roomId: String, state: RoomEncryptionTrustLevel?) { + val lock = CountDownLatch(1) + val roomLiveData = withContext(Dispatchers.Main) { + roomService().getRoomSummaryLive(roomId) + } + val observer = object : Observer> { + override fun onChanged(value: Optional) { + Log.v("#E2E TEST ${this@assertRoomShieldIs.myUserId.take(6)}", "Shield Update ${value.getOrNull()?.roomEncryptionTrustLevel}") + if (value.getOrNull()?.roomEncryptionTrustLevel == state) { + lock.countDown() + roomLiveData.removeObserver(this) + } + } + } + GlobalScope.launch(Dispatchers.Main) { roomLiveData.observeForever(observer) } + + lock.await(40_000, TimeUnit.MILLISECONDS) + } +} diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt index 3090bb805e..e020946484 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -49,7 +49,6 @@ import org.matrix.android.sdk.internal.di.SessionId import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.di.WorkManagerProvider import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.util.JsonCanonicalizer import org.matrix.android.sdk.internal.util.logLimit import org.matrix.android.sdk.internal.worker.WorkerParamsFactory @@ -66,7 +65,6 @@ internal class DefaultCrossSigningService @Inject constructor( private val deviceListManager: DeviceListManager, private val initializeCrossSigningTask: InitializeCrossSigningTask, private val uploadSignaturesTask: UploadSignaturesTask, - private val taskExecutor: TaskExecutor, private val coroutineDispatchers: MatrixCoroutineDispatchers, private val cryptoCoroutineScope: CoroutineScope, private val workManagerProvider: WorkManagerProvider, @@ -612,9 +610,7 @@ internal class DefaultCrossSigningService @Inject constructor( withContext(coroutineDispatchers.crypto) { // This device should be yours val device = cryptoStore.getUserDevice(myUserId, deviceId) - if (device == null) { - throw IllegalArgumentException("This device [$deviceId] is not known, or not yours") - } + ?: throw IllegalArgumentException("This device [$deviceId] is not known, or not yours") val myKeys = getUserCrossSigningKeys(myUserId) ?: throw Throwable("CrossSigning is not setup for this account") diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt index ce6e046de5..80f37a6c57 100644 --- a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt @@ -31,7 +31,7 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerif import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.internal.SessionManager -import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore +import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntityFields @@ -40,10 +40,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.TrustLevelEntity import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntity import org.matrix.android.sdk.internal.crypto.store.db.model.UserEntityFields import org.matrix.android.sdk.internal.database.awaitTransaction -import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity -import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity -import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.di.CryptoDatabase import org.matrix.android.sdk.internal.di.SessionDatabase @@ -83,35 +80,54 @@ internal class UpdateTrustWorker(context: Context, params: WorkerParameters, ses @Inject lateinit var myUserId: String @Inject lateinit var crossSigningKeysMapper: CrossSigningKeysMapper @Inject lateinit var updateTrustWorkerDataRepository: UpdateTrustWorkerDataRepository + @Inject lateinit var cryptoSessionInfoProvider: CryptoSessionInfoProvider // @Inject lateinit var roomSummaryUpdater: RoomSummaryUpdater - @Inject lateinit var cryptoStore: IMXCryptoStore +// @Inject lateinit var cryptoStore: IMXCryptoStore override fun injectWith(injector: SessionComponent) { injector.inject(this) } override suspend fun doSafeWork(params: Params): Result { - val userList = params.filename + val sId = myUserId.take(5) + Timber.v("## CrossSigning - UpdateTrustWorker started..") + val workerParams = params.filename ?.let { updateTrustWorkerDataRepository.getParam(it) } - ?.userIds - ?: params.updatedUserIds.orEmpty() + ?: return Result.success().also { + Timber.w("## CrossSigning - UpdateTrustWorker failed to get params") + cleanup(params) + } + + Timber.v("## CrossSigning [$sId]- UpdateTrustWorker userIds:${workerParams.userIds.logLimit()}, roomIds:${workerParams.roomIds.orEmpty().logLimit()}") + val userList = workerParams.userIds // List should not be empty, but let's avoid go further in case of empty list if (userList.isNotEmpty()) { // Unfortunately we don't have much info on what did exactly changed (is it the cross signing keys of that user, // or a new device?) So we check all again :/ - Timber.v("## CrossSigning - Updating trust for users: ${userList.logLimit()}") + Timber.v("## CrossSigning [$sId]- Updating trust for users: ${userList.logLimit()}") updateTrust(userList) } + val roomsToCheck = workerParams.roomIds ?: cryptoSessionInfoProvider.getRoomsWhereUsersAreParticipating(userList) + Timber.v("## CrossSigning [$sId]- UpdateTrustWorker roomShield to check:${roomsToCheck.logLimit()}") + var myCrossSigningInfo: MXCrossSigningInfo? + Realm.getInstance(cryptoRealmConfiguration).use { realm -> + myCrossSigningInfo = getCrossSigningInfo(realm, myUserId) + } + // So Cross Signing keys trust is updated, device trust is updated + // We can now update room shields? in the session DB? + updateRoomShieldInSummaries(roomsToCheck, myCrossSigningInfo) + cleanup(params) return Result.success() } private suspend fun updateTrust(userListParam: List) { + val sId = myUserId.take(5) var userList = userListParam - var myCrossSigningInfo: MXCrossSigningInfo? = null + var myCrossSigningInfo: MXCrossSigningInfo? // First we check that the users MSK are trusted by mine // After that we check the trust chain for each devices of each users @@ -123,7 +139,7 @@ internal class UpdateTrustWorker(context: Context, params: WorkerParameters, ses var myTrustResult: UserTrustResult? = null if (userList.contains(myUserId)) { - Timber.d("## CrossSigning - Clear all trust as a change on my user was detected") + Timber.d("## CrossSigning [$sId]- Clear all trust as a change on my user was detected") // i am in the list.. but i don't know exactly the delta of change :/ // If it's my cross signing keys we should refresh all trust // do it anyway ? @@ -153,7 +169,7 @@ internal class UpdateTrustWorker(context: Context, params: WorkerParameters, ses myUserId -> myTrustResult else -> { crossSigningService.checkOtherMSKTrusted(myCrossSigningInfo, entry.value).also { - Timber.v("## CrossSigning - user:${entry.key} result:$it") + Timber.v("## CrossSigning [$sId]- user:${entry.key} result:$it") } } } @@ -163,12 +179,12 @@ internal class UpdateTrustWorker(context: Context, params: WorkerParameters, ses // i have all the new trusts, update DB trusts.forEach { val verified = it.value?.isVerified() == true - Timber.v("[$myUserId] ## CrossSigning - Updating user trust: ${it.key} to $verified") + Timber.v("[$myUserId] ## CrossSigning [$sId]- Updating user trust: ${it.key} to $verified") updateCrossSigningKeysTrust(cryptoRealm, it.key, verified) } // Ok so now we have to check device trust for all these users.. - Timber.v("## CrossSigning - Updating devices cross trust users: ${trusts.keys.logLimit()}") + Timber.v("## CrossSigning [$sId]- Updating devices cross trust users: ${trusts.keys.logLimit()}") trusts.keys.forEach { userId -> val devicesEntities = cryptoRealm.where() .equalTo(UserEntityFields.USER_ID, userId) @@ -184,9 +200,9 @@ internal class UpdateTrustWorker(context: Context, params: WorkerParameters, ses // Update trust if needed devicesEntities?.forEach { device -> val crossSignedVerified = trustMap?.get(device)?.isCrossSignedVerified() - Timber.v("## CrossSigning - Trust for ${device.userId}|${device.deviceId} : cross verified: ${trustMap?.get(device)}") + Timber.v("## CrossSigning [$sId]- Trust for ${device.userId}|${device.deviceId} : cross verified: ${trustMap?.get(device)}") if (device.trustLevelEntity?.crossSignedVerified != crossSignedVerified) { - Timber.d("## CrossSigning - Trust change detected for ${device.userId}|${device.deviceId} : cross verified: $crossSignedVerified") + Timber.d("## CrossSigning [$sId]- Trust change detected for ${device.userId}|${device.deviceId} : cross verified: $crossSignedVerified") // need to save val trustEntity = device.trustLevelEntity if (trustEntity == null) { @@ -197,50 +213,46 @@ internal class UpdateTrustWorker(context: Context, params: WorkerParameters, ses } else { trustEntity.crossSignedVerified = crossSignedVerified } + } else { + Timber.v("## CrossSigning [$sId]- Trust unchanged for ${device.userId}|${device.deviceId} : cross verified: $crossSignedVerified") } } } } - - // So Cross Signing keys trust is updated, device trust is updated - // We can now update room shields? in the session DB? - updateTrustStep2(userList, myCrossSigningInfo) } - private suspend fun updateTrustStep2(userList: List, myCrossSigningInfo: MXCrossSigningInfo?) { - Timber.d("## CrossSigning - Updating shields for impacted rooms...") + private suspend fun updateRoomShieldInSummaries(roomList: List, myCrossSigningInfo: MXCrossSigningInfo?) { + val sId = myUserId.take(5) + Timber.d("## CrossSigning [$sId]- Updating shields for impacted rooms... ${roomList.logLimit()}") awaitTransaction(sessionRealmConfiguration) { sessionRealm -> Timber.d("## CrossSigning - Updating shields for impacted rooms - in transaction") Realm.getInstance(cryptoRealmConfiguration).use { cryptoRealm -> - sessionRealm.where(RoomMemberSummaryEntity::class.java) - .`in`(RoomMemberSummaryEntityFields.USER_ID, userList.toTypedArray()) - .distinct(RoomMemberSummaryEntityFields.ROOM_ID) - .findAll() - .map { it.roomId } - .also { Timber.d("## CrossSigning - ... impacted rooms ${it.logLimit()}") } - .forEach { roomId -> - RoomSummaryEntity.where(sessionRealm, roomId) - .equalTo(RoomSummaryEntityFields.IS_ENCRYPTED, true) - .findFirst() - ?.let { roomSummary -> - Timber.v("## CrossSigning - Check shield state for room $roomId") - val allActiveRoomMembers = RoomMemberHelper(sessionRealm, roomId).getActiveRoomMemberIds() - try { - val updatedTrust = computeRoomShield( - myCrossSigningInfo, - cryptoRealm, - allActiveRoomMembers, - roomSummary - ) - if (roomSummary.roomEncryptionTrustLevel != updatedTrust) { - Timber.d("## CrossSigning - Shield change detected for $roomId -> $updatedTrust") - roomSummary.roomEncryptionTrustLevel = updatedTrust - } - } catch (failure: Throwable) { - Timber.e(failure) - } + roomList.forEach { roomId -> + Timber.v("## CrossSigning [$sId]- Checking room $roomId") + RoomSummaryEntity.where(sessionRealm, roomId) +// .equalTo(RoomSummaryEntityFields.IS_ENCRYPTED, true) + .findFirst() + ?.let { roomSummary -> + Timber.v("## CrossSigning [$sId]- Check shield state for room $roomId") + val allActiveRoomMembers = RoomMemberHelper(sessionRealm, roomId).getActiveRoomMemberIds() + try { + val updatedTrust = computeRoomShield( + myCrossSigningInfo, + cryptoRealm, + allActiveRoomMembers, + roomSummary + ) + if (roomSummary.roomEncryptionTrustLevel != updatedTrust) { + Timber.d("## CrossSigning [$sId]- Shield change detected for $roomId -> $updatedTrust") + roomSummary.roomEncryptionTrustLevel = updatedTrust + } else { + Timber.v("## CrossSigning [$sId]- Shield unchanged for $roomId -> $updatedTrust") } - } + } catch (failure: Throwable) { + Timber.e(failure) + } + } + } } } Timber.d("## CrossSigning - Updating shields for impacted rooms - END") diff --git a/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/session/sync/handler/ShieldSummaryUpdater.kt b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/session/sync/handler/ShieldSummaryUpdater.kt new file mode 100644 index 0000000000..bcc078b550 --- /dev/null +++ b/matrix-sdk-android/src/kotlinCrypto/java/org/matrix/android/sdk/internal/session/sync/handler/ShieldSummaryUpdater.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2023 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.sync.handler + +import androidx.work.BackoffPolicy +import androidx.work.ExistingWorkPolicy +import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorker +import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorkerDataRepository +import org.matrix.android.sdk.internal.di.SessionId +import org.matrix.android.sdk.internal.di.WorkManagerProvider +import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.util.logLimit +import org.matrix.android.sdk.internal.worker.WorkerParamsFactory +import timber.log.Timber +import java.util.concurrent.TimeUnit +import javax.inject.Inject + +@SessionScope +internal class ShieldSummaryUpdater @Inject constructor( + @SessionId private val sessionId: String, + private val workManagerProvider: WorkManagerProvider, + private val updateTrustWorkerDataRepository: UpdateTrustWorkerDataRepository, +) { + + fun refreshShieldsForRoomIds(roomIds: Set) { + Timber.d("## CrossSigning - checkAffectedRoomShields for roomIds: ${roomIds.logLimit()}") + val workerParams = UpdateTrustWorker.Params( + sessionId = sessionId, + filename = updateTrustWorkerDataRepository.createParam(emptyList(), roomIds = roomIds.toList()) + ) + val workerData = WorkerParamsFactory.toData(workerParams) + + val workRequest = workManagerProvider.matrixOneTimeWorkRequestBuilder() + .setInputData(workerData) + .setBackoffCriteria(BackoffPolicy.LINEAR, WorkManagerProvider.BACKOFF_DELAY_MILLIS, TimeUnit.MILLISECONDS) + .build() + + workManagerProvider.workManager + .beginUniqueWork("TRUST_UPDATE_QUEUE", ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest) + .enqueue() + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt index e26ca2f86a..086d741acc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoSessionInfoProvider.kt @@ -19,19 +19,19 @@ package org.matrix.android.sdk.internal.crypto import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.internal.database.mapper.EventMapper import org.matrix.android.sdk.internal.database.model.EventEntity import org.matrix.android.sdk.internal.database.model.EventEntityFields -import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntity -import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity +import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.database.query.where import org.matrix.android.sdk.internal.database.query.whereType import org.matrix.android.sdk.internal.di.SessionDatabase import org.matrix.android.sdk.internal.di.UserId +import org.matrix.android.sdk.internal.query.process import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper import org.matrix.android.sdk.internal.util.fetchCopied -import org.matrix.android.sdk.internal.util.logLimit import timber.log.Timber import javax.inject.Inject @@ -89,14 +89,30 @@ internal class CryptoSessionInfoProvider @Inject constructor( } fun getRoomsWhereUsersAreParticipating(userList: List): List { + if (userList.contains(myUserId)) { + // just take all + val roomIds: List? = null + monarchy.doWithRealm { sessionRealm -> + RoomSummaryEntity.where(sessionRealm) + .process(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.activeMemberships()) + .findAll() + .map { it.roomId } + } + return roomIds.orEmpty() + } var roomIds: List? = null monarchy.doWithRealm { sessionRealm -> - roomIds = sessionRealm.where(RoomMemberSummaryEntity::class.java) - .`in`(RoomMemberSummaryEntityFields.USER_ID, userList.toTypedArray()) - .distinct(RoomMemberSummaryEntityFields.ROOM_ID) + roomIds = RoomSummaryEntity.where(sessionRealm) + .process(RoomSummaryEntityFields.MEMBERSHIP_STR, Membership.activeMemberships()) .findAll() + .filter { it.otherMemberIds.any { it in userList } } .map { it.roomId } - .also { Timber.d("## CrossSigning - ... impacted rooms ${it.logLimit()}") } +// roomIds = sessionRealm.where(RoomMemberSummaryEntity::class.java) +// .`in`(RoomMemberSummaryEntityFields.USER_ID, userList.toTypedArray()) +// .distinct(RoomMemberSummaryEntityFields.ROOM_ID) +// .findAll() +// .map { it.roomId } +// .also { Timber.d("## CrossSigning - ... impacted rooms ${it.logLimit()}") } } return roomIds.orEmpty() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorkerDataRepository.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorkerDataRepository.kt index 0878a9f765..d9207d05be 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorkerDataRepository.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorkerDataRepository.kt @@ -28,7 +28,10 @@ import javax.inject.Inject @JsonClass(generateAdapter = true) internal data class UpdateTrustWorkerData( @Json(name = "userIds") - val userIds: List + val userIds: List, + // When we just need to refresh the room shield (no change on user keys, but a membership change) + @Json(name = "roomIds") + val roomIds: List? = null ) internal class UpdateTrustWorkerDataRepository @Inject constructor( @@ -38,12 +41,12 @@ internal class UpdateTrustWorkerDataRepository @Inject constructor( private val jsonAdapter = MoshiProvider.providesMoshi().adapter(UpdateTrustWorkerData::class.java) // Return the path of the created file - fun createParam(userIds: List): String { + fun createParam(userIds: List, roomIds: List? = null): String { val filename = "${UUID.randomUUID()}.json" workingDirectory.mkdirs() val file = File(workingDirectory, filename) - UpdateTrustWorkerData(userIds = userIds) + UpdateTrustWorkerData(userIds = userIds, roomIds = roomIds) .let { jsonAdapter.toJson(it) } .let { file.writeText(it) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index b251bc24f0..cbb75398c4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -168,6 +168,9 @@ internal class RoomSummaryUpdater @Inject constructor( val roomAliases = ContentMapper.map(lastAliasesEvent?.content).toModel()?.aliases .orEmpty() roomSummaryEntity.updateAliases(roomAliases) + + val wasEncrypted = roomSummaryEntity.isEncrypted + roomSummaryEntity.isEncrypted = encryptionEvent != null roomSummaryEntity.e2eAlgorithm = ContentMapper.map(encryptionEvent?.content) @@ -197,17 +200,13 @@ internal class RoomSummaryUpdater @Inject constructor( // better to use what we know roomSummaryEntity.joinedMembersCount = otherRoomMembers.size + 1 } - if (roomSummaryEntity.isEncrypted && otherRoomMembers.isNotEmpty()) { - if (aggregator == null) { - // Do it now - // mmm maybe we could only refresh shield instead of checking trust also? - // XXX why doing this here? we don't show shield anymore and it will be refreshed - // by the sdk - // crossSigningService.checkTrustAndAffectedRoomShields(otherRoomMembers) - } else { - // Schedule it - aggregator.userIdsForCheckingTrustAndAffectedRoomShields.addAll(otherRoomMembers) - } + } + + if (roomSummaryEntity.isEncrypted) { + if (!wasEncrypted || updateMembers || roomSummaryEntity.roomEncryptionTrustLevel == null) { + // trigger a shield update + // if users add devices/keys or signatures the device list manager will trigger a refresh + aggregator?.roomsWithMembershipChangesForShieldUpdate?.add(roomId) } } } @@ -410,7 +409,7 @@ internal class RoomSummaryUpdater @Inject constructor( val relatedSpaces = lookupMap.keys .filter { it.roomType == RoomType.SPACE } .filter { - dmRoom.otherMemberIds.toList().intersect(it.otherMemberIds.toList()).isNotEmpty() + dmRoom.otherMemberIds.toList().intersect(it.otherMemberIds.toSet()).isNotEmpty() } .map { it.roomId } .distinct() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt index af05e08da3..4532a8d418 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt @@ -29,7 +29,8 @@ internal class SyncResponsePostTreatmentAggregator { val userIdsToFetch = mutableSetOf() // Set of users to call `crossSigningService.checkTrustAndAffectedRoomShields` once per sync - val userIdsForCheckingTrustAndAffectedRoomShields = mutableSetOf() + + val roomsWithMembershipChangesForShieldUpdate = mutableSetOf() // For the crypto store val cryptoStoreAggregator = CryptoStoreAggregator() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt index 948a0a2501..3700bbf46f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt @@ -19,7 +19,6 @@ package org.matrix.android.sdk.internal.session.sync.handler import androidx.work.BackoffPolicy import androidx.work.ExistingWorkPolicy import org.matrix.android.sdk.api.MatrixPatterns -import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorker import org.matrix.android.sdk.internal.crypto.crosssigning.UpdateTrustWorkerDataRepository import org.matrix.android.sdk.internal.di.SessionId @@ -39,16 +38,16 @@ internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor( private val directChatsHelper: DirectChatsHelper, private val ephemeralTemporaryStore: RoomSyncEphemeralTemporaryStore, private val updateUserAccountDataTask: UpdateUserAccountDataTask, - private val crossSigningService: CrossSigningService, private val updateTrustWorkerDataRepository: UpdateTrustWorkerDataRepository, private val workManagerProvider: WorkManagerProvider, + private val roomShieldSummaryUpdater: ShieldSummaryUpdater, @SessionId private val sessionId: String, ) { suspend fun handle(aggregator: SyncResponsePostTreatmentAggregator) { cleanupEphemeralFiles(aggregator.ephemeralFilesToDelete) updateDirectUserIds(aggregator.directChatsToCheck) fetchAndUpdateUsers(aggregator.userIdsToFetch) - handleUserIdsForCheckingTrustAndAffectedRoomShields(aggregator.userIdsForCheckingTrustAndAffectedRoomShields) + handleRefreshRoomShieldsForRooms(aggregator.roomsWithMembershipChangesForShieldUpdate) } private fun cleanupEphemeralFiles(ephemeralFilesToDelete: List) { @@ -105,8 +104,8 @@ internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor( .enqueue() } - private suspend fun handleUserIdsForCheckingTrustAndAffectedRoomShields(userIdsWithDeviceUpdate: Collection) { - if (userIdsWithDeviceUpdate.isEmpty()) return - crossSigningService.checkTrustAndAffectedRoomShields(userIdsWithDeviceUpdate.toList()) + private fun handleRefreshRoomShieldsForRooms(roomIds: Set) { + if (roomIds.isEmpty()) return + roomShieldSummaryUpdater.refreshShieldsForRoomIds(roomIds) } } diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/network/OutgoingRequestsProcessor.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/network/OutgoingRequestsProcessor.kt index 77fd9b3ea3..9e0301f487 100644 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/network/OutgoingRequestsProcessor.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/network/OutgoingRequestsProcessor.kt @@ -27,10 +27,10 @@ import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.internal.crypto.ComputeShieldForGroupUseCase import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider import org.matrix.android.sdk.internal.crypto.OlmMachine import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.session.sync.handler.ShieldSummaryUpdater import org.matrix.rustcomponents.sdk.crypto.Request import org.matrix.rustcomponents.sdk.crypto.RequestType import timber.log.Timber @@ -43,7 +43,7 @@ internal class OutgoingRequestsProcessor @Inject constructor( private val requestSender: RequestSender, private val coroutineScope: CoroutineScope, private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, - private val computeShieldForGroup: ComputeShieldForGroupUseCase, + private val shieldSummaryUpdater: ShieldSummaryUpdater, private val matrixConfiguration: MatrixConfiguration, private val coroutineDispatchers: MatrixCoroutineDispatchers, ) { @@ -137,7 +137,7 @@ internal class OutgoingRequestsProcessor @Inject constructor( return try { val response = requestSender.queryKeys(request) olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_QUERY, response) - coroutineScope.updateShields(olmMachine, request.users) + shieldSummaryUpdater.refreshShieldsForRoomsWithMembers(request.users) coroutineScope.markMessageVerificationStatesAsDirty(request.users) true } catch (throwable: Throwable) { @@ -146,18 +146,6 @@ internal class OutgoingRequestsProcessor @Inject constructor( } } - private fun CoroutineScope.updateShields(olmMachine: OlmMachine, userIds: List) = launch(coroutineDispatchers.computation) { - cryptoSessionInfoProvider.getRoomsWhereUsersAreParticipating(userIds).forEach { roomId -> - if (cryptoSessionInfoProvider.isRoomEncrypted(roomId)) { - val userGroup = cryptoSessionInfoProvider.getUserListForShieldComputation(roomId) - val shield = computeShieldForGroup(olmMachine, userGroup) - cryptoSessionInfoProvider.updateShieldForRoom(roomId, shield) - } else { - cryptoSessionInfoProvider.updateShieldForRoom(roomId, null) - } - } - } - private fun CoroutineScope.markMessageVerificationStatesAsDirty(userIds: List) = launch(coroutineDispatchers.computation) { cryptoSessionInfoProvider.markMessageVerificationStateAsDirty(userIds) } diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/session/sync/handler/ShieldSummaryUpdater.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/session/sync/handler/ShieldSummaryUpdater.kt new file mode 100644 index 0000000000..9f77d7003e --- /dev/null +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/session/sync/handler/ShieldSummaryUpdater.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.sync.handler + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.MatrixCoroutineDispatchers +import org.matrix.android.sdk.internal.crypto.ComputeShieldForGroupUseCase +import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider +import org.matrix.android.sdk.internal.crypto.OlmMachine +import org.matrix.android.sdk.internal.session.SessionScope +import javax.inject.Inject + +@SessionScope +internal class ShieldSummaryUpdater @Inject constructor( + private val olmMachine: dagger.Lazy, + private val coroutineScope: CoroutineScope, + private val coroutineDispatchers: MatrixCoroutineDispatchers, + private val cryptoSessionInfoProvider: CryptoSessionInfoProvider, + private val computeShieldForGroup: ComputeShieldForGroupUseCase, +) { + + fun refreshShieldsForRoomsWithMembers(userIds: List) { + coroutineScope.launch(coroutineDispatchers.computation) { + cryptoSessionInfoProvider.getRoomsWhereUsersAreParticipating(userIds).forEach { roomId -> + if (cryptoSessionInfoProvider.isRoomEncrypted(roomId)) { + val userGroup = cryptoSessionInfoProvider.getUserListForShieldComputation(roomId) + val shield = computeShieldForGroup(olmMachine.get(), userGroup) + cryptoSessionInfoProvider.updateShieldForRoom(roomId, shield) + } else { + cryptoSessionInfoProvider.updateShieldForRoom(roomId, null) + } + } + } + } + + fun refreshShieldsForRoomIds(roomIds: Set) { + coroutineScope.launch(coroutineDispatchers.computation) { + roomIds.forEach { roomId -> + val userGroup = cryptoSessionInfoProvider.getUserListForShieldComputation(roomId) + val shield = computeShieldForGroup(olmMachine.get(), userGroup) + cryptoSessionInfoProvider.updateShieldForRoom(roomId, shield) + } + } + } +} From 1d651db82ba581eac333ba980b85e82a0633f632 Mon Sep 17 00:00:00 2001 From: valere Date: Thu, 8 Jun 2023 09:07:21 +0200 Subject: [PATCH 132/234] Add change log --- changelog.d/8507.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/8507.bugfix diff --git a/changelog.d/8507.bugfix b/changelog.d/8507.bugfix new file mode 100644 index 0000000000..eb609dd0fc --- /dev/null +++ b/changelog.d/8507.bugfix @@ -0,0 +1 @@ +In some conditions the room shield is not refreshed correctly From 257072330f858eeecce8872ed515ff8a6142ad0a Mon Sep 17 00:00:00 2001 From: random Date: Mon, 12 Jun 2023 09:18:33 +0000 Subject: [PATCH 133/234] Translated using Weblate (Italian) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- library/ui-strings/src/main/res/values-it/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-it/strings.xml b/library/ui-strings/src/main/res/values-it/strings.xml index 0df7d9d6b0..5d7cffd320 100644 --- a/library/ui-strings/src/main/res/values-it/strings.xml +++ b/library/ui-strings/src/main/res/values-it/strings.xml @@ -677,7 +677,7 @@ ${app_name} non è influenzato dall\'ottimizzazione della batteria. Se si lascia un dispositivo scollegato, fermo e con lo schermo spento, dopo un certo tempo questo entra in modalità Doze. Ciò impedisce alle App di accedere alla rete e ritarda le attività, le sincronizzazioni e la ricezione dei normali allarmi. Ignora l\'ottimizzazione - Nessun APK Google Play Services trovato. Le notifiche non funzioneranno bene. + Google Play Services non trovato. Le notifiche non funzioneranno bene. Chiamata video in corso… Backup delle chiavi Usa il Backup delle chiavi From 572bdb6dfe214be5dbfd35ca34664a034e2d7fff Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Wed, 14 Jun 2023 16:20:21 -0500 Subject: [PATCH 134/234] Fix fallbackKeySharingStrategy Signed-off-by: Alex Baker --- changelog.d/8541.bugfix | 1 + .../main/java/im/vector/app/core/di/ConfigurationModule.kt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelog.d/8541.bugfix diff --git a/changelog.d/8541.bugfix b/changelog.d/8541.bugfix new file mode 100644 index 0000000000..9e419327da --- /dev/null +++ b/changelog.d/8541.bugfix @@ -0,0 +1 @@ +Fix crypto config fallback key sharing strategy diff --git a/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt b/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt index 7a1f7f2292..7c8dea3b7d 100644 --- a/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/ConfigurationModule.kt @@ -77,8 +77,8 @@ object ConfigurationModule { fun providesCryptoConfig() = CryptoConfig( fallbackKeySharingStrategy = when (Config.KEY_SHARING_STRATEGY) { KeySharingStrategy.WhenSendingEvent -> OutboundSessionKeySharingStrategy.WhenSendingEvent - KeySharingStrategy.WhenEnteringRoom -> OutboundSessionKeySharingStrategy.WhenSendingEvent - KeySharingStrategy.WhenTyping -> OutboundSessionKeySharingStrategy.WhenSendingEvent + KeySharingStrategy.WhenEnteringRoom -> OutboundSessionKeySharingStrategy.WhenEnteringRoom + KeySharingStrategy.WhenTyping -> OutboundSessionKeySharingStrategy.WhenTyping } ) From 7497cf6729e6b9b44431a4e4736d77bfb5ebb937 Mon Sep 17 00:00:00 2001 From: Someone Date: Thu, 15 Jun 2023 10:14:44 +0000 Subject: [PATCH 135/234] Translated using Weblate (Vietnamese) Currently translated at 87.2% (2300 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- .../src/main/res/values-vi/strings.xml | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index cc6e185e1c..38da26bd3d 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2496,5 +2496,39 @@ Trước khi người dùng này tin tưởng phiên này, các tin nhắn gửi đến phiên và từ phiên đều mang nhãn cảnh báo. Xác thực danh tính để truy cập vào các tin nhắn được mã hóa và chứng minh danh tính của bạn với những người khác. Tải bản dựng mới nhất (ghi chú: bạn có thể gặp vấn đề khi đăng nhập) - + + Xem lại để chắc chắn rằng tài khoản bạn an toàn + %1$d phút %2$d giây + Hoạt động lần cuối + Tên phiên + Mã hóa bởi một thiết bị đã xóa + Mã hóa bị thiết lập sai + Chọn các phiên + Hủy bộ lọc + Thông báo đẩy + Tên + Địa chỉ + Phiên không hoạt động + Phiên chưa xác thực + Yêu cầu bàn phím không được phép cập nhật các dữ liệu cá nhân hóa như lịch sử nhập và từ điển dựa trên những gì bạn nhắn trong trò chuyện. Tuy vậy một số bàn phím sẽ không tuân theo cài đặt này. + Tính xác thực của tin nhắn đã mã hóa này không thể được đảm bảo trên thiết bị này. + Bạn có các phiên chưa xác thực + %1$s, %2$s, %3$s + Đăng xuất + Đăng xuất khỏi phiên này + Chi tiết phiên + Thông tin phần mềm, thiết bị, và hoạt động. + Phiên bản + Trình duyệt + Mẫu mã + Đổi tên phiên + Hiện địa chỉ Internet (IP) + Phần mềm + Địa chỉ Internet (IP) + Tên phiên + Gửi tin nhắn đầu tiên để mời %s vào cuộc trò chuyện + Bàn phím ẩn danh + Ẩn địa chỉ Internet (IP) + Phiên đã xác thực + Hệ điều hành \ No newline at end of file From 710d21f6a4e76c7a3a1121a0b70fd2ef4380b1d8 Mon Sep 17 00:00:00 2001 From: Yoan Pintas Date: Fri, 16 Jun 2023 11:13:13 +0200 Subject: [PATCH 136/234] Implement MSC3987: Push actions clean-up (#8530) --- changelog.d/8503.misc | 1 + .../org/matrix/android/sdk/api/session/pushrules/Action.kt | 4 +--- .../android/sdk/api/session/pushrules/rest/PushRule.kt | 4 +--- .../session/room/notification/RoomPushRuleMapper.kt | 4 ++-- .../vector/app/features/notifications/NotificationAction.kt | 1 - .../app/features/settings/notifications/StandardActions.kt | 2 +- .../usecase/GetPushRulesOnInvalidStateUseCaseTest.kt | 6 +++--- .../usecase/UpdatePushRulesIfNeededUseCaseTest.kt | 4 ++-- 8 files changed, 11 insertions(+), 15 deletions(-) create mode 100644 changelog.d/8503.misc diff --git a/changelog.d/8503.misc b/changelog.d/8503.misc new file mode 100644 index 0000000000..26f9e76959 --- /dev/null +++ b/changelog.d/8503.misc @@ -0,0 +1 @@ +MSC3987 implementation: the 'dont_notify' action for a push_rule is now deprecated and replaced by an empty action list. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt index 6122aae972..bbf65288cc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/Action.kt @@ -20,7 +20,6 @@ import timber.log.Timber sealed class Action { object Notify : Action() - object DoNotNotify : Action() data class Sound(val sound: String = ACTION_OBJECT_VALUE_VALUE_DEFAULT) : Action() data class Highlight(val highlight: Boolean) : Action() @@ -72,7 +71,6 @@ fun List.toJson(): List { return map { action -> when (action) { is Action.Notify -> Action.ACTION_NOTIFY - is Action.DoNotNotify -> Action.ACTION_DONT_NOTIFY is Action.Sound -> { mapOf( Action.ACTION_OBJECT_SET_TWEAK_KEY to Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND, @@ -95,7 +93,7 @@ fun PushRule.getActions(): List { actions.forEach { actionStrOrObj -> when (actionStrOrObj) { Action.ACTION_NOTIFY -> Action.Notify - Action.ACTION_DONT_NOTIFY -> Action.DoNotNotify + Action.ACTION_DONT_NOTIFY -> return@forEach is Map<*, *> -> { when (actionStrOrObj[Action.ACTION_OBJECT_SET_TWEAK_KEY]) { Action.ACTION_OBJECT_SET_TWEAK_VALUE_SOUND -> { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt index a11ffc0a98..31dbd8dd2e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/pushrules/rest/PushRule.kt @@ -121,8 +121,6 @@ data class PushRule( if (notify) { mutableActions.add(Action.ACTION_NOTIFY) - } else { - mutableActions.add(Action.ACTION_DONT_NOTIFY) } return copy(actions = mutableActions) @@ -140,5 +138,5 @@ data class PushRule( * * @return true if the rule should not play sound */ - fun shouldNotNotify() = actions.contains(Action.ACTION_DONT_NOTIFY) + fun shouldNotNotify() = actions.isEmpty() || actions.contains(Action.ACTION_DONT_NOTIFY) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt index 42b069f8fa..8707c24383 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/notification/RoomPushRuleMapper.kt @@ -63,7 +63,7 @@ internal fun RoomNotificationState.toRoomPushRule(roomId: String): RoomPushRule? pattern = roomId ) val rule = PushRule( - actions = listOf(Action.DoNotNotify).toJson(), + actions = emptyList().toJson(), enabled = true, ruleId = roomId, conditions = listOf(condition) @@ -81,7 +81,7 @@ internal fun RoomNotificationState.toRoomPushRule(roomId: String): RoomPushRule? internal fun RoomPushRule.toRoomNotificationState(): RoomNotificationState { return if (rule.enabled) { val actions = rule.getActions() - if (actions.contains(Action.DoNotNotify)) { + if (actions.isEmpty()) { if (kind == RuleSetKey.OVERRIDE) { RoomNotificationState.MUTE } else { diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationAction.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationAction.kt index 19c7fcea7d..ffa833b7ce 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationAction.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationAction.kt @@ -30,7 +30,6 @@ fun List.toNotificationAction(): NotificationAction { forEach { action -> when (action) { is Action.Notify -> shouldNotify = true - is Action.DoNotNotify -> shouldNotify = false is Action.Highlight -> highlight = action.highlight is Action.Sound -> sound = action.sound } diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/StandardActions.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/StandardActions.kt index b19b5bcdd6..46aaa38ae5 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/StandardActions.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/StandardActions.kt @@ -26,6 +26,6 @@ sealed class StandardActions( object NotifyRingSound : StandardActions(actions = listOf(Action.Notify, Action.Sound(sound = Action.ACTION_OBJECT_VALUE_VALUE_RING))) object Highlight : StandardActions(actions = listOf(Action.Notify, Action.Highlight(highlight = true))) object HighlightDefaultSound : StandardActions(actions = listOf(Action.Notify, Action.Highlight(highlight = true), Action.Sound())) - object DontNotify : StandardActions(actions = listOf(Action.DoNotNotify)) + object DontNotify : StandardActions(actions = emptyList()) object Disabled : StandardActions(actions = null) } diff --git a/vector/src/test/java/im/vector/app/features/settings/notifications/usecase/GetPushRulesOnInvalidStateUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/notifications/usecase/GetPushRulesOnInvalidStateUseCaseTest.kt index a434ac93d3..8ab90c18dc 100644 --- a/vector/src/test/java/im/vector/app/features/settings/notifications/usecase/GetPushRulesOnInvalidStateUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/features/settings/notifications/usecase/GetPushRulesOnInvalidStateUseCaseTest.kt @@ -48,19 +48,19 @@ internal class GetPushRulesOnInvalidStateUseCaseTest { fun `given a list of push rules with children not matching their parent when execute then returns the list of not matching rules`() { // Given val firstActions = listOf(Action.Notify) - val secondActions = listOf(Action.DoNotNotify) + val secondActions = emptyList() givenARuleList( listOf( // first set of related rules givenARuleId(RuleIds.RULE_ID_ONE_TO_ONE_ROOM, true, firstActions), - givenARuleId(RuleIds.RULE_ID_POLL_START_ONE_TO_ONE, true, listOf(Action.DoNotNotify)), // diff + givenARuleId(RuleIds.RULE_ID_POLL_START_ONE_TO_ONE, true, emptyList()), // diff givenARuleId(RuleIds.RULE_ID_POLL_START_ONE_TO_ONE_UNSTABLE, true, emptyList()), // diff givenARuleId(RuleIds.RULE_ID_POLL_END_ONE_TO_ONE, false, listOf(Action.Notify)), // diff givenARuleId(RuleIds.RULE_ID_POLL_END_ONE_TO_ONE_UNSTABLE, true, listOf(Action.Notify)), // second set of related rules givenARuleId(RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, false, secondActions), givenARuleId(RuleIds.RULE_ID_POLL_START, true, listOf(Action.Notify)), // diff - givenARuleId(RuleIds.RULE_ID_POLL_START_UNSTABLE, false, listOf(Action.DoNotNotify)), + givenARuleId(RuleIds.RULE_ID_POLL_START_UNSTABLE, false, emptyList()), givenARuleId(RuleIds.RULE_ID_POLL_END, false, listOf(Action.Notify)), // diff givenARuleId(RuleIds.RULE_ID_POLL_END_UNSTABLE, true, listOf()), // diff // Another rule diff --git a/vector/src/test/java/im/vector/app/features/settings/notifications/usecase/UpdatePushRulesIfNeededUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/notifications/usecase/UpdatePushRulesIfNeededUseCaseTest.kt index 1f76a7f9a5..77d21c39dc 100644 --- a/vector/src/test/java/im/vector/app/features/settings/notifications/usecase/UpdatePushRulesIfNeededUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/features/settings/notifications/usecase/UpdatePushRulesIfNeededUseCaseTest.kt @@ -54,12 +54,12 @@ internal class UpdatePushRulesIfNeededUseCaseTest { val firstParentActions = listOf(Action.Notify) val firstParent = givenARuleId(RuleIds.RULE_ID_ONE_TO_ONE_ROOM, firstParentEnabled, firstParentActions) val secondParentEnabled = false - val secondParentActions = listOf(Action.DoNotNotify) + val secondParentActions = emptyList() val secondParent = givenARuleId(RuleIds.RULE_ID_ALL_OTHER_MESSAGES_ROOMS, secondParentEnabled, secondParentActions) val rulesOnError = listOf( // first set of related rules firstParent, - givenARuleId(RuleIds.RULE_ID_POLL_START_ONE_TO_ONE, true, listOf(Action.DoNotNotify)), // diff + givenARuleId(RuleIds.RULE_ID_POLL_START_ONE_TO_ONE, true, emptyList()), // diff givenARuleId(RuleIds.RULE_ID_POLL_START_ONE_TO_ONE_UNSTABLE, true, emptyList()), // diff givenARuleId(RuleIds.RULE_ID_POLL_END_ONE_TO_ONE, false, listOf(Action.Notify)), // diff // second set of related rules From cd5737276c7cf1ec5f32ba9c96ad9745d85737d5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Jun 2023 11:08:53 +0000 Subject: [PATCH 137/234] Translated using Weblate (Portuguese (Brazil)) Currently translated at 98.0% (2584 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- library/ui-strings/src/main/res/values-pt-rBR/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml index 7d1db41989..a113ecec2d 100644 --- a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml +++ b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml @@ -2527,7 +2527,7 @@ Você precisa ter as permissões certas a fim de compartilhar localização ao vivo nesta sala. Você não tem permissão para compartilhar localização ao vivo Resultados vão ser visíveis quando a sondagem estiver terminada - Ao convidar alguém para uma uma sala criptografada que compartilha o histórico de texto, ele será visível mesmo sendo criptografado. + Ao convidar alguém para uma sala criptografada que compartilha o histórico de texto, ele será visível mesmo sendo criptografado. MSC3061: Compartilhando chaves de sala para mensagens passadas Envie sua primeira mensagem para convidar %s a fazer chat Mensagens neste chat vão ser encriptadas ponta-a-ponta. From 38ba1cbbe9115ab72abcf20028e009da5e7d73dd Mon Sep 17 00:00:00 2001 From: random Date: Fri, 16 Jun 2023 10:10:30 +0000 Subject: [PATCH 138/234] Translated using Weblate (Italian) Currently translated at 100.0% (2636 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/it/ --- .../src/main/res/values-it/strings.xml | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/library/ui-strings/src/main/res/values-it/strings.xml b/library/ui-strings/src/main/res/values-it/strings.xml index 5d7cffd320..8a12dc5ca4 100644 --- a/library/ui-strings/src/main/res/values-it/strings.xml +++ b/library/ui-strings/src/main/res/values-it/strings.xml @@ -2,9 +2,9 @@ Invito di %s %1$s ha invitato %2$s - %1$s ti ha invitato - %1$s è entrato nella stanza - %1$s è uscito dalla stanza + %1$s ti ha invitato/a + %1$s è entrato/a nella stanza + %1$s è uscito/a dalla stanza %1$s ha rifiutato l\'invito %1$s ha buttato fuori %2$s %1$s ha rimosso il ban nei confronti di %2$s @@ -60,8 +60,8 @@ Invito di %1$s. Motivo: %2$s %1$s ha invitato %2$s. Motivo: %3$s %1$s ti ha invitato. Motivo: %2$s - %1$s è entrato nella stanza. Motivo: %2$s - %1$s è uscito dalla stanza. Motivo: %2$s + %1$s è entrato/a nella stanza. Motivo: %2$s + %1$s è uscito/a dalla stanza. Motivo: %2$s %1$s ha rifiutato l\'invito. Motivo: %2$s %1$s ha cacciato fuori %2$s. Motivo: %3$s %1$s ha riammesso %2$s. Motivo: %3$s @@ -87,8 +87,8 @@ Il tuo invito Hai creato la stanza Hai invitato %1$s - Sei entrato nella stanza - Sei uscito dalla stanza + Sei entrato/a nella stanza + Sei uscito/a dalla stanza Hai rifiutato l\'invito Hai buttato fuori %1$s Hai rimosso il ban nei confronti di %1$s @@ -133,8 +133,8 @@ %1$s da %2$s a %3$s Il tuo invito. Motivo: %1$s Hai invitato %1$s. Motivo: %2$s - Sei entrato nella stanza. Motivo: %1$s - Sei uscito dalla stanza. Motivo: %1$s + Sei entrato/a nella stanza. Motivo: %1$s + Sei uscito/a dalla stanza. Motivo: %1$s Hai rifiutato l\'invito. Motivo: %1$s Hai cacciato %1$s. Motivo: %2$s Hai riammesso %1$s. Motivo: %2$s @@ -160,10 +160,10 @@ %1$s ha impedito l\'accesso alla stanza agli ospiti. Hai permesso l\'accesso agli ospiti. %1$s ha permesso l\'accesso agli ospiti. - Sei entrato. Motivo: %1$s - Sei uscito. Motivo: %1$s - %1$s è uscito. Motivo: %2$s - %1$s è entrato. Motivo: %2$s + Sei entrato/a. Motivo: %1$s + Sei uscito/a. Motivo: %1$s + %1$s è uscito/a. Motivo: %2$s + %1$s è entrato/a. Motivo: %2$s Hai revocato l\'invito a %1$s %1$s ha revocato l\'invito a %2$s Hai invitato %1$s @@ -172,10 +172,10 @@ %s ha aggiornato la stanza. Hai reso visibili i messaggi futuri a %1$s %1$s ha reso visibili i messaggi futuri a %2$s - Sei uscito dalla stanza - %1$s è uscito dalla stanza - Sei entrato - %1$s è entrato + Sei uscito/a dalla stanza + %1$s è uscito/a dalla stanza + Sei entrato/a + %1$s è entrato/a Hai creato la discussione %1$s ha creato la discussione Stanza vuota (era %s) @@ -528,7 +528,7 @@ Crea Home Stanze - Invitato + Invitato/a %2$s ti ha buttato fuori da %1$s %2$s ti ha bannato da %1$s Motivo: %1$s @@ -851,7 +851,7 @@ Rispondi Riprova Ti ha inviato un invito - Invitato da %s + Invitato/a da %s Non hai più messaggi non letti Conversazioni Le tue conversazioni dirette verranno mostrate qui. Tocca il pulsante + in basso a destra per iniziarne qualcuna. @@ -1684,7 +1684,7 @@ Fallo solo se non hai altri dispositivi con cui fare la verifica. Reimposta tutto Hai dimenticato o perso tutte le opzioni di ripristino\? Reimposta tutto - Sei entrato. + Sei entrato/a. I messaggi in questa conversazione sono cifrati end-to-end. Esci Impostazioni @@ -1716,7 +1716,7 @@ Il codice PIN è richiesto ogni volta che apri ${app_name}. Il codice PIN è richiesto dopo 2 minuti di inattività su ${app_name}. Richiedi il PIN dopo 2 minuti - %s è entrato. + %s è entrato/a. L\'applicazione è in attesa del PUSH Scarta le modifiche Ci sono modifiche non salvate. Scartare le modifiche\? @@ -1932,7 +1932,7 @@ Sincronizzazione iniziale: \nIn attesa di risposta dal server… Messaggio inviato - Sei stato invitato + Sei stato/a invitato/a Gli Spazi sono un nuovo modo per raggruppare stanze e contatti. Aggiungi stanze e Spazi esistenti Esci @@ -2008,7 +2008,7 @@ Consigliato Gestisci stanze Cerchi qualcuno che non è in %s\? - %s ti ha invitato + %s ti ha invitato/a Stanza pubblica Invia i file multimediali nella dimensione originale From 7d4af8d05939693c09abc2d852a0da29e7d883ff Mon Sep 17 00:00:00 2001 From: rofyobilte Date: Sat, 17 Jun 2023 03:31:29 +0000 Subject: [PATCH 139/234] Translated using Weblate (Portuguese (Brazil)) Currently translated at 98.5% (2597 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/ --- .../src/main/res/values-pt-rBR/strings.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml index a113ecec2d..ee6431ea3f 100644 --- a/library/ui-strings/src/main/res/values-pt-rBR/strings.xml +++ b/library/ui-strings/src/main/res/values-pt-rBR/strings.xml @@ -2896,4 +2896,17 @@ Incapaz de reproduzir esse broadcast de voz. Incapaz de decriptar esse broadcast de voz. Erro de conexão - Gravação pausada + Aplicação actualizada + Versão criptográfica + Não foi possível contactar o servidor doméstico. Se ainda assim terminar sessão, este dispositivo não será apagado da sua lista de dispositivos, poderá querer removê-lo utilizando outro cliente. + Imagem de perfil do utilizador %1$s + Iniciou uma emissão de voz + Histórico da sondagem + Verificar com outro dispositivo + Verifique a sua identidade para aceder a mensagens encriptadas e provar a sua identidade a outros. + Foi enviado um pedido de verificação. Abra uma das suas outras sessões para aceitar e iniciar a verificação. + Só é possível convidar um email de cada vez + Terminar sessão ainda assim + Verificação a partir de Chave ou Frase Segura… + Até que este utilizador confie nesta sessão, as mensagens enviadas para e a partir dela são marcadas com avisos. \ No newline at end of file From e8e8e7c5bcb527032179c1971ad74529bf3aa9f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Sat, 17 Jun 2023 07:39:17 +0000 Subject: [PATCH 140/234] Translated using Weblate (Estonian) Currently translated at 100.0% (2640 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/et/ --- library/ui-strings/src/main/res/values-et/strings.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/ui-strings/src/main/res/values-et/strings.xml b/library/ui-strings/src/main/res/values-et/strings.xml index 21ad8c2fd6..cf70cbf5d8 100644 --- a/library/ui-strings/src/main/res/values-et/strings.xml +++ b/library/ui-strings/src/main/res/values-et/strings.xml @@ -2958,4 +2958,12 @@ Rakendus on uuendatud Jah, ikkagi logi välja Ühendus koduserveriga puudub. Kui sa jätkad ja logid võrgust välja, siis seda seadet ei kustutata sinu seadmete loendist ning saad seda hiljem mõnest muust Matrixi kliendist teha. + Ikkagi alusta vestlust + Kutsu siiski + Allpool loetletud Matrix\'i kasutajatunnustele ei leidunud profiile. Kas sa ikkagi tahaksid nendega vestlust alustada\? +\n +\n%s + Allpool loetletud Matrix\'i kasutajatunnustele ei leidunud profiile. Kas sa ikkagi tahaksid neile kutse saata\? +\n +\n%s \ No newline at end of file From f5ac1f120a873be7bea7c65c99f745586975ac25 Mon Sep 17 00:00:00 2001 From: th ad Date: Sat, 17 Jun 2023 21:11:20 +0000 Subject: [PATCH 141/234] Translated using Weblate (Slovenian) Currently translated at 2.1% (57 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sl/ --- .../src/main/res/values-sl/strings.xml | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-sl/strings.xml b/library/ui-strings/src/main/res/values-sl/strings.xml index 80bc09dd34..a94ab8c2ef 100644 --- a/library/ui-strings/src/main/res/values-sl/strings.xml +++ b/library/ui-strings/src/main/res/values-sl/strings.xml @@ -1,5 +1,5 @@ - + Ime Prijava hrošča Pošlji ekransko sliko @@ -22,4 +22,44 @@ %1$s je ustvaril sobo Ni omrežja. Preveri internetno povezavo. Ustvari novo sobo + Ustvaril si razpravo + %1$s je povabil %2$s + Pridružil si se + %1$s je izključil %2$s + Preklical si povabilo %1$s + %1$s je spremenil svojega avatarja + %1$s je spremenil svoje prikazno ime v %2$s + Svoje prikazno ime si spremenil v %1$s + %1$s je spremenil svoje prikazno ime iz %2$s v %3$s + %1$s je odstranil svoje prikazno ime (bilo je %2$s) + Tvoje povabilo + Odstranil si %1$s + %1$s je preklical povabilo %2$s + %1$s je spremenil temo v: %2$s + %1$s je spremenil avatarja sobe + Spremenil si avatarja sobe + Začel si video klic. + %s je začel video klic. + Začel si video klic. + %s je končal klic. + Končal si klic. + %1$s je %2$s omogočil ogled prihodnje zgodovine sobe + Omogočil si ogled prihodnje zgodovine sobe %1$s + + %1$d izbran + %1$d izbrana + %1$d izbranih + %1$d izbranih + + %1$s je ustvaril razpravo + Povabil si %1$s + %1$s je odstranil %2$s + %1$s je izključil %2$s + Izključil si %1$s + Spremenil si svojega avatarja + %1$s je spremenil svoje prikazno ime v %2$s + Svoje prikazno ime si spremenil iz %1$s v %2$s + Odstranil si svoje prikazno ime (bilo je %1$s) + Temo si spremenil v: %1$s + %s je začel video klic. \ No newline at end of file From 3c645ef1bbcbe7354c18c53ae33c61087a5c1df9 Mon Sep 17 00:00:00 2001 From: th ad Date: Sun, 18 Jun 2023 07:18:45 +0000 Subject: [PATCH 142/234] Translated using Weblate (Slovenian) Currently translated at 2.2% (59 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sl/ --- library/ui-strings/src/main/res/values-sl/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ui-strings/src/main/res/values-sl/strings.xml b/library/ui-strings/src/main/res/values-sl/strings.xml index a94ab8c2ef..4d7ffd3d3d 100644 --- a/library/ui-strings/src/main/res/values-sl/strings.xml +++ b/library/ui-strings/src/main/res/values-sl/strings.xml @@ -62,4 +62,6 @@ Odstranil si svoje prikazno ime (bilo je %1$s) Temo si spremenil v: %1$s %s je začel video klic. + %1$s je omočil %2$s ogled prihodnjih sporočil + %1$s si omogočil ogled prihodnjih sporočil \ No newline at end of file From 9d239bf94da509006be576312c39762398ecd59f Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Mon, 19 Jun 2023 13:41:08 +0100 Subject: [PATCH 143/234] Use proper API to insert mention from timeline user --- .../composer/MessageComposerFragment.kt | 57 +++++++++++-------- .../detail/composer/RichTextComposerLayout.kt | 4 ++ 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt index 6a3ca0f1c0..2b85fc482f 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt @@ -101,6 +101,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.content.ContentAttachmentData +import org.matrix.android.sdk.api.session.permalinks.PermalinkService import org.matrix.android.sdk.api.util.MatrixItem import reactivecircus.flowbinding.android.view.focusChanges import reactivecircus.flowbinding.android.widget.textChanges @@ -123,6 +124,9 @@ class MessageComposerFragment : VectorBaseFragment(), A @Inject lateinit var session: Session @Inject lateinit var errorTracker: ErrorTracker + private val permalinkService: PermalinkService + get() = session.permalinkService() + private val roomId: String get() = withState(timelineViewModel) { it.roomId } private val autoCompleters: MutableMap = hashMapOf() @@ -792,30 +796,37 @@ class MessageComposerFragment : VectorBaseFragment(), A } else { val roomMember = timelineViewModel.getMember(userId) val displayName = sanitizeDisplayName(roomMember?.displayName ?: userId) - val pill = buildSpannedString { - append(displayName) - setSpan( - PillImageSpan( - glideRequests, - avatarRenderer, - requireContext(), - MatrixItem.UserItem(userId, displayName, roomMember?.avatarUrl) - ) - .also { it.bind(composer.editText) }, - 0, - displayName.length, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE - ) - append(if (startToCompose) ": " else " ") - } - if (startToCompose && displayName.startsWith("/")) { - // Ensure displayName will not be interpreted as a Slash command - composer.editText.append("\\") + if ((composer as? RichTextComposerLayout)?.isTextFormattingEnabled == true) { + // Rich text editor is enabled so we need to use its APIs + permalinkService.createPermalink(userId)?.let { url -> + (composer as RichTextComposerLayout).insertMention(url, displayName) + } + } else { + val pill = buildSpannedString { + append(displayName) + setSpan( + PillImageSpan( + glideRequests, + avatarRenderer, + requireContext(), + MatrixItem.UserItem(userId, displayName, roomMember?.avatarUrl), + ) + .also { it.bind(composer.editText) }, + 0, + displayName.length, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + append(if (startToCompose) ": " else " ") + } + if (startToCompose && displayName.startsWith("/")) { + // Ensure displayName will not be interpreted as a Slash command + composer.editText.append("\\") + } + // Always use EditText.getText().insert for adding pills as TextView.append doesn't appear + // to upgrade to BufferType.Spannable as hinted at in the docs: + // https://developer.android.com/reference/android/widget/TextView#append(java.lang.CharSequence) + composer.editText.text.insert(composer.editText.selectionStart, pill) } - // Always use EditText.getText().insert for adding pills as TextView.append doesn't appear - // to upgrade to BufferType.Spannable as hinted at in the docs: - // https://developer.android.com/reference/android/widget/TextView#append(java.lang.CharSequence) - composer.editText.text.insert(composer.editText.selectionStart, pill) } focusComposerAndShowKeyboard() } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt index c028498405..14c9e0f95e 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt @@ -305,6 +305,10 @@ internal class RichTextComposerLayout @JvmOverloads constructor( fun removeLink() = views.richTextComposerEditText.removeLink() + // TODO: update the API to insertMention when available + fun insertMention(url: String, displayText: String) = + views.richTextComposerEditText.insertLink(url, displayText) + @SuppressLint("ClickableViewAccessibility") private fun disallowParentInterceptTouchEvent(view: View) { view.setOnTouchListener { v, event -> From 107f51da0db0bb66a7ba49d1a3eea6afb9f7d34d Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 19 Jun 2023 10:48:46 +0000 Subject: [PATCH 144/234] Translated using Weblate (Czech) Currently translated at 100.0% (2640 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- library/ui-strings/src/main/res/values-cs/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index 5007940e48..dcfbe345c9 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -380,7 +380,7 @@ %s píše… %1$s a %2$s píší… %1$s a %2$s a další píší… - Nemáte právo odesílat v této místnosti. + Nemáte oprávnění vkládat příspěvky do této místnosti. %d nová zpráva %d nové zprávy @@ -1512,7 +1512,7 @@ Odeslat Přehrát Odmítnout - Nemáte povolení zahájit konferenční hovor v této místnosti + Nemáte oprávnění zahájit konferenční hovor v této místnosti Zahájit video schůzku Zahájit hlasovou schůzku Schůzky používají pravidla zabezpečení a přístupu Jitsi. Všichni lidé nyní v místnosti uvidí pozvánku k připojení, zatímco vaše schůzka probíhá. @@ -1795,7 +1795,7 @@ Toto je počátek této konverzace. Toto je počátek %s. Exportovat audit - K zapnutí šifrování v této místnosti nemáte oprávnění. + Nemáte oprávnění povolit šifrování v této místnosti. Přímá zpráva Zakládám místnost… Některé znaky nejsou dovoleny From eeec549bd0b504b64952ec4c46cb3cf0c93d6b57 Mon Sep 17 00:00:00 2001 From: th ad Date: Mon, 19 Jun 2023 08:22:02 +0000 Subject: [PATCH 145/234] Translated using Weblate (Slovenian) Currently translated at 2.2% (60 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sl/ --- library/ui-strings/src/main/res/values-sl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-sl/strings.xml b/library/ui-strings/src/main/res/values-sl/strings.xml index 4d7ffd3d3d..9fec98dab7 100644 --- a/library/ui-strings/src/main/res/values-sl/strings.xml +++ b/library/ui-strings/src/main/res/values-sl/strings.xml @@ -64,4 +64,5 @@ %s je začel video klic. %1$s je omočil %2$s ogled prihodnjih sporočil %1$s si omogočil ogled prihodnjih sporočil + vsi člani sobe, od trenutka povabila. \ No newline at end of file From 90e752472f4a93a95f32f13f7745a42dcb0851d0 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Tue, 20 Jun 2023 10:27:19 +0000 Subject: [PATCH 146/234] Translated using Weblate (Czech) Currently translated at 100.0% (2640 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- library/ui-strings/src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index dcfbe345c9..b36ef5d59f 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -380,7 +380,7 @@ %s píše… %1$s a %2$s píší… %1$s a %2$s a další píší… - Nemáte oprávnění vkládat příspěvky do této místnosti. + Nemáte oprávnění zveřejňovat příspěvky v této místnosti. %d nová zpráva %d nové zprávy From 3170d07f9b0f9dd81cd9d486002398f2a6f794d5 Mon Sep 17 00:00:00 2001 From: Makkkkus Date: Tue, 20 Jun 2023 22:06:32 +0000 Subject: [PATCH 147/234] Translated using Weblate (Norwegian Nynorsk) Currently translated at 19.0% (503 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/nn/ --- .../src/main/res/values-nn/strings.xml | 27 ++----------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/library/ui-strings/src/main/res/values-nn/strings.xml b/library/ui-strings/src/main/res/values-nn/strings.xml index 45c8679736..37b159f21f 100644 --- a/library/ui-strings/src/main/res/values-nn/strings.xml +++ b/library/ui-strings/src/main/res/values-nn/strings.xml @@ -38,7 +38,6 @@ Telefonnummer Rominnbjoding %1$s og %2$s - Tomt rom %s oppgraderte rommet. %1$s forlot rommet. Grunn: %2$s @@ -67,7 +66,6 @@ Slett Gje nytt namn Rapporter innhaldet - eller Inviter Logg av @@ -127,7 +125,6 @@ Dette ser ikkje ut som ei gyldig e-postadresse Denne e-postadressa er allereie i bruk. Gløymt passord\? - Heimtenaren ynskjer å stadfeste at du ikkje er ein robot Fekk ikkje til å stadfesta e-postadressa: sjå til at du klikka på lenken i e-posten Skriv inn ein gyldig URL @@ -152,14 +149,10 @@ Samtalen er i gang… Den andre parten tok ikkje samtalen. Info - - ${app_name} treng tilgang til mikrofonen din for å utføra talesamtalar. - ${app_name} treng tilgang til kameraet og mikrofonen din for å utføra videosamtalar. \n \nGjer vel og gjev tilgang på sprettvindauget som kjem for å utføra samtalen. - JA NEI Gå fram @@ -168,8 +161,6 @@ Avvis Medlemsoversikt Hopp til første uleste melding. - - %d medlem %d medlem @@ -205,12 +196,9 @@ Sertifikatet har forandra seg frå det som var stolt på av mobilen din. Dette er SÆRS UVANLEG. Det er tilrådd å IKKJE GODKJENNA dette nye sertifikatet. Sertifikatet har endra seg frå eit som tidlegare var stole på, til eit som ikkje er det. Det kan henda at tenaren har fornya sertifikatet. Snakk med administrator for å få det forventa fingeravtrykket. Godkjenn BERRE sertifikatet viss tenaradministratoren har publisert eit fingeravtrykk som samsvarar med det over. - Søk Filtrer rommedlemmar Ingi treff - - Alle meldingar Legg til på heimskjermen Profilbilete @@ -270,7 +258,6 @@ Oppdater offentleg namn Sist sedd %1$s @ %2$s - Stadfesting Logga inn som Heimtenar @@ -306,7 +293,6 @@ Desse funksjonane er under utprøving og uventa vanskar kan dukka opp. Bruk med omhug. Set som hovudadresse Fjern som hovudadresse - Preg Noko gjekk gale med dekrypteringa Offentleg namn @@ -329,7 +315,6 @@ Godkjenn For å godkjenna at denne sesjonen er til å stola på, ver venleg og snakk med eigaren på ein anna måte (t.d. ansikt til ansikt eller på telefon) og spør han om nøkkelen han ser i Brukarinnstillingane for denne sesjonen samsvarar med nøkkelen under: Viss det samsvarer, klikk Verifiser-knappen under. Viss det ikkje gjer det, avlyttar nokon andre denne sesjonen og du bør sannsynlegvis svarteliste den. I framtida vil denne verifikasjonsprosessen bli meir forbetra. - Vel ein romkatalog Heimtenar-URL Alle rom på %s-tenaren @@ -337,7 +322,6 @@ %d ulest varsla melding %d uleste varsla meldingar - %d rom %d rom @@ -413,16 +397,10 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Rommet er ein vidareføring av ei anna samtale Klikk her for å sjå gamle meldingar Systemvarsel - - - - %d valt %d valde - - kontakt tenesteadministratoren din Heimtenaren har truffe ei av ressursgrensene sine so nokre brukarar vil ikkje kunna logga inn. Heimtenaren har forbigått ei av ressursgrensene sine. @@ -482,7 +460,6 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Trekk tilbake Koble frå Avvis - Logg inn med SSO (single sign-on) Dette er ikkje ei gyldig Matrix-tenaradresse Klarar ikkje å nå ein heimetenar på denne URL\'en, sjekk at den er korrekt @@ -503,7 +480,7 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Versjon Matrix SDK versjon Innstillingar - Sikkerheit og personvern + Tryggleik og personvern Tale og video Hjelp og om Vis skjulte hendelsar i historikken @@ -561,4 +538,4 @@ Meldingssynlegheit på Matrix liknar på epost. At vi gløymer meldingane dine t Nullstill Folk Folk - + \ No newline at end of file From ff0873f5e82c05cbb0b51cbccb6c25d4362b2781 Mon Sep 17 00:00:00 2001 From: Martin Berg Alstad Date: Tue, 20 Jun 2023 21:59:53 +0000 Subject: [PATCH 148/234] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l=20(nb))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 4.0% (4 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/nb/ --- fastlane/metadata/android/nb/short_description.txt | 2 +- fastlane/metadata/android/nb/title.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane/metadata/android/nb/short_description.txt b/fastlane/metadata/android/nb/short_description.txt index b7cad4c849..ebe1e02ede 100644 --- a/fastlane/metadata/android/nb/short_description.txt +++ b/fastlane/metadata/android/nb/short_description.txt @@ -1 +1 @@ -Sikker desentralisert chat & VoIP. Beskytt dataene dine fra tredjeparter. +Gruppe-meldingsapp - krypterte meldinger, gruppechat og videosamtaler diff --git a/fastlane/metadata/android/nb/title.txt b/fastlane/metadata/android/nb/title.txt index aacee5be54..fff0c3fe11 100644 --- a/fastlane/metadata/android/nb/title.txt +++ b/fastlane/metadata/android/nb/title.txt @@ -1 +1 @@ -Element (tidligere Riot.im) +Element - Sikker Meldingsapp From e988308dc6d9969d198bfa8cabc43ec56f482ee2 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 21 Jun 2023 09:30:45 +0100 Subject: [PATCH 149/234] Add space after mention inserstion. --- .../home/room/detail/composer/MessageComposerFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt index 2b85fc482f..338a635818 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerFragment.kt @@ -800,6 +800,7 @@ class MessageComposerFragment : VectorBaseFragment(), A // Rich text editor is enabled so we need to use its APIs permalinkService.createPermalink(userId)?.let { url -> (composer as RichTextComposerLayout).insertMention(url, displayName) + composer.editText.append(" ") } } else { val pill = buildSpannedString { From cfae6e9e514df2b2c12a91679504e37c34d4f248 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 21 Jun 2023 09:49:44 +0100 Subject: [PATCH 150/234] Remove TODO causing failed lint check. --- .../home/room/detail/composer/RichTextComposerLayout.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt index 14c9e0f95e..b7a8d195d8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt @@ -305,7 +305,7 @@ internal class RichTextComposerLayout @JvmOverloads constructor( fun removeLink() = views.richTextComposerEditText.removeLink() - // TODO: update the API to insertMention when available + // Update the API to insertMention when available fun insertMention(url: String, displayText: String) = views.richTextComposerEditText.insertLink(url, displayText) From 08ae1105ff555783637f1fbf215c3f9ba7792aac Mon Sep 17 00:00:00 2001 From: valere Date: Thu, 22 Jun 2023 16:56:15 +0200 Subject: [PATCH 151/234] Bump rust sdk version to 0.3.10 --- matrix-sdk-android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 7420fba45e..32e9c80503 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -216,7 +216,7 @@ dependencies { implementation libs.google.phonenumber - rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.9") + rustCryptoImplementation("org.matrix.rustcomponents:crypto-android:0.3.10") // rustCryptoApi project(":library:rustCrypto") testImplementation libs.tests.junit From 6ef955769821ed1223601df8d6d480eb9642d794 Mon Sep 17 00:00:00 2001 From: valere Date: Thu, 22 Jun 2023 16:57:48 +0200 Subject: [PATCH 152/234] add changelog --- changelog.d/8554.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/8554.misc diff --git a/changelog.d/8554.misc b/changelog.d/8554.misc new file mode 100644 index 0000000000..0fad74289c --- /dev/null +++ b/changelog.d/8554.misc @@ -0,0 +1 @@ +Update crypto rust sdk version to 0.3.10 From 93d3c73306e912e05b97e3905b50156abbd4ccf5 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Thu, 22 Jun 2023 06:42:18 +0000 Subject: [PATCH 153/234] Translated using Weblate (Czech) Currently translated at 100.0% (2640 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/ --- library/ui-strings/src/main/res/values-cs/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/ui-strings/src/main/res/values-cs/strings.xml b/library/ui-strings/src/main/res/values-cs/strings.xml index b36ef5d59f..b74d4825e0 100644 --- a/library/ui-strings/src/main/res/values-cs/strings.xml +++ b/library/ui-strings/src/main/res/values-cs/strings.xml @@ -798,7 +798,7 @@ Tiché Hlučné Vytvořit - Úvod + Domov Místnosti Pozvaní %2$s Vás vykopnul z %1$s @@ -2182,8 +2182,8 @@ Propojte tento e-mail se svým účtem Pozvánka do této místnosti byla odeslána na adresu %s, která není spojena s vaším účtem Pozvánka do tohoto prostoru byla odeslána na adresu %s, která není spojena s vaším účtem - Všechny místnosti, ve kterých se nacházíte, se zobrazí v Úvodu. - Zobrazit všechny místnosti v Úvodu + Všechny místnosti, ve kterých se nacházíte, se zobrazí v Domovu. + Zobrazit všechny místnosti v Domovu Posunutím ukončíte hovor %1$s Klepněte pro návrat Probíhající hovor (%1$s) · From f304e40d57525f81a44dc4783aff568c9f704752 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 17:14:58 +0200 Subject: [PATCH 154/234] Import source from https://github.com/amulyakhare/TextDrawable --- dependencies_groups.gradle | 1 - library/external/textdrawable/build.gradle | 25 ++ .../textdrawable/TextDrawable.java | 316 ++++++++++++++++++ settings.gradle | 1 + vector/build.gradle | 2 +- 5 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 library/external/textdrawable/build.gradle create mode 100644 library/external/textdrawable/src/main/java/com/amulyakhare/textdrawable/TextDrawable.java diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 66d07f258b..07dfa8787f 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -238,7 +238,6 @@ ext.groups = [ regex: [ ], group: [ - 'com.amulyakhare', 'com.otaliastudios', 'com.yqritc', // https://github.com/cmelchior/realmfieldnameshelper/issues/42 diff --git a/library/external/textdrawable/build.gradle b/library/external/textdrawable/build.gradle new file mode 100644 index 0000000000..5eb27bf6aa --- /dev/null +++ b/library/external/textdrawable/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'com.android.library' + +apply plugin: 'com.android.library' + +android { + namespace "com.amulyakhare.textdrawable" + + compileSdk versions.compileSdk + + defaultConfig { + minSdk versions.minSdk + targetSdk versions.targetSdk + } + + compileOptions { + sourceCompatibility versions.sourceCompat + targetCompatibility versions.targetCompat + } +} + +afterEvaluate { + tasks.findAll { it.name.startsWith("lint") }.each { + it.enabled = false + } +} diff --git a/library/external/textdrawable/src/main/java/com/amulyakhare/textdrawable/TextDrawable.java b/library/external/textdrawable/src/main/java/com/amulyakhare/textdrawable/TextDrawable.java new file mode 100644 index 0000000000..db42f8b764 --- /dev/null +++ b/library/external/textdrawable/src/main/java/com/amulyakhare/textdrawable/TextDrawable.java @@ -0,0 +1,316 @@ +package com.amulyakhare.textdrawable; + +import android.graphics.*; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.OvalShape; +import android.graphics.drawable.shapes.RectShape; +import android.graphics.drawable.shapes.RoundRectShape; + +/** + * @author amulya + * @datetime 14 Oct 2014, 3:53 PM + */ +public class TextDrawable extends ShapeDrawable { + + private final Paint textPaint; + private final Paint borderPaint; + private static final float SHADE_FACTOR = 0.9f; + private final String text; + private final int color; + private final RectShape shape; + private final int height; + private final int width; + private final int fontSize; + private final float radius; + private final int borderThickness; + + private TextDrawable(Builder builder) { + super(builder.shape); + + // shape properties + shape = builder.shape; + height = builder.height; + width = builder.width; + radius = builder.radius; + + // text and color + text = builder.toUpperCase ? builder.text.toUpperCase() : builder.text; + color = builder.color; + + // text paint settings + fontSize = builder.fontSize; + textPaint = new Paint(); + textPaint.setColor(builder.textColor); + textPaint.setAntiAlias(true); + textPaint.setFakeBoldText(builder.isBold); + textPaint.setStyle(Paint.Style.FILL); + textPaint.setTypeface(builder.font); + textPaint.setTextAlign(Paint.Align.CENTER); + textPaint.setStrokeWidth(builder.borderThickness); + + // border paint settings + borderThickness = builder.borderThickness; + borderPaint = new Paint(); + borderPaint.setColor(getDarkerShade(color)); + borderPaint.setStyle(Paint.Style.STROKE); + borderPaint.setStrokeWidth(borderThickness); + + // drawable paint color + Paint paint = getPaint(); + paint.setColor(color); + + } + + private int getDarkerShade(int color) { + return Color.rgb((int)(SHADE_FACTOR * Color.red(color)), + (int)(SHADE_FACTOR * Color.green(color)), + (int)(SHADE_FACTOR * Color.blue(color))); + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + Rect r = getBounds(); + + + // draw border + if (borderThickness > 0) { + drawBorder(canvas); + } + + int count = canvas.save(); + canvas.translate(r.left, r.top); + + // draw text + int width = this.width < 0 ? r.width() : this.width; + int height = this.height < 0 ? r.height() : this.height; + int fontSize = this.fontSize < 0 ? (Math.min(width, height) / 2) : this.fontSize; + textPaint.setTextSize(fontSize); + canvas.drawText(text, width / 2, height / 2 - ((textPaint.descent() + textPaint.ascent()) / 2), textPaint); + + canvas.restoreToCount(count); + + } + + private void drawBorder(Canvas canvas) { + RectF rect = new RectF(getBounds()); + rect.inset(borderThickness/2, borderThickness/2); + + if (shape instanceof OvalShape) { + canvas.drawOval(rect, borderPaint); + } + else if (shape instanceof RoundRectShape) { + canvas.drawRoundRect(rect, radius, radius, borderPaint); + } + else { + canvas.drawRect(rect, borderPaint); + } + } + + @Override + public void setAlpha(int alpha) { + textPaint.setAlpha(alpha); + } + + @Override + public void setColorFilter(ColorFilter cf) { + textPaint.setColorFilter(cf); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public int getIntrinsicWidth() { + return width; + } + + @Override + public int getIntrinsicHeight() { + return height; + } + + public static IShapeBuilder builder() { + return new Builder(); + } + + public static class Builder implements IConfigBuilder, IShapeBuilder, IBuilder { + + private String text; + + private int color; + + private int borderThickness; + + private int width; + + private int height; + + private Typeface font; + + private RectShape shape; + + public int textColor; + + private int fontSize; + + private boolean isBold; + + private boolean toUpperCase; + + public float radius; + + private Builder() { + text = ""; + color = Color.GRAY; + textColor = Color.WHITE; + borderThickness = 0; + width = -1; + height = -1; + shape = new RectShape(); + font = Typeface.create("sans-serif-light", Typeface.NORMAL); + fontSize = -1; + isBold = false; + toUpperCase = false; + } + + public IConfigBuilder width(int width) { + this.width = width; + return this; + } + + public IConfigBuilder height(int height) { + this.height = height; + return this; + } + + public IConfigBuilder textColor(int color) { + this.textColor = color; + return this; + } + + public IConfigBuilder withBorder(int thickness) { + this.borderThickness = thickness; + return this; + } + + public IConfigBuilder useFont(Typeface font) { + this.font = font; + return this; + } + + public IConfigBuilder fontSize(int size) { + this.fontSize = size; + return this; + } + + public IConfigBuilder bold() { + this.isBold = true; + return this; + } + + public IConfigBuilder toUpperCase() { + this.toUpperCase = true; + return this; + } + + @Override + public IConfigBuilder beginConfig() { + return this; + } + + @Override + public IShapeBuilder endConfig() { + return this; + } + + @Override + public IBuilder rect() { + this.shape = new RectShape(); + return this; + } + + @Override + public IBuilder round() { + this.shape = new OvalShape(); + return this; + } + + @Override + public IBuilder roundRect(int radius) { + this.radius = radius; + float[] radii = {radius, radius, radius, radius, radius, radius, radius, radius}; + this.shape = new RoundRectShape(radii, null, null); + return this; + } + + @Override + public TextDrawable buildRect(String text, int color) { + rect(); + return build(text, color); + } + + @Override + public TextDrawable buildRoundRect(String text, int color, int radius) { + roundRect(radius); + return build(text, color); + } + + @Override + public TextDrawable buildRound(String text, int color) { + round(); + return build(text, color); + } + + @Override + public TextDrawable build(String text, int color) { + this.color = color; + this.text = text; + return new TextDrawable(this); + } + } + + public interface IConfigBuilder { + public IConfigBuilder width(int width); + + public IConfigBuilder height(int height); + + public IConfigBuilder textColor(int color); + + public IConfigBuilder withBorder(int thickness); + + public IConfigBuilder useFont(Typeface font); + + public IConfigBuilder fontSize(int size); + + public IConfigBuilder bold(); + + public IConfigBuilder toUpperCase(); + + public IShapeBuilder endConfig(); + } + + public static interface IBuilder { + + public TextDrawable build(String text, int color); + } + + public static interface IShapeBuilder { + + public IConfigBuilder beginConfig(); + + public IBuilder rect(); + + public IBuilder round(); + + public IBuilder roundRect(int radius); + + public TextDrawable buildRect(String text, int color); + + public TextDrawable buildRoundRect(String text, int color, int radius); + + public TextDrawable buildRound(String text, int color); + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index ea20f12175..a704d0d81a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,7 @@ include ':library:multipicker' include ':library:external:jsonviewer' include ':library:external:diff-match-patch' include ':library:external:dialpad' +include ':library:external:textdrawable' include ':library:rustCrypto' include ':matrix-sdk-android' diff --git a/vector/build.gradle b/vector/build.gradle index dab8b8bdeb..e38f1ea5e5 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -116,6 +116,7 @@ dependencies { implementation project(":matrix-sdk-android-flow") implementation project(":library:external:jsonviewer") implementation project(":library:external:diff-match-patch") + implementation project(":library:external:textdrawable") implementation project(":library:ui-strings") implementation project(":library:ui-styles") implementation project(":library:core-utils") @@ -184,7 +185,6 @@ dependencies { api libs.androidx.preferenceKtx // UI - implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation libs.google.material api('me.gujun.android:span:1.7') { exclude group: 'com.android.support', module: 'support-annotations' From 3da1497d2743da7b31b307ad86ebaa24a8b2ad28 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 17:40:29 +0200 Subject: [PATCH 155/234] Import source from https://github.com/natario1/Autocomplete --- dependencies_groups.gradle | 2 +- library/external/autocomplete/build.gradle | 32 ++ .../autocomplete/Autocomplete.java | 434 +++++++++++++++ .../autocomplete/AutocompleteCallback.java | 29 + .../autocomplete/AutocompletePolicy.java | 64 +++ .../autocomplete/AutocompletePopup.java | 521 ++++++++++++++++++ .../autocomplete/AutocompletePresenter.java | 129 +++++ .../autocomplete/CharPolicy.java | 184 +++++++ .../autocomplete/RecyclerViewPresenter.java | 152 +++++ settings.gradle | 1 + vector/build.gradle | 3 +- .../autocomplete/RecyclerViewPresenter.kt | 2 +- .../command/CommandAutocompletePolicy.kt | 9 +- 13 files changed, 1553 insertions(+), 9 deletions(-) create mode 100644 library/external/autocomplete/build.gradle create mode 100644 library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/Autocomplete.java create mode 100644 library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompleteCallback.java create mode 100644 library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePolicy.java create mode 100644 library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePopup.java create mode 100644 library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePresenter.java create mode 100644 library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/CharPolicy.java create mode 100644 library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/RecyclerViewPresenter.java diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 07dfa8787f..4fe36dcf0d 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -115,6 +115,7 @@ ext.groups = [ 'com.linkedin.dexmaker', 'com.mapbox.mapboxsdk', 'com.nulab-inc', + 'com.otaliastudios', 'com.otaliastudios.opengl', 'com.parse.bolts', 'com.pinterest', @@ -238,7 +239,6 @@ ext.groups = [ regex: [ ], group: [ - 'com.otaliastudios', 'com.yqritc', // https://github.com/cmelchior/realmfieldnameshelper/issues/42 'dk.ilios', diff --git a/library/external/autocomplete/build.gradle b/library/external/autocomplete/build.gradle new file mode 100644 index 0000000000..39d4d4b19e --- /dev/null +++ b/library/external/autocomplete/build.gradle @@ -0,0 +1,32 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + namespace "com.otaliastudios.autocomplete" + + compileSdk versions.compileSdk + + defaultConfig { + minSdk versions.minSdk + targetSdk versions.targetSdk + } + + compileOptions { + sourceCompatibility versions.sourceCompat + targetCompatibility versions.targetCompat + } + + kotlinOptions { + jvmTarget = "11" + } +} + +dependencies { + implementation libs.androidx.recyclerview +} + +afterEvaluate { + tasks.findAll { it.name.startsWith("lint") }.each { + it.enabled = false + } +} diff --git a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/Autocomplete.java b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/Autocomplete.java new file mode 100644 index 0000000000..cf58146f14 --- /dev/null +++ b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/Autocomplete.java @@ -0,0 +1,434 @@ +package com.otaliastudios.autocomplete; + +import android.database.DataSetObserver; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; +import android.text.Editable; +import android.text.Selection; +import android.text.SpanWatcher; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextWatcher; +import android.util.Log; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.Window; +import android.view.WindowManager; +import android.widget.EditText; +import android.widget.PopupWindow; + +import androidx.annotation.NonNull; + + +/** + * Entry point for adding Autocomplete behavior to a {@link EditText}. + * + * You can construct a {@code Autocomplete} using the builder provided by {@link Autocomplete#on(EditText)}. + * Building is enough, but you can hold a reference to this class to call its public methods. + * + * Requires: + * - {@link EditText}: this is both the anchor for the popup, and the source of text events that we listen to + * - {@link AutocompletePresenter}: this presents items in the popup window. See class for more info. + * - {@link AutocompleteCallback}: if specified, this listens to click events and visibility changes + * - {@link AutocompletePolicy}: if specified, this controls how and when to show the popup based on text events + * If not, this defaults to {@link SimplePolicy}: shows the popup when text.length() bigger than 0. + */ +public final class Autocomplete implements TextWatcher, SpanWatcher { + + private final static String TAG = Autocomplete.class.getSimpleName(); + private final static boolean DEBUG = false; + + private static void log(String log) { + if (DEBUG) Log.e(TAG, log); + } + + /** + * Builder for building {@link Autocomplete}. + * The only mandatory item is a presenter, {@link #with(AutocompletePresenter)}. + * + * @param the data model + */ + public final static class Builder { + private EditText source; + private AutocompletePresenter presenter; + private AutocompletePolicy policy; + private AutocompleteCallback callback; + private Drawable backgroundDrawable; + private float elevationDp = 6; + + private Builder(EditText source) { + this.source = source; + } + + /** + * Registers the {@link AutocompletePresenter} to be used, responsible for showing + * items. See the class for info. + * + * @param presenter desired presenter + * @return this for chaining + */ + public Builder with(AutocompletePresenter presenter) { + this.presenter = presenter; + return this; + } + + /** + * Registers the {@link AutocompleteCallback} to be used, responsible for listening to + * clicks provided by the presenter, and visibility changes. + * + * @param callback desired callback + * @return this for chaining + */ + public Builder with(AutocompleteCallback callback) { + this.callback = callback; + return this; + } + + /** + * Registers the {@link AutocompletePolicy} to be used, responsible for showing / dismissing + * the popup when certain events happen (e.g. certain characters are typed). + * + * @param policy desired policy + * @return this for chaining + */ + public Builder with(AutocompletePolicy policy) { + this.policy = policy; + return this; + } + + /** + * Sets a background drawable for the popup. + * + * @param backgroundDrawable drawable + * @return this for chaining + */ + public Builder with(Drawable backgroundDrawable) { + this.backgroundDrawable = backgroundDrawable; + return this; + } + + /** + * Sets elevation for the popup. Defaults to 6 dp. + * + * @param elevationDp popup elevation, in DP + * @return this for chaning. + */ + public Builder with(float elevationDp) { + this.elevationDp = elevationDp; + return this; + } + + /** + * Builds an Autocomplete instance. This is enough for autocomplete to be set up, + * but you can hold a reference to the object and call its public methods. + * + * @return an Autocomplete instance, if you need it + * + * @throws RuntimeException if either EditText or the presenter are null + */ + public Autocomplete build() { + if (source == null) throw new RuntimeException("Autocomplete needs a source!"); + if (presenter == null) throw new RuntimeException("Autocomplete needs a presenter!"); + if (policy == null) policy = new SimplePolicy(); + return new Autocomplete(this); + } + + private void clear() { + source = null; + presenter = null; + callback = null; + policy = null; + backgroundDrawable = null; + elevationDp = 6; + } + } + + /** + * Entry point for building autocomplete on a certain {@link EditText}. + * @param anchor the anchor for the popup, and the source of text events + * @param your data model + * @return a Builder for set up + */ + public static Builder on(EditText anchor) { + return new Builder(anchor); + } + + private AutocompletePolicy policy; + private AutocompletePopup popup; + private AutocompletePresenter presenter; + private AutocompleteCallback callback; + private EditText source; + + private boolean block; + private boolean disabled; + private boolean openBefore; + private String lastQuery = "null"; + + private Autocomplete(Builder builder) { + policy = builder.policy; + presenter = builder.presenter; + callback = builder.callback; + source = builder.source; + + // Set up popup + popup = new AutocompletePopup(source.getContext()); + popup.setAnchorView(source); + popup.setGravity(Gravity.START); + popup.setModal(false); + popup.setBackgroundDrawable(builder.backgroundDrawable); + popup.setElevation(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, builder.elevationDp, + source.getContext().getResources().getDisplayMetrics())); + + // popup dimensions + AutocompletePresenter.PopupDimensions dim = this.presenter.getPopupDimensions(); + popup.setWidth(dim.width); + popup.setHeight(dim.height); + popup.setMaxWidth(dim.maxWidth); + popup.setMaxHeight(dim.maxHeight); + + // Fire visibility events + popup.setOnDismissListener(new PopupWindow.OnDismissListener() { + @Override + public void onDismiss() { + lastQuery = "null"; + if (callback != null) callback.onPopupVisibilityChanged(false); + boolean saved = block; + block = true; + policy.onDismiss(source.getText()); + block = saved; + presenter.hideView(); + } + }); + + // Set up source + source.getText().setSpan(this, 0, source.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); + source.addTextChangedListener(this); + + // Set up presenter + presenter.registerClickProvider(new AutocompletePresenter.ClickProvider() { + @Override + public void click(@NonNull T item) { + AutocompleteCallback callback = Autocomplete.this.callback; + EditText edit = Autocomplete.this.source; + if (callback == null) return; + boolean saved = block; + block = true; + boolean dismiss = callback.onPopupItemClicked(edit.getText(), item); + if (dismiss) dismissPopup(); + block = saved; + } + }); + + builder.clear(); + } + + /** + * Controls how the popup operates with an input method. + * + * If the popup is showing, calling this method will take effect only + * the next time the popup is shown. + * + * @param mode a {@link PopupWindow} input method mode + */ + public void setInputMethodMode(int mode) { + popup.setInputMethodMode(mode); + } + + /** + * Sets the operating mode for the soft input area. + * + * @param mode The desired mode, see {@link WindowManager.LayoutParams#softInputMode} + */ + public void setSoftInputMode(int mode) { + popup.setSoftInputMode(mode); + } + + /** + * Shows the popup with the given query. + * There is rarely need to call this externally: it is already triggered by events on the anchor. + * To control when this is called, provide a good implementation of {@link AutocompletePolicy}. + * + * @param query query text. + */ + public void showPopup(@NonNull CharSequence query) { + if (isPopupShowing() && lastQuery.equals(query.toString())) return; + lastQuery = query.toString(); + + log("showPopup: called with filter "+query); + if (!isPopupShowing()) { + log("showPopup: showing"); + presenter.registerDataSetObserver(new Observer()); // Calling new to avoid leaking... maybe... + popup.setView(presenter.getView()); + presenter.showView(); + popup.show(); + if (callback != null) callback.onPopupVisibilityChanged(true); + } + log("showPopup: popup should be showing... "+isPopupShowing()); + presenter.onQuery(query); + } + + /** + * Dismisses the popup, if showing. + * There is rarely need to call this externally: it is already triggered by events on the anchor. + * To control when this is called, provide a good implementation of {@link AutocompletePolicy}. + */ + public void dismissPopup() { + if (isPopupShowing()) { + popup.dismiss(); + } + } + + /** + * Returns true if the popup is showing. + * @return whether the popup is currently showing + */ + public boolean isPopupShowing() { + return this.popup.isShowing(); + } + + /** + * Switch to control the autocomplete behavior. When disabled, no popup is shown. + * This is useful if you want to do runtime edits to the anchor text, without triggering + * the popup. + * + * @param enabled whether to enable autocompletion + */ + public void setEnabled(boolean enabled) { + disabled = !enabled; + } + + /** + * Sets the gravity for the popup. Basically only {@link Gravity#START} and {@link Gravity#END} + * do work. + * + * @param gravity gravity for the popup + */ + public void setGravity(int gravity) { + popup.setGravity(gravity); + } + + /** + * Controls the vertical offset of the popup from the EditText anchor. + * + * @param offset offset in pixels. + */ + public void setOffsetFromAnchor(int offset) { popup.setVerticalOffset(offset); } + + /** + * Controls whether the popup should listen to clicks outside its boundaries. + * + * @param outsideTouchable true to listen to outside clicks + */ + public void setOutsideTouchable(boolean outsideTouchable) { popup.setOutsideTouchable(outsideTouchable); } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (block || disabled) return; + openBefore = isPopupShowing(); + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (block || disabled) return; + if (openBefore && !isPopupShowing()) { + return; // Copied from somewhere. + } + if (!(s instanceof Spannable)) { + source.setText(new SpannableString(s)); + return; + } + Spannable sp = (Spannable) s; + + int cursor = source.getSelectionEnd(); + log("onTextChanged: cursor end position is "+cursor); + if (cursor == -1) { // No cursor present. + dismissPopup(); return; + } + if (cursor != source.getSelectionStart()) { + // Not sure about this. We should have no problems dealing with multi selections, + // we just take the end... + // dismissPopup(); return; + } + + boolean b = block; + block = true; // policy might add spans or other stuff. + if (isPopupShowing() && policy.shouldDismissPopup(sp, cursor)) { + log("onTextChanged: dismissing"); + dismissPopup(); + } else if (isPopupShowing() || policy.shouldShowPopup(sp, cursor)) { + // LOG.now("onTextChanged: updating with filter "+policy.getQuery(sp)); + showPopup(policy.getQuery(sp)); + } + block = b; + } + + @Override + public void afterTextChanged(Editable s) {} + + @Override + public void onSpanAdded(Spannable text, Object what, int start, int end) {} + + @Override + public void onSpanRemoved(Spannable text, Object what, int start, int end) {} + + @Override + public void onSpanChanged(Spannable text, Object what, int ostart, int oend, int nstart, int nend) { + if (disabled || block) return; + if (what == Selection.SELECTION_END) { + // Selection end changed from ostart to nstart. Trigger a check. + log("onSpanChanged: selection end moved from "+ostart+" to "+nstart); + log("onSpanChanged: block is "+block); + boolean b = block; + block = true; + if (!isPopupShowing() && policy.shouldShowPopup(text, nstart)) { + showPopup(policy.getQuery(text)); + } + block = b; + } + } + + private class Observer extends DataSetObserver implements Runnable { + private Handler ui = new Handler(Looper.getMainLooper()); + + @Override + public void onChanged() { + // ??? Not sure this is needed... + ui.post(this); + } + + @Override + public void run() { + if (isPopupShowing()) { + // Call show again to revisit width and height. + popup.show(); + } + } + } + + /** + * A very simple {@link AutocompletePolicy} implementation. + * Popup is shown when text length is bigger than 0, and hidden when text is empty. + * The query string is the whole text. + */ + public static class SimplePolicy implements AutocompletePolicy { + @Override + public boolean shouldShowPopup(@NonNull Spannable text, int cursorPos) { + return text.length() > 0; + } + + @Override + public boolean shouldDismissPopup(@NonNull Spannable text, int cursorPos) { + return text.length() == 0; + } + + @NonNull + @Override + public CharSequence getQuery(@NonNull Spannable text) { + return text; + } + + @Override + public void onDismiss(@NonNull Spannable text) {} + } +} diff --git a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompleteCallback.java b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompleteCallback.java new file mode 100644 index 0000000000..56870db610 --- /dev/null +++ b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompleteCallback.java @@ -0,0 +1,29 @@ +package com.otaliastudios.autocomplete; + +import android.text.Editable; + +import androidx.annotation.NonNull; + +/** + * Optional callback to be passed to {@link Autocomplete.Builder}. + */ +public interface AutocompleteCallback { + + /** + * Called when an item inside your list is clicked. + * This works if your presenter has dispatched a click event. + * At this point you can edit the text, e.g. {@code editable.append(item.toString())}. + * + * @param editable editable text that you can work on + * @param item item that was clicked + * @return true if the action is valid and the popup can be dismissed + */ + boolean onPopupItemClicked(@NonNull Editable editable, @NonNull T item); + + /** + * Called when popup visibility state changes. + * + * @param shown true if the popup was just shown, false if it was just hidden + */ + void onPopupVisibilityChanged(boolean shown); +} diff --git a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePolicy.java b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePolicy.java new file mode 100644 index 0000000000..05dfaa9f0a --- /dev/null +++ b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePolicy.java @@ -0,0 +1,64 @@ +package com.otaliastudios.autocomplete; + +import android.text.Spannable; + +import androidx.annotation.NonNull; + +/** + * This interface controls when to show or hide the popup window, and, in the first case, + * what text should be passed to the popup {@link AutocompletePresenter}. + * + * @see Autocomplete.SimplePolicy for the simplest possible implementation + */ +public interface AutocompletePolicy { + + /** + * Called to understand whether the popup should be shown. Some naive examples: + * - Show when there's text: {@code return text.length() > 0} + * - Show when last char is @: {@code return text.getCharAt(text.length()-1) == '@'} + * + * @param text current text, along with its Spans + * @param cursorPos the position of the cursor + * @return true if popup should be shown + */ + boolean shouldShowPopup(@NonNull Spannable text, int cursorPos); + + /** + * Called to understand whether a currently shown popup should be closed, maybe + * because text is invalid. A reasonable implementation is + * {@code return !shouldShowPopup(text, cursorPos)}. + * + * However this is defined so you can add or clear spans. + * + * @param text current text, along with its Spans + * @param cursorPos the position of the cursor + * @return true if popup should be hidden + */ + boolean shouldDismissPopup(@NonNull Spannable text, int cursorPos); + + /** + * Called to understand which query should be passed to {@link AutocompletePresenter} + * for a showing popup. If this is called, {@link #shouldShowPopup(Spannable, int)} just returned + * true, or {@link #shouldDismissPopup(Spannable, int)} just returned false. + * + * This is useful to understand which part of the text should be passed to presenters. + * For example, user might have typed '@john' to select a username, but you just want to + * search for 'john'. + * + * For more complex cases, you can add inclusive Spans in {@link #shouldShowPopup(Spannable, int)}, + * and get the span position here. + * + * @param text current text, along with its Spans + * @return the query for presenter + */ + @NonNull + CharSequence getQuery(@NonNull Spannable text); + + /** + * Called when popup is dismissed. This can be used, for instance, to clear custom Spans + * from the text. + * + * @param text text at the moment of dismissing + */ + void onDismiss(@NonNull Spannable text); +} diff --git a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePopup.java b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePopup.java new file mode 100644 index 0000000000..6467085068 --- /dev/null +++ b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePopup.java @@ -0,0 +1,521 @@ +package com.otaliastudios.autocomplete; + +import android.content.Context; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.PopupWindow; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.core.view.ViewCompat; +import androidx.core.widget.PopupWindowCompat; + +/** + * A simplified version of andriod.widget.ListPopupWindow, which is the class used by + * AutocompleteTextView. + * + * Other than being simplified, this deals with Views rather than ListViews, so the content + * can be whatever. Lots of logic (clicks, selections etc.) has been removed because we manage that + * in {@link AutocompletePresenter}. + * + */ +class AutocompletePopup { + private Context mContext; + private ViewGroup mView; + private int mHeight = ViewGroup.LayoutParams.WRAP_CONTENT; + private int mWidth = ViewGroup.LayoutParams.WRAP_CONTENT; + private int mMaxHeight = Integer.MAX_VALUE; + private int mMaxWidth = Integer.MAX_VALUE; + private int mUserMaxHeight = Integer.MAX_VALUE; + private int mUserMaxWidth = Integer.MAX_VALUE; + private int mHorizontalOffset = 0; + private int mVerticalOffset = 0; + private boolean mVerticalOffsetSet; + private int mGravity = Gravity.NO_GRAVITY; + private boolean mAlwaysVisible = false; + private boolean mOutsideTouchable = true; + private View mAnchorView; + private final Rect mTempRect = new Rect(); + private boolean mModal; + private PopupWindow mPopup; + + + /** + * Create a new, empty popup window capable of displaying items from a ListAdapter. + * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}. + * + * @param context Context used for contained views. + */ + AutocompletePopup(@NonNull Context context) { + super(); + mContext = context; + mPopup = new PopupWindow(context); + mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); + } + + + /** + * Set whether this window should be modal when shown. + * + *

If a popup window is modal, it will receive all touch and key input. + * If the user touches outside the popup window's content area the popup window + * will be dismissed. + * @param modal {@code true} if the popup window should be modal, {@code false} otherwise. + */ + @SuppressWarnings("SameParameterValue") + void setModal(boolean modal) { + mModal = modal; + mPopup.setFocusable(modal); + } + + /** + * Returns whether the popup window will be modal when shown. + * @return {@code true} if the popup window will be modal, {@code false} otherwise. + */ + @SuppressWarnings("unused") + boolean isModal() { + return mModal; + } + + void setElevation(float elevationPx) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) mPopup.setElevation(elevationPx); + } + + /** + * Sets whether the drop-down should remain visible under certain conditions. + * + * The drop-down will occupy the entire screen below {@link #getAnchorView} regardless + * of the size or content of the list. {@link #getBackground()} will fill any space + * that is not used by the list. + * @param dropDownAlwaysVisible Whether to keep the drop-down visible. + * + */ + @SuppressWarnings("unused") + void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) { + mAlwaysVisible = dropDownAlwaysVisible; + } + + /** + * @return Whether the drop-down is visible under special conditions. + */ + @SuppressWarnings("unused") + boolean isDropDownAlwaysVisible() { + return mAlwaysVisible; + } + + void setOutsideTouchable(boolean outsideTouchable) { + mOutsideTouchable = outsideTouchable; + } + + @SuppressWarnings("WeakerAccess") + boolean isOutsideTouchable() { + return mOutsideTouchable && !mAlwaysVisible; + } + + /** + * Sets the operating mode for the soft input area. + * @param mode The desired mode, see + * {@link android.view.WindowManager.LayoutParams#softInputMode} + * for the full list + * @see android.view.WindowManager.LayoutParams#softInputMode + * @see #getSoftInputMode() + */ + void setSoftInputMode(int mode) { + mPopup.setSoftInputMode(mode); + } + + /** + * Returns the current value in {@link #setSoftInputMode(int)}. + * @see #setSoftInputMode(int) + * @see android.view.WindowManager.LayoutParams#softInputMode + */ + @SuppressWarnings({"WeakerAccess", "unused"}) + int getSoftInputMode() { + return mPopup.getSoftInputMode(); + } + + /** + * @return The background drawable for the popup window. + */ + @SuppressWarnings({"WeakerAccess", "unused"}) + @Nullable + Drawable getBackground() { + return mPopup.getBackground(); + } + + /** + * Sets a drawable to be the background for the popup window. + * @param d A drawable to set as the background. + */ + void setBackgroundDrawable(@Nullable Drawable d) { + mPopup.setBackgroundDrawable(d); + } + + /** + * Set an animation style to use when the popup window is shown or dismissed. + * @param animationStyle Animation style to use. + */ + @SuppressWarnings("unused") + void setAnimationStyle(@StyleRes int animationStyle) { + mPopup.setAnimationStyle(animationStyle); + } + + /** + * Returns the animation style that will be used when the popup window is + * shown or dismissed. + * @return Animation style that will be used. + */ + @SuppressWarnings("unused") + @StyleRes + int getAnimationStyle() { + return mPopup.getAnimationStyle(); + } + + /** + * Returns the view that will be used to anchor this popup. + * @return The popup's anchor view + */ + @SuppressWarnings("WeakerAccess") + View getAnchorView() { + return mAnchorView; + } + + /** + * Sets the popup's anchor view. This popup will always be positioned relative to + * the anchor view when shown. + * @param anchor The view to use as an anchor. + */ + void setAnchorView(@NonNull View anchor) { + mAnchorView = anchor; + } + + /** + * Set the horizontal offset of this popup from its anchor view in pixels. + * @param offset The horizontal offset of the popup from its anchor. + */ + @SuppressWarnings("unused") + void setHorizontalOffset(int offset) { + mHorizontalOffset = offset; + } + + /** + * Set the vertical offset of this popup from its anchor view in pixels. + * @param offset The vertical offset of the popup from its anchor. + */ + void setVerticalOffset(int offset) { + mVerticalOffset = offset; + mVerticalOffsetSet = true; + } + + /** + * Set the gravity of the dropdown list. This is commonly used to + * set gravity to START or END for alignment with the anchor. + * @param gravity Gravity value to use + */ + void setGravity(int gravity) { + mGravity = gravity; + } + + /** + * @return The width of the popup window in pixels. + */ + @SuppressWarnings("unused") + int getWidth() { + return mWidth; + } + + /** + * Sets the width of the popup window in pixels. Can also be MATCH_PARENT + * or WRAP_CONTENT. + * @param width Width of the popup window. + */ + void setWidth(int width) { + mWidth = width; + } + + /** + * Sets the width of the popup window by the size of its content. The final width may be + * larger to accommodate styled window dressing. + * @param width Desired width of content in pixels. + */ + @SuppressWarnings("unused") + void setContentWidth(int width) { + Drawable popupBackground = mPopup.getBackground(); + if (popupBackground != null) { + popupBackground.getPadding(mTempRect); + width += mTempRect.left + mTempRect.right; + } + setWidth(width); + } + + void setMaxWidth(int width) { + if (width > 0) { + mUserMaxWidth = width; + } + } + + /** + * @return The height of the popup window in pixels. + */ + @SuppressWarnings("unused") + int getHeight() { + return mHeight; + } + + /** + * Sets the height of the popup window in pixels. Can also be MATCH_PARENT. + * @param height Height of the popup window. + */ + void setHeight(int height) { + mHeight = height; + } + + /** + * Sets the height of the popup window by the size of its content. The final height may be + * larger to accommodate styled window dressing. + * @param height Desired height of content in pixels. + */ + @SuppressWarnings("unused") + void setContentHeight(int height) { + Drawable popupBackground = mPopup.getBackground(); + if (popupBackground != null) { + popupBackground.getPadding(mTempRect); + height += mTempRect.top + mTempRect.bottom; + } + setHeight(height); + } + + void setMaxHeight(int height) { + if (height > 0) { + mUserMaxHeight = height; + } + } + + void setOnDismissListener(PopupWindow.OnDismissListener listener) { + mPopup.setOnDismissListener(listener); + } + + /** + * Show the popup list. If the list is already showing, this method + * will recalculate the popup's size and position. + */ + void show() { + if (!ViewCompat.isAttachedToWindow(getAnchorView())) return; + + int height = buildDropDown(); + final boolean noInputMethod = isInputMethodNotNeeded(); + int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; + PopupWindowCompat.setWindowLayoutType(mPopup, mDropDownWindowLayoutType); + + if (mPopup.isShowing()) { + // First pass for this special case, don't know why. + if (mHeight == ViewGroup.LayoutParams.MATCH_PARENT) { + int tempWidth = mWidth == ViewGroup.LayoutParams.MATCH_PARENT ? ViewGroup.LayoutParams.MATCH_PARENT : 0; + if (noInputMethod) { + mPopup.setWidth(tempWidth); + mPopup.setHeight(0); + } else { + mPopup.setWidth(tempWidth); + mPopup.setHeight(ViewGroup.LayoutParams.MATCH_PARENT); + } + } + + // The call to PopupWindow's update method below can accept -1 + // for any value you do not want to update. + + // Width. + int widthSpec; + if (mWidth == ViewGroup.LayoutParams.MATCH_PARENT) { + widthSpec = -1; + } else if (mWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { + widthSpec = getAnchorView().getWidth(); + } else { + widthSpec = mWidth; + } + widthSpec = Math.min(widthSpec, mMaxWidth); + widthSpec = (widthSpec < 0) ? - 1 : widthSpec; + + // Height. + int heightSpec; + if (mHeight == ViewGroup.LayoutParams.MATCH_PARENT) { + heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT; + } else if (mHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { + heightSpec = height; + } else { + heightSpec = mHeight; + } + heightSpec = Math.min(heightSpec, mMaxHeight); + heightSpec = (heightSpec < 0) ? - 1 : heightSpec; + + // Update. + mPopup.setOutsideTouchable(isOutsideTouchable()); + if (heightSpec == 0) { + dismiss(); + } else { + mPopup.update(getAnchorView(), mHorizontalOffset, mVerticalOffset, widthSpec, heightSpec); + } + + } else { + int widthSpec; + if (mWidth == ViewGroup.LayoutParams.MATCH_PARENT) { + widthSpec = ViewGroup.LayoutParams.MATCH_PARENT; + } else if (mWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { + widthSpec = getAnchorView().getWidth(); + } else { + widthSpec = mWidth; + } + widthSpec = Math.min(widthSpec, mMaxWidth); + + int heightSpec; + if (mHeight == ViewGroup.LayoutParams.MATCH_PARENT) { + heightSpec = ViewGroup.LayoutParams.MATCH_PARENT; + } else if (mHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { + heightSpec = height; + } else { + heightSpec = mHeight; + } + heightSpec = Math.min(heightSpec, mMaxHeight); + + // Set width and height. + mPopup.setWidth(widthSpec); + mPopup.setHeight(heightSpec); + mPopup.setClippingEnabled(true); + + // use outside touchable to dismiss drop down when touching outside of it, so + // only set this if the dropdown is not always visible + mPopup.setOutsideTouchable(isOutsideTouchable()); + PopupWindowCompat.showAsDropDown(mPopup, getAnchorView(), mHorizontalOffset, mVerticalOffset, mGravity); + } + } + + /** + * Dismiss the popup window. + */ + void dismiss() { + mPopup.dismiss(); + mPopup.setContentView(null); + mView = null; + } + + /** + * Control how the popup operates with an input method: one of + * INPUT_METHOD_FROM_FOCUSABLE, INPUT_METHOD_NEEDED, + * or INPUT_METHOD_NOT_NEEDED. + * + *

If the popup is showing, calling this method will take effect only + * the next time the popup is shown or through a manual call to the {@link #show()} + * method.

+ * + * @see #show() + */ + void setInputMethodMode(int mode) { + mPopup.setInputMethodMode(mode); + } + + + /** + * @return {@code true} if the popup is currently showing, {@code false} otherwise. + */ + boolean isShowing() { + return mPopup.isShowing(); + } + + /** + * @return {@code true} if this popup is configured to assume the user does not need + * to interact with the IME while it is showing, {@code false} otherwise. + */ + @SuppressWarnings("WeakerAccess") + boolean isInputMethodNotNeeded() { + return mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; + } + + + void setView(ViewGroup view) { + mView = view; + mView.setFocusable(true); + mView.setFocusableInTouchMode(true); + ViewGroup dropDownView = mView; + mPopup.setContentView(dropDownView); + ViewGroup.LayoutParams params = mView.getLayoutParams(); + if (params != null) { + if (params.height > 0) setHeight(params.height); + if (params.width > 0) setWidth(params.width); + } + } + + /** + *

Builds the popup window's content and returns the height the popup + * should have. Returns -1 when the content already exists.

+ * + * @return the content's wrap content height or -1 if content already exists + */ + private int buildDropDown() { + int otherHeights = 0; + + // getMaxAvailableHeight() subtracts the padding, so we put it back + // to get the available height for the whole window. + final int paddingVert; + final int paddingHoriz; + final Drawable background = mPopup.getBackground(); + if (background != null) { + background.getPadding(mTempRect); + paddingVert = mTempRect.top + mTempRect.bottom; + paddingHoriz = mTempRect.left + mTempRect.right; + + // If we don't have an explicit vertical offset, determine one from + // the window background so that content will line up. + if (!mVerticalOffsetSet) { + mVerticalOffset = -mTempRect.top; + } + } else { + mTempRect.setEmpty(); + paddingVert = 0; + paddingHoriz = 0; + } + + // Redefine dimensions taking into account maxWidth and maxHeight. + final boolean ignoreBottomDecorations = mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; + final int maxContentHeight = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? + mPopup.getMaxAvailableHeight(getAnchorView(), mVerticalOffset, ignoreBottomDecorations) : + mPopup.getMaxAvailableHeight(getAnchorView(), mVerticalOffset); + final int maxContentWidth = mContext.getResources().getDisplayMetrics().widthPixels - paddingHoriz; + + mMaxHeight = Math.min(maxContentHeight + paddingVert, mUserMaxHeight); + mMaxWidth = Math.min(maxContentWidth + paddingHoriz, mUserMaxWidth); + // if (mHeight > 0) mHeight = Math.min(mHeight, maxContentHeight); + // if (mWidth > 0) mWidth = Math.min(mWidth, maxContentWidth); + + if (mAlwaysVisible || mHeight == ViewGroup.LayoutParams.MATCH_PARENT) { + return mMaxHeight; + } + + final int childWidthSpec; + switch (mWidth) { + case ViewGroup.LayoutParams.WRAP_CONTENT: + childWidthSpec = View.MeasureSpec.makeMeasureSpec(maxContentWidth, View.MeasureSpec.AT_MOST); break; + case ViewGroup.LayoutParams.MATCH_PARENT: + childWidthSpec = View.MeasureSpec.makeMeasureSpec(maxContentWidth, View.MeasureSpec.EXACTLY); break; + default: + //noinspection Range + childWidthSpec = View.MeasureSpec.makeMeasureSpec(mWidth, View.MeasureSpec.EXACTLY); break; + } + + // Add padding only if the list has items in it, that way we don't show + // the popup if it is not needed. For this reason, we measure as wrap_content. + mView.measure(childWidthSpec, View.MeasureSpec.makeMeasureSpec(maxContentHeight, View.MeasureSpec.AT_MOST)); + final int viewHeight = mView.getMeasuredHeight(); + if (viewHeight > 0) { + otherHeights += paddingVert + mView.getPaddingTop() + mView.getPaddingBottom(); + } + + return Math.min(viewHeight + otherHeights, mMaxHeight); + } + + +} \ No newline at end of file diff --git a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePresenter.java b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePresenter.java new file mode 100644 index 0000000000..d49e8c8f30 --- /dev/null +++ b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/AutocompletePresenter.java @@ -0,0 +1,129 @@ +package com.otaliastudios.autocomplete; + +import android.content.Context; +import android.database.DataSetObserver; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * Base class for presenting items inside a popup. This is abstract and must be implemented. + * + * Most important methods are {@link #getView()} and {@link #onQuery(CharSequence)}. + */ +public abstract class AutocompletePresenter { + + private Context context; + private boolean isShowing; + + @SuppressWarnings("WeakerAccess") + public AutocompletePresenter(@NonNull Context context) { + this.context = context; + } + + /** + * At this point the presenter is passed the {@link ClickProvider}. + * The contract is that {@link ClickProvider#click(Object)} must be called when a list item + * is clicked. This ensure that the autocomplete callback will receive the event. + * + * @param provider a click provider for this presenter. + */ + protected void registerClickProvider(ClickProvider provider) { + + } + + /** + * Useful if you wish to change width/height based on content height. + * The contract is to call {@link DataSetObserver#onChanged()} when your view has + * changes. + * + * This is called after {@link #getView()}. + * + * @param observer the observer. + */ + protected void registerDataSetObserver(@NonNull DataSetObserver observer) {} + + /** + * Called each time the popup is shown. You are meant to inflate the view here. + * You can get a LayoutInflater using {@link #getContext()}. + * + * @return a ViewGroup for the popup + */ + @NonNull + protected abstract ViewGroup getView(); + + /** + * Provide the {@link PopupDimensions} for this popup. Called just once. + * You can use fixed dimensions or {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and + * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}. + * + * @return a PopupDimensions object + */ + // Called at first to understand which dimensions to use for the popup. + @NonNull + protected PopupDimensions getPopupDimensions() { + return new PopupDimensions(); + } + + /** + * Perform firther initialization here. Called after {@link #getView()}, + * each time the popup is shown. + */ + protected abstract void onViewShown(); + + /** + * Called to update the view to filter results with the query. + * It is called any time the popup is shown, and any time the text changes and query is updated. + * + * @param query query from the edit text, to filter our results + */ + protected abstract void onQuery(@Nullable CharSequence query); + + /** + * Called when the popup is hidden, to release resources. + */ + protected abstract void onViewHidden(); + + /** + * @return this presenter context + */ + @NonNull + protected final Context getContext() { + return context; + } + + /** + * @return whether we are showing currently + */ + @SuppressWarnings("unused") + protected final boolean isShowing() { + return isShowing; + } + + final void showView() { + isShowing = true; + onViewShown(); + } + + final void hideView() { + isShowing = false; + onViewHidden(); + } + + public interface ClickProvider { + void click(@NonNull T item); + } + + /** + * Provides width, height, maxWidth and maxHeight for the popup. + * @see #getPopupDimensions() + */ + @SuppressWarnings("WeakerAccess") + public static class PopupDimensions { + public int width = ViewGroup.LayoutParams.WRAP_CONTENT; + public int height = ViewGroup.LayoutParams.WRAP_CONTENT; + public int maxWidth = Integer.MAX_VALUE; + public int maxHeight = Integer.MAX_VALUE; + } +} diff --git a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/CharPolicy.java b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/CharPolicy.java new file mode 100644 index 0000000000..9c94983317 --- /dev/null +++ b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/CharPolicy.java @@ -0,0 +1,184 @@ +package com.otaliastudios.autocomplete; + +import android.text.Spannable; +import android.text.Spanned; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + + +/** + * A special {@link AutocompletePolicy} for cases when you want to trigger the popup when a + * certain character is shown. + * + * For instance, this might be the case for hashtags ('#') or usernames ('@') or whatever you wish. + * Passing this to {@link Autocomplete.Builder} ensures the following behavior (assuming '@'): + * - text "@john" : presenter will be passed the query "john" + * - text "You should see this @j" : presenter will be passed the query "j" + * - text "You should see this @john @m" : presenter will be passed the query "m" + */ +public class CharPolicy implements AutocompletePolicy { + + private final static String TAG = CharPolicy.class.getSimpleName(); + private final static boolean DEBUG = false; + + private static void log(@NonNull String log) { + if (DEBUG) Log.e(TAG, log); + } + + private final char CH; + private final int[] INT = new int[2]; + private boolean needSpaceBefore = true; + + /** + * Constructs a char policy for the given character. + * + * @param trigger the triggering character. + */ + public CharPolicy(char trigger) { + CH = trigger; + } + + /** + * Constructs a char policy for the given character. + * You can choose whether a whitespace is needed before 'trigger'. + * + * @param trigger the triggering character. + * @param needSpaceBefore whether we need a space before trigger + */ + @SuppressWarnings("unused") + public CharPolicy(char trigger, boolean needSpaceBefore) { + CH = trigger; + this.needSpaceBefore = needSpaceBefore; + } + + /** + * Can be overriden to understand which characters are valid. The default implementation + * returns true for any character except whitespaces. + * + * @param ch the character + * @return whether it's valid part of a query + */ + @SuppressWarnings("WeakerAccess") + protected boolean isValidChar(char ch) { + return !Character.isWhitespace(ch); + } + + @Nullable + private int[] checkText(@NonNull Spannable text, int cursorPos) { + final int spanEnd = cursorPos; + char last = 'x'; + cursorPos -= 1; // If the cursor is at the end, we will have cursorPos = length. Go back by 1. + while (cursorPos >= 0 && last != CH) { + char ch = text.charAt(cursorPos); + log("checkText: char is "+ch); + if (isValidChar(ch)) { + // We are going back + log("checkText: char is valid"); + cursorPos -= 1; + last = ch; + } else { + // We got a whitespace before getting a CH. This is invalid. + log("checkText: char is not valid, returning NULL"); + return null; + } + } + cursorPos += 1; // + 1 because we end BEHIND the valid selection + + // Start checking. + if (cursorPos == 0 && last != CH) { + // We got to the start of the string, and no CH was encountered. Nothing to do. + log("checkText: got to start but no CH, returning NULL"); + return null; + } + + // Additional checks for cursorPos - 1 + if (cursorPos > 0 && needSpaceBefore) { + char ch = text.charAt(cursorPos-1); + if (!Character.isWhitespace(ch)) { + log("checkText: char before is not whitespace, returning NULL"); + return null; + } + } + + // All seems OK. + final int spanStart = cursorPos + 1; // + 1 because we want to exclude CH from the query + INT[0] = spanStart; + INT[1] = spanEnd; + log("checkText: found! cursorPos="+cursorPos); + log("checkText: found! spanStart="+spanStart); + log("checkText: found! spanEnd="+spanEnd); + return INT; + } + + @Override + public boolean shouldShowPopup(@NonNull Spannable text, int cursorPos) { + // Returning true if, right before cursorPos, we have a word starting with @. + log("shouldShowPopup: text is "+text); + log("shouldShowPopup: cursorPos is "+cursorPos); + int[] show = checkText(text, cursorPos); + if (show != null) { + text.setSpan(new QuerySpan(), show[0], show[1], Spanned.SPAN_INCLUSIVE_INCLUSIVE); + return true; + } + log("shouldShowPopup: returning false"); + return false; + } + + @Override + public boolean shouldDismissPopup(@NonNull Spannable text, int cursorPos) { + log("shouldDismissPopup: text is "+text); + log("shouldDismissPopup: cursorPos is "+cursorPos); + boolean dismiss = checkText(text, cursorPos) == null; + log("shouldDismissPopup: returning "+dismiss); + return dismiss; + } + + @NonNull + @Override + public CharSequence getQuery(@NonNull Spannable text) { + QuerySpan[] span = text.getSpans(0, text.length(), QuerySpan.class); + if (span == null || span.length == 0) { + // Should never happen. + log("getQuery: there's no span!"); + return ""; + } + log("getQuery: found spans: "+span.length); + QuerySpan sp = span[0]; + log("getQuery: span start is "+text.getSpanStart(sp)); + log("getQuery: span end is "+text.getSpanEnd(sp)); + CharSequence seq = text.subSequence(text.getSpanStart(sp), text.getSpanEnd(sp)); + log("getQuery: returning "+seq); + return seq; + } + + + @Override + public void onDismiss(@NonNull Spannable text) { + // Remove any span added by shouldShow. Should be useless, but anyway. + QuerySpan[] span = text.getSpans(0, text.length(), QuerySpan.class); + for (QuerySpan s : span) { + text.removeSpan(s); + } + } + + private static class QuerySpan {} + + /** + * Returns the current query out of the given Spannable. + * @param text the anchor text + * @return an int[] with query start and query end positions + */ + @Nullable + public static int[] getQueryRange(@NonNull Spannable text) { + QuerySpan[] span = text.getSpans(0, text.length(), QuerySpan.class); + if (span == null || span.length == 0) return null; + if (span.length > 1) { + // Won't happen + log("getQueryRange: ERR: MORE THAN ONE QuerySpan."); + } + QuerySpan sp = span[0]; + return new int[]{text.getSpanStart(sp), text.getSpanEnd(sp)}; + } +} diff --git a/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/RecyclerViewPresenter.java b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/RecyclerViewPresenter.java new file mode 100644 index 0000000000..1338ec7cac --- /dev/null +++ b/library/external/autocomplete/src/main/java/com/otaliastudios/autocomplete/RecyclerViewPresenter.java @@ -0,0 +1,152 @@ +package com.otaliastudios.autocomplete; + +import android.content.Context; +import android.database.DataSetObserver; +import android.view.ViewGroup; + +import androidx.annotation.CallSuper; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * Simple {@link AutocompletePresenter} implementation that hosts a {@link RecyclerView}. + * Supports {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} natively. + * The only contract is to + * + * - provide a {@link RecyclerView.Adapter} in {@link #instantiateAdapter()} + * - call {@link #dispatchClick(Object)} when an object is clicked + * - update your data during {@link #onQuery(CharSequence)} + * + * @param your model object (the object displayed by the list) + */ +public abstract class RecyclerViewPresenter extends AutocompletePresenter { + + private RecyclerView recycler; + private ClickProvider clicks; + private Observer observer; + + public RecyclerViewPresenter(@NonNull Context context) { + super(context); + } + + @Override + protected final void registerClickProvider(@NonNull ClickProvider provider) { + this.clicks = provider; + } + + @Override + protected final void registerDataSetObserver(@NonNull DataSetObserver observer) { + this.observer = new Observer(observer); + } + + @NonNull + @Override + protected ViewGroup getView() { + recycler = new RecyclerView(getContext()); + RecyclerView.Adapter adapter = instantiateAdapter(); + recycler.setAdapter(adapter); + recycler.setLayoutManager(instantiateLayoutManager()); + if (observer != null) { + adapter.registerAdapterDataObserver(observer); + observer = null; + } + return recycler; + } + + @Override + protected void onViewShown() {} + + @CallSuper + @Override + protected void onViewHidden() { + recycler = null; + observer = null; + } + + @SuppressWarnings("unused") + @Nullable + protected final RecyclerView getRecyclerView() { + return recycler; + } + + /** + * Dispatch click event to {@link AutocompleteCallback}. + * Should be called when items are clicked. + * + * @param item the clicked item. + */ + protected final void dispatchClick(@NonNull T item) { + if (clicks != null) clicks.click(item); + } + + /** + * Request that the popup should recompute its dimensions based on a recent change in + * the view being displayed. + * + * This is already managed internally for {@link RecyclerView} events. + * Only use it for changes in other views that you have added to the popup, + * and only if one of the dimensions for the popup is WRAP_CONTENT . + */ + @SuppressWarnings("unused") + protected final void dispatchLayoutChange() { + if (observer != null) observer.onChanged(); + } + + /** + * Provide an adapter for the recycler. + * This should be a fresh instance every time this is called. + * + * @return a new adapter. + */ + @NonNull + protected abstract RecyclerView.Adapter instantiateAdapter(); + + /** + * Provides a layout manager for the recycler. + * This should be a fresh instance every time this is called. + * Defaults to a vertical LinearLayoutManager, which is guaranteed to work well. + * + * @return a new layout manager. + */ + @SuppressWarnings("WeakerAccess") + @NonNull + protected RecyclerView.LayoutManager instantiateLayoutManager() { + return new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false); + } + + private final static class Observer extends RecyclerView.AdapterDataObserver { + + private DataSetObserver root; + + Observer(@NonNull DataSetObserver root) { + this.root = root; + } + + @Override + public void onChanged() { + root.onChanged(); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount) { + root.onChanged(); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { + root.onChanged(); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + root.onChanged(); + } + + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + root.onChanged(); + } + } +} diff --git a/settings.gradle b/settings.gradle index a704d0d81a..b3ecd410d6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,6 +12,7 @@ include ':library:external:jsonviewer' include ':library:external:diff-match-patch' include ':library:external:dialpad' include ':library:external:textdrawable' +include ':library:external:autocomplete' include ':library:rustCrypto' include ':matrix-sdk-android' diff --git a/vector/build.gradle b/vector/build.gradle index e38f1ea5e5..83f09fb10b 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -117,6 +117,7 @@ dependencies { implementation project(":library:external:jsonviewer") implementation project(":library:external:diff-match-patch") implementation project(":library:external:textdrawable") + implementation project(":library:external:autocomplete") implementation project(":library:ui-strings") implementation project(":library:ui-styles") implementation project(":library:core-utils") @@ -210,8 +211,6 @@ dependencies { // Alerter implementation 'com.github.tapadoo:alerter:7.2.4' - implementation 'com.otaliastudios:autocomplete:1.1.0' - // Shake detection implementation 'com.squareup:seismic:1.0.3' diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/RecyclerViewPresenter.kt b/vector/src/main/java/im/vector/app/features/autocomplete/RecyclerViewPresenter.kt index 7625eb6216..2648f2f210 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/RecyclerViewPresenter.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/RecyclerViewPresenter.kt @@ -23,7 +23,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.otaliastudios.autocomplete.AutocompletePresenter -abstract class RecyclerViewPresenter(context: Context?) : AutocompletePresenter(context) { +abstract class RecyclerViewPresenter(context: Context) : AutocompletePresenter(context) { private var recyclerView: RecyclerView? = null private var clicks: ClickProvider? = null diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/command/CommandAutocompletePolicy.kt b/vector/src/main/java/im/vector/app/features/autocomplete/command/CommandAutocompletePolicy.kt index 08f61be0f8..9097d2be43 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/command/CommandAutocompletePolicy.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/command/CommandAutocompletePolicy.kt @@ -32,16 +32,15 @@ class CommandAutocompletePolicy @Inject constructor() : AutocompletePolicy { return "" } - override fun onDismiss(text: Spannable?) { + override fun onDismiss(text: Spannable) { } // Only if text which starts with '/' and without space - override fun shouldShowPopup(text: Spannable?, cursorPos: Int): Boolean { - return enabled && text?.startsWith("/") == true && - !text.contains(" ") + override fun shouldShowPopup(text: Spannable, cursorPos: Int): Boolean { + return enabled && text.startsWith("/") && !text.contains(" ") } - override fun shouldDismissPopup(text: Spannable?, cursorPos: Int): Boolean { + override fun shouldDismissPopup(text: Spannable, cursorPos: Int): Boolean { return !shouldShowPopup(text, cursorPos) } } From 1dd3c1589eb38dd7957998f36fd303fe8fe0f522 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 17:48:06 +0200 Subject: [PATCH 156/234] Remove unused dep. --- dependencies_groups.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 4fe36dcf0d..6ca6c00dfa 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -239,7 +239,6 @@ ext.groups = [ regex: [ ], group: [ - 'com.yqritc', // https://github.com/cmelchior/realmfieldnameshelper/issues/42 'dk.ilios', 'im.dlg', From cd292488b6b48731f04eb6ebd5a86ea65a0548d3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 17:51:57 +0200 Subject: [PATCH 157/234] Fix warning --- .../vector/app/features/autocomplete/RecyclerViewPresenter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/RecyclerViewPresenter.kt b/vector/src/main/java/im/vector/app/features/autocomplete/RecyclerViewPresenter.kt index 2648f2f210..cd7ecb8a00 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/RecyclerViewPresenter.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/RecyclerViewPresenter.kt @@ -23,7 +23,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.otaliastudios.autocomplete.AutocompletePresenter -abstract class RecyclerViewPresenter(context: Context) : AutocompletePresenter(context) { +abstract class RecyclerViewPresenter(context: Context) : AutocompletePresenter(context) { private var recyclerView: RecyclerView? = null private var clicks: ClickProvider? = null From ff09ba1208fb50b29dba464e693a65a1367063a4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 17:58:51 +0200 Subject: [PATCH 158/234] Import source from https://github.com/cmelchior/realmfieldnameshelper --- dependencies_groups.gradle | 2 - .../realmfieldnameshelper/build.gradle | 23 +++ .../dk/ilios/realmfieldnames/ClassData.kt | 24 +++ .../realmfieldnames/FieldNameFormatter.kt | 75 +++++++ .../dk/ilios/realmfieldnames/FileGenerator.kt | 82 ++++++++ .../RealmFieldNamesProcessor.kt | 187 ++++++++++++++++++ .../gradle/incremental.annotation.processors | 1 + .../javax.annotation.processing.Processor | 1 + matrix-sdk-android/build.gradle | 2 +- settings.gradle | 1 + 10 files changed, 395 insertions(+), 3 deletions(-) create mode 100644 library/external/realmfieldnameshelper/build.gradle create mode 100644 library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/ClassData.kt create mode 100644 library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt create mode 100644 library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt create mode 100644 library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/RealmFieldNamesProcessor.kt create mode 100644 library/external/realmfieldnameshelper/src/main/resources/META-INF/gradle/incremental.annotation.processors create mode 100644 library/external/realmfieldnameshelper/src/main/resources/META-INF/services/javax.annotation.processing.Processor diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 6ca6c00dfa..35ba4b41a9 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -239,8 +239,6 @@ ext.groups = [ regex: [ ], group: [ - // https://github.com/cmelchior/realmfieldnameshelper/issues/42 - 'dk.ilios', 'im.dlg', 'me.dm7.barcodescanner', 'me.gujun.android', diff --git a/library/external/realmfieldnameshelper/build.gradle b/library/external/realmfieldnameshelper/build.gradle new file mode 100644 index 0000000000..13d8de7ca3 --- /dev/null +++ b/library/external/realmfieldnameshelper/build.gradle @@ -0,0 +1,23 @@ +apply plugin: 'kotlin' +apply plugin: 'java' + +sourceCompatibility = '1.7' +targetCompatibility = '1.7' + +dependencies { + implementation 'com.squareup:javapoet:1.13.0' +} + +task javadocJar(type: Jar, dependsOn: 'javadoc') { + from javadoc.destinationDir + classifier = 'javadoc' +} +task sourcesJar(type: Jar, dependsOn: 'classes') { + from sourceSets.main.allSource + classifier = 'sources' +} + +sourceSets { + main.java.srcDirs += 'src/main/kotlin' +} + diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/ClassData.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/ClassData.kt new file mode 100644 index 0000000000..d683a2adef --- /dev/null +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/ClassData.kt @@ -0,0 +1,24 @@ +package dk.ilios.realmfieldnames + +import java.util.TreeMap + +/** + * Class responsible for keeping track of the metadata for each Realm model class. + */ +class ClassData(val packageName: String?, val simpleClassName: String, val libraryClass: Boolean = false) { + + val fields = TreeMap() // + + fun addField(field: String, linkedType: String?) { + fields.put(field, linkedType) + } + + val qualifiedClassName: String + get() { + if (packageName != null && !packageName.isEmpty()) { + return packageName + "." + simpleClassName + } else { + return simpleClassName + } + } +} diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt new file mode 100644 index 0000000000..fbb44d333b --- /dev/null +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt @@ -0,0 +1,75 @@ +package dk.ilios.realmfieldnames + +import java.util.Locale + +/** + * Class for encapsulating the rules for converting between the field name in the Realm model class + * and the matching name in the "<class>Fields" class. + */ +class FieldNameFormatter { + + @JvmOverloads fun format(fieldName: String?, locale: Locale = Locale.US): String { + if (fieldName == null || fieldName == "") { + return "" + } + + // Normalize word separator chars + val normalizedFieldName : String = fieldName.replace('-', '_') + + // Iterate field name using the following rules + // lowerCase m followed by upperCase anything is considered hungarian notation + // lowercase char followed by uppercase char is considered camel case + // Two uppercase chars following each other is considered non-standard camelcase + // _ and - are treated as word separators + val result = StringBuilder(normalizedFieldName.length) + + if (normalizedFieldName.codePointCount(0, normalizedFieldName.length) == 1) { + result.append(normalizedFieldName) + } else { + var previousCodepoint: Int? + var currentCodepoint: Int? = null + val length = normalizedFieldName.length + var offset = 0 + while (offset < length) { + previousCodepoint = currentCodepoint + currentCodepoint = normalizedFieldName.codePointAt(offset) + + if (previousCodepoint != null) { + if (Character.isUpperCase(currentCodepoint) && !Character.isUpperCase(previousCodepoint) && previousCodepoint === 'm'.code as Int? && result.length == 1) { + // Hungarian notation starting with: mX + result.delete(0, 1) + result.appendCodePoint(currentCodepoint) + + } else if (Character.isUpperCase(currentCodepoint) && Character.isUpperCase(previousCodepoint)) { + // InvalidCamelCase: XXYx (should have been xxYx) + if (offset + Character.charCount(currentCodepoint) < normalizedFieldName.length) { + val nextCodePoint = normalizedFieldName.codePointAt(offset + Character.charCount(currentCodepoint)) + if (Character.isLowerCase(nextCodePoint)) { + result.append("_") + } + } + result.appendCodePoint(currentCodepoint) + + } else if (currentCodepoint === '-'.code as Int? || currentCodepoint === '_'.code as Int?) { + // Word-separator: x-x or x_x + result.append("_") + + } else if (Character.isUpperCase(currentCodepoint) && !Character.isUpperCase(previousCodepoint) && Character.isLetterOrDigit(previousCodepoint)) { + // camelCase: xX + result.append("_") + result.appendCodePoint(currentCodepoint) + } else { + // Unknown type + result.appendCodePoint(currentCodepoint) + } + } else { + // Only triggered for first code point + result.appendCodePoint(currentCodepoint) + } + offset += Character.charCount(currentCodepoint) + } + } + + return result.toString().uppercase(locale) + } +} diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt new file mode 100644 index 0000000000..02bdc70f44 --- /dev/null +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt @@ -0,0 +1,82 @@ +package dk.ilios.realmfieldnames + +import com.squareup.javapoet.FieldSpec +import com.squareup.javapoet.JavaFile +import com.squareup.javapoet.TypeSpec + +import java.io.IOException + +import javax.annotation.processing.Filer +import javax.lang.model.element.Modifier + +/** + * Class responsible for creating the final output files. + */ +class FileGenerator(private val filer: Filer) { + private val formatter: FieldNameFormatter + + init { + this.formatter = FieldNameFormatter() + } + + /** + * Generates all the "<class>Fields" fields with field name references. + * @param fileData Files to create. + * * + * @return `true` if the files where generated, `false` if not. + */ + fun generate(fileData: Set): Boolean { + return fileData + .filter { !it.libraryClass } + .all { generateFile(it, fileData) } + } + + private fun generateFile(classData: ClassData, classPool: Set): Boolean { + + val fileBuilder = TypeSpec.classBuilder(classData.simpleClassName + "Fields") + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addJavadoc("This class enumerate all queryable fields in {@link \$L.\$L}\n", + classData.packageName, classData.simpleClassName) + + + // Add a static field reference to each queryable field in the Realm model class + classData.fields.forEach { fieldName, value -> + if (value != null) { + // Add linked field names (only up to depth 1) + for (data in classPool) { + if (data.qualifiedClassName == value) { + val linkedTypeSpec = TypeSpec.classBuilder(formatter.format(fieldName)) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC) + val linkedClassFields = data.fields + addField(linkedTypeSpec, "$", fieldName) + for (linkedFieldName in linkedClassFields.keys) { + addField(linkedTypeSpec, linkedFieldName, fieldName + "." + linkedFieldName) + } + fileBuilder.addType(linkedTypeSpec.build()) + } + } + } else { + // Add normal field name + addField(fileBuilder, fieldName, fieldName) + } + } + + val javaFile = JavaFile.builder(classData.packageName, fileBuilder.build()).build() + try { + javaFile.writeTo(filer) + return true + } catch (e: IOException) { + e.printStackTrace() + return false + } + + } + + private fun addField(fileBuilder: TypeSpec.Builder, fieldName: String, fieldNameValue: String) { + val field = FieldSpec.builder(String::class.java, formatter.format(fieldName)) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("\$S", fieldNameValue) + .build() + fileBuilder.addField(field) + } +} diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/RealmFieldNamesProcessor.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/RealmFieldNamesProcessor.kt new file mode 100644 index 0000000000..6f82882333 --- /dev/null +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/RealmFieldNamesProcessor.kt @@ -0,0 +1,187 @@ +package dk.ilios.realmfieldnames + +import java.util.* + +import javax.annotation.processing.AbstractProcessor +import javax.annotation.processing.Messager +import javax.annotation.processing.ProcessingEnvironment +import javax.annotation.processing.RoundEnvironment +import javax.annotation.processing.SupportedAnnotationTypes +import javax.lang.model.SourceVersion +import javax.lang.model.element.* +import javax.lang.model.type.DeclaredType +import javax.lang.model.type.TypeMirror +import javax.lang.model.util.Elements +import javax.lang.model.util.Types +import javax.tools.Diagnostic + +/** + * The Realm Field Names Generator is a processor that looks at all available Realm model classes + * and create an companion class with easy, type-safe access to all field names. + */ + +@SupportedAnnotationTypes("io.realm.annotations.RealmClass") +class RealmFieldNamesProcessor : AbstractProcessor() { + + private val classes = HashSet() + lateinit private var typeUtils: Types + lateinit private var messager: Messager + lateinit private var elementUtils: Elements + private var ignoreAnnotation: TypeMirror? = null + private var realmClassAnnotation: TypeElement? = null + private var realmModelInterface: TypeMirror? = null + private var realmListClass: DeclaredType? = null + private var realmResultsClass: DeclaredType? = null + private var fileGenerator: FileGenerator? = null + private var done = false + + @Synchronized override fun init(processingEnv: ProcessingEnvironment) { + super.init(processingEnv) + typeUtils = processingEnv.typeUtils!! + messager = processingEnv.messager!! + elementUtils = processingEnv.elementUtils!! + + // If the Realm class isn't found something is wrong the project setup. + // Most likely Realm isn't on the class path, so just disable the + // annotation processor + val isRealmAvailable = elementUtils.getTypeElement("io.realm.Realm") != null + if (!isRealmAvailable) { + done = true + } else { + ignoreAnnotation = elementUtils.getTypeElement("io.realm.annotations.Ignore")?.asType() + realmClassAnnotation = elementUtils.getTypeElement("io.realm.annotations.RealmClass") + realmModelInterface = elementUtils.getTypeElement("io.realm.RealmModel")?.asType() + realmListClass = typeUtils.getDeclaredType(elementUtils.getTypeElement("io.realm.RealmList"), + typeUtils.getWildcardType(null, null)) + realmResultsClass = typeUtils.getDeclaredType(elementUtils.getTypeElement("io.realm.RealmResults"), + typeUtils.getWildcardType(null, null)) + fileGenerator = FileGenerator(processingEnv.filer) + } + } + + override fun getSupportedSourceVersion(): SourceVersion { + return SourceVersion.latestSupported() + } + + override fun process(annotations: Set, roundEnv: RoundEnvironment): Boolean { + if (done) { + return CONSUME_ANNOTATIONS + } + + // Create all proxy classes + roundEnv.getElementsAnnotatedWith(realmClassAnnotation).forEach { classElement -> + if (typeUtils.isAssignable(classElement.asType(), realmModelInterface)) { + val classData = processClass(classElement as TypeElement) + classes.add(classData) + } + } + + // If a model class references a library class, the library class will not be part of this + // annotation processor round. For all those references we need to pull field information + // from the classpath instead. + val libraryClasses = HashMap() + classes.forEach { + it.fields.forEach { _, value -> + // Analyze the library class file the first time it is encountered. + if (value != null ) { + if (classes.all{ it.qualifiedClassName != value } && !libraryClasses.containsKey(value)) { + libraryClasses.put(value, processLibraryClass(value)) + } + } + } + } + classes.addAll(libraryClasses.values) + + done = fileGenerator!!.generate(classes) + return CONSUME_ANNOTATIONS + } + + private fun processClass(classElement: TypeElement): ClassData { + val packageName = getPackageName(classElement) + val className = classElement.simpleName.toString() + val data = ClassData(packageName, className) + + // Find all appropriate fields + classElement.enclosedElements.forEach { + val elementKind = it.kind + if (elementKind == ElementKind.FIELD) { + val variableElement = it as VariableElement + + val modifiers = variableElement.modifiers + if (modifiers.contains(Modifier.STATIC)) { + return@forEach // completely ignore any static fields + } + + // Don't add any fields marked with @Ignore + val ignoreField = variableElement.annotationMirrors + .map { it.annotationType.toString() } + .contains("io.realm.annotations.Ignore") + + if (!ignoreField) { + data.addField(it.getSimpleName().toString(), getLinkedFieldType(it)) + } + } + } + + return data + } + + private fun processLibraryClass(qualifiedClassName: String): ClassData { + val libraryClass = Class.forName(qualifiedClassName) // Library classes should be on the classpath + val packageName = libraryClass.`package`.name + val className = libraryClass.simpleName + val data = ClassData(packageName, className, libraryClass = true) + + libraryClass.declaredFields.forEach { field -> + if (java.lang.reflect.Modifier.isStatic(field.modifiers)) { + return@forEach // completely ignore any static fields + } + + // Add field if it is not being ignored. + if (field.annotations.all { it.toString() != "io.realm.annotations.Ignore" }) { + data.addField(field.name, field.type.name) + } + } + + return data + } + + /** + * Returns the qualified name of the linked Realm class field or `null` if it is not a linked + * class. + */ + private fun getLinkedFieldType(field: Element): String? { + if (typeUtils.isAssignable(field.asType(), realmModelInterface)) { + // Object link + val typeElement = elementUtils.getTypeElement(field.asType().toString()) + return typeElement.qualifiedName.toString() + } else if (typeUtils.isAssignable(field.asType(), realmListClass) || typeUtils.isAssignable(field.asType(), realmResultsClass)) { + // List link or LinkingObjects + val fieldType = field.asType() + val typeArguments = (fieldType as DeclaredType).typeArguments + if (typeArguments.size == 0) { + return null + } + return typeArguments[0].toString() + } else { + return null + } + } + + private fun getPackageName(classElement: TypeElement): String? { + val enclosingElement = classElement.enclosingElement + + if (enclosingElement.kind != ElementKind.PACKAGE) { + messager.printMessage(Diagnostic.Kind.ERROR, + "Could not determine the package name. Enclosing element was: " + enclosingElement.kind) + return null + } + + val packageElement = enclosingElement as PackageElement + return packageElement.qualifiedName.toString() + } + + companion object { + private const val CONSUME_ANNOTATIONS = false + } +} diff --git a/library/external/realmfieldnameshelper/src/main/resources/META-INF/gradle/incremental.annotation.processors b/library/external/realmfieldnameshelper/src/main/resources/META-INF/gradle/incremental.annotation.processors new file mode 100644 index 0000000000..57897c8297 --- /dev/null +++ b/library/external/realmfieldnameshelper/src/main/resources/META-INF/gradle/incremental.annotation.processors @@ -0,0 +1 @@ +dk.ilios.realmfieldnames.RealmFieldNamesProcessor,aggregating \ No newline at end of file diff --git a/library/external/realmfieldnameshelper/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/library/external/realmfieldnameshelper/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 0000000000..58fadd699c --- /dev/null +++ b/library/external/realmfieldnameshelper/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +dk.ilios.realmfieldnames.RealmFieldNamesProcessor \ No newline at end of file diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 7420fba45e..82bb0b31d5 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -189,7 +189,7 @@ dependencies { // Database implementation 'com.github.Zhuinden:realm-monarchy:0.7.1' - kapt 'dk.ilios:realmfieldnameshelper:2.0.0' + kapt project(":library:external:realmfieldnameshelper") // Shared Preferences implementation libs.androidx.preferenceKtx diff --git a/settings.gradle b/settings.gradle index b3ecd410d6..7b57b530f7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,7 @@ include ':library:external:diff-match-patch' include ':library:external:dialpad' include ':library:external:textdrawable' include ':library:external:autocomplete' +include ':library:external:realmfieldnameshelper' include ':library:rustCrypto' include ':matrix-sdk-android' From e9b94346716d300c8e9503c66606424115fc48c9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 18:01:36 +0200 Subject: [PATCH 159/234] Remove unused dep. --- dependencies_groups.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 35ba4b41a9..60808a0d7f 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -239,7 +239,6 @@ ext.groups = [ regex: [ ], group: [ - 'im.dlg', 'me.dm7.barcodescanner', 'me.gujun.android', ] From 69680a98560e675dacb56422737204414cb79e74 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 18:15:22 +0200 Subject: [PATCH 160/234] Import source from https://github.com/2dxgujun/Kpan --- dependencies_groups.gradle | 1 - library/external/jsonviewer/build.gradle | 4 +- library/external/span/build.gradle | 20 ++ .../main/kotlin/me/gujun/android/span/span.kt | 316 ++++++++++++++++++ .../android/span/style/CustomTypefaceSpan.kt | 36 ++ .../android/span/style/LineSpacingSpan.kt | 31 ++ .../android/span/style/SimpleClickableSpan.kt | 10 + .../span/style/TextDecorationLineSpan.kt | 29 ++ .../android/span/style/VerticalPaddingSpan.kt | 41 +++ settings.gradle | 1 + vector-app/build.gradle | 1 + vector/build.gradle | 4 +- 12 files changed, 487 insertions(+), 7 deletions(-) create mode 100644 library/external/span/build.gradle create mode 100644 library/external/span/src/main/kotlin/me/gujun/android/span/span.kt create mode 100644 library/external/span/src/main/kotlin/me/gujun/android/span/style/CustomTypefaceSpan.kt create mode 100644 library/external/span/src/main/kotlin/me/gujun/android/span/style/LineSpacingSpan.kt create mode 100644 library/external/span/src/main/kotlin/me/gujun/android/span/style/SimpleClickableSpan.kt create mode 100644 library/external/span/src/main/kotlin/me/gujun/android/span/style/TextDecorationLineSpan.kt create mode 100644 library/external/span/src/main/kotlin/me/gujun/android/span/style/VerticalPaddingSpan.kt diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 60808a0d7f..5505e34b25 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -240,7 +240,6 @@ ext.groups = [ ], group: [ 'me.dm7.barcodescanner', - 'me.gujun.android', ] ] ] diff --git a/library/external/jsonviewer/build.gradle b/library/external/jsonviewer/build.gradle index 7b3b62c082..c501f583d0 100644 --- a/library/external/jsonviewer/build.gradle +++ b/library/external/jsonviewer/build.gradle @@ -58,9 +58,7 @@ dependencies { implementation libs.airbnb.mavericks // Span utils - implementation('me.gujun.android:span:1.7') { - exclude group: 'com.android.support', module: 'support-annotations' - } + implementation project(":library:external:span") implementation libs.jetbrains.coroutinesCore implementation libs.jetbrains.coroutinesAndroid diff --git a/library/external/span/build.gradle b/library/external/span/build.gradle new file mode 100644 index 0000000000..05adbacb4d --- /dev/null +++ b/library/external/span/build.gradle @@ -0,0 +1,20 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + namespace "me.gujun.android.span" + compileSdk versions.compileSdk + + defaultConfig { + minSdk versions.minSdk + targetSdk versions.targetSdk + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } +} + +dependencies { + implementation 'com.android.support:support-annotations:28.0.0' +} diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/span.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/span.kt new file mode 100644 index 0000000000..5ca63b7e01 --- /dev/null +++ b/library/external/span/src/main/kotlin/me/gujun/android/span/span.kt @@ -0,0 +1,316 @@ +package me.gujun.android.span + +import android.graphics.Typeface +import android.graphics.drawable.Drawable +import android.text.Layout +import android.text.Spannable +import android.text.SpannableStringBuilder +import android.text.TextUtils +import android.text.style.AbsoluteSizeSpan +import android.text.style.AlignmentSpan +import android.text.style.BackgroundColorSpan +import android.text.style.ForegroundColorSpan +import android.text.style.ImageSpan +import android.text.style.QuoteSpan +import android.text.style.StyleSpan +import android.text.style.SubscriptSpan +import android.text.style.SuperscriptSpan +import android.text.style.TypefaceSpan +import android.text.style.URLSpan +import android.view.View +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import me.gujun.android.span.style.CustomTypefaceSpan +import me.gujun.android.span.style.LineSpacingSpan +import me.gujun.android.span.style.SimpleClickableSpan +import me.gujun.android.span.style.TextDecorationLineSpan +import me.gujun.android.span.style.VerticalPaddingSpan + +class Span(val parent: Span? = null) : SpannableStringBuilder() { + + companion object { + val EMPTY_STYLE = Span() + + var globalStyle: Span = EMPTY_STYLE + } + + var text: CharSequence = "" + + @ColorInt var textColor: Int? = parent?.textColor + + @ColorInt var backgroundColor: Int? = parent?.backgroundColor + + @Dimension(unit = Dimension.PX) var textSize: Int? = parent?.textSize + + var fontFamily: String? = parent?.fontFamily + + var typeface: Typeface? = parent?.typeface + + var textStyle: String? = parent?.textStyle + + var alignment: String? = parent?.alignment + + var textDecorationLine: String? = parent?.textDecorationLine + + @Dimension(unit = Dimension.PX) var lineSpacing: Int? = null + + @Dimension(unit = Dimension.PX) var paddingTop: Int? = null + + @Dimension(unit = Dimension.PX) var paddingBottom: Int? = null + + @Dimension(unit = Dimension.PX) var verticalPadding: Int? = null + + var onClick: (() -> Unit)? = null + + var spans: ArrayList = ArrayList() + + var style: Span = EMPTY_STYLE + + private fun buildCharacterStyle(builder: ArrayList) { + if (textColor != null) { + builder.add(ForegroundColorSpan(textColor!!)) + } + + if (backgroundColor != null) { + builder.add(BackgroundColorSpan(backgroundColor!!)) + } + + if (textSize != null) { + builder.add(AbsoluteSizeSpan(textSize!!)) + } + + if (!TextUtils.isEmpty(fontFamily)) { + builder.add(TypefaceSpan(fontFamily)) + } + + if (typeface != null) { + builder.add(CustomTypefaceSpan(typeface!!)) + } + + if (!TextUtils.isEmpty(textStyle)) { + builder.add(StyleSpan(when (textStyle) { + "normal" -> Typeface.NORMAL + "bold" -> Typeface.BOLD + "italic" -> Typeface.ITALIC + "bold_italic" -> Typeface.BOLD_ITALIC + else -> throw RuntimeException("Unknown text style") + })) + } + + if (!TextUtils.isEmpty(textDecorationLine)) { + builder.add(TextDecorationLineSpan(textDecorationLine!!)) + } + + if (onClick != null) { + builder.add(object : SimpleClickableSpan() { + override fun onClick(widget: View) { + onClick?.invoke() + } + }) + } + } + + private fun buildParagraphStyle(builder: ArrayList) { + if (!TextUtils.isEmpty(alignment)) { + builder.add(AlignmentSpan.Standard(when (alignment) { + "normal" -> Layout.Alignment.ALIGN_NORMAL + "opposite" -> Layout.Alignment.ALIGN_OPPOSITE + "center" -> Layout.Alignment.ALIGN_CENTER + else -> throw RuntimeException("Unknown text alignment") + })) + } + + if (lineSpacing != null) { + builder.add(LineSpacingSpan(lineSpacing!!)) + } + + paddingTop = when { + paddingTop != null -> paddingTop + verticalPadding != null -> verticalPadding + else -> 0 + } + paddingBottom = when { + paddingBottom != null -> paddingBottom + verticalPadding != null -> verticalPadding + else -> 0 + } + if (paddingTop != 0 || paddingBottom != 0) { + builder.add(VerticalPaddingSpan(paddingTop!!, paddingBottom!!)) + } + } + + private fun prebuild() { + override(style) + } + + fun build(): Span { + prebuild() + val builder = ArrayList() + if (!TextUtils.isEmpty(text)) { + var p = this.parent + while (p != null) { + if (!TextUtils.isEmpty(p.text)) { + throw RuntimeException("Can't nest \"$text\" in spans") + } + p = p.parent + } + append(text) + buildCharacterStyle(builder) + buildParagraphStyle(builder) + } else { + buildParagraphStyle(builder) + } + + builder.addAll(spans) + builder.forEach { + setSpan(it, 0, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + } + return this + } + + fun override(style: Span) { + if (textColor == null) { + textColor = style.textColor + } + if (backgroundColor == null) { + backgroundColor = style.backgroundColor + } + if (textSize == null) { + textSize = style.textSize + } + if (fontFamily == null) { + fontFamily = style.fontFamily + } + if (typeface == null) { + typeface = style.typeface + } + if (textStyle == null) { + textStyle = style.textStyle + } + if (alignment == null) { + alignment = style.alignment + } + if (textDecorationLine == null) { + textDecorationLine = style.textDecorationLine + } + if (lineSpacing == null) { + lineSpacing = style.lineSpacing + } + if (paddingTop == null) { + paddingTop = style.paddingTop + } + if (paddingBottom == null) { + paddingBottom = style.paddingBottom + } + if (verticalPadding == null) { + verticalPadding = style.verticalPadding + } + if (onClick == null) { + onClick = style.onClick + } + spans.addAll(style.spans) + } + + operator fun CharSequence.unaryPlus(): CharSequence { + return append(Span(parent = this@Span).apply { + text = this@unaryPlus + build() + }) + } + + operator fun Span.plus(other: CharSequence): CharSequence { + return append(Span(parent = this).apply { + text = other + build() + }) + } +} + +fun span(init: Span.() -> Unit): Span = Span().apply { + override(Span.globalStyle) + init() + build() +} + +fun span(text: CharSequence, init: Span.() -> Unit): Span = Span().apply { + override(Span.globalStyle) + this.text = text + init() + build() +} + +fun style(init: Span.() -> Unit): Span = Span().apply { + init() +} + +fun Span.span(init: Span.() -> Unit = {}): Span = apply { + append(Span(parent = this).apply { + init() + build() + }) +} + +fun Span.span(text: CharSequence, init: Span.() -> Unit = {}): Span = apply { + append(Span(parent = this).apply { + this.text = text + init() + build() + }) +} + +fun Span.link(url: String, text: CharSequence = "", + init: Span.() -> Unit = {}): Span = apply { + append(Span(parent = this).apply { + this.text = text + this.spans.add(URLSpan(url)) + init() + build() + }) +} + +fun Span.quote(@ColorInt color: Int, text: CharSequence = "", + init: Span.() -> Unit = {}): Span = apply { + append(Span(parent = this).apply { + this.text = text + this.spans.add(QuoteSpan(color)) + init() + build() + }) +} + +fun Span.superscript(text: CharSequence = "", init: Span.() -> Unit = {}): Span = apply { + append(Span(parent = this).apply { + this.text = text + this.spans.add(SuperscriptSpan()) + init() + build() + }) +} + +fun Span.subscript(text: CharSequence = "", init: Span.() -> Unit = {}): Span = apply { + append(Span(parent = this).apply { + this.text = text + this.spans.add(SubscriptSpan()) + init() + build() + }) +} + +fun Span.image(drawable: Drawable, alignment: String = "bottom", + init: Span.() -> Unit = {}): Span = apply { + drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight) + append(Span(parent = this).apply { + this.text = " " + this.spans.add(ImageSpan(drawable, when (alignment) { + "bottom" -> ImageSpan.ALIGN_BOTTOM + "baseline" -> ImageSpan.ALIGN_BASELINE + else -> throw RuntimeException("Unknown image alignment") + })) + init() + build() + }) +} + +fun Span.addSpan(what: Any) = apply { + this.spans.add(what) +} diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/style/CustomTypefaceSpan.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/style/CustomTypefaceSpan.kt new file mode 100644 index 0000000000..57ae4548b6 --- /dev/null +++ b/library/external/span/src/main/kotlin/me/gujun/android/span/style/CustomTypefaceSpan.kt @@ -0,0 +1,36 @@ +package me.gujun.android.span.style + +import android.graphics.Paint +import android.graphics.Typeface +import android.text.TextPaint +import android.text.style.MetricAffectingSpan + +class CustomTypefaceSpan(private val tf: Typeface) : MetricAffectingSpan() { + + override fun updateMeasureState(paint: TextPaint) { + apply(paint, tf) + } + + override fun updateDrawState(ds: TextPaint) { + apply(ds, tf) + } + + private fun apply(paint: Paint, tf: Typeface) { + val oldStyle: Int + + val old = paint.typeface + oldStyle = old?.style ?: 0 + + val fake = oldStyle and tf.style.inv() + + if (fake and Typeface.BOLD != 0) { + paint.isFakeBoldText = true + } + + if (fake and Typeface.ITALIC != 0) { + paint.textSkewX = -0.25f + } + + paint.typeface = tf + } +} \ No newline at end of file diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/style/LineSpacingSpan.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/style/LineSpacingSpan.kt new file mode 100644 index 0000000000..53aa42aa83 --- /dev/null +++ b/library/external/span/src/main/kotlin/me/gujun/android/span/style/LineSpacingSpan.kt @@ -0,0 +1,31 @@ +package me.gujun.android.span.style + +import android.graphics.Paint.FontMetricsInt +import android.text.Spanned +import android.text.style.LineHeightSpan + +class LineSpacingSpan(private val add: Int) : LineHeightSpan { + + override fun chooseHeight(text: CharSequence, start: Int, end: Int, spanstartv: Int, v: Int, + fm: FontMetricsInt) { + text as Spanned + /*val spanStart =*/ text.getSpanStart(this) + val spanEnd = text.getSpanEnd(this) + +// Log.d("DEBUG", "Text: start=$start end=$end v=$v") // end may include the \n character +// Log.d("DEBUG", "${text.slice(start until end)}".replace("\n", "#")) +// Log.d("DEBUG", "LineSpacingSpan: spanStart=$spanStart spanEnd=$spanEnd spanstartv=$spanstartv") +// Log.d("DEBUG", "$fm") +// Log.d("DEBUG", "-----------------------") + + if (spanstartv == v) { + fm.descent += add + } else if (text[start - 1] == '\n') { + fm.descent += add + } + + if (end == spanEnd || end - 1 == spanEnd) { + fm.descent -= add + } + } +} diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/style/SimpleClickableSpan.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/style/SimpleClickableSpan.kt new file mode 100644 index 0000000000..2ae524bca9 --- /dev/null +++ b/library/external/span/src/main/kotlin/me/gujun/android/span/style/SimpleClickableSpan.kt @@ -0,0 +1,10 @@ +package me.gujun.android.span.style + +import android.text.TextPaint +import android.text.style.ClickableSpan + +abstract class SimpleClickableSpan : ClickableSpan() { + override fun updateDrawState(ds: TextPaint) { + // no-op + } +} diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/style/TextDecorationLineSpan.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/style/TextDecorationLineSpan.kt new file mode 100644 index 0000000000..662cb82fed --- /dev/null +++ b/library/external/span/src/main/kotlin/me/gujun/android/span/style/TextDecorationLineSpan.kt @@ -0,0 +1,29 @@ +package me.gujun.android.span.style + +import android.text.TextPaint +import android.text.style.CharacterStyle + +class TextDecorationLineSpan(private val textDecorationLine: String) : CharacterStyle() { + + override fun updateDrawState(tp: TextPaint) { + when (textDecorationLine) { + "none" -> { + tp.isUnderlineText = false + tp.isStrikeThruText = false + } + "underline" -> { + tp.isUnderlineText = true + tp.isStrikeThruText = false + } + "line-through" -> { + tp.isUnderlineText = false + tp.isStrikeThruText = true + } + "underline line-through" -> { + tp.isUnderlineText = true + tp.isStrikeThruText = true + } + else -> throw RuntimeException("Unknown text decoration line") + } + } +} \ No newline at end of file diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/style/VerticalPaddingSpan.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/style/VerticalPaddingSpan.kt new file mode 100644 index 0000000000..600ea72e57 --- /dev/null +++ b/library/external/span/src/main/kotlin/me/gujun/android/span/style/VerticalPaddingSpan.kt @@ -0,0 +1,41 @@ +package me.gujun.android.span.style + +import android.graphics.Paint.FontMetricsInt +import android.text.Spanned +import android.text.style.LineHeightSpan + +class VerticalPaddingSpan(private val paddingTop: Int, + private val paddingBottom: Int) : LineHeightSpan { + + private var flag: Boolean = true + + override fun chooseHeight(text: CharSequence, start: Int, end: Int, spanstartv: Int, v: Int, + fm: FontMetricsInt) { + text as Spanned + /*val spanStart =*/ text.getSpanStart(this) + val spanEnd = text.getSpanEnd(this) + +// Log.d("DEBUG", "Text: start=$start end=$end v=$v") // end may include the \n character +// Log.d("DEBUG", "${text.slice(start until end)}".replace("\n", "#")) +// Log.d("DEBUG", "VerticalPadding: spanStart=$spanStart spanEnd=$spanEnd spanstartv=$spanstartv") +// Log.d("DEBUG", "$fm") +// Log.d("DEBUG", "-----------------------") + + if (spanstartv == v) { + fm.top -= paddingTop + fm.ascent -= paddingTop + flag = true + } else if (flag && text[start - 1] != '\n') { + fm.top += paddingTop + fm.ascent += paddingTop + flag = false + } else { + flag = false + } + + if (end == spanEnd || end - 1 == spanEnd) { + fm.descent += paddingBottom + fm.bottom += paddingBottom + } + } +} diff --git a/settings.gradle b/settings.gradle index 7b57b530f7..bccfa7913a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,6 +14,7 @@ include ':library:external:dialpad' include ':library:external:textdrawable' include ':library:external:autocomplete' include ':library:external:realmfieldnameshelper' +include ':library:external:span' include ':library:rustCrypto' include ':matrix-sdk-android' diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 8221497e74..25980df834 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -396,6 +396,7 @@ dependencies { implementation project(':vector') implementation project(':vector-config') implementation project(':library:core-utils') + debugImplementation project(':library:external:span') debugImplementation project(':library:ui-styles') implementation libs.dagger.hilt implementation 'androidx.multidex:multidex:2.0.1' diff --git a/vector/build.gradle b/vector/build.gradle index 83f09fb10b..e45db64548 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -187,9 +187,7 @@ dependencies { // UI implementation libs.google.material - api('me.gujun.android:span:1.7') { - exclude group: 'com.android.support', module: 'support-annotations' - } + implementation project(":library:external:span") implementation libs.markwon.core implementation libs.markwon.extLatex implementation libs.markwon.imageGlide From e9f9decf00e6a8d80fc3dd1e6c5e2030871e3e16 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 18:58:42 +0200 Subject: [PATCH 161/234] Import source from https://github.com/dm77/barcodescanner --- dependencies_groups.gradle | 1 - .../external/barcodescanner/core/build.gradle | 26 ++ .../core/BarcodeScannerView.java | 339 ++++++++++++++++++ .../core/CameraHandlerThread.java | 37 ++ .../barcodescanner/core/CameraPreview.java | 312 ++++++++++++++++ .../dm7/barcodescanner/core/CameraUtils.java | 63 ++++ .../barcodescanner/core/CameraWrapper.java | 23 ++ .../dm7/barcodescanner/core/DisplayUtils.java | 41 +++ .../dm7/barcodescanner/core/IViewFinder.java | 53 +++ .../barcodescanner/core/ViewFinderView.java | 259 +++++++++++++ .../core/src/main/res/values-hdpi/strings.xml | 5 + .../src/main/res/values-xhdpi/strings.xml | 5 + .../src/main/res/values-xxhdpi/strings.xml | 5 + .../core/src/main/res/values/attrs.xml | 17 + .../core/src/main/res/values/colors.xml | 6 + .../core/src/main/res/values/strings.xml | 4 + .../barcodescanner/zxing/build.gradle | 29 ++ .../zxing/ZXingScannerView.java | 198 ++++++++++ settings.gradle | 2 + vector/build.gradle | 6 +- 20 files changed, 1425 insertions(+), 6 deletions(-) create mode 100644 library/external/barcodescanner/core/build.gradle create mode 100644 library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/BarcodeScannerView.java create mode 100644 library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraHandlerThread.java create mode 100644 library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraPreview.java create mode 100644 library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraUtils.java create mode 100644 library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraWrapper.java create mode 100644 library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/DisplayUtils.java create mode 100644 library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/IViewFinder.java create mode 100644 library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/ViewFinderView.java create mode 100644 library/external/barcodescanner/core/src/main/res/values-hdpi/strings.xml create mode 100644 library/external/barcodescanner/core/src/main/res/values-xhdpi/strings.xml create mode 100644 library/external/barcodescanner/core/src/main/res/values-xxhdpi/strings.xml create mode 100644 library/external/barcodescanner/core/src/main/res/values/attrs.xml create mode 100644 library/external/barcodescanner/core/src/main/res/values/colors.xml create mode 100644 library/external/barcodescanner/core/src/main/res/values/strings.xml create mode 100644 library/external/barcodescanner/zxing/build.gradle create mode 100644 library/external/barcodescanner/zxing/src/main/java/me/dm7/barcodescanner/zxing/ZXingScannerView.java diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 5505e34b25..9e5d1e4072 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -239,7 +239,6 @@ ext.groups = [ regex: [ ], group: [ - 'me.dm7.barcodescanner', ] ] ] diff --git a/library/external/barcodescanner/core/build.gradle b/library/external/barcodescanner/core/build.gradle new file mode 100644 index 0000000000..583b435dd7 --- /dev/null +++ b/library/external/barcodescanner/core/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'com.android.library' + +android { + namespace "me.dm7.barcodescanner.core" + compileSdk versions.compileSdk + + defaultConfig { + minSdk versions.minSdk + targetSdk versions.targetSdk + } + + compileOptions { + sourceCompatibility versions.sourceCompat + targetCompatibility versions.targetCompat + } +} + +dependencies { + implementation 'androidx.annotation:annotation-jvm:1.6.0' +} + +afterEvaluate { + tasks.findAll { it.name.startsWith("lint") }.each { + it.enabled = false + } +} diff --git a/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/BarcodeScannerView.java b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/BarcodeScannerView.java new file mode 100644 index 0000000000..ecfba76d89 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/BarcodeScannerView.java @@ -0,0 +1,339 @@ +package me.dm7.barcodescanner.core; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.Rect; +import android.hardware.Camera; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; + +import androidx.annotation.ColorInt; + +public abstract class BarcodeScannerView extends FrameLayout implements Camera.PreviewCallback { + + private CameraWrapper mCameraWrapper; + private CameraPreview mPreview; + private IViewFinder mViewFinderView; + private Rect mFramingRectInPreview; + private CameraHandlerThread mCameraHandlerThread; + private Boolean mFlashState; + private boolean mAutofocusState = true; + private boolean mShouldScaleToFill = true; + + private boolean mIsLaserEnabled = true; + @ColorInt private int mLaserColor = getResources().getColor(R.color.viewfinder_laser); + @ColorInt private int mBorderColor = getResources().getColor(R.color.viewfinder_border); + private int mMaskColor = getResources().getColor(R.color.viewfinder_mask); + private int mBorderWidth = getResources().getInteger(R.integer.viewfinder_border_width); + private int mBorderLength = getResources().getInteger(R.integer.viewfinder_border_length); + private boolean mRoundedCorner = false; + private int mCornerRadius = 0; + private boolean mSquaredFinder = false; + private float mBorderAlpha = 1.0f; + private int mViewFinderOffset = 0; + private float mAspectTolerance = 0.1f; + + public BarcodeScannerView(Context context) { + super(context); + init(); + } + + public BarcodeScannerView(Context context, AttributeSet attributeSet) { + super(context, attributeSet); + + TypedArray a = context.getTheme().obtainStyledAttributes( + attributeSet, + R.styleable.BarcodeScannerView, + 0, 0); + + try { + setShouldScaleToFill(a.getBoolean(R.styleable.BarcodeScannerView_shouldScaleToFill, true)); + mIsLaserEnabled = a.getBoolean(R.styleable.BarcodeScannerView_laserEnabled, mIsLaserEnabled); + mLaserColor = a.getColor(R.styleable.BarcodeScannerView_laserColor, mLaserColor); + mBorderColor = a.getColor(R.styleable.BarcodeScannerView_borderColor, mBorderColor); + mMaskColor = a.getColor(R.styleable.BarcodeScannerView_maskColor, mMaskColor); + mBorderWidth = a.getDimensionPixelSize(R.styleable.BarcodeScannerView_borderWidth, mBorderWidth); + mBorderLength = a.getDimensionPixelSize(R.styleable.BarcodeScannerView_borderLength, mBorderLength); + + mRoundedCorner = a.getBoolean(R.styleable.BarcodeScannerView_roundedCorner, mRoundedCorner); + mCornerRadius = a.getDimensionPixelSize(R.styleable.BarcodeScannerView_cornerRadius, mCornerRadius); + mSquaredFinder = a.getBoolean(R.styleable.BarcodeScannerView_squaredFinder, mSquaredFinder); + mBorderAlpha = a.getFloat(R.styleable.BarcodeScannerView_borderAlpha, mBorderAlpha); + mViewFinderOffset = a.getDimensionPixelSize(R.styleable.BarcodeScannerView_finderOffset, mViewFinderOffset); + } finally { + a.recycle(); + } + + init(); + } + + private void init() { + mViewFinderView = createViewFinderView(getContext()); + } + + public final void setupLayout(CameraWrapper cameraWrapper) { + removeAllViews(); + + mPreview = new CameraPreview(getContext(), cameraWrapper, this); + mPreview.setAspectTolerance(mAspectTolerance); + mPreview.setShouldScaleToFill(mShouldScaleToFill); + if (!mShouldScaleToFill) { + RelativeLayout relativeLayout = new RelativeLayout(getContext()); + relativeLayout.setGravity(Gravity.CENTER); + relativeLayout.setBackgroundColor(Color.BLACK); + relativeLayout.addView(mPreview); + addView(relativeLayout); + } else { + addView(mPreview); + } + + if (mViewFinderView instanceof View) { + addView((View) mViewFinderView); + } else { + throw new IllegalArgumentException("IViewFinder object returned by " + + "'createViewFinderView()' should be instance of android.view.View"); + } + } + + /** + *

Method that creates view that represents visual appearance of a barcode scanner

+ *

Override it to provide your own view for visual appearance of a barcode scanner

+ * + * @param context {@link Context} + * @return {@link android.view.View} that implements {@link ViewFinderView} + */ + protected IViewFinder createViewFinderView(Context context) { + ViewFinderView viewFinderView = new ViewFinderView(context); + viewFinderView.setBorderColor(mBorderColor); + viewFinderView.setLaserColor(mLaserColor); + viewFinderView.setLaserEnabled(mIsLaserEnabled); + viewFinderView.setBorderStrokeWidth(mBorderWidth); + viewFinderView.setBorderLineLength(mBorderLength); + viewFinderView.setMaskColor(mMaskColor); + + viewFinderView.setBorderCornerRounded(mRoundedCorner); + viewFinderView.setBorderCornerRadius(mCornerRadius); + viewFinderView.setSquareViewFinder(mSquaredFinder); + viewFinderView.setViewFinderOffset(mViewFinderOffset); + return viewFinderView; + } + + public void setLaserColor(int laserColor) { + mLaserColor = laserColor; + mViewFinderView.setLaserColor(mLaserColor); + mViewFinderView.setupViewFinder(); + } + public void setMaskColor(int maskColor) { + mMaskColor = maskColor; + mViewFinderView.setMaskColor(mMaskColor); + mViewFinderView.setupViewFinder(); + } + public void setBorderColor(int borderColor) { + mBorderColor = borderColor; + mViewFinderView.setBorderColor(mBorderColor); + mViewFinderView.setupViewFinder(); + } + public void setBorderStrokeWidth(int borderStrokeWidth) { + mBorderWidth = borderStrokeWidth; + mViewFinderView.setBorderStrokeWidth(mBorderWidth); + mViewFinderView.setupViewFinder(); + } + public void setBorderLineLength(int borderLineLength) { + mBorderLength = borderLineLength; + mViewFinderView.setBorderLineLength(mBorderLength); + mViewFinderView.setupViewFinder(); + } + public void setLaserEnabled(boolean isLaserEnabled) { + mIsLaserEnabled = isLaserEnabled; + mViewFinderView.setLaserEnabled(mIsLaserEnabled); + mViewFinderView.setupViewFinder(); + } + public void setIsBorderCornerRounded(boolean isBorderCornerRounded) { + mRoundedCorner = isBorderCornerRounded; + mViewFinderView.setBorderCornerRounded(mRoundedCorner); + mViewFinderView.setupViewFinder(); + } + public void setBorderCornerRadius(int borderCornerRadius) { + mCornerRadius = borderCornerRadius; + mViewFinderView.setBorderCornerRadius(mCornerRadius); + mViewFinderView.setupViewFinder(); + } + public void setSquareViewFinder(boolean isSquareViewFinder) { + mSquaredFinder = isSquareViewFinder; + mViewFinderView.setSquareViewFinder(mSquaredFinder); + mViewFinderView.setupViewFinder(); + } + public void setBorderAlpha(float borderAlpha) { + mBorderAlpha = borderAlpha; + mViewFinderView.setBorderAlpha(mBorderAlpha); + mViewFinderView.setupViewFinder(); + } + + public void startCamera(int cameraId) { + if(mCameraHandlerThread == null) { + mCameraHandlerThread = new CameraHandlerThread(this); + } + mCameraHandlerThread.startCamera(cameraId); + } + + public void setupCameraPreview(CameraWrapper cameraWrapper) { + mCameraWrapper = cameraWrapper; + if(mCameraWrapper != null) { + setupLayout(mCameraWrapper); + mViewFinderView.setupViewFinder(); + if(mFlashState != null) { + setFlash(mFlashState); + } + setAutoFocus(mAutofocusState); + } + } + + public void startCamera() { + startCamera(CameraUtils.getDefaultCameraId()); + } + + public void stopCamera() { + if(mCameraWrapper != null) { + mPreview.stopCameraPreview(); + mPreview.setCamera(null, null); + mCameraWrapper.mCamera.release(); + mCameraWrapper = null; + } + if(mCameraHandlerThread != null) { + mCameraHandlerThread.quit(); + mCameraHandlerThread = null; + } + } + + public void stopCameraPreview() { + if(mPreview != null) { + mPreview.stopCameraPreview(); + } + } + + protected void resumeCameraPreview() { + if(mPreview != null) { + mPreview.showCameraPreview(); + } + } + + public synchronized Rect getFramingRectInPreview(int previewWidth, int previewHeight) { + if (mFramingRectInPreview == null) { + Rect framingRect = mViewFinderView.getFramingRect(); + int viewFinderViewWidth = mViewFinderView.getWidth(); + int viewFinderViewHeight = mViewFinderView.getHeight(); + if (framingRect == null || viewFinderViewWidth == 0 || viewFinderViewHeight == 0) { + return null; + } + + Rect rect = new Rect(framingRect); + + if(previewWidth < viewFinderViewWidth) { + rect.left = rect.left * previewWidth / viewFinderViewWidth; + rect.right = rect.right * previewWidth / viewFinderViewWidth; + } + + if(previewHeight < viewFinderViewHeight) { + rect.top = rect.top * previewHeight / viewFinderViewHeight; + rect.bottom = rect.bottom * previewHeight / viewFinderViewHeight; + } + + mFramingRectInPreview = rect; + } + return mFramingRectInPreview; + } + + public void setFlash(boolean flag) { + mFlashState = flag; + if(mCameraWrapper != null && CameraUtils.isFlashSupported(mCameraWrapper.mCamera)) { + + Camera.Parameters parameters = mCameraWrapper.mCamera.getParameters(); + if(flag) { + if(parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH)) { + return; + } + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); + } else { + if(parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_OFF)) { + return; + } + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + } + mCameraWrapper.mCamera.setParameters(parameters); + } + } + + public boolean getFlash() { + if(mCameraWrapper != null && CameraUtils.isFlashSupported(mCameraWrapper.mCamera)) { + Camera.Parameters parameters = mCameraWrapper.mCamera.getParameters(); + if(parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH)) { + return true; + } else { + return false; + } + } + return false; + } + + public void toggleFlash() { + if(mCameraWrapper != null && CameraUtils.isFlashSupported(mCameraWrapper.mCamera)) { + Camera.Parameters parameters = mCameraWrapper.mCamera.getParameters(); + if(parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH)) { + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + } else { + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); + } + mCameraWrapper.mCamera.setParameters(parameters); + } + } + + public void setAutoFocus(boolean state) { + mAutofocusState = state; + if(mPreview != null) { + mPreview.setAutoFocus(state); + } + } + + public void setShouldScaleToFill(boolean shouldScaleToFill) { + mShouldScaleToFill = shouldScaleToFill; + } + + public void setAspectTolerance(float aspectTolerance) { + mAspectTolerance = aspectTolerance; + } + + public byte[] getRotatedData(byte[] data, Camera camera) { + Camera.Parameters parameters = camera.getParameters(); + Camera.Size size = parameters.getPreviewSize(); + int width = size.width; + int height = size.height; + + int rotationCount = getRotationCount(); + + if(rotationCount == 1 || rotationCount == 3) { + for (int i = 0; i < rotationCount; i++) { + byte[] rotatedData = new byte[data.length]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) + rotatedData[x * height + height - y - 1] = data[x + y * width]; + } + data = rotatedData; + int tmp = width; + width = height; + height = tmp; + } + } + + return data; + } + + public int getRotationCount() { + int displayOrientation = mPreview.getDisplayOrientation(); + return displayOrientation / 90; + } +} + diff --git a/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraHandlerThread.java b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraHandlerThread.java new file mode 100644 index 0000000000..2d4bcee7bf --- /dev/null +++ b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraHandlerThread.java @@ -0,0 +1,37 @@ +package me.dm7.barcodescanner.core; + + +import android.hardware.Camera; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; + +// This code is mostly based on the top answer here: http://stackoverflow.com/questions/18149964/best-use-of-handlerthread-over-other-similar-classes +public class CameraHandlerThread extends HandlerThread { + private static final String LOG_TAG = "CameraHandlerThread"; + + private BarcodeScannerView mScannerView; + + public CameraHandlerThread(BarcodeScannerView scannerView) { + super("CameraHandlerThread"); + mScannerView = scannerView; + start(); + } + + public void startCamera(final int cameraId) { + Handler localHandler = new Handler(getLooper()); + localHandler.post(new Runnable() { + @Override + public void run() { + final Camera camera = CameraUtils.getCameraInstance(cameraId); + Handler mainHandler = new Handler(Looper.getMainLooper()); + mainHandler.post(new Runnable() { + @Override + public void run() { + mScannerView.setupCameraPreview(CameraWrapper.getWrapper(camera, cameraId)); + } + }); + } + }); + } +} diff --git a/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraPreview.java b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraPreview.java new file mode 100644 index 0000000000..b066e25b2c --- /dev/null +++ b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraPreview.java @@ -0,0 +1,312 @@ +package me.dm7.barcodescanner.core; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Point; +import android.hardware.Camera; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Display; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; + +import java.util.List; + +public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { + private static final String TAG = "CameraPreview"; + + private CameraWrapper mCameraWrapper; + private Handler mAutoFocusHandler; + private boolean mPreviewing = true; + private boolean mAutoFocus = true; + private boolean mSurfaceCreated = false; + private boolean mShouldScaleToFill = true; + private Camera.PreviewCallback mPreviewCallback; + private float mAspectTolerance = 0.1f; + + public CameraPreview(Context context, CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) { + super(context); + init(cameraWrapper, previewCallback); + } + + public CameraPreview(Context context, AttributeSet attrs, CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) { + super(context, attrs); + init(cameraWrapper, previewCallback); + } + + public void init(CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) { + setCamera(cameraWrapper, previewCallback); + mAutoFocusHandler = new Handler(); + getHolder().addCallback(this); + getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + } + + public void setCamera(CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) { + mCameraWrapper = cameraWrapper; + mPreviewCallback = previewCallback; + } + + public void setShouldScaleToFill(boolean scaleToFill) { + mShouldScaleToFill = scaleToFill; + } + + public void setAspectTolerance(float aspectTolerance) { + mAspectTolerance = aspectTolerance; + } + + @Override + public void surfaceCreated(SurfaceHolder surfaceHolder) { + mSurfaceCreated = true; + } + + @Override + public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) { + if(surfaceHolder.getSurface() == null) { + return; + } + stopCameraPreview(); + showCameraPreview(); + } + + @Override + public void surfaceDestroyed(SurfaceHolder surfaceHolder) { + mSurfaceCreated = false; + stopCameraPreview(); + } + + public void showCameraPreview() { + if(mCameraWrapper != null) { + try { + getHolder().addCallback(this); + mPreviewing = true; + setupCameraParameters(); + mCameraWrapper.mCamera.setPreviewDisplay(getHolder()); + mCameraWrapper.mCamera.setDisplayOrientation(getDisplayOrientation()); + mCameraWrapper.mCamera.setOneShotPreviewCallback(mPreviewCallback); + mCameraWrapper.mCamera.startPreview(); + if(mAutoFocus) { + if (mSurfaceCreated) { // check if surface created before using autofocus + safeAutoFocus(); + } else { + scheduleAutoFocus(); // wait 1 sec and then do check again + } + } + } catch (Exception e) { + Log.e(TAG, e.toString(), e); + } + } + } + + public void safeAutoFocus() { + try { + mCameraWrapper.mCamera.autoFocus(autoFocusCB); + } catch (RuntimeException re) { + // Horrible hack to deal with autofocus errors on Sony devices + // See https://github.com/dm77/barcodescanner/issues/7 for example + scheduleAutoFocus(); // wait 1 sec and then do check again + } + } + + public void stopCameraPreview() { + if(mCameraWrapper != null) { + try { + mPreviewing = false; + getHolder().removeCallback(this); + mCameraWrapper.mCamera.cancelAutoFocus(); + mCameraWrapper.mCamera.setOneShotPreviewCallback(null); + mCameraWrapper.mCamera.stopPreview(); + } catch(Exception e) { + Log.e(TAG, e.toString(), e); + } + } + } + + public void setupCameraParameters() { + Camera.Size optimalSize = getOptimalPreviewSize(); + Camera.Parameters parameters = mCameraWrapper.mCamera.getParameters(); + parameters.setPreviewSize(optimalSize.width, optimalSize.height); + mCameraWrapper.mCamera.setParameters(parameters); + adjustViewSize(optimalSize); + } + + private void adjustViewSize(Camera.Size cameraSize) { + Point previewSize = convertSizeToLandscapeOrientation(new Point(getWidth(), getHeight())); + float cameraRatio = ((float) cameraSize.width) / cameraSize.height; + float screenRatio = ((float) previewSize.x) / previewSize.y; + + if (screenRatio > cameraRatio) { + setViewSize((int) (previewSize.y * cameraRatio), previewSize.y); + } else { + setViewSize(previewSize.x, (int) (previewSize.x / cameraRatio)); + } + } + + @SuppressWarnings("SuspiciousNameCombination") + private Point convertSizeToLandscapeOrientation(Point size) { + if (getDisplayOrientation() % 180 == 0) { + return size; + } else { + return new Point(size.y, size.x); + } + } + + @SuppressWarnings("SuspiciousNameCombination") + private void setViewSize(int width, int height) { + ViewGroup.LayoutParams layoutParams = getLayoutParams(); + int tmpWidth; + int tmpHeight; + if (getDisplayOrientation() % 180 == 0) { + tmpWidth = width; + tmpHeight = height; + } else { + tmpWidth = height; + tmpHeight = width; + } + + if (mShouldScaleToFill) { + int parentWidth = ((View) getParent()).getWidth(); + int parentHeight = ((View) getParent()).getHeight(); + float ratioWidth = (float) parentWidth / (float) tmpWidth; + float ratioHeight = (float) parentHeight / (float) tmpHeight; + + float compensation; + + if (ratioWidth > ratioHeight) { + compensation = ratioWidth; + } else { + compensation = ratioHeight; + } + + tmpWidth = Math.round(tmpWidth * compensation); + tmpHeight = Math.round(tmpHeight * compensation); + } + + layoutParams.width = tmpWidth; + layoutParams.height = tmpHeight; + setLayoutParams(layoutParams); + } + + public int getDisplayOrientation() { + if (mCameraWrapper == null) { + //If we don't have a camera set there is no orientation so return dummy value + return 0; + } + + Camera.CameraInfo info = new Camera.CameraInfo(); + if(mCameraWrapper.mCameraId == -1) { + Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info); + } else { + Camera.getCameraInfo(mCameraWrapper.mCameraId, info); + } + + WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + + int rotation = display.getRotation(); + int degrees = 0; + switch (rotation) { + case Surface.ROTATION_0: degrees = 0; break; + case Surface.ROTATION_90: degrees = 90; break; + case Surface.ROTATION_180: degrees = 180; break; + case Surface.ROTATION_270: degrees = 270; break; + } + + int result; + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + result = (info.orientation + degrees) % 360; + result = (360 - result) % 360; // compensate the mirror + } else { // back-facing + result = (info.orientation - degrees + 360) % 360; + } + return result; + } + + private Camera.Size getOptimalPreviewSize() { + if(mCameraWrapper == null) { + return null; + } + + List sizes = mCameraWrapper.mCamera.getParameters().getSupportedPreviewSizes(); + int w = getWidth(); + int h = getHeight(); + if (DisplayUtils.getScreenOrientation(getContext()) == Configuration.ORIENTATION_PORTRAIT) { + int portraitWidth = h; + h = w; + w = portraitWidth; + } + + double targetRatio = (double) w / h; + if (sizes == null) return null; + + Camera.Size optimalSize = null; + double minDiff = Double.MAX_VALUE; + + int targetHeight = h; + + // Try to find an size match aspect ratio and size + for (Camera.Size size : sizes) { + double ratio = (double) size.width / size.height; + if (Math.abs(ratio - targetRatio) > mAspectTolerance) continue; + if (Math.abs(size.height - targetHeight) < minDiff) { + optimalSize = size; + minDiff = Math.abs(size.height - targetHeight); + } + } + + // Cannot find the one match the aspect ratio, ignore the requirement + if (optimalSize == null) { + minDiff = Double.MAX_VALUE; + for (Camera.Size size : sizes) { + if (Math.abs(size.height - targetHeight) < minDiff) { + optimalSize = size; + minDiff = Math.abs(size.height - targetHeight); + } + } + } + return optimalSize; + } + + public void setAutoFocus(boolean state) { + if(mCameraWrapper != null && mPreviewing) { + if(state == mAutoFocus) { + return; + } + mAutoFocus = state; + if(mAutoFocus) { + if (mSurfaceCreated) { // check if surface created before using autofocus + Log.v(TAG, "Starting autofocus"); + safeAutoFocus(); + } else { + scheduleAutoFocus(); // wait 1 sec and then do check again + } + } else { + Log.v(TAG, "Cancelling autofocus"); + mCameraWrapper.mCamera.cancelAutoFocus(); + } + } + } + + private Runnable doAutoFocus = new Runnable() { + public void run() { + if(mCameraWrapper != null && mPreviewing && mAutoFocus && mSurfaceCreated) { + safeAutoFocus(); + } + } + }; + + // Mimic continuous auto-focusing + Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() { + public void onAutoFocus(boolean success, Camera camera) { + scheduleAutoFocus(); + } + }; + + private void scheduleAutoFocus() { + mAutoFocusHandler.postDelayed(doAutoFocus, 1000); + } +} diff --git a/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraUtils.java b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraUtils.java new file mode 100644 index 0000000000..599bd5fa48 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraUtils.java @@ -0,0 +1,63 @@ +package me.dm7.barcodescanner.core; + +import android.hardware.Camera; + +import java.util.List; + +public class CameraUtils { + /** A safe way to get an instance of the Camera object. */ + public static Camera getCameraInstance() { + return getCameraInstance(getDefaultCameraId()); + } + + /** Favor back-facing camera by default. If none exists, fallback to whatever camera is available **/ + public static int getDefaultCameraId() { + int numberOfCameras = Camera.getNumberOfCameras(); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + int defaultCameraId = -1; + for (int i = 0; i < numberOfCameras; i++) { + defaultCameraId = i; + Camera.getCameraInfo(i, cameraInfo); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { + return i; + } + } + return defaultCameraId; + } + + /** A safe way to get an instance of the Camera object. */ + public static Camera getCameraInstance(int cameraId) { + Camera c = null; + try { + if(cameraId == -1) { + c = Camera.open(); // attempt to get a Camera instance + } else { + c = Camera.open(cameraId); // attempt to get a Camera instance + } + } + catch (Exception e) { + // Camera is not available (in use or does not exist) + } + return c; // returns null if camera is unavailable + } + + public static boolean isFlashSupported(Camera camera) { + /* Credits: Top answer at http://stackoverflow.com/a/19599365/868173 */ + if (camera != null) { + Camera.Parameters parameters = camera.getParameters(); + + if (parameters.getFlashMode() == null) { + return false; + } + + List supportedFlashModes = parameters.getSupportedFlashModes(); + if (supportedFlashModes == null || supportedFlashModes.isEmpty() || supportedFlashModes.size() == 1 && supportedFlashModes.get(0).equals(Camera.Parameters.FLASH_MODE_OFF)) { + return false; + } + } else { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraWrapper.java b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraWrapper.java new file mode 100644 index 0000000000..49759ae0f9 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraWrapper.java @@ -0,0 +1,23 @@ +package me.dm7.barcodescanner.core; + +import android.hardware.Camera; + +import androidx.annotation.NonNull; + +public class CameraWrapper { + public final Camera mCamera; + public final int mCameraId; + + private CameraWrapper(@NonNull Camera camera, int cameraId) { + this.mCamera = camera; + this.mCameraId = cameraId; + } + + public static CameraWrapper getWrapper(Camera camera, int cameraId) { + if (camera == null) { + return null; + } else { + return new CameraWrapper(camera, cameraId); + } + } +} diff --git a/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/DisplayUtils.java b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/DisplayUtils.java new file mode 100644 index 0000000000..6c47312221 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/DisplayUtils.java @@ -0,0 +1,41 @@ +package me.dm7.barcodescanner.core; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Point; +import android.view.Display; +import android.view.WindowManager; + +public class DisplayUtils { + public static Point getScreenResolution(Context context) { + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + Point screenResolution = new Point(); + if (android.os.Build.VERSION.SDK_INT >= 13) { + display.getSize(screenResolution); + } else { + screenResolution.set(display.getWidth(), display.getHeight()); + } + + return screenResolution; + } + + public static int getScreenOrientation(Context context) + { + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + + int orientation = Configuration.ORIENTATION_UNDEFINED; + if(display.getWidth()==display.getHeight()){ + orientation = Configuration.ORIENTATION_SQUARE; + } else{ + if(display.getWidth() < display.getHeight()){ + orientation = Configuration.ORIENTATION_PORTRAIT; + }else { + orientation = Configuration.ORIENTATION_LANDSCAPE; + } + } + return orientation; + } + +} diff --git a/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/IViewFinder.java b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/IViewFinder.java new file mode 100644 index 0000000000..a6caaa4cb6 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/IViewFinder.java @@ -0,0 +1,53 @@ +package me.dm7.barcodescanner.core; + +import android.graphics.Rect; + +public interface IViewFinder { + + void setLaserColor(int laserColor); + void setMaskColor(int maskColor); + void setBorderColor(int borderColor); + void setBorderStrokeWidth(int borderStrokeWidth); + void setBorderLineLength(int borderLineLength); + void setLaserEnabled(boolean isLaserEnabled); + + void setBorderCornerRounded(boolean isBorderCornersRounded); + void setBorderAlpha(float alpha); + void setBorderCornerRadius(int borderCornersRadius); + void setViewFinderOffset(int offset); + void setSquareViewFinder(boolean isSquareViewFinder); + /** + * Method that executes when Camera preview is starting. + * It is recommended to update framing rect here and invalidate view after that.
+ * For example see: {@link ViewFinderView#setupViewFinder()} + */ + void setupViewFinder(); + + /** + * Provides {@link Rect} that identifies area where barcode scanner can detect visual codes + *

Note: This rect is a area representation in absolute pixel values.
+ * For example:
+ * If View's size is 1024x800 so framing rect might be 500x400

+ * + * @return {@link Rect} that identifies barcode scanner area + */ + Rect getFramingRect(); + + /** + * Width of a {@link android.view.View} that implements this interface + *

Note: this is already implemented in {@link android.view.View}, + * so you don't need to override method and provide your implementation

+ * + * @return width of a view + */ + int getWidth(); + + /** + * Height of a {@link android.view.View} that implements this interface + *

Note: this is already implemented in {@link android.view.View}, + * so you don't need to override method and provide your implementation

+ * + * @return height of a view + */ + int getHeight(); +} diff --git a/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/ViewFinderView.java b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/ViewFinderView.java new file mode 100644 index 0000000000..307a8a42b4 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/ViewFinderView.java @@ -0,0 +1,259 @@ +package me.dm7.barcodescanner.core; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Canvas; +import android.graphics.CornerPathEffect; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Point; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.View; + +public class ViewFinderView extends View implements IViewFinder { + private static final String TAG = "ViewFinderView"; + + private Rect mFramingRect; + + private static final float PORTRAIT_WIDTH_RATIO = 6f/8; + private static final float PORTRAIT_WIDTH_HEIGHT_RATIO = 0.75f; + + private static final float LANDSCAPE_HEIGHT_RATIO = 5f/8; + private static final float LANDSCAPE_WIDTH_HEIGHT_RATIO = 1.4f; + private static final int MIN_DIMENSION_DIFF = 50; + + private static final float DEFAULT_SQUARE_DIMENSION_RATIO = 5f / 8; + + private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64}; + private int scannerAlpha; + private static final int POINT_SIZE = 10; + private static final long ANIMATION_DELAY = 80l; + + private final int mDefaultLaserColor = getResources().getColor(R.color.viewfinder_laser); + private final int mDefaultMaskColor = getResources().getColor(R.color.viewfinder_mask); + private final int mDefaultBorderColor = getResources().getColor(R.color.viewfinder_border); + private final int mDefaultBorderStrokeWidth = getResources().getInteger(R.integer.viewfinder_border_width); + private final int mDefaultBorderLineLength = getResources().getInteger(R.integer.viewfinder_border_length); + + protected Paint mLaserPaint; + protected Paint mFinderMaskPaint; + protected Paint mBorderPaint; + protected int mBorderLineLength; + protected boolean mSquareViewFinder; + private boolean mIsLaserEnabled; + private float mBordersAlpha; + private int mViewFinderOffset = 0; + + public ViewFinderView(Context context) { + super(context); + init(); + } + + public ViewFinderView(Context context, AttributeSet attributeSet) { + super(context, attributeSet); + init(); + } + + private void init() { + //set up laser paint + mLaserPaint = new Paint(); + mLaserPaint.setColor(mDefaultLaserColor); + mLaserPaint.setStyle(Paint.Style.FILL); + + //finder mask paint + mFinderMaskPaint = new Paint(); + mFinderMaskPaint.setColor(mDefaultMaskColor); + + //border paint + mBorderPaint = new Paint(); + mBorderPaint.setColor(mDefaultBorderColor); + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setStrokeWidth(mDefaultBorderStrokeWidth); + mBorderPaint.setAntiAlias(true); + + mBorderLineLength = mDefaultBorderLineLength; + } + + @Override + public void setLaserColor(int laserColor) { + mLaserPaint.setColor(laserColor); + } + + @Override + public void setMaskColor(int maskColor) { + mFinderMaskPaint.setColor(maskColor); + } + + @Override + public void setBorderColor(int borderColor) { + mBorderPaint.setColor(borderColor); + } + + @Override + public void setBorderStrokeWidth(int borderStrokeWidth) { + mBorderPaint.setStrokeWidth(borderStrokeWidth); + } + + @Override + public void setBorderLineLength(int borderLineLength) { + mBorderLineLength = borderLineLength; + } + + @Override + public void setLaserEnabled(boolean isLaserEnabled) { mIsLaserEnabled = isLaserEnabled; } + + @Override + public void setBorderCornerRounded(boolean isBorderCornersRounded) { + if (isBorderCornersRounded) { + mBorderPaint.setStrokeJoin(Paint.Join.ROUND); + } else { + mBorderPaint.setStrokeJoin(Paint.Join.BEVEL); + } + } + + @Override + public void setBorderAlpha(float alpha) { + int colorAlpha = (int) (255 * alpha); + mBordersAlpha = alpha; + mBorderPaint.setAlpha(colorAlpha); + } + + @Override + public void setBorderCornerRadius(int borderCornersRadius) { + mBorderPaint.setPathEffect(new CornerPathEffect(borderCornersRadius)); + } + + @Override + public void setViewFinderOffset(int offset) { + mViewFinderOffset = offset; + } + + // TODO: Need a better way to configure this. Revisit when working on 2.0 + @Override + public void setSquareViewFinder(boolean set) { + mSquareViewFinder = set; + } + + public void setupViewFinder() { + updateFramingRect(); + invalidate(); + } + + public Rect getFramingRect() { + return mFramingRect; + } + + @Override + public void onDraw(Canvas canvas) { + if(getFramingRect() == null) { + return; + } + + drawViewFinderMask(canvas); + drawViewFinderBorder(canvas); + + if (mIsLaserEnabled) { + drawLaser(canvas); + } + } + + public void drawViewFinderMask(Canvas canvas) { + int width = canvas.getWidth(); + int height = canvas.getHeight(); + Rect framingRect = getFramingRect(); + + canvas.drawRect(0, 0, width, framingRect.top, mFinderMaskPaint); + canvas.drawRect(0, framingRect.top, framingRect.left, framingRect.bottom + 1, mFinderMaskPaint); + canvas.drawRect(framingRect.right + 1, framingRect.top, width, framingRect.bottom + 1, mFinderMaskPaint); + canvas.drawRect(0, framingRect.bottom + 1, width, height, mFinderMaskPaint); + } + + public void drawViewFinderBorder(Canvas canvas) { + Rect framingRect = getFramingRect(); + + // Top-left corner + Path path = new Path(); + path.moveTo(framingRect.left, framingRect.top + mBorderLineLength); + path.lineTo(framingRect.left, framingRect.top); + path.lineTo(framingRect.left + mBorderLineLength, framingRect.top); + canvas.drawPath(path, mBorderPaint); + + // Top-right corner + path.moveTo(framingRect.right, framingRect.top + mBorderLineLength); + path.lineTo(framingRect.right, framingRect.top); + path.lineTo(framingRect.right - mBorderLineLength, framingRect.top); + canvas.drawPath(path, mBorderPaint); + + // Bottom-right corner + path.moveTo(framingRect.right, framingRect.bottom - mBorderLineLength); + path.lineTo(framingRect.right, framingRect.bottom); + path.lineTo(framingRect.right - mBorderLineLength, framingRect.bottom); + canvas.drawPath(path, mBorderPaint); + + // Bottom-left corner + path.moveTo(framingRect.left, framingRect.bottom - mBorderLineLength); + path.lineTo(framingRect.left, framingRect.bottom); + path.lineTo(framingRect.left + mBorderLineLength, framingRect.bottom); + canvas.drawPath(path, mBorderPaint); + } + + public void drawLaser(Canvas canvas) { + Rect framingRect = getFramingRect(); + + // Draw a red "laser scanner" line through the middle to show decoding is active + mLaserPaint.setAlpha(SCANNER_ALPHA[scannerAlpha]); + scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length; + int middle = framingRect.height() / 2 + framingRect.top; + canvas.drawRect(framingRect.left + 2, middle - 1, framingRect.right - 1, middle + 2, mLaserPaint); + + postInvalidateDelayed(ANIMATION_DELAY, + framingRect.left - POINT_SIZE, + framingRect.top - POINT_SIZE, + framingRect.right + POINT_SIZE, + framingRect.bottom + POINT_SIZE); + } + + @Override + protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) { + updateFramingRect(); + } + + public synchronized void updateFramingRect() { + Point viewResolution = new Point(getWidth(), getHeight()); + int width; + int height; + int orientation = DisplayUtils.getScreenOrientation(getContext()); + + if(mSquareViewFinder) { + if(orientation != Configuration.ORIENTATION_PORTRAIT) { + height = (int) (getHeight() * DEFAULT_SQUARE_DIMENSION_RATIO); + width = height; + } else { + width = (int) (getWidth() * DEFAULT_SQUARE_DIMENSION_RATIO); + height = width; + } + } else { + if(orientation != Configuration.ORIENTATION_PORTRAIT) { + height = (int) (getHeight() * LANDSCAPE_HEIGHT_RATIO); + width = (int) (LANDSCAPE_WIDTH_HEIGHT_RATIO * height); + } else { + width = (int) (getWidth() * PORTRAIT_WIDTH_RATIO); + height = (int) (PORTRAIT_WIDTH_HEIGHT_RATIO * width); + } + } + + if(width > getWidth()) { + width = getWidth() - MIN_DIMENSION_DIFF; + } + + if(height > getHeight()) { + height = getHeight() - MIN_DIMENSION_DIFF; + } + + int leftOffset = (viewResolution.x - width) / 2; + int topOffset = (viewResolution.y - height) / 2; + mFramingRect = new Rect(leftOffset + mViewFinderOffset, topOffset + mViewFinderOffset, leftOffset + width - mViewFinderOffset, topOffset + height - mViewFinderOffset); + } +} + diff --git a/library/external/barcodescanner/core/src/main/res/values-hdpi/strings.xml b/library/external/barcodescanner/core/src/main/res/values-hdpi/strings.xml new file mode 100644 index 0000000000..d5979caaf8 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/res/values-hdpi/strings.xml @@ -0,0 +1,5 @@ + + + 4 + 60 + \ No newline at end of file diff --git a/library/external/barcodescanner/core/src/main/res/values-xhdpi/strings.xml b/library/external/barcodescanner/core/src/main/res/values-xhdpi/strings.xml new file mode 100644 index 0000000000..7f57b00a3a --- /dev/null +++ b/library/external/barcodescanner/core/src/main/res/values-xhdpi/strings.xml @@ -0,0 +1,5 @@ + + + 5 + 80 + \ No newline at end of file diff --git a/library/external/barcodescanner/core/src/main/res/values-xxhdpi/strings.xml b/library/external/barcodescanner/core/src/main/res/values-xxhdpi/strings.xml new file mode 100644 index 0000000000..d69e2a8b0f --- /dev/null +++ b/library/external/barcodescanner/core/src/main/res/values-xxhdpi/strings.xml @@ -0,0 +1,5 @@ + + + 6 + 100 + \ No newline at end of file diff --git a/library/external/barcodescanner/core/src/main/res/values/attrs.xml b/library/external/barcodescanner/core/src/main/res/values/attrs.xml new file mode 100644 index 0000000000..8e7485ebb3 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/res/values/attrs.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/library/external/barcodescanner/core/src/main/res/values/colors.xml b/library/external/barcodescanner/core/src/main/res/values/colors.xml new file mode 100644 index 0000000000..58c019a6a9 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #60000000 + #ffcc0000 + #ffafed44 + \ No newline at end of file diff --git a/library/external/barcodescanner/core/src/main/res/values/strings.xml b/library/external/barcodescanner/core/src/main/res/values/strings.xml new file mode 100644 index 0000000000..9cfbb9e1c4 --- /dev/null +++ b/library/external/barcodescanner/core/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + 4 + 60 + diff --git a/library/external/barcodescanner/zxing/build.gradle b/library/external/barcodescanner/zxing/build.gradle new file mode 100644 index 0000000000..e84d0f5bb9 --- /dev/null +++ b/library/external/barcodescanner/zxing/build.gradle @@ -0,0 +1,29 @@ +apply plugin: 'com.android.library' + +android { + namespace "me.dm7.barcodescanner.zxing" + + compileSdk versions.compileSdk + + defaultConfig { + minSdk versions.minSdk + targetSdk versions.targetSdk + } + + compileOptions { + sourceCompatibility versions.sourceCompat + targetCompatibility versions.targetCompat + } +} + +dependencies { + api project(":library:external:barcodescanner:core") + // Stick to 3.3.3 because of https://github.com/zxing/zxing/issues/1170 + api 'com.google.zxing:core:3.3.3' +} + +afterEvaluate { + tasks.findAll { it.name.startsWith("lint") }.each { + it.enabled = false + } +} diff --git a/library/external/barcodescanner/zxing/src/main/java/me/dm7/barcodescanner/zxing/ZXingScannerView.java b/library/external/barcodescanner/zxing/src/main/java/me/dm7/barcodescanner/zxing/ZXingScannerView.java new file mode 100644 index 0000000000..d1717ba5be --- /dev/null +++ b/library/external/barcodescanner/zxing/src/main/java/me/dm7/barcodescanner/zxing/ZXingScannerView.java @@ -0,0 +1,198 @@ +package me.dm7.barcodescanner.zxing; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.hardware.Camera; +import android.os.Handler; +import android.os.Looper; +import android.util.AttributeSet; +import android.util.Log; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.BinaryBitmap; +import com.google.zxing.DecodeHintType; +import com.google.zxing.LuminanceSource; +import com.google.zxing.MultiFormatReader; +import com.google.zxing.NotFoundException; +import com.google.zxing.PlanarYUVLuminanceSource; +import com.google.zxing.ReaderException; +import com.google.zxing.Result; +import com.google.zxing.common.HybridBinarizer; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +import me.dm7.barcodescanner.core.BarcodeScannerView; +import me.dm7.barcodescanner.core.DisplayUtils; + +public class ZXingScannerView extends BarcodeScannerView { + private static final String TAG = "ZXingScannerView"; + + public interface ResultHandler { + void handleResult(Result rawResult); + } + + private MultiFormatReader mMultiFormatReader; + public static final List ALL_FORMATS = new ArrayList<>(); + private List mFormats; + private ResultHandler mResultHandler; + + static { + ALL_FORMATS.add(BarcodeFormat.AZTEC); + ALL_FORMATS.add(BarcodeFormat.CODABAR); + ALL_FORMATS.add(BarcodeFormat.CODE_39); + ALL_FORMATS.add(BarcodeFormat.CODE_93); + ALL_FORMATS.add(BarcodeFormat.CODE_128); + ALL_FORMATS.add(BarcodeFormat.DATA_MATRIX); + ALL_FORMATS.add(BarcodeFormat.EAN_8); + ALL_FORMATS.add(BarcodeFormat.EAN_13); + ALL_FORMATS.add(BarcodeFormat.ITF); + ALL_FORMATS.add(BarcodeFormat.MAXICODE); + ALL_FORMATS.add(BarcodeFormat.PDF_417); + ALL_FORMATS.add(BarcodeFormat.QR_CODE); + ALL_FORMATS.add(BarcodeFormat.RSS_14); + ALL_FORMATS.add(BarcodeFormat.RSS_EXPANDED); + ALL_FORMATS.add(BarcodeFormat.UPC_A); + ALL_FORMATS.add(BarcodeFormat.UPC_E); + ALL_FORMATS.add(BarcodeFormat.UPC_EAN_EXTENSION); + } + + public ZXingScannerView(Context context) { + super(context); + initMultiFormatReader(); + } + + public ZXingScannerView(Context context, AttributeSet attributeSet) { + super(context, attributeSet); + initMultiFormatReader(); + } + + public void setFormats(List formats) { + mFormats = formats; + initMultiFormatReader(); + } + + public void setResultHandler(ResultHandler resultHandler) { + mResultHandler = resultHandler; + } + + public Collection getFormats() { + if(mFormats == null) { + return ALL_FORMATS; + } + return mFormats; + } + + private void initMultiFormatReader() { + Map hints = new EnumMap<>(DecodeHintType.class); + hints.put(DecodeHintType.POSSIBLE_FORMATS, getFormats()); + mMultiFormatReader = new MultiFormatReader(); + mMultiFormatReader.setHints(hints); + } + + @Override + public void onPreviewFrame(byte[] data, Camera camera) { + if(mResultHandler == null) { + return; + } + + try { + Camera.Parameters parameters = camera.getParameters(); + Camera.Size size = parameters.getPreviewSize(); + int width = size.width; + int height = size.height; + + if (DisplayUtils.getScreenOrientation(getContext()) == Configuration.ORIENTATION_PORTRAIT) { + int rotationCount = getRotationCount(); + if (rotationCount == 1 || rotationCount == 3) { + int tmp = width; + width = height; + height = tmp; + } + data = getRotatedData(data, camera); + } + + Result rawResult = null; + PlanarYUVLuminanceSource source = buildLuminanceSource(data, width, height); + + if (source != null) { + BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); + try { + rawResult = mMultiFormatReader.decodeWithState(bitmap); + } catch (ReaderException re) { + // continue + } catch (NullPointerException npe) { + // This is terrible + } catch (ArrayIndexOutOfBoundsException aoe) { + + } finally { + mMultiFormatReader.reset(); + } + + if (rawResult == null) { + LuminanceSource invertedSource = source.invert(); + bitmap = new BinaryBitmap(new HybridBinarizer(invertedSource)); + try { + rawResult = mMultiFormatReader.decodeWithState(bitmap); + } catch (NotFoundException e) { + // continue + } finally { + mMultiFormatReader.reset(); + } + } + } + + final Result finalRawResult = rawResult; + + if (finalRawResult != null) { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + @Override + public void run() { + // Stopping the preview can take a little long. + // So we want to set result handler to null to discard subsequent calls to + // onPreviewFrame. + ResultHandler tmpResultHandler = mResultHandler; + mResultHandler = null; + + stopCameraPreview(); + if (tmpResultHandler != null) { + tmpResultHandler.handleResult(finalRawResult); + } + } + }); + } else { + camera.setOneShotPreviewCallback(this); + } + } catch(RuntimeException e) { + // TODO: Terrible hack. It is possible that this method is invoked after camera is released. + Log.e(TAG, e.toString(), e); + } + } + + public void resumeCameraPreview(ResultHandler resultHandler) { + mResultHandler = resultHandler; + super.resumeCameraPreview(); + } + + public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) { + Rect rect = getFramingRectInPreview(width, height); + if (rect == null) { + return null; + } + // Go ahead and assume it's YUV rather than die. + PlanarYUVLuminanceSource source = null; + + try { + source = new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, + rect.width(), rect.height(), false); + } catch(Exception e) { + } + + return source; + } +} diff --git a/settings.gradle b/settings.gradle index bccfa7913a..a0b9ce65ed 100644 --- a/settings.gradle +++ b/settings.gradle @@ -15,6 +15,8 @@ include ':library:external:textdrawable' include ':library:external:autocomplete' include ':library:external:realmfieldnameshelper' include ':library:external:span' +include ':library:external:barcodescanner:core' +include ':library:external:barcodescanner:zxing' include ':library:rustCrypto' include ':matrix-sdk-android' diff --git a/vector/build.gradle b/vector/build.gradle index e45db64548..eef4e333cf 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -263,11 +263,7 @@ dependencies { // Stick to 3.3.3 because of https://github.com/zxing/zxing/issues/1170 implementation 'com.google.zxing:core:3.3.3' - // Excludes the legacy support library annotation usages - // https://github.com/dm77/barcodescanner/blob/d036996c8a6f36a68843ffe539c834c28944b2d5/core/src/main/java/me/dm7/barcodescanner/core/CameraWrapper.java#L4 - implementation ('me.dm7.barcodescanner:zxing:1.9.13') { - exclude group: 'com.android.support', module: 'support-v4' - } + implementation project(":library:external:barcodescanner:zxing") // Emoji Keyboard api libs.vanniktech.emojiMaterial From dc9e649703b0fe5fcdb4b82ad162df57728035cf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 19:00:06 +0200 Subject: [PATCH 162/234] Remove Jcenter repository ref (#2773) --- build.gradle | 11 ----------- dependencies_groups.gradle | 6 ------ 2 files changed, 17 deletions(-) diff --git a/build.gradle b/build.gradle index a70b54a833..edf07c097a 100644 --- a/build.gradle +++ b/build.gradle @@ -112,16 +112,6 @@ allprojects { groups.google.group.each { includeGroup it } } } - //noinspection JcenterRepositoryObsolete - // Do not use `jcenter`, it prevents Dependabot from working properly - maven { - url 'https://jcenter.bintray.com' - content { - groups.jcenter.regex.each { includeGroupByRegex it } - groups.jcenter.group.each { includeGroup it } - } - } - maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots' content { @@ -129,7 +119,6 @@ allprojects { groups.mavenSnapshots.group.each { includeGroup it } } } - } tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 9e5d1e4072..c023eab2eb 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -235,10 +235,4 @@ ext.groups = [ 'xml-apis', ] ], - jcenter : [ - regex: [ - ], - group: [ - ] - ] ] From ea424f29fb67f5368b9b79606cb80241e21dcdeb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 22:58:28 +0200 Subject: [PATCH 163/234] Fix ktlint issue --- .../realmfieldnameshelper/build.gradle | 4 +- .../realmfieldnames/FieldNameFormatter.kt | 5 +-- .../dk/ilios/realmfieldnames/FileGenerator.kt | 5 --- .../RealmFieldNamesProcessor.kt | 40 ++++++++++++------- .../android/span/style/CustomTypefaceSpan.kt | 2 +- .../span/style/TextDecorationLineSpan.kt | 2 +- 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/library/external/realmfieldnameshelper/build.gradle b/library/external/realmfieldnameshelper/build.gradle index 13d8de7ca3..e051550210 100644 --- a/library/external/realmfieldnameshelper/build.gradle +++ b/library/external/realmfieldnameshelper/build.gradle @@ -1,8 +1,8 @@ apply plugin: 'kotlin' apply plugin: 'java' -sourceCompatibility = '1.7' -targetCompatibility = '1.7' +sourceCompatibility = versions.sourceCompat +targetCompatibility = versions.sourceCompat dependencies { implementation 'com.squareup:javapoet:1.13.0' diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt index fbb44d333b..80ec9f779b 100644 --- a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt @@ -14,7 +14,7 @@ class FieldNameFormatter { } // Normalize word separator chars - val normalizedFieldName : String = fieldName.replace('-', '_') + val normalizedFieldName: String = fieldName.replace('-', '_') // Iterate field name using the following rules // lowerCase m followed by upperCase anything is considered hungarian notation @@ -39,7 +39,6 @@ class FieldNameFormatter { // Hungarian notation starting with: mX result.delete(0, 1) result.appendCodePoint(currentCodepoint) - } else if (Character.isUpperCase(currentCodepoint) && Character.isUpperCase(previousCodepoint)) { // InvalidCamelCase: XXYx (should have been xxYx) if (offset + Character.charCount(currentCodepoint) < normalizedFieldName.length) { @@ -49,11 +48,9 @@ class FieldNameFormatter { } } result.appendCodePoint(currentCodepoint) - } else if (currentCodepoint === '-'.code as Int? || currentCodepoint === '_'.code as Int?) { // Word-separator: x-x or x_x result.append("_") - } else if (Character.isUpperCase(currentCodepoint) && !Character.isUpperCase(previousCodepoint) && Character.isLetterOrDigit(previousCodepoint)) { // camelCase: xX result.append("_") diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt index 02bdc70f44..eeeb5a45b8 100644 --- a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt @@ -3,9 +3,7 @@ package dk.ilios.realmfieldnames import com.squareup.javapoet.FieldSpec import com.squareup.javapoet.JavaFile import com.squareup.javapoet.TypeSpec - import java.io.IOException - import javax.annotation.processing.Filer import javax.lang.model.element.Modifier @@ -32,13 +30,11 @@ class FileGenerator(private val filer: Filer) { } private fun generateFile(classData: ClassData, classPool: Set): Boolean { - val fileBuilder = TypeSpec.classBuilder(classData.simpleClassName + "Fields") .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addJavadoc("This class enumerate all queryable fields in {@link \$L.\$L}\n", classData.packageName, classData.simpleClassName) - // Add a static field reference to each queryable field in the Realm model class classData.fields.forEach { fieldName, value -> if (value != null) { @@ -69,7 +65,6 @@ class FileGenerator(private val filer: Filer) { e.printStackTrace() return false } - } private fun addField(fileBuilder: TypeSpec.Builder, fieldName: String, fieldNameValue: String) { diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/RealmFieldNamesProcessor.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/RealmFieldNamesProcessor.kt index 6f82882333..29d044c46c 100644 --- a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/RealmFieldNamesProcessor.kt +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/RealmFieldNamesProcessor.kt @@ -1,14 +1,17 @@ package dk.ilios.realmfieldnames -import java.util.* - import javax.annotation.processing.AbstractProcessor import javax.annotation.processing.Messager import javax.annotation.processing.ProcessingEnvironment import javax.annotation.processing.RoundEnvironment import javax.annotation.processing.SupportedAnnotationTypes import javax.lang.model.SourceVersion -import javax.lang.model.element.* +import javax.lang.model.element.Element +import javax.lang.model.element.ElementKind +import javax.lang.model.element.Modifier +import javax.lang.model.element.PackageElement +import javax.lang.model.element.TypeElement +import javax.lang.model.element.VariableElement import javax.lang.model.type.DeclaredType import javax.lang.model.type.TypeMirror import javax.lang.model.util.Elements @@ -24,9 +27,9 @@ import javax.tools.Diagnostic class RealmFieldNamesProcessor : AbstractProcessor() { private val classes = HashSet() - lateinit private var typeUtils: Types - lateinit private var messager: Messager - lateinit private var elementUtils: Elements + private lateinit var typeUtils: Types + private lateinit var messager: Messager + private lateinit var elementUtils: Elements private var ignoreAnnotation: TypeMirror? = null private var realmClassAnnotation: TypeElement? = null private var realmModelInterface: TypeMirror? = null @@ -35,7 +38,8 @@ class RealmFieldNamesProcessor : AbstractProcessor() { private var fileGenerator: FileGenerator? = null private var done = false - @Synchronized override fun init(processingEnv: ProcessingEnvironment) { + @Synchronized + override fun init(processingEnv: ProcessingEnvironment) { super.init(processingEnv) typeUtils = processingEnv.typeUtils!! messager = processingEnv.messager!! @@ -51,10 +55,14 @@ class RealmFieldNamesProcessor : AbstractProcessor() { ignoreAnnotation = elementUtils.getTypeElement("io.realm.annotations.Ignore")?.asType() realmClassAnnotation = elementUtils.getTypeElement("io.realm.annotations.RealmClass") realmModelInterface = elementUtils.getTypeElement("io.realm.RealmModel")?.asType() - realmListClass = typeUtils.getDeclaredType(elementUtils.getTypeElement("io.realm.RealmList"), - typeUtils.getWildcardType(null, null)) - realmResultsClass = typeUtils.getDeclaredType(elementUtils.getTypeElement("io.realm.RealmResults"), - typeUtils.getWildcardType(null, null)) + realmListClass = typeUtils.getDeclaredType( + elementUtils.getTypeElement("io.realm.RealmList"), + typeUtils.getWildcardType(null, null) + ) + realmResultsClass = typeUtils.getDeclaredType( + elementUtils.getTypeElement("io.realm.RealmResults"), + typeUtils.getWildcardType(null, null) + ) fileGenerator = FileGenerator(processingEnv.filer) } } @@ -83,8 +91,8 @@ class RealmFieldNamesProcessor : AbstractProcessor() { classes.forEach { it.fields.forEach { _, value -> // Analyze the library class file the first time it is encountered. - if (value != null ) { - if (classes.all{ it.qualifiedClassName != value } && !libraryClasses.containsKey(value)) { + if (value != null) { + if (classes.all { it.qualifiedClassName != value } && !libraryClasses.containsKey(value)) { libraryClasses.put(value, processLibraryClass(value)) } } @@ -172,8 +180,10 @@ class RealmFieldNamesProcessor : AbstractProcessor() { val enclosingElement = classElement.enclosingElement if (enclosingElement.kind != ElementKind.PACKAGE) { - messager.printMessage(Diagnostic.Kind.ERROR, - "Could not determine the package name. Enclosing element was: " + enclosingElement.kind) + messager.printMessage( + Diagnostic.Kind.ERROR, + "Could not determine the package name. Enclosing element was: " + enclosingElement.kind + ) return null } diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/style/CustomTypefaceSpan.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/style/CustomTypefaceSpan.kt index 57ae4548b6..c737c5bf11 100644 --- a/library/external/span/src/main/kotlin/me/gujun/android/span/style/CustomTypefaceSpan.kt +++ b/library/external/span/src/main/kotlin/me/gujun/android/span/style/CustomTypefaceSpan.kt @@ -33,4 +33,4 @@ class CustomTypefaceSpan(private val tf: Typeface) : MetricAffectingSpan() { paint.typeface = tf } -} \ No newline at end of file +} diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/style/TextDecorationLineSpan.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/style/TextDecorationLineSpan.kt index 662cb82fed..ce37c138f7 100644 --- a/library/external/span/src/main/kotlin/me/gujun/android/span/style/TextDecorationLineSpan.kt +++ b/library/external/span/src/main/kotlin/me/gujun/android/span/style/TextDecorationLineSpan.kt @@ -26,4 +26,4 @@ class TextDecorationLineSpan(private val textDecorationLine: String) : Character else -> throw RuntimeException("Unknown text decoration line") } } -} \ No newline at end of file +} From 2c57453efd69171995489fbc0a9d00cf85998b46 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 23:00:00 +0200 Subject: [PATCH 164/234] Fix detekt issue --- .../dk/ilios/realmfieldnames/FieldNameFormatter.kt | 13 ++++++++++--- .../dk/ilios/realmfieldnames/FileGenerator.kt | 2 +- .../me/gujun/android/span/{span.kt => Span.kt} | 0 3 files changed, 11 insertions(+), 4 deletions(-) rename library/external/span/src/main/kotlin/me/gujun/android/span/{span.kt => Span.kt} (100%) diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt index 80ec9f779b..95f0024721 100644 --- a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FieldNameFormatter.kt @@ -8,7 +8,8 @@ import java.util.Locale */ class FieldNameFormatter { - @JvmOverloads fun format(fieldName: String?, locale: Locale = Locale.US): String { + @JvmOverloads + fun format(fieldName: String?, locale: Locale = Locale.US): String { if (fieldName == null || fieldName == "") { return "" } @@ -35,7 +36,11 @@ class FieldNameFormatter { currentCodepoint = normalizedFieldName.codePointAt(offset) if (previousCodepoint != null) { - if (Character.isUpperCase(currentCodepoint) && !Character.isUpperCase(previousCodepoint) && previousCodepoint === 'm'.code as Int? && result.length == 1) { + if (Character.isUpperCase(currentCodepoint) && + !Character.isUpperCase(previousCodepoint) && + previousCodepoint === 'm'.code as Int? && + result.length == 1 + ) { // Hungarian notation starting with: mX result.delete(0, 1) result.appendCodePoint(currentCodepoint) @@ -51,7 +56,9 @@ class FieldNameFormatter { } else if (currentCodepoint === '-'.code as Int? || currentCodepoint === '_'.code as Int?) { // Word-separator: x-x or x_x result.append("_") - } else if (Character.isUpperCase(currentCodepoint) && !Character.isUpperCase(previousCodepoint) && Character.isLetterOrDigit(previousCodepoint)) { + } else if (Character.isUpperCase(currentCodepoint) && !Character.isUpperCase(previousCodepoint) && Character.isLetterOrDigit( + previousCodepoint + )) { // camelCase: xX result.append("_") result.appendCodePoint(currentCodepoint) diff --git a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt index eeeb5a45b8..2ddba1ccbd 100644 --- a/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt +++ b/library/external/realmfieldnameshelper/src/main/kotlin/dk/ilios/realmfieldnames/FileGenerator.kt @@ -62,7 +62,7 @@ class FileGenerator(private val filer: Filer) { javaFile.writeTo(filer) return true } catch (e: IOException) { - e.printStackTrace() + // e.printStackTrace() return false } } diff --git a/library/external/span/src/main/kotlin/me/gujun/android/span/span.kt b/library/external/span/src/main/kotlin/me/gujun/android/span/Span.kt similarity index 100% rename from library/external/span/src/main/kotlin/me/gujun/android/span/span.kt rename to library/external/span/src/main/kotlin/me/gujun/android/span/Span.kt From 9b63293e45eb9d5def78ce7886e237b0ef715c46 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 23:13:33 +0200 Subject: [PATCH 165/234] Rename files to avoid danger issue. --- .../src/main/res/values-hdpi/{strings.xml => integers.xml} | 0 .../src/main/res/values-xhdpi/{strings.xml => integers.xml} | 0 .../src/main/res/values-xxhdpi/{strings.xml => integers.xml} | 0 .../core/src/main/res/values/{strings.xml => integers.xml} | 3 ++- 4 files changed, 2 insertions(+), 1 deletion(-) rename library/external/barcodescanner/core/src/main/res/values-hdpi/{strings.xml => integers.xml} (100%) rename library/external/barcodescanner/core/src/main/res/values-xhdpi/{strings.xml => integers.xml} (100%) rename library/external/barcodescanner/core/src/main/res/values-xxhdpi/{strings.xml => integers.xml} (100%) rename library/external/barcodescanner/core/src/main/res/values/{strings.xml => integers.xml} (71%) diff --git a/library/external/barcodescanner/core/src/main/res/values-hdpi/strings.xml b/library/external/barcodescanner/core/src/main/res/values-hdpi/integers.xml similarity index 100% rename from library/external/barcodescanner/core/src/main/res/values-hdpi/strings.xml rename to library/external/barcodescanner/core/src/main/res/values-hdpi/integers.xml diff --git a/library/external/barcodescanner/core/src/main/res/values-xhdpi/strings.xml b/library/external/barcodescanner/core/src/main/res/values-xhdpi/integers.xml similarity index 100% rename from library/external/barcodescanner/core/src/main/res/values-xhdpi/strings.xml rename to library/external/barcodescanner/core/src/main/res/values-xhdpi/integers.xml diff --git a/library/external/barcodescanner/core/src/main/res/values-xxhdpi/strings.xml b/library/external/barcodescanner/core/src/main/res/values-xxhdpi/integers.xml similarity index 100% rename from library/external/barcodescanner/core/src/main/res/values-xxhdpi/strings.xml rename to library/external/barcodescanner/core/src/main/res/values-xxhdpi/integers.xml diff --git a/library/external/barcodescanner/core/src/main/res/values/strings.xml b/library/external/barcodescanner/core/src/main/res/values/integers.xml similarity index 71% rename from library/external/barcodescanner/core/src/main/res/values/strings.xml rename to library/external/barcodescanner/core/src/main/res/values/integers.xml index 9cfbb9e1c4..690b6cd3c9 100644 --- a/library/external/barcodescanner/core/src/main/res/values/strings.xml +++ b/library/external/barcodescanner/core/src/main/res/values/integers.xml @@ -1,4 +1,5 @@ - + + 4 60 From 7940584674eea326304f1fd21abd078494b940e0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 23 Jun 2023 23:20:30 +0200 Subject: [PATCH 166/234] Changelog. --- changelog.d/8556.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/8556.misc diff --git a/changelog.d/8556.misc b/changelog.d/8556.misc new file mode 100644 index 0000000000..42ff3f60fe --- /dev/null +++ b/changelog.d/8556.misc @@ -0,0 +1 @@ +Include some source code in our project to remove our dependency to artifact hosted by bintray (Jcenter). From 3e73137c18e44f462a8470214a5f88ae179b19c1 Mon Sep 17 00:00:00 2001 From: valere Date: Wed, 14 Jun 2023 11:01:11 +0200 Subject: [PATCH 167/234] Fixes new device detections banner problems --- .../android/sdk/internal/crypto/Device.kt | 3 +-- .../self/SelfVerificationBottomSheet.kt | 5 +++- .../features/home/NewHomeDetailFragment.kt | 22 ++++++++++++---- .../UnknownDeviceDetectorSharedViewModel.kt | 13 +++++++--- .../features/navigation/DefaultNavigator.kt | 25 ++++--------------- .../app/features/popup/PopupAlertManager.kt | 2 +- 6 files changed, 37 insertions(+), 33 deletions(-) diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/Device.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/Device.kt index 7f2b1232fe..8d52099f4e 100644 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/Device.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/Device.kt @@ -187,8 +187,7 @@ internal class Device @AssistedInject constructor( locallyVerified = innerDevice.locallyTrusted ), isBlocked = innerDevice.isBlocked, - // TODO - firstTimeSeenLocalTs = null + firstTimeSeenLocalTs = innerDevice.firstTimeSeenTs.toLong() * 1000 ) } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt index 5005ccd12b..05743d0a06 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt @@ -156,7 +156,7 @@ class SelfVerificationBottomSheet : VectorBaseBottomSheetDialogFragment { - dismiss() + dismiss() } is VerificationBottomSheetViewEvents.ConfirmCancel -> { // TODO? applies to self? @@ -229,6 +229,9 @@ class SelfVerificationBottomSheet : VectorBaseBottomSheetDialogFragment state.unknownSessions.invoke()?.let { unknownDevices -> + val uid = PopupAlertManager.REVIEW_LOGIN_UID if (unknownDevices.firstOrNull()?.currentSessionTrust == true) { - val uid = PopupAlertManager.REVIEW_LOGIN_UID alertManager.cancelAlert(uid) val olderUnverified = unknownDevices.filter { !it.isNew } val newest = unknownDevices.firstOrNull { it.isNew }?.deviceInfo @@ -172,6 +174,9 @@ class NewHomeDetailFragment : // In this case we prompt to go to settings to review logins promptToReviewChanges(uid, state, olderUnverified.map { it.deviceInfo }) } + } else { + // cancel as there are not anymore untrusted devices + alertManager.cancelAlert(uid) } } } @@ -278,7 +283,14 @@ class NewHomeDetailFragment : uid = uid, title = getString(R.string.review_unverified_sessions_title), description = getString(R.string.review_unverified_sessions_description), - iconId = R.drawable.ic_shield_warning + iconId = R.drawable.ic_shield_warning, + shouldBeDisplayedIn = { activity -> + // do not show when there is an ongoing verification flow + if (activity is VectorBaseActivity<*>) { + activity.supportFragmentManager.findFragmentByTag(SelfVerificationBottomSheet.TAG) == null && + activity !is QrCodeScannerActivity + } else true + } ).apply { viewBinder = VerificationVectorAlert.ViewBinder(user, avatarRenderer) colorInt = colorProvider.getColorFromAttribute(R.attr.colorPrimary) @@ -351,9 +363,9 @@ class NewHomeDetailFragment : }) } - /* ========================================================================================== - * KeysBackupBanner Listener - * ========================================================================================== */ +/* ========================================================================================== + * KeysBackupBanner Listener + * ========================================================================================== */ override fun onCloseClicked() { serverBackupStatusViewModel.handle(ServerBackupStatusAction.OnBannerClosed) diff --git a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt index 6ba5976eb8..7a28c98a7d 100644 --- a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt @@ -39,7 +39,6 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.sample import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo @@ -116,8 +115,14 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor( session.sessionParams.deviceId != it.deviceId } .filter { info -> - // filter out verified sessions or those which do not support encryption (i.e. without crypto info) - cryptoList.firstOrNull { info.deviceId == it.deviceId }?.isVerified?.not().orFalse() + val matchingDeviceWithKeys = cryptoList.firstOrNull { it.deviceId == info.deviceId } + if (matchingDeviceWithKeys == null) { + // filter out verified sessions or those which do not support encryption (i.e. without crypto info) + false + } else { + // Only report unverified + !matchingDeviceWithKeys.isVerified + } } // filter out ignored devices .filter { shouldShowUnverifiedSessionsAlertUseCase.execute(it.deviceId) } @@ -136,7 +141,7 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor( } .distinctUntilChanged() .execute { async -> - Timber.v("## Detector trigger passed distinct") + Timber.v("## Detector trigger passed distinct ${async.invoke()}") copy( myMatrixItem = session.getUserOrDefault(session.myUserId).toMatrixItem(), unknownSessions = async diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index b38805f05a..3496ced21c 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -242,8 +242,8 @@ class DefaultNavigator @Inject constructor( } if (context is AppCompatActivity) { - SelfVerificationBottomSheet.forTransaction(tx.transactionId) - .show(context.supportFragmentManager, "VERIF") + SelfVerificationBottomSheet.forTransaction(tx.transactionId) + .show(context.supportFragmentManager, "VERIF") } } } @@ -258,7 +258,7 @@ class DefaultNavigator @Inject constructor( ) if (context is AppCompatActivity) { context.supportFragmentManager.commitTransaction(allowStateLoss = true) { - add(SelfVerificationBottomSheet.forTransaction(request.transactionId), "VERIF") + add(SelfVerificationBottomSheet.forTransaction(request.transactionId), SelfVerificationBottomSheet.TAG) } } } @@ -266,25 +266,10 @@ class DefaultNavigator @Inject constructor( override fun requestSelfSessionVerification(context: Context) { coroutineScope.launch { - // TODO - // val session = sessionHolder.getSafeActiveSession() ?: return@launch -// val otherSessions = session.cryptoService() -// .getCryptoDeviceInfoList(session.myUserId) -// .filter { it.deviceId != session.sessionParams.deviceId } -// .map { it.deviceId } if (context is AppCompatActivity) { context.supportFragmentManager.commitTransaction(allowStateLoss = true) { - add(SelfVerificationBottomSheet.verifyOwnUntrustedDevice(), "VERIF") + add(SelfVerificationBottomSheet.verifyOwnUntrustedDevice(), SelfVerificationBottomSheet.TAG) } -// if (otherSessions.isNotEmpty()) { -// val pr = session.cryptoService().verificationService().requestSelfKeyVerification( -// supportedVerificationMethodsProvider.provide()) -// VerificationBottomSheet.forSelfVerification(session, pr.transactionId) -// .show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG) -// } else { -// VerificationBottomSheet.forSelfVerification(session) -// .show(context.supportFragmentManager, VerificationBottomSheet.WAITING_SELF_VERIF_TAG) -// } } } } @@ -293,7 +278,7 @@ class DefaultNavigator @Inject constructor( // val session = sessionHolder.getSafeActiveSession() ?: return coroutineScope.launch(Dispatchers.Main) { SelfVerificationBottomSheet.forTransaction(transactionId) - .show(fragmentActivity.supportFragmentManager, "SELF_VERIF_TAG") + .show(fragmentActivity.supportFragmentManager, SelfVerificationBottomSheet.TAG) } } diff --git a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt index 02275c933e..c59b2c7216 100644 --- a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt +++ b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt @@ -164,7 +164,7 @@ class PopupAlertManager @Inject constructor( next = alertQueue.maxByOrNull { it.priority } // If next alert with highest priority is higher than the current one, we should display it // and add the current one to queue again. - if (next != null && next.priority > currentAlerter?.priority ?: Int.MIN_VALUE) { + if (next != null && next.priority > (currentAlerter?.priority ?: Int.MIN_VALUE)) { alertQueue.remove(next) currentAlerter?.also { alertQueue.add(0, it) From 5f20ceeb1c60cd4c79794d9a08937a71211fbc63 Mon Sep 17 00:00:00 2001 From: valere Date: Wed, 14 Jun 2023 11:11:00 +0200 Subject: [PATCH 168/234] Add change log --- changelog.d/8353 | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/8353 diff --git a/changelog.d/8353 b/changelog.d/8353 new file mode 100644 index 0000000000..f92b1adad2 --- /dev/null +++ b/changelog.d/8353 @@ -0,0 +1 @@ +Fix | Got asked twice about verification #8353 (and other verification banners problems) From 51c4dfc6751beb15e69520bec1a7e12846df7e2d Mon Sep 17 00:00:00 2001 From: valere Date: Wed, 14 Jun 2023 11:17:57 +0200 Subject: [PATCH 169/234] fix changelog --- changelog.d/{8353 => 8353.bugfix} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/{8353 => 8353.bugfix} (100%) diff --git a/changelog.d/8353 b/changelog.d/8353.bugfix similarity index 100% rename from changelog.d/8353 rename to changelog.d/8353.bugfix From 7205cd73d487abd1c14a8ec163e691af83d18702 Mon Sep 17 00:00:00 2001 From: valere Date: Mon, 26 Jun 2023 11:13:08 +0200 Subject: [PATCH 170/234] quality --- .../crypto/verification/self/SelfVerificationBottomSheet.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt index 05743d0a06..e63c149a26 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/self/SelfVerificationBottomSheet.kt @@ -230,7 +230,7 @@ class SelfVerificationBottomSheet : VectorBaseBottomSheetDialogFragment Date: Mon, 26 Jun 2023 11:55:04 +0200 Subject: [PATCH 171/234] fix sdk ts is already in milliseconds --- .../java/org/matrix/android/sdk/internal/crypto/Device.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/Device.kt b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/Device.kt index 8d52099f4e..4cb329175b 100644 --- a/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/Device.kt +++ b/matrix-sdk-android/src/rustCrypto/java/org/matrix/android/sdk/internal/crypto/Device.kt @@ -187,7 +187,7 @@ internal class Device @AssistedInject constructor( locallyVerified = innerDevice.locallyTrusted ), isBlocked = innerDevice.isBlocked, - firstTimeSeenLocalTs = innerDevice.firstTimeSeenTs.toLong() * 1000 + firstTimeSeenLocalTs = innerDevice.firstTimeSeenTs.toLong() ) } } From 61b05edd9e2098e99095f203dbb0dd2dec13602d Mon Sep 17 00:00:00 2001 From: FIONover Date: Mon, 26 Jun 2023 18:11:59 +0000 Subject: [PATCH 172/234] Translated using Weblate (Armenian) Currently translated at 1.0% (1 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/hy/ --- fastlane/metadata/android/hy/short_description.txt | 1 + fastlane/metadata/android/hy/title.txt | 1 + 2 files changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/hy/short_description.txt create mode 100644 fastlane/metadata/android/hy/title.txt diff --git a/fastlane/metadata/android/hy/short_description.txt b/fastlane/metadata/android/hy/short_description.txt new file mode 100644 index 0000000000..3b02739117 --- /dev/null +++ b/fastlane/metadata/android/hy/short_description.txt @@ -0,0 +1 @@ +Խմբային մեսինջեր - գաղտնագրված շփում, խմբային չատեր և վիդեո զանգեր diff --git a/fastlane/metadata/android/hy/title.txt b/fastlane/metadata/android/hy/title.txt new file mode 100644 index 0000000000..2f3fd83a51 --- /dev/null +++ b/fastlane/metadata/android/hy/title.txt @@ -0,0 +1 @@ +Element - Անվտանգ Մեսինջեր From 8cd51ea803f7877d7ebf9b6aa2521c1af9e311e9 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 27 Jun 2023 10:04:39 +0200 Subject: [PATCH 173/234] Setting version for the release 1.6.3 --- matrix-sdk-android/build.gradle | 2 +- vector-app/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 32e9c80503..b9e9a71d75 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -63,7 +63,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.6.4\"" + buildConfigField "String", "SDK_VERSION", "\"1.6.3\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 8221497e74..7a09213bb9 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -37,7 +37,7 @@ ext.versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -ext.versionPatch = 4 +ext.versionPatch = 3 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From 042f144afe44455bf3669590e37f21fa88b10933 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 27 Jun 2023 12:11:42 +0200 Subject: [PATCH 174/234] Changelog for version 1.6.3 --- CHANGES.md | 23 +++++++++++++++++++++++ changelog.d/8270.bugfix | 1 - changelog.d/8353.bugfix | 1 - changelog.d/8440.feature | 1 - changelog.d/8468.bugfix | 1 - changelog.d/8471.bugfix | 1 - changelog.d/8503.misc | 1 - changelog.d/8507.bugfix | 1 - changelog.d/8541.bugfix | 1 - changelog.d/8554.misc | 1 - 10 files changed, 23 insertions(+), 9 deletions(-) delete mode 100644 changelog.d/8270.bugfix delete mode 100644 changelog.d/8353.bugfix delete mode 100644 changelog.d/8440.feature delete mode 100644 changelog.d/8468.bugfix delete mode 100644 changelog.d/8471.bugfix delete mode 100644 changelog.d/8503.misc delete mode 100644 changelog.d/8507.bugfix delete mode 100644 changelog.d/8541.bugfix delete mode 100644 changelog.d/8554.misc diff --git a/CHANGES.md b/CHANGES.md index 39ea3f1477..0fa9d9bb15 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,26 @@ +Changes in Element v1.6.3 (2023-06-27) +====================================== + +Features ✨ +---------- + - **Element Android is now using the Crypto Rust SDK**. Migration of user's data should be done at first launch after application upgrade. ([#8390](https://github.com/vector-im/element-android/issues/8390)) + - [Rich text editor] Add mentions and slash commands ([#8440](https://github.com/vector-im/element-android/issues/8440)) + +Bugfixes 🐛 +---------- + - Update rich text editor library to support pasting of images. ([#8270](https://github.com/vector-im/element-android/issues/8270)) + - Fix | Got asked twice about verification #8353 (and other verification banners problems) ([#8353](https://github.com/vector-im/element-android/issues/8353)) + - Prompt the user when the invited MatrixId is not recognized ([#8468](https://github.com/vector-im/element-android/issues/8468)) + - The correct title and options are now displayed When a poll that was edited is ended. ([#8471](https://github.com/vector-im/element-android/issues/8471)) + - In some conditions the room shield is not refreshed correctly ([#8507](https://github.com/vector-im/element-android/issues/8507)) + - Fix crypto config fallback key sharing strategy ([#8541](https://github.com/vector-im/element-android/issues/8541)) + +Other changes +------------- + - MSC3987 implementation: the 'dont_notify' action for a push_rule is now deprecated and replaced by an empty action list. ([#8503](https://github.com/vector-im/element-android/issues/8503)) + - Update crypto rust sdk version to 0.3.10 ([#8554](https://github.com/vector-im/element-android/issues/8554)) + + Changes in Element v1.6.2 (2023-06-02) ====================================== diff --git a/changelog.d/8270.bugfix b/changelog.d/8270.bugfix deleted file mode 100644 index e2d3056de4..0000000000 --- a/changelog.d/8270.bugfix +++ /dev/null @@ -1 +0,0 @@ -Update rich text editor library to support pasting of images. diff --git a/changelog.d/8353.bugfix b/changelog.d/8353.bugfix deleted file mode 100644 index f92b1adad2..0000000000 --- a/changelog.d/8353.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix | Got asked twice about verification #8353 (and other verification banners problems) diff --git a/changelog.d/8440.feature b/changelog.d/8440.feature deleted file mode 100644 index 19c9d919eb..0000000000 --- a/changelog.d/8440.feature +++ /dev/null @@ -1 +0,0 @@ -[Rich text editor] Add mentions and slash commands \ No newline at end of file diff --git a/changelog.d/8468.bugfix b/changelog.d/8468.bugfix deleted file mode 100644 index f250d48dc6..0000000000 --- a/changelog.d/8468.bugfix +++ /dev/null @@ -1 +0,0 @@ -Prompt the user when the invited MatrixId is not recognized diff --git a/changelog.d/8471.bugfix b/changelog.d/8471.bugfix deleted file mode 100644 index ff0b0f5493..0000000000 --- a/changelog.d/8471.bugfix +++ /dev/null @@ -1 +0,0 @@ -The correct title and options are now displayed When a poll that was edited is ended. diff --git a/changelog.d/8503.misc b/changelog.d/8503.misc deleted file mode 100644 index 26f9e76959..0000000000 --- a/changelog.d/8503.misc +++ /dev/null @@ -1 +0,0 @@ -MSC3987 implementation: the 'dont_notify' action for a push_rule is now deprecated and replaced by an empty action list. diff --git a/changelog.d/8507.bugfix b/changelog.d/8507.bugfix deleted file mode 100644 index eb609dd0fc..0000000000 --- a/changelog.d/8507.bugfix +++ /dev/null @@ -1 +0,0 @@ -In some conditions the room shield is not refreshed correctly diff --git a/changelog.d/8541.bugfix b/changelog.d/8541.bugfix deleted file mode 100644 index 9e419327da..0000000000 --- a/changelog.d/8541.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crypto config fallback key sharing strategy diff --git a/changelog.d/8554.misc b/changelog.d/8554.misc deleted file mode 100644 index 0fad74289c..0000000000 --- a/changelog.d/8554.misc +++ /dev/null @@ -1 +0,0 @@ -Update crypto rust sdk version to 0.3.10 From 637b1483cc685bb680c8037d25ddf74d3524c9c3 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 27 Jun 2023 12:12:06 +0200 Subject: [PATCH 175/234] Adding fastlane file for version 1.6.3 --- fastlane/metadata/android/en-US/changelogs/40106030.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40106030.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40106030.txt b/fastlane/metadata/android/en-US/changelogs/40106030.txt new file mode 100644 index 0000000000..badf979955 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40106030.txt @@ -0,0 +1,2 @@ +Main changes in this version: Element Android is now using the Crypto Rust SDK. +Full changelog: https://github.com/vector-im/element-android/releases From 7b8cf5d917725c52bd6fb036f117bc8b20ef4224 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 27 Jun 2023 13:30:17 +0200 Subject: [PATCH 176/234] version++ --- matrix-sdk-android/build.gradle | 2 +- vector-app/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index b9e9a71d75..722b4fc0b3 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -63,7 +63,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.6.3\"" + buildConfigField "String", "SDK_VERSION", "\"1.6.5\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 7a09213bb9..10fe0c7525 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -37,7 +37,7 @@ ext.versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -ext.versionPatch = 3 +ext.versionPatch = 5 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From cf6de0948309dce649608cf09f0fcca3d0dbbdb6 Mon Sep 17 00:00:00 2001 From: Vri Date: Wed, 28 Jun 2023 04:09:41 +0000 Subject: [PATCH 177/234] Translated using Weblate (German) Currently translated at 100.0% (2640 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/de/ --- library/ui-strings/src/main/res/values-de/strings.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/ui-strings/src/main/res/values-de/strings.xml b/library/ui-strings/src/main/res/values-de/strings.xml index 334a1f45be..0871842a4d 100644 --- a/library/ui-strings/src/main/res/values-de/strings.xml +++ b/library/ui-strings/src/main/res/values-de/strings.xml @@ -2957,4 +2957,12 @@ App aktualisiert Dein Heim-Server ist nicht erreichbar. Falls du dich dennoch abmeldest, wird dieses Gerät nicht von deiner Geräteliste entfernt, also müsstest du dies mit einer anderen Sitzung selbst machen. Dennoch abmelden + Dennoch Unterhaltung beginnen + Konnte keine Profile für die folgenden Matrix-IDs finden. Möchtest du dennoch eine Unterhaltung beginnen\? +\n +\n%s + Konnte keine Profile für die folgenden Matrix-IDs finden. Möchtest du sie dennoch einladen\? +\n +\n%s + Dennoch einladen \ No newline at end of file From 7080ee1c2651800032af7e63f8251a3a10f0941b Mon Sep 17 00:00:00 2001 From: Edgars Andersons Date: Thu, 29 Jun 2023 07:17:41 +0000 Subject: [PATCH 178/234] Translated using Weblate (Latvian) Currently translated at 68.0% (1795 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/lv/ --- library/ui-strings/src/main/res/values-lv/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/ui-strings/src/main/res/values-lv/strings.xml b/library/ui-strings/src/main/res/values-lv/strings.xml index 81a7a10dcc..ad70dbafbc 100644 --- a/library/ui-strings/src/main/res/values-lv/strings.xml +++ b/library/ui-strings/src/main/res/values-lv/strings.xml @@ -477,9 +477,9 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Visas istabas %s serverī Visas vietējās %s istabas - %d nelasītu paziņotu ziņu - %d nelasīta paziņota ziņa - %d nelasītas paziņotas ziņu + %d paziņojumu par nelasītām ziņām + %d paziņojums par nelasītām ziņām + %d paziņojumi par nelasītām ziņām %d istaba From 05ce2cab2708733d12f6be8074babcf474a0eb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C4=83n=20Huy=20D=C6=B0=C6=A1ng?= Date: Thu, 29 Jun 2023 06:10:11 +0000 Subject: [PATCH 179/234] Translated using Weblate (Vietnamese) Currently translated at 88.0% (2320 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- .../src/main/res/values-vi/strings.xml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 38da26bd3d..0a252ed7da 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2531,4 +2531,24 @@ Ẩn địa chỉ Internet (IP) Phiên đã xác thực Hệ điều hành + Bộ lọc + Bộ lọc các chủ đề trong phòng + Sao chép liên kết vào cuộc trò chuyện + Các chủ đề + Bản Beta của Chủ đề + Bản Beta của Chủ đề + Các chủ đề đã chuyển sang Beta 🎉 + Hiển thị tất cả chủ đề trong phòng + Tất cả chủ đề + Sắp xếp các cuộc thảo luận với các chủ đề + Chủ đề + Hiển thị tất cả chủ đề bạn đã tham gia + Element đã được đơn giản hóa với các mục tùy chọn + Chỉ tạo cuộc trò chuyện riêng cho tin nhắn đầu tiên + Bật trì hoãn cho các tin nhắn riêng + Các chủ đề của tôi + Từ một chủ đề + \'\'Chủ đề\'\' giúp giữ cho các cuộc trò chuyện của bạn theo chủ đề và dễ theo dõi. + Máy chủ cục bộ của bạn chưa hỗ trợ cho việc liệt kê các chủ đề + \'\'Chủ đề\'\' giúp giữ cho các cuộc trò chuyện của bạn theo chủ đề và dễ theo dõi. %sBật chủ đề sẽ làm mới ứng dụng. Quá trình này có thể mất nhiều thời gian hơn đối với một số tài khoản. \ No newline at end of file From 0a4bdceff8970bb12d43a1cdd143c1872b679a53 Mon Sep 17 00:00:00 2001 From: Someone Date: Thu, 29 Jun 2023 10:41:20 +0000 Subject: [PATCH 180/234] Translated using Weblate (Vietnamese) Currently translated at 88.0% (2320 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- library/ui-strings/src/main/res/values-vi/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 0a252ed7da..3b7a299fee 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -2549,6 +2549,6 @@ Các chủ đề của tôi Từ một chủ đề \'\'Chủ đề\'\' giúp giữ cho các cuộc trò chuyện của bạn theo chủ đề và dễ theo dõi. - Máy chủ cục bộ của bạn chưa hỗ trợ cho việc liệt kê các chủ đề + Máy chủ nhà của bạn chưa hỗ trợ cho việc liệt kê các chủ đề. \'\'Chủ đề\'\' giúp giữ cho các cuộc trò chuyện của bạn theo chủ đề và dễ theo dõi. %sBật chủ đề sẽ làm mới ứng dụng. Quá trình này có thể mất nhiều thời gian hơn đối với một số tài khoản. \ No newline at end of file From e4e17d865b4fd4bbcbf5453be0b9a989b2232bc0 Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 30 Jun 2023 10:24:14 +0000 Subject: [PATCH 181/234] Translated using Weblate (Vietnamese) Currently translated at 56.0% (56 of 100 strings) Translation: Element Android/Element Android Store Translate-URL: https://translate.element.io/projects/element-android/element-store/vi/ --- .../metadata/android/vi/full_description.txt | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/fastlane/metadata/android/vi/full_description.txt b/fastlane/metadata/android/vi/full_description.txt index 282914188b..b54e04e1c8 100644 --- a/fastlane/metadata/android/vi/full_description.txt +++ b/fastlane/metadata/android/vi/full_description.txt @@ -1,42 +1,42 @@ Element vừa là một ứng dụng nhắn tin bảo mật vừa là một ứng dụng cộng tác nhóm năng suất, lý tưởng cho các cuộc trò chuyện nhóm khi làm việc từ xa. Ứng dụng trò chuyện này sử dụng mã hóa đầu cuối để cung cấp tính năng hội thảo truyền hình, chia sẻ tệp và cuộc gọi thoại mạnh mẽ. - Các tính năng của Element bao gồm: -- Các công cụ giao tiếp trực tuyến tiên tiến +Các tính năng của Element bao gồm: +- Công cụ giao tiếp trực tuyến nâng cao - Các tin nhắn được mã hóa hoàn toàn để cho phép liên lạc doanh nghiệp an toàn hơn, ngay cả đối với những người làm việc từ xa - Trò chuyện phi tập trung dựa trên khung mã nguồn mở Matrix -- Chia sẻ tệp một cách an toàn với dữ liệu được mã hóa trong khi quản lý dự án -- Trò chuyện video với gọi thoại qua giao thức Internet (IP - VoIP) và chia sẻ màn hình +- Chia sẻ tệp bảo mật với dữ liệu được mã hóa trong khi quản lý dự án +- Trò chuyện video với gọi thoại qua giao thức Internet (VoIP) và chia sẻ màn hình - Tích hợp dễ dàng với các công cụ cộng tác trực tuyến yêu thích của bạn, công cụ quản lý dự án, dịch vụ VoIP và các ứng dụng nhắn tin nhóm khác -Element hoàn toàn khác với các ứng dụng nhắn tin và cộng tác khác. Hoạt động trên Matrix, một mạng mở để nhắn tin bảo mật và giao tiếp phi tập trung. Đồng thời, cho phép tự lưu trữ để cung cấp cho người dùng quyền sở hữu và kiểm soát tối đa dữ liệu và tin nhắn của họ. +Element hoàn toàn khác với các ứng dụng nhắn tin và cộng tác khác. Hoạt động trên Matrix, một mạng mở để nhắn tin bảo mật và giao tiếp phi tập trung. Đồng thời, cho phép tự vận hành để cung cấp cho người dùng quyền sở hữu và kiểm soát tối đa dữ liệu và tin nhắn của họ. - Nhắn tin mã hóa và riêng tư -Element bảo vệ bạn khỏi các quảng cáo không mong muốn, khai thác dữ liệu và kiểm soát khu vực. Element cũng bảo mật tất cả dữ liệu của bạn, video 1-1 và giao tiếp thoại thông qua mã hóa đầu cuối và xác minh thiết bị có chữ ký chéo. +Nhắn tin mã hóa và riêng tư +Element bảo vệ bạn khỏi các quảng cáo không mong muốn, khai thác dữ liệu và kiểm soát khu vực. Element cũng bảo mật tất cả dữ liệu của bạn, truyền hình 1-1 và giao tiếp thoại thông qua mã hóa đầu cuối và xác thực chéo thiết bị. -Element cung cấp cho bạn quyền kiểm soát quyền riêng tư của mình đồng thời cho phép bạn giao tiếp an toàn với bất kỳ ai trên mạng Matrix hoặc các công cụ cộng tác kinh doanh khác bằng cách tích hợp với các ứng dụng như Slack. +Element cung cấp cho bạn quyền kiểm soát quyền riêng tư của mình đồng thời cho phép bạn giao tiếp bảo mật với bất kỳ ai trên mạng Matrix hoặc các công cụ cộng tác kinh doanh khác bằng cách tích hợp với các ứng dụng như Slack. - Element có thể được tự lưu trữ -Để cho phép kiểm soát nhiều hơn dữ liệu nhạy cảm và các cuộc trò chuyện của bạn, Element có thể được tự lưu trữ hoặc bạn có thể chọn bất kỳ máy chủ Matrix nào - tiêu chuẩn cho giao tiếp phi tập trung, mã nguồn mở. Element cung cấp cho bạn quyền riêng tư, tuân thủ bảo mật và tính linh hoạt trong tích hợp. +Element có thể được tự vận hành +Để cho phép kiểm soát nhiều hơn dữ liệu nhạy cảm và các cuộc trò chuyện của bạn, Element có thể được tự vận hành hoặc bạn có thể chọn bất kỳ máy chủ Matrix nào - tiêu chuẩn cho giao tiếp phi tập trung, mã nguồn mở. Element cung cấp cho bạn quyền riêng tư, tuân thủ bảo mật và tính linh hoạt trong tích hợp. - Sở hữu dữ liệu của bạn -Bạn quyết định nơi lưu giữ dữ liệu và tin nhắn của mình. Không có rủi ro khai thác dữ liệu hoặc truy cập từ bên thứ ba. +Sở hữu dữ liệu của bạn +Bạn quyết định nơi lưu trữ dữ liệu và tin nhắn của mình. Không có rủi ro khai thác dữ liệu hoặc truy cập từ bên thứ ba. Element giúp bạn kiểm soát theo những cách khác nhau: -1. Tạo một tài khoản miễn phí trên máy chủ công cộng matrix.org do các nhà phát triển Matrix vận hành hoặc chọn từ hàng nghìn máy chủ công cộng do các tình nguyện viên lưu trữ +1. Tạo một tài khoản miễn phí trên máy chủ công cộng matrix.org do các nhà phát triển Matrix vận hành hoặc chọn từ hàng nghìn máy chủ công cộng do các tình nguyện viên vận hành 2. Tự lưu trữ tài khoản của bạn bằng cách chạy một máy chủ trên cơ sở hạ tầng CNTT của riêng bạn 3. Đăng ký tài khoản trên máy chủ tùy chỉnh bằng cách chỉ cần đăng ký nền tảng Element Matrix Services hosting - Nhắn tin và cộng tác mở +Nhắn tin và cộng tác mở Bạn có thể trò chuyện với bất kỳ ai trên mạng Matrix, cho dù họ đang sử dụng Element, một ứng dụng Matrix khác hay ngay cả khi họ đang sử dụng một ứng dụng nhắn tin khác. - Siêu bảo mật -Mã hóa đầu-cuối thực (chỉ những người trong cuộc trò chuyện mới có thể giải mã tin nhắn) và xác minh thiết bị xác thực chéo. +Siêu bảo mật +Mã hóa đầu-cuối có thực (chỉ những người trong cuộc trò chuyện mới có thể giải mã tin nhắn) và xác thực chéo thiết bị. - Giao tiếp và tích hợp hoàn chỉnh -Nhắn tin, cuộc gọi thoại và video, chia sẻ tệp, chia sẻ màn hình và một loạt các tích hợp, bot và widget. Xây dựng phòng, cộng đồng, giữ liên lạc và hoàn thành công việc. +Giao tiếp và tích hợp hoàn chỉnh +Nhắn tin, gọi thoại và truyền hình, chia sẻ tệp, chia sẻ màn hình và một loạt các tích hợp, bot và widget. Tạo phòng, cộng đồng, giữ liên lạc và hoàn thành công việc. - Tiếp tục nơi bạn đã dừng lại +Tiếp tục nơi bạn đã dừng lạ Giữ liên lạc mọi lúc mọi nơi với lịch sử tin nhắn được đồng bộ hóa hoàn toàn trên tất cả các thiết bị của bạn và trên web tại https://app.element.io - Mã nguồn mở -Element Android là một dự án mã nguồn mở, được lưu trữ trên GitHub. Vui lòng báo cáo lỗi và / hoặc đóng góp phát triển tại https://github.com/vector-im/element-android +Mã nguồn mở +Element Android là một dự án mã nguồn mở, được lưu trữ trên GitHub. Vui lòng báo cáo lỗi và / hoặc đóng góp, phát triển tại https://github.com/vector-im/element-android From 6fcd582f2d3e00924ee5de151a9f2416f63e1459 Mon Sep 17 00:00:00 2001 From: Someone Date: Fri, 30 Jun 2023 10:36:28 +0000 Subject: [PATCH 182/234] Translated using Weblate (Vietnamese) Currently translated at 88.0% (2320 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- .../src/main/res/values-vi/strings.xml | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index 3b7a299fee..c35964ee3c 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -359,9 +359,9 @@ Nhập các mã khoá phòng E2E Quản lý bản sao lưu mã khoá ip không xác định - Nếu chúng không khớp, sự bảo mật của việc giao tiếp của bạn có thể bị can thiệp. - Xác nhận bằng cách so sánh những điều sau đây với Cài đặt người dùng trong phiên làm việc kia của bạn: - Xác minh + Nếu chúng không khớp, bảo mật của việc giao tiếp của bạn có thể bị can thiệp. + Xác thực bằng cách so sánh những thứ sau với Cài đặt người dùng trong phiên làm việc kia của bạn: + Xác thực URL máy chủ nhà Bạn có chắc bạn muốn rời khỏi phòng không\? Rời khỏi phòng @@ -1027,7 +1027,7 @@ Chọn vai trò được yêu cầu để thay đổi thiết lập của phòng Quyền hạn Việc này có thể có nghĩa là ai đó đang can thiệp vào lưu lượng của bạn, hoặc điện thoại của bạn không tin cậy chứng chỉ được máy chủ trên mạng cung cấp. - Không thể xác minh danh tính của máy chủ trên mạng. + Không thể xác thực danh tính của máy chủ trên mạng. Mã kiểm tra (%s): Bỏ qua Đăng xuất @@ -1148,7 +1148,7 @@ Các lời mời đã gửi tới %1$s và %2$d người nữa - Hiển thị %d thiết bị bạn có thể xác minh ngay bây giờ + Hiển thị %d thiết bị bạn có thể xác thực ngay bây giờ %d phiên đang hoạt động @@ -1466,11 +1466,11 @@ Vui lòng chọn tên người dùng. Thất bại trong việc thiết lập Xác thực chéo Xác nhận danh tính của bạn bằng cách xác minh đăng nhập này, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. - Xác nhận danh tính của bạn bằng cách xác minh đăng nhập này từ một trong các phiên khác của bạn, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. - Xác minh tương tác bằng Emoji + Xác thực danh tính của bạn bằng cách xác nhận đăng nhập này từ một trong các phiên khác của bạn, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. + Xác thực tương tác bằng Emoji Xác minh đăng nhập - Xác minh thủ công bằng Văn bản - Xác minh thông tin đăng nhập mới truy cập vào tài khoản của bạn: %1$s + Xác thực thủ công bằng Văn bản + Xác thực thông tin đăng nhập mới truy cập vào tài khoản của bạn: %1$s Được mã hóa bởi một thiết bị chưa được xác minh Không được mã hóa gửi tuyết rơi ❄️ @@ -1479,7 +1479,7 @@ Gửi tin nhắn đã cho với hoa giấy Bạn sẽ khởi động lại mà không có lịch sử, không có tin nhắn, thiết bị đáng tin cậy hoặc người dùng đáng tin cậy Nếu bạn đặt lại mọi thứ - Chỉ làm điều này nếu bạn không có thiết bị nào khác mà bạn có thể xác minh thiết bị này. + Chỉ làm điều này nếu bạn không có thiết bị nào khác mà bạn có thể xác thực thiết bị này. Đặt lại mọi thứ Quên hoặc mất tất cả các tùy chọn phục hồi\? Đặt lại mọi thứ Không truy nhập được dung lượng lưu trữ an toàn @@ -1514,7 +1514,7 @@ Nó không phải là một khóa phục hồi hợp lệ Sử dụng Tệp Nhập %s của bạn để tiếp tục - Xác minh bản thân và người khác để giữ an toàn cho cuộc trò chuyện của bạn + Xác thực bản thân và người khác để giữ an toàn cho cuộc trò chuyện của bạn Nâng cấp mã hóa có sẵn Tin nhắn… Tài khoản này đã bị vô hiệu hóa. @@ -1560,7 +1560,7 @@ Mã hóa được sử dụng bởi phòng này không được hỗ trợ Mã hóa không được bật Tin nhắn trong phòng này được mã hóa đầu cuối. - Tin nhắn trong phòng này được mã hóa đầu cuối. Tìm hiểu thêm và xác minh người dùng trong hồ sơ của họ. + Tin nhắn trong phòng này được mã hóa đầu cuối. Tìm hiểu thêm và xác thực người dùng trong hồ sơ của họ. Mã hóa được bật Nếu bạn hủy ngay bây giờ, bạn có thể mất tin nhắn và dữ liệu được mã hóa nếu bạn mất quyền truy cập vào thông tin đăng nhập của mình. \n @@ -1597,7 +1597,7 @@ So sánh mã với mã được hiển thị trên màn hình của người dùng khác. So sánh biểu tượng cảm xúc độc đáo, đảm bảo chúng xuất hiện theo cùng một thứ tự. Để được an toàn, hãy làm điều này trực tiếp hoặc sử dụng một cách khác để giao tiếp. - Để an toàn, hãy xác minh %s bằng cách kiểm tra mã một lần. + Để an toàn, hãy xác thực %s bằng cách kiểm tra mã một lần. Bật mã hóa Sau khi được bật, mã hóa cho một căn phòng không thể bị vô hiệu hóa. Tin nhắn được gửi trong một căn phòng được mã hóa không thể được nhìn thấy bởi máy chủ, chỉ bởi những người tham gia của căn phòng. Cho phép mã hóa có thể ngăn nhiều bot và cầu hoạt động chính xác. Bật mã hóa\? @@ -1607,8 +1607,8 @@ Dòng thời gian Gửi emote đã cho màu cầu vồng Gửi tin nhắn đã cho có màu cầu vồng - Phiên này không thể chia sẻ xác minh này với các phiên khác của bạn. -\nViệc xác minh sẽ được lưu cục bộ và chia sẻ trong phiên bản tương lai của ứng dụng. + Phiên này không thể chia sẻ xác thực này với các phiên khác của bạn. +\nViệc xác thực sẽ được lưu cục bộ và chia sẻ trong phiên bản tương lai của ứng dụng. Hủy bỏ qua ${app_name} gặp sự cố khi hiển thị nội dung sự kiện với id \'%1$s\' ${app_name} không xử lý các sự kiện thuộc loại \'%1$s\' @@ -1644,16 +1644,16 @@ Tin nhắn trong phòng này không được mã hóa đầu cuối. Đang chờ %s… Đã xác minh %s - Xác minh %s - Xác minh bằng cách so sánh biểu tượng cảm xúc - Thay vào đó, xác minh bằng cách so sánh biểu tượng cảm xúc + Xác thực %s + Xác thực bằng cách so sánh biểu tượng cảm xúc + Thay vào đó, xác thực bằng cách so sánh biểu tượng cảm xúc Nếu bạn không trực tiếp, hãy so sánh biểu tượng cảm xúc thay thế Không thể quét Quét bằng thiết bị này Quét mã của họ Quét mã bằng thiết bị khác của bạn hoặc chuyển đổi và quét bằng thiết bị này - Quét mã bằng thiết bị của người dùng khác để xác minh lẫn nhau một cách an toàn - Xác minh phiên này + Quét mã bằng thiết bị của người dùng khác để xác thực lẫn nhau một cách an toàn + Xác thực phiên này Yêu cầu xác minh Xác minh đã gửi Bạn đã chấp nhận @@ -1672,8 +1672,8 @@ Video. Một trong những điều sau đây có thể bị xâm phạm: \n -\n - Homeserver của bạn -\n - Homeserver mà bạn đang xác minh được kết nối với +\n - Máy chủ nhà của bạn +\n - Máy chủ nhà mà bạn đang xác minh được kết nối với \n - Kết nối internet của bạn hoặc của người dùng khác \n - Thiết bị của bạn hoặc thiết bị của người dùng khác Không bảo mật @@ -1862,7 +1862,7 @@ Có vẻ như bạn đang cố gắng kết nối với một homeserver khác. Bạn có muốn đăng xuất không\? Bạn không sử dụng bất kỳ máy chủ xác thực nào Lỗi không xác định - %s muốn xác minh phiên của bạn + %s muốn xác thực phiên của bạn Yêu cầu xác minh Đã nhận được Đã xác minh! @@ -1968,17 +1968,17 @@ Một trong những điều sau đây có thể bị xâm phạm: \n \n- Mật khẩu của bạn -\n- Người ở nhà của anh -\n- Thiết bị này hoặc thiết bị khác +\n- Máy chủ nhà của bạn +\n- Thiết bị này hoặc thiết bị kia \n- Kết nối internet mà một trong hai thiết bị đang sử dụng \n \nChúng tôi khuyên bạn nên thay đổi mật khẩu và khóa khôi phục trong Cài đặt ngay lập tức. - Bạn sẽ không xác minh %1$s (%2$s) nếu bạn hủy ngay. Bắt đầu lại trong hồ sơ người dùng của họ. + Bạn sẽ không xác thực %1$s (%2$s) nếu bạn hủy ngay. Bắt đầu lại trong hồ sơ người dùng của họ. Nếu bạn hủy, bạn sẽ không thể đọc tin nhắn được mã hóa trên thiết bị mới của mình và những người dùng khác sẽ không tin tưởng nó Nếu bạn hủy, bạn sẽ không thể đọc tin nhắn được mã hóa trên thiết bị này và những người dùng khác sẽ không tin tưởng nó Tài khoản của bạn có thể bị xâm phạm Không phải tôi - Sử dụng phiên này để xác minh phiên mới của bạn, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. + Sử dụng phiên này để xác thực phiên mới của bạn, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. Đăng nhập mới. Đây có phải là bạn không\? Làm tươi Mở khóa lịch sử tin nhắn được mã hóa @@ -2011,7 +2011,7 @@ Mã QR Đặt lại khóa Khởi tạo xác thực chéo - Cho đến khi người dùng này tin tưởng phiên này, tin nhắn được gửi đến nó và từ nó đều mang nhãn cảnh báo. Ngoài ra, bạn có thể xác minh thủ công. + Cho đến khi người dùng này tin tưởng phiên này, tin nhắn được gửi đến nó và từ nó đều mang nhãn cảnh báo. Ngoài ra, bạn có thể xác thực thủ công. %1$s (%2$s) đã đăng nhập bằng phiên mới: Phiên này được tin cậy để nhắn tin an toàn vì %1$s (%2$s) đã xác minh: Không tin cậy @@ -2020,10 +2020,10 @@ Không nhận được phiên Cảnh báo Đã xác minh - Xác minh - Sử dụng phiên hiện có để xác minh phiên này, cấp cho nó quyền truy cập vào các thư được mã hóa. - Xác minh đăng nhập này - Xác minh phiên này để đánh dấu nó là đáng tin cậy và cấp cho nó quyền truy cập vào các thư được mã hóa. Nếu bạn không đăng nhập vào phiên này, tài khoản của bạn có thể bị xâm phạm: + Xác thực + Sử dụng phiên hiện có để xác thực phiên này, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. + Xác thực thiết bị này + Xác thực phiên này để đánh dấu nó là đáng tin cậy và cấp cho nó quyền truy cập vào các thư được mã hóa. Nếu bạn không đăng nhập vào phiên này, tài khoản của bạn có thể bị xâm phạm: Phiên này được tin cậy để nhắn tin an toàn vì bạn đã xác minh nó: Không có thông tin mật mã sẵn dùng bất ổn định @@ -2463,7 +2463,7 @@ Chọn máy chủ của bạn Bạn nắm quyền kiểm soát. Muốn chạy một máy chủ của mình\? - %s cần xác nhận tài khoản của bạn + %s cần xác thực tài khoản của bạn Đi thôi Bạn sẽ trò chuyện với ai nhiều nhất\? Chưa chắc chắn\? %s @@ -2477,7 +2477,7 @@ Chính sách máy chủ %s sẽ gửi bạn một liên kết xác nhận Làm chủ cuộc trò chuyện. - %s cần xác nhận tài khoản của bạn + %s cần xác thực tài khoản của bạn Chào mừng trở lại! Địa chỉ máy chủ của bạn là gì\? Chúng tôi sẽ giúp bạn kết nối From bbcea97120bdc263088bdd0cfe43bc7cc90a669c Mon Sep 17 00:00:00 2001 From: Kat Gerasimova Date: Fri, 30 Jun 2023 15:18:15 +0100 Subject: [PATCH 183/234] Send new issues to new triage board (#8567) Issues should go to the V2 triage board --- .github/workflows/triage-incoming.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/triage-incoming.yml b/.github/workflows/triage-incoming.yml index 56bad8a2d7..4f9c239429 100644 --- a/.github/workflows/triage-incoming.yml +++ b/.github/workflows/triage-incoming.yml @@ -15,3 +15,11 @@ jobs: project: Issue triage column: Incoming repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }} + + triage-new-issues: + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@main + with: + project-url: https://github.com/orgs/vector-im/projects/91 + github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} From 0c9ebfdab67e0180103d3ac7f4b7118d5c5b62c1 Mon Sep 17 00:00:00 2001 From: Someone Date: Sat, 1 Jul 2023 08:13:43 +0000 Subject: [PATCH 184/234] Translated using Weblate (Vietnamese) Currently translated at 88.1% (2324 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/vi/ --- .../src/main/res/values-vi/strings.xml | 217 +++++++++--------- 1 file changed, 110 insertions(+), 107 deletions(-) diff --git a/library/ui-strings/src/main/res/values-vi/strings.xml b/library/ui-strings/src/main/res/values-vi/strings.xml index c35964ee3c..d7f2c07a08 100644 --- a/library/ui-strings/src/main/res/values-vi/strings.xml +++ b/library/ui-strings/src/main/res/values-vi/strings.xml @@ -84,7 +84,7 @@ Bạn có chắc không\? Đang sao lưu khoá… Tôi không muốn các tin nhắn của tôi được mã hoá - Sao lưu Khoá Bảo mật nên được kích hoạt trên tất cả các phiên để tránh mất các tin nhắn được mã hoá. + Sao lưu bảo mật khoá nên được kích hoạt trên tất cả các phiên để tránh mất các tin nhắn được mã hoá. Đang sao lưu khoá. Nếu bạn đăng xuất bây giờ bạn sẽ không thể xem các tin nhắn được mã hoá. Bạn sẽ mất các tin nhắn được mã hoá nếu bạn đăng xuất ngay bây giờ Sử dụng Sao lưu Khóa @@ -99,7 +99,7 @@ Chủ đề tối Chủ đề sáng Quên mật khẩu\? - Đấy không giống một địa chỉ email hợp lệ + Đấy không giống một địa chỉ thư điện tử hợp lệ Tên người dùng hoặc mật khẩu không đúng Đăng nhập Xin lỗi, không có ứng dụng nào được tìm thấy có thể hoàn thành hành động này. @@ -196,7 +196,7 @@ Đã gửi Đang gửi Số điện thoại - Địa chỉ email + Địa chỉ thư điện tử Lỗi Matrix %1$s đã thay đổi cấp độ quyền lực của %2$s. Bạn đã thay đổi cấp độ quyền lực của %1$s. @@ -234,12 +234,12 @@ (ảnh đại diện cũng được thay đổi) 🎉 Tất cả máy chủ bị cấm không được tham gia! Phòng này không thể được sử dụng nữa. Không có thay đổi. - Bạn đã thay đổi ACL máy chủ cho phòng này. - %s đã thay đổi ACL máy chủ cho phòng này. + Bạn đã thay đổi danh sách máy chủ truy cập máy chủ cho phòng này. + %s đã thay đổi danh sách máy chủ truy cập máy chủ cho phòng này. • Những máy chủ khớp với %s được cho phép. • Những máy chủ khớp với %s bị cấm. - Bạn đã đặt ACL máy chủ cho phòng này. - %s đã đặt ACL máy chủ cho phòng này. + Bạn đã đặt danh sách máy chủ truy cập cho phòng này. + %s đã đặt danh sách máy chủ truy cập cho phòng này. Bạn đã nâng cấp ở đây. %s đã nâng cấp ở đây. Bạn đã nâng cấp phòng này. @@ -256,16 +256,16 @@ %1$s đã cấm %2$s Bạn đã bỏ cấm %1$s %1$s đã bỏ cấm %2$s - Bạn đã xoá tên hiển thị (nó đã là %1$s) - %1$s đã xoá tên hiển thị (nó đã là %2$s) + Bạn đã xoá tên hiển thị (từng là %1$s) + %1$s đã xoá tên hiển thị (từng là %2$s) Bạn đã đổi tên hiển thị từ %1$s thành %2$s %1$s đã đổi tên hiển thị từ %2$s thành %3$s Bạn đã đặt tên hiển thị thành %1$s %1$s đã đặt tên hiển thị thành %2$s Bạn đã thay đổi ảnh đại diện %1$s đã thay đổi ảnh đại diện - Bạn đã rút lại lời mời của %1$s - %1$s đã rút lại lời mời của %2$s + Bạn đã hủy lời mời của %1$s + %1$s đã hủy lời mời của %2$s Chủ đề của bạn Chủ đề Bạn đã kết thúc cuộc gọi. @@ -286,8 +286,8 @@ Bạn đã thay đổi chủ đề thành: %1$s Xoá các tin nhắn chưa được gửi Bạn có chắc bạn muốn xoá tất cả tin nhắn chưa được gửi trong phòng này không\? - Bạn đã kick %1$s - %1$s đã kick %2$s + Bạn đã loại bỏ %1$s + %1$s đã loại bỏ %2$s Bạn đã từ chối lời mời %1$s đã từ chối lời mời Bạn đã rời phòng @@ -329,7 +329,7 @@ %1$s đã rời phòng. Lý do: %2$s Máy chủ nhà này muốn chắc chắn bạn không phải rô bốt Số điện thoại này đã được định nghĩa rồi. - Địa chỉ email này đã được định nghĩa rồi. + Địa chỉ thư điện tử này đã được sử dụng rồi. Đăng nhập bằng đăng nhập một lần Sử dụng làm mặc định và không hỏi lại Luôn hỏi @@ -341,8 +341,8 @@ Xoá tiện ích thất bại Thêm tiện ích thất bại Chuyển - Đã xác minh - Chưa xác minh + Đã xác thực + Chưa xác thực Nhập %1$d/%2$d mã khoá thành công. @@ -402,14 +402,14 @@ %d thay đổi thành viên Vui lòng khởi chạy ${app_name} trên một thiết bị khác mà có thể giải mã tin nhắn để nó có thể gửi các mã khoá vào phiên làm việc này. - Yêu cầu lại các mã khoá mã hoá từ các phiên làm việc khác của bạn. + Yêu cầu lại các mã khoá mã hoá từ các phiên khác của bạn. Quá nhiều yêu cầu đã được gửi Đã không chứa JSON hợp lệ Không được uỷ quyền, thiếu thông tin xác thực hợp lệ Không thể kết nối đến máy chủ nhà tại URL này, vui lòng kiểm tra nó Vui lòng nhập URL hợp lệ Vui lòng xem xét và chấp nhận chính sách của máy chủ nhà này: - Xác minh địa chỉ email thất bại: hãy chắc chắn là bạn đã nhấn vào liên kết trong email + Xác nhận địa chỉ thư điện tử thất bại: hãy chắc chắn là bạn đã nhấn vào liên kết trong email Hiện tất cả phòng trong thư mục phòng, bao gồm cả các phòng có nội dung phản cảm. Hiện các phòng có nội dung phản cảm Danh sách phòng @@ -517,8 +517,8 @@ Lời mời vào phòng • Những máy chủ khớp với IP bây giờ sẽ bị cấm. • Những máy chủ khớp với IP bây giờ sẽ được cho phép. - • Những máy chủ khớp với IP bị cấm. - • Những máy chủ khớp với IP được cho phép. + • Những máy chủ chỉ có địa chỉ Internet (IP) bị cấm. + • Những máy chủ chỉ có địa chỉ Internet (IP) được cho phép. Hủy bỏ qua người dùng Bỏ qua Bỏ qua người dùng này sẽ xóa những tin nhắn của họ khỏi những phòng bạn chia sẻ. @@ -593,7 +593,7 @@ Hủy các giới hạn Hủy tài khoản Xem lại ngay - Chìa khóa phiên + Khóa phiên Mã phiên Tên công khai Lỗi giải mã @@ -790,7 +790,7 @@ Media Chọn quốc gia Quản lý địa chỉ thư điện tử và số điện thoại liên kết với tài khoản Matrix - Email và số điện thoại + Địa chỉ thư điện tử và số điện thoại Hiện tất cả tin nhắn từ %s\? Mật khẩu của bạn vừa được cập nhật Mật khẩu này không hợp lệ @@ -800,7 +800,7 @@ Đổi mật khẩu Mật khẩu Số điện thoại này đã được sử dụng. - Địa chỉ Email này đã được sử dụng. + Địa chỉ thư điện tử này đã được sử dụng. Chọn ngôn ngữ Ngôn ngữ Giao diện người dùng @@ -878,9 +878,9 @@
Thời gian chờ giữa 2 lần đồng bộ Mã nhập vào không hợp lệ. Vui lòng kiểm tra. - Chúng tôi vừa gửi email tới %1$s. -\nClick vào đường link trong email để tiếp tục quá trình tạo tài khoản. - Hãy kiểm tra email của bạn + Chúng tôi vừa gửi thư điện tử tới %1$s. +\nNhấp vào liên kết trong thư để tiếp tục quá trình tạo tài khoản. + Hãy kiểm tra hòm thư của bạn Chấp nhận điều khoản để tiếp tục Hãy thực hiện thách thức captcha Chọn một máy chủ khác @@ -892,7 +892,7 @@ Tiếp Mật khẩu Tên đăng nhập - Username hoặc email + Tên người dùng hoặc thư điện tử Đăng ký với %1$s Số điện thoại có vẻ không hợp lệ. Hãy kiểm tra lại Số điện thoại quốc tế phải bắt đầu với dấu \'+\' @@ -908,11 +908,11 @@ Vui lòng sử dụng mẫu quốc tế. Thêm số điện thoại để tùy chọn cho phép người khác tìm bạn qua số điện thoại. Thêm số điện thoại - Tiếp - Email (tùy chọn) - Email + Tiếp tục + Địa chỉ thư điện tử (tùy chọn) + Địa chỉ thư điện tử Thêm địa chỉ thư điện tử để có thể phục hồi tài khoản. Sau này bạn có thể tùy chọn cho phép người khác tìm mình qua thông tin này. - Thêm địa chỉ email + Thêm địa chỉ thư điện tử Mật khẩu chưa được thay đổi. \n \nBạn muốn ngừng tiến trình đổi mật khẩu\? @@ -921,18 +921,18 @@ Bạn vừa đăng xuất tất cả phiên đăng nhập và không còn nhận được thông báo đẩy. Đăng nhập lại để nhận thông báo trên thiết bị. Mật khẩu của bạn đã được đặt lại. Thành công! - Tôi đã xác minh địa chỉ email + Tôi đã xác nhận địa chỉ email Nhấp vào đường dẫn để xác nhận mật khẩu mới. Sau khi bạn nhâp vào đường dẫn, hãy nhấp vào bên dưới. - Email xác thực đã được gửi tới %1$s. + Thư xác nhận đã được gửi tới %1$s. Kiểm tra mailbox Địa chỉ thư điện tử này không được liên kết với tài khoản nào Tiếp tục Đổi mật khẩu sẽ đặt lại tất cả khóa bảo mật trên tất cả phiên của bạn, làm cho lịch sử chat mã hóa không đọc được. Vui lòng Sao lưu Khóa hoặc xuất khẩu tất cả khóa bảo mật các phòng từ một phiên đăng nhập khác trước khi đặt lại mật khẩu. Cảnh báo! Mật khẩu mới - Email + Địa chỉ thư điện tử Tiếp - Email xác thực thông tin đã được gửi tới bạn để xác nhận đặt lại mật khẩu mới. + Email xác nhận đã được gửi tới bạn để xác nhận đặt lại mật khẩu mới. Đặt lại mật khẩu ở %1$s Địa chỉ thư điện tử này không được liên kết với tài khoản nào. Địa chỉ @@ -954,7 +954,7 @@ Thiết lập tùy chỉnh và nâng cao Khác Xem thêm - Giống như email, tài khoản cần có nhà riêng, dù bạn có thể nói chuyện với bất kỳ ai + Giống như tài khoản thư điện tử, tài khoản cần có nhà riêng, dù bạn có thể nói chuyện với bất kỳ ai Thiết lập tùy chỉnh. Khả dụng Thông báo không được bật cho phiên này. @@ -982,16 +982,16 @@ Thông báo mặc định Mức quan trọng của thông báo theo sự kiện Thiết lập Thông báo nâng cao - Đảm bảo rằng bạn nhấp vào đường link trong email được gửi tới bạn. + Đảm bảo rằng bạn nhấp vào đường link trong thư điện tử được gửi tới bạn. Loại bỏ %s\? Số điện thoại Không có địa chỉ thư điện tử nào trong tài khoản của bạn - Địa chỉ email + Địa chỉ thư điện tử Hiển thị thông tin ứng dụng trong thiết lập hệ thống. Thông tin ứng dụng Thêm số điện thoại Chưa có số điện thoại trong tài khoản của bạn - Thêm địa chỉ email + Thêm địa chỉ thư điện tử Tên hiển thị Hình đại diện Thêm vào màn hình Home @@ -1060,7 +1060,7 @@ Ai có thể tìm và tham gia không gian Truy cập không gian Ai có quyền truy cập\? - Vui lòng kiểm tra email và bấm vào liên kết trong đó. Một khi xong, bấm tiếp tục. + Vui lòng kiểm tra thư điện tử và bấm vào liên kết trong đó. Một khi xong, bấm tiếp tục. Sử dụng trình quản lý chung để quản lý bot, các cầu nối, widget và các gói nhãn dán. \nTrình quản lý chung sẽ nhận được dữ liệu hiệu chỉnh, và sẽ có thể điều chỉnh các widget, gửi lời mời vào phòng và thiết lập các mốc quyền lợi theo ý bạn. ${app_name} sẽ đồng bộ hóa dưới nền trong một khoảng thời gian nhất định (có thể điều chỉnh thời gian). @@ -1115,9 +1115,9 @@ Đang chạy… (%1$d of %2$d) Chạy thử Chuẩn đoán khắc phục sự cố - Bật thông báo qua email cho %s + Bật thông báo qua thư điện tử cho %s Để được nhận thông báo qua thư điện tử, hãy liên kết một địa chỉ thư điện tử với tài khoản Matrix của bạn - Thông báo qua email + Thông báo qua thư điện tử Nâng cấp không gian Thay đổi tên không gian Bật mã hóa không gian @@ -1151,7 +1151,7 @@ Hiển thị %d thiết bị bạn có thể xác thực ngay bây giờ
- %d phiên đang hoạt động + %d phiên hoạt động %1$d người @@ -1271,15 +1271,15 @@ Khám phá phòng Khám phá (%s) Hoàn tất cài đặt - Mời qua email, tìm liên hệ và hơn thế nữa… + Mời qua thư điện tử, tìm liên hệ và hơn thế nữa… Hoàn tất việc cài đặt khám phá. - Hiện tại bạn không sử dụng máy chủ xác thực. Để mời đồng đội và có thể khám phá bởi họ, hãy cấu hình một bên dưới. + Hiện tại bạn không sử dụng máy chủ định danh. Để mời đồng đội và có thể khám phá bởi họ, hãy cấu hình một bên dưới. Tham gia Space Tạo space Bỏ qua ngay bây giờ Gia nhập Space của tôi %1$s %2$s Mời theo tên người dùng hoặc thư - Mời qua email + Mời qua thư điện tử Chỉ có anh lúc này thôi. %s sẽ còn tốt hơn với những người khác. Mời đến %s Mời mọi người @@ -1424,19 +1424,19 @@ Quyền Đặt quyền Xác nhận - Nhập URL của máy chủ xác thực - Ngoài ra, bạn có thể nhập bất kỳ URL máy chủ xác thực nào khác + Nhập URL của máy chủ định danh + Ngoài ra, bạn có thể nhập bất kỳ URL máy chủ định danh nào khác Dùng %1$s - Homeerver của bạn (%1$s) đề xuất sử dụng %2$s cho máy chủ xác thực của bạn + Máy chủ nhà của bạn (%1$s) đề xuất sử dụng %2$s cho máy chủ định danh của bạn Sự đồng ý của người dùng chưa được cung cấp. - Không có mối liên hệ hiện tại với mã định danh này. - Sự kết hợp đã thất bại. + Không có mối liên hệ hiện tại với định danh này. + Không thể liên kết. Để đảm bảo quyền riêng tư cho bạn, ${app_name} chỉ hỗ trợ gửi địa chỉ thư điện tử và số điện thoại của người dùng khi đã được băm. - Trước tiên, vui lòng chấp nhận các điều khoản của máy chủ nhận dạng trong cài đặt. - Trước tiên, vui lòng cấu hình máy chủ nhận dạng. - Hoạt động này là không thể. Homeerver đã lỗi thời. - Máy chủ nhận dạng này đã lỗi thời. ${app_name} chỉ hỗ trợ API V2. - Ngắt kết nối khỏi máy chủ nhận dạng %s\? + Trước tiên, vui lòng chấp nhận các điều khoản của máy chủ định danh trong cài đặt. + Trước tiên, vui lòng cấu hình máy chủ định danh. + Hoạt động này là không thể. Máy chủ nhà đã lỗi thời. + Máy chủ định danh này đã lỗi thời. ${app_name} chỉ hỗ trợ API V2. + Ngắt kết nối khỏi máy chủ định danh %s\? Mở các điều khoản của %s Tải các ngôn ngữ có sẵn… Các ngôn ngữ có sẵn khác @@ -1468,10 +1468,10 @@ Xác nhận danh tính của bạn bằng cách xác minh đăng nhập này, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. Xác thực danh tính của bạn bằng cách xác nhận đăng nhập này từ một trong các phiên khác của bạn, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. Xác thực tương tác bằng Emoji - Xác minh đăng nhập + Xác thực đăng nhập Xác thực thủ công bằng Văn bản Xác thực thông tin đăng nhập mới truy cập vào tài khoản của bạn: %1$s - Được mã hóa bởi một thiết bị chưa được xác minh + Được mã hóa bởi một thiết bị chưa được xác thực Không được mã hóa gửi tuyết rơi ❄️ gửi hoa giấy 🎉 @@ -1579,9 +1579,9 @@ Phiên bản máy chủ Tên máy chủ Đăng xuất khỏi phiên này - Quản lý Phiên - Hiện Tất cả Phiên - Phiên Hoạt động + Quản lý phiên + Hiện tất cả phiên + Phiên hoạt động Người quản trị máy chủ của bạn đã vô hiệu hóa mã hóa đầu cuối theo mặc định trong phòng riêng và Tin nhắn trực tiếp. Xác thực chéo không được kích hoạt Xác thực chéo được kích hoạt. @@ -1592,7 +1592,7 @@ Xác thực chéo được kích hoạt \nKhóa riêng trên thiết bị. Xác thực chéo - Phiên mới của bạn hiện đã được xác minh. Nó có quyền truy cập vào các tin nhắn được mã hóa của bạn và những người dùng khác sẽ thấy nó đáng tin cậy. + Phiên mới của bạn hiện đã được xác thực. Nó có quyền truy cập vào các tin nhắn được mã hóa của bạn và những người dùng khác sẽ thấy nó đáng tin cậy. Tin nhắn với người dùng này được mã hóa đầu cuối và không thể được đọc bởi các bên thứ ba. So sánh mã với mã được hiển thị trên màn hình của người dùng khác. So sánh biểu tượng cảm xúc độc đáo, đảm bảo chúng xuất hiện theo cùng một thứ tự. @@ -1643,7 +1643,7 @@ Tin nhắn ở đây không được mã hóa đầu cuối. Tin nhắn trong phòng này không được mã hóa đầu cuối. Đang chờ %s… - Đã xác minh %s + Đã xác thực %s Xác thực %s Xác thực bằng cách so sánh biểu tượng cảm xúc Thay vào đó, xác thực bằng cách so sánh biểu tượng cảm xúc @@ -1673,14 +1673,14 @@ Một trong những điều sau đây có thể bị xâm phạm: \n \n - Máy chủ nhà của bạn -\n - Máy chủ nhà mà bạn đang xác minh được kết nối với +\n - Máy chủ nhà mà người bạn đang xác thực được kết nối với \n - Kết nối internet của bạn hoặc của người dùng khác \n - Thiết bị của bạn hoặc thiết bị của người dùng khác Không bảo mật Chúng không phù hợp Chúng phù hợp Đăng nhập không tin cậy - Tên miền email của bạn không được phép đăng ký trên máy chủ này + Tên miền địa chỉ thư điện tử của bạn không được phép đăng ký trên máy chủ này Tạo Space… Tạo phòng… Một số ký tự không được phép @@ -1749,7 +1749,7 @@ Đăng nhập bằng Matrix ID Homeerver này đang chạy một phiên bản cũ. Yêu cầu người quản trị homeerver của bạn nâng cấp. Bạn có thể tiếp tục, nhưng một số tính năng có thể không hoạt động chính xác. Homeerver lỗi thời - Không giống như một địa chỉ email hợp lệ + Không giống một địa chỉ thư điện tử hợp lệ Ứng dụng không thể tạo tài khoản trên homeerver này. \n \nBạn có muốn đăng ký bằng máy khách web không\? @@ -1769,8 +1769,8 @@ Vui lòng thử lại một khi bạn đã chấp nhận các điều khoản và điều kiện của homeserver của bạn. Nhật ký verbose sẽ giúp các nhà phát triển bằng cách cung cấp thêm nhật ký khi bạn lắc mạnh thiết bị. Ngay cả khi được bật, ứng dụng không ghi lại nội dung tin nhắn hoặc bất kỳ dữ liệu riêng tư nào khác. Bật nhật ký verbose. - Đồng ý với điều khoản dịch vụ của máy chủ xác thực (%s) để cho phép bản thân có thể khám phá bằng địa chỉ email hoặc số điện thoại. - Bạn hiện đang chia sẻ địa chỉ email hoặc số điện thoại trên máy chủ xác thực %1$s. Bạn sẽ cần kết nối lại với %2$s để ngừng chia sẻ chúng. + Đồng ý với điều khoản dịch vụ của máy chủ định danh (%s) để cho phép bản thân có thể khám phá bằng địa chỉ email hoặc số điện thoại. + Bạn hiện đang chia sẻ địa chỉ thư điện tử hoặc số điện thoại trên máy chủ định danh %1$s. Bạn sẽ cần kết nối lại với %2$s để ngừng chia sẻ chúng. Mã xác minh không chính xác. Có lỗi tra cứu số điện thoại Bàn phím số @@ -1790,24 +1790,24 @@ %1$s đã từ chối cuộc gọi này Bạn đã từ chối cuộc gọi này - Thư văn bản đã được gửi đến %s. Vui lòng nhập mã xác minh mà nó chứa. - Máy chủ xác thực bạn đã chọn không có bất kỳ điều khoản dịch vụ nào. Chỉ tiếp tục nếu bạn tin tưởng chủ sở hữu dịch vụ - Máy chủ xác thực không có điều khoản dịch vụ - Vui lòng nhập url máy chủ xác thực - Không thể kết nối với máy chủ xác thực - Nhập URL máy chủ xác thực + Tin nhắn văn bản đã được gửi đến %s. Vui lòng nhập mã xác minh mà nó chứa. + Máy chủ định danh bạn đã chọn không có bất kỳ điều khoản dịch vụ nào. Chỉ tiếp tục nếu bạn tin tưởng chủ sở hữu dịch vụ + Máy chủ định danh không có điều khoản dịch vụ + Vui lòng nhập đường dẫn máy chủ định danh + Không thể kết nối với máy chủ định danh + Nhập URL máy chủ định danh Bạn có đồng ý gửi thông tin này không\? Để khám phá các liên hệ hiện có, bạn cần gửi thông tin liên hệ (địa chỉ thư điện tử và số điện thoại) đến máy chủ định danh của mình. Chúng tôi băm dữ liệu của bạn trước khi gửi để đảm bảo quyền riêng tư. Gửi địa chỉ thư điện tử và số điện thoại đến %s Đồng ý Thu hồi sự đồng ý của tôi - Các liên hệ của bạn là riêng tư. Để khám phá người dùng từ danh bạ của bạn, chúng tôi cần sự cho phép của bạn để gửi thông tin liên hệ đến máy chủ xác thực của bạn. + Các liên hệ của bạn là riêng tư. Để khám phá người dùng từ danh bạ của bạn, chúng tôi cần sự cho phép của bạn để gửi thông tin liên hệ đến máy chủ định danh của bạn. Bạn đã đồng ý gửi địa chỉ thư điện tử và số điện thoại đến máy chủ định danh này để khám phá những người dùng khác từ danh bạ của bạn. - Gửi email và số điện thoại + Gửi thư điện tử và số điện thoại Chúng tôi đã gửi một thư đến %s, trước tiên vui lòng kiểm tra hòm thư của bạn và nhấp vào liên kết xác nhận Chúng tôi đã gửi một thư đến %s, kiểm tra hòm thư của bạn và nhấp vào liên kết xác nhận Số điện thoại có thể khám phá - Ngắt kết nối khỏi máy chủ xác thực của bạn sẽ có nghĩa là bạn sẽ không thể khám phá bởi những người dùng khác và bạn sẽ không thể mời người khác qua email hoặc điện thoại. + Ngắt kết nối khỏi máy chủ định danh của bạn sẽ có nghĩa là bạn sẽ không thể khám phá bởi những người dùng khác và bạn sẽ không thể mời người khác qua thư điện tử hoặc điện thoại. Tùy chọn Khám phá sẽ xuất hiện khi bạn đã thêm số điện thoại. Định danh ứng dụng (ID): Không có cổng Push đã đăng ký @@ -1860,12 +1860,12 @@ Các cuộc hội thoại tin nhắn trực tiếp của bạn sẽ được hiển thị tại đây. Nhấp vào dấu + dưới cùng bên phải để bắt đầu. Các cuộc hội thoại Có vẻ như bạn đang cố gắng kết nối với một homeserver khác. Bạn có muốn đăng xuất không\? - Bạn không sử dụng bất kỳ máy chủ xác thực nào + Bạn không sử dụng bất kỳ máy chủ định danh nào Lỗi không xác định %s muốn xác thực phiên của bạn - Yêu cầu xác minh + Yêu cầu xác thực Đã nhận được - Đã xác minh! + Đã xác thực! Chữ ký Thuật toán Phiên bản @@ -1882,16 +1882,16 @@ Xóa Sao lưu Kiểm tra trạng thái sao lưu Đang xóa bản sao lưu… - Để sử dụng Sao lưu Chính trong phiên này, hãy khôi phục bằng cụm mật khẩu hoặc khóa khôi phục của bạn ngay bây giờ. - Sao lưu có chữ ký không hợp lệ từ phiên chưa được xác minh %s - Sao lưu có chữ ký không hợp lệ từ phiên đã xác minh %s - Sao lưu có chữ ký hợp lệ từ phiên chưa được xác minh %s - Sao lưu có chữ ký hợp lệ từ phiên đã xác minh %s. + Để sử dụng Sao lưu khóa trong phiên này, hãy khôi phục bằng cụm mật khẩu hoặc khóa khôi phục của bạn ngay bây giờ. + Sao lưu có chữ ký không hợp lệ từ phiên chưa được xác thực %s + Sao lưu có chữ ký không hợp lệ từ phiên đã xác thực %s + Sao lưu có chữ ký hợp lệ từ phiên chưa được xác thực %s + Sao lưu có chữ ký hợp lệ từ phiên đã xác thực %s. Sao lưu có chữ ký hợp lệ từ phiên này. - Sao lưu có chữ ký từ phiên không xác định với ID %s. + Sao lưu có chữ ký từ phiên không xác định với định danh %s. Khóa của bạn không được sao lưu từ phiên này. - Sao lưu chính không hoạt động trong phiên này. - Key Backup đã được thiết lập chính xác cho phiên này. + Sao lưu khóa không hoạt động trong phiên này. + Sao lưu khóa đã được thiết lập chính xác cho phiên này. Xóa Sao lưu Khôi phục từ Sao lưu Thất bại trong việc nhận được phiên bản khóa khôi phục mới nhất (%s). @@ -2013,18 +2013,18 @@ Khởi tạo xác thực chéo Cho đến khi người dùng này tin tưởng phiên này, tin nhắn được gửi đến nó và từ nó đều mang nhãn cảnh báo. Ngoài ra, bạn có thể xác thực thủ công. %1$s (%2$s) đã đăng nhập bằng phiên mới: - Phiên này được tin cậy để nhắn tin an toàn vì %1$s (%2$s) đã xác minh: + Phiên này được tin cậy để nhắn tin an toàn vì %1$s (%2$s) đã xác thực: Không tin cậy Tin cậy Phiên Không nhận được phiên Cảnh báo - Đã xác minh + Đã xác thực Xác thực Sử dụng phiên hiện có để xác thực phiên này, cấp cho nó quyền truy cập vào các tin nhắn được mã hóa. Xác thực thiết bị này Xác thực phiên này để đánh dấu nó là đáng tin cậy và cấp cho nó quyền truy cập vào các thư được mã hóa. Nếu bạn không đăng nhập vào phiên này, tài khoản của bạn có thể bị xâm phạm: - Phiên này được tin cậy để nhắn tin an toàn vì bạn đã xác minh nó: + Phiên này được tin cậy để nhắn tin an toàn vì bạn đã xác thực nó: Không có thông tin mật mã sẵn dùng bất ổn định ổn định @@ -2058,9 +2058,9 @@ Vui lòng nhập tên người dùng. Hủy kích hoạt Tài khoản Vui lòng quên tất cả các tin nhắn tôi đã gửi khi tài khoản của tôi bị vô hiệu hóa (Cảnh báo: điều này sẽ khiến người dùng trong tương lai thấy chế độ xem cuộc hội thoại không đầy đủ) - Điều này sẽ làm cho tài khoản của bạn vĩnh viễn không thể sử dụng được. Bạn sẽ không thể đăng nhập và không ai có thể đăng ký lại cùng một ID người dùng. Điều này sẽ khiến tài khoản của bạn rời khỏi tất cả các phòng mà nó đang tham gia và nó sẽ xóa chi tiết tài khoản của bạn khỏi máy chủ nhận dạng của bạn. Điều này là không thể đảo ngược. + Điều này sẽ làm cho tài khoản của bạn vĩnh viễn không thể sử dụng được. Bạn sẽ không thể đăng nhập và không ai có thể đăng ký lại cùng một ID người dùng. Điều này sẽ khiến tài khoản của bạn rời khỏi tất cả các phòng mà nó đang tham gia và nó sẽ xóa chi tiết tài khoản của bạn khỏi máy chủ định danh của bạn. <b>Điều này là không thể đảo ngược</b>. \n -\nHủy kích hoạt tài khoản của bạn does không theo mặc định khiến chúng tôi quên tin nhắn bạn đã gửi. Nếu bạn muốn chúng tôi quên tin nhắn của bạn, vui lòng đánh dấu vào hộp bên dưới. +\nHủy kích hoạt tài khoản của bạn <b>does không theo mặc định khiến chúng tôi quên tin nhắn bạn đã gửi</b>. Nếu bạn muốn chúng tôi quên tin nhắn của bạn, vui lòng đánh dấu vào hộp bên dưới. \n \nKhả năng hiển thị tin nhắn trong Matrix tương tự như email. Chúng tôi quên tin nhắn của bạn có nghĩa là tin nhắn bạn đã gửi sẽ không được chia sẻ với bất kỳ người dùng mới hoặc chưa đăng ký nào, nhưng người dùng đã đăng ký đã có quyền truy cập vào các tin nhắn này vẫn sẽ có quyền truy cập vào bản sao của họ. Để tiếp tục sử dụng homeserver %1$s, bạn phải xem xét và đồng ý với các điều khoản và điều kiện. @@ -2102,11 +2102,11 @@ Lệnh không được nhận ra: %s Lỗi lệnh Yêu cầu Chia sẻ Khóa - Một phiên chưa được xác minh đang yêu cầu khóa mã hóa. + Một phiên chưa được xác thực đang yêu cầu khóa mã hóa. \nTên phiên: %1$s \nLần nhìn thấy lần cuối: %2$s \nNếu bạn không đăng nhập vào phiên khác, hãy bỏ qua yêu cầu này. - Phiên chưa được xác thực của bạn \'%s\' đang yêu cầu khóa mã hóa. + Phiên chưa được xác thực \'%s\' đang yêu cầu khóa mã hóa. Một phiên mới đang yêu cầu các khóa mã hóa. \nTên phiên: %1$s \nLần nhìn thấy lần cuối: %2$s @@ -2182,13 +2182,13 @@ Tất cả các phòng trên %s server Tên máy chủ Chọn thư mục phòng - Không bao giờ gửi tin nhắn được mã hóa đến các phiên chưa được xác minh từ phiên này. - Chỉ mã hóa cho các phiên đã xác minh + Không bao giờ gửi tin nhắn được mã hóa đến các phiên chưa được xác thực từ phiên này. + Chỉ mã hóa cho các phiên đã xác thực Bỏ đặt làm địa chỉ chính Đặt làm địa chỉ chính Máy chủ này không cung cấp bất kỳ chính sách nào. Thư viện bên thứ ba - Chính sách máy chủ xác thực của bạn + Chính sách máy chủ định danh của bạn Chính sách homeerver của bạn Chính sách ${app_name} Bạn có thể tắt tính năng này bất cứ lúc nào trong cài đặt @@ -2199,7 +2199,7 @@ \n \nBạn có thể đọc tất cả các thuật ngữ của chúng tôi %s. Giúp cải thiện ${app_name} - Thiết bị đã bị đăng xuất! + Phiên đã bị đăng xuất! Căn phòng đã bị bỏ lại! Chọn homeerver Không thể kết nối đến một homeserver tại URL %s. Vui lòng kiểm tra liên kết của bạn hoặc chọn homeerver thủ công. @@ -2207,11 +2207,11 @@ Kích hoạt Nghe thông báo Tùy chọn Khám phá sẽ xuất hiện sau khi bạn đã thêm địa chỉ thư điện tử. - Địa chỉ email có thể khám phá - Hiện tại bạn không sử dụng máy chủ xác thực. Để khám phá và có thể khám phá bởi các liên hệ hiện có mà bạn biết, hãy cấu hình một danh bạ dưới đây. - Không có chính sách được cung cấp bởi máy chủ xác thực - Ẩn chính sách máy chủ xác thực - Hiện chính sách máy chủ xác thực + Địa chỉ thư điện tử có thể khám phá + Hiện tại bạn không sử dụng máy chủ định danh. Để khám phá và có thể khám phá bởi các liên hệ hiện có mà bạn biết, hãy cấu hình một danh bạ dưới đây. + Máy chủ định danh không cung cấp chính sách nào + Ẩn chính sách máy chủ định danh + Hiện chính sách máy chủ định danh Mở Cài đặt Khám phá Thêm tab dành riêng cho các thông báo chưa đọc trên màn hình chính. Tìm kiếm theo tên, ID hoặc thư @@ -2334,7 +2334,7 @@ Bạn có thể đổi lại sau Tên hiển thị Chọn tên hiển thị - Tên người dùng / Thư điện tử / Số điện thoại + Tên người dùng / Địa chỉ thư điện tử / Số điện thoại Bạn có phải con người\? Làm theo chỉ dẫn gửi tới %s Đặt lại mật khẩu @@ -2376,7 +2376,7 @@ Gửi phản hồi Đã bật: Thẻ hồ sơ: - Định danh của phiên: + Định danh phiên: Đi Đang cập nhật dữ liệu của bạn… Mọi người @@ -2463,7 +2463,7 @@ Chọn máy chủ của bạn Bạn nắm quyền kiểm soát. Muốn chạy một máy chủ của mình\? - %s cần xác thực tài khoản của bạn + %s cần xác nhận tài khoản của bạn Đi thôi Bạn sẽ trò chuyện với ai nhiều nhất\? Chưa chắc chắn\? %s @@ -2551,4 +2551,7 @@ \'\'Chủ đề\'\' giúp giữ cho các cuộc trò chuyện của bạn theo chủ đề và dễ theo dõi. Máy chủ nhà của bạn chưa hỗ trợ cho việc liệt kê các chủ đề. \'\'Chủ đề\'\' giúp giữ cho các cuộc trò chuyện của bạn theo chủ đề và dễ theo dõi. %sBật chủ đề sẽ làm mới ứng dụng. Quá trình này có thể mất nhiều thời gian hơn đối với một số tài khoản. + Phiên + Thiết bị + Hoạt động cuối %1$s \ No newline at end of file From 1ab2bb9bf81da98be17f2c3fa746f70a1d9b6c8e Mon Sep 17 00:00:00 2001 From: Edgars Andersons Date: Mon, 3 Jul 2023 20:46:15 +0000 Subject: [PATCH 185/234] Translated using Weblate (Latvian) Currently translated at 68.1% (1797 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/lv/ --- library/ui-strings/src/main/res/values-lv/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/ui-strings/src/main/res/values-lv/strings.xml b/library/ui-strings/src/main/res/values-lv/strings.xml index ad70dbafbc..0d0fcda97f 100644 --- a/library/ui-strings/src/main/res/values-lv/strings.xml +++ b/library/ui-strings/src/main/res/values-lv/strings.xml @@ -2067,4 +2067,10 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. 2 1 Izmēģināt + + %1$d atlasīti + %1$d atlasīts + %1$d atlasīti + + %1$s nomainīja attēlojamo vārdu uz %2$s \ No newline at end of file From 0573915a0a734e5c0ceab888d701877fa6f0876f Mon Sep 17 00:00:00 2001 From: Yoan Pintas Date: Tue, 4 Jul 2023 15:12:37 +0200 Subject: [PATCH 186/234] Update MSC3912 implementation: Redaction of related events (#8532) --- changelog.d/8481.misc | 1 + .../api/session/homeserver/HomeServerCapabilities.kt | 4 ++-- .../android/sdk/api/session/room/send/SendService.kt | 4 ++-- .../android/sdk/internal/auth/version/Versions.kt | 10 ++++------ .../sdk/internal/crypto/tasks/RedactEventTask.kt | 10 +++++----- .../database/mapper/HomeServerCapabilitiesMapper.kt | 2 +- .../homeserver/GetHomeServerCapabilitiesTask.kt | 4 ++-- .../internal/session/room/send/DefaultSendService.kt | 6 +++--- .../session/room/send/LocalEchoEventFactory.kt | 6 +++--- .../internal/session/room/send/RedactEventWorker.kt | 4 ++-- .../session/room/send/model/EventRedactBody.kt | 9 +++++++-- .../session/room/send/queue/EventSenderProcessor.kt | 4 ++-- .../room/send/queue/EventSenderProcessorCoroutine.kt | 8 ++++---- .../internal/session/room/send/queue/QueueMemento.kt | 2 +- .../session/room/send/queue/QueuedTaskFactory.kt | 4 ++-- .../session/room/send/queue/RedactQueuedTask.kt | 4 ++-- 16 files changed, 43 insertions(+), 39 deletions(-) create mode 100644 changelog.d/8481.misc diff --git a/changelog.d/8481.misc b/changelog.d/8481.misc new file mode 100644 index 0000000000..069c2e8b3f --- /dev/null +++ b/changelog.d/8481.misc @@ -0,0 +1 @@ +Update MSC3912 implementation: Redaction of related events diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 4968df775a..78672adb00 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -77,9 +77,9 @@ data class HomeServerCapabilities( val canRemotelyTogglePushNotificationsOfDevices: Boolean = false, /** - * True if the home server supports event redaction with relations. + * True if the home server supports redaction of related events. */ - var canRedactEventWithRelations: Boolean = false, + var canRedactRelatedEvents: Boolean = false, /** * External account management url for use with MSC3824 delegated OIDC, provided in Wellknown. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt index 07036f4b65..9eb0fa4097 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt @@ -158,10 +158,10 @@ interface SendService { * Redact (delete) the given event. * @param event the event to redact * @param reason optional reason string - * @param withRelations the list of relation types to redact with this event + * @param withRelTypes the list of relation types to redact with this event * @param additionalContent additional content to put in the event content */ - fun redactEvent(event: Event, reason: String?, withRelations: List? = null, additionalContent: Content? = null): Cancelable + fun redactEvent(event: Event, reason: String?, withRelTypes: List? = null, additionalContent: Content? = null): Cancelable /** * Schedule this message to be resent. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt index 3fe5541b68..83186344bb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt @@ -59,8 +59,7 @@ private const val FEATURE_QR_CODE_LOGIN = "org.matrix.msc3882" private const val FEATURE_THREADS_MSC3771 = "org.matrix.msc3771" private const val FEATURE_THREADS_MSC3773 = "org.matrix.msc3773" private const val FEATURE_REMOTE_TOGGLE_PUSH_NOTIFICATIONS_MSC3881 = "org.matrix.msc3881" -private const val FEATURE_EVENT_REDACTION_WITH_RELATIONS = "org.matrix.msc3912" -private const val FEATURE_EVENT_REDACTION_WITH_RELATIONS_STABLE = "org.matrix.msc3912.stable" +private const val FEATURE_REDACTION_OF_RELATED_EVENT = "org.matrix.msc3912" /** * Return true if the SDK supports this homeserver version. @@ -162,9 +161,8 @@ internal fun Versions.doesServerSupportRemoteToggleOfPushNotifications(): Boolea /** * Indicate if the server supports MSC3912: https://github.com/matrix-org/matrix-spec-proposals/pull/3912. * - * @return true if event redaction with relations is supported + * @return true if redaction of related events is supported */ -internal fun Versions.doesServerSupportRedactEventWithRelations(): Boolean { - return unstableFeatures?.get(FEATURE_EVENT_REDACTION_WITH_RELATIONS).orFalse() || - unstableFeatures?.get(FEATURE_EVENT_REDACTION_WITH_RELATIONS_STABLE).orFalse() +internal fun Versions.doesServerSupportRedactionOfRelatedEvents(): Boolean { + return unstableFeatures?.get(FEATURE_REDACTION_OF_RELATED_EVENT).orFalse() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/RedactEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/RedactEventTask.kt index b060748a61..01d59a8c80 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/RedactEventTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/RedactEventTask.kt @@ -30,7 +30,7 @@ internal interface RedactEventTask : Task { val roomId: String, val eventId: String, val reason: String?, - val withRelations: List?, + val withRelTypes: List?, ) } @@ -41,9 +41,9 @@ internal class DefaultRedactEventTask @Inject constructor( ) : RedactEventTask { override suspend fun execute(params: RedactEventTask.Params): String { - val withRelations = if (homeServerCapabilitiesDataSource.getHomeServerCapabilities()?.canRedactEventWithRelations.orFalse() && - !params.withRelations.isNullOrEmpty()) { - params.withRelations + val withRelTypes = if (homeServerCapabilitiesDataSource.getHomeServerCapabilities()?.canRedactRelatedEvents.orFalse() && + !params.withRelTypes.isNullOrEmpty()) { + params.withRelTypes } else { null } @@ -55,7 +55,7 @@ internal class DefaultRedactEventTask @Inject constructor( eventId = params.eventId, body = EventRedactBody( reason = params.reason, - withRelations = withRelations, + unstableWithRelTypes = withRelTypes, ) ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt index 1c7a0591a1..b566cf7cb6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt @@ -47,7 +47,7 @@ internal object HomeServerCapabilitiesMapper { canLoginWithQrCode = entity.canLoginWithQrCode, canUseThreadReadReceiptsAndNotifications = entity.canUseThreadReadReceiptsAndNotifications, canRemotelyTogglePushNotificationsOfDevices = entity.canRemotelyTogglePushNotificationsOfDevices, - canRedactEventWithRelations = entity.canRedactEventWithRelations, + canRedactRelatedEvents = entity.canRedactEventWithRelations, externalAccountManagementUrl = entity.externalAccountManagementUrl, ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index a368325793..71f6ebd6e3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities import org.matrix.android.sdk.internal.auth.version.Versions import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices import org.matrix.android.sdk.internal.auth.version.doesServerSupportQrCodeLogin -import org.matrix.android.sdk.internal.auth.version.doesServerSupportRedactEventWithRelations +import org.matrix.android.sdk.internal.auth.version.doesServerSupportRedactionOfRelatedEvents import org.matrix.android.sdk.internal.auth.version.doesServerSupportRemoteToggleOfPushNotifications import org.matrix.android.sdk.internal.auth.version.doesServerSupportThreadUnreadNotifications import org.matrix.android.sdk.internal.auth.version.doesServerSupportThreads @@ -154,7 +154,7 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( homeServerCapabilitiesEntity.canRemotelyTogglePushNotificationsOfDevices = getVersionResult.doesServerSupportRemoteToggleOfPushNotifications() homeServerCapabilitiesEntity.canRedactEventWithRelations = - getVersionResult.doesServerSupportRedactEventWithRelations() + getVersionResult.doesServerSupportRedactionOfRelatedEvents() } if (getWellknownResult != null && getWellknownResult is WellknownResult.Prompt) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt index 7176e36e0c..04749103c1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt @@ -140,11 +140,11 @@ internal class DefaultSendService @AssistedInject constructor( .let { sendEvent(it) } } - override fun redactEvent(event: Event, reason: String?, withRelations: List?, additionalContent: Content?): Cancelable { + override fun redactEvent(event: Event, reason: String?, withRelTypes: List?, additionalContent: Content?): Cancelable { // TODO manage media/attachements? - val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason, withRelations, additionalContent) + val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason, withRelTypes, additionalContent) .also { createLocalEcho(it) } - return eventSenderProcessor.postRedaction(redactionEcho, reason, withRelations) + return eventSenderProcessor.postRedaction(redactionEcho, reason, withRelTypes) } override fun resendTextMessage(localEcho: TimelineEvent): Cancelable { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt index c2bdec3596..9510f50420 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt @@ -812,12 +812,12 @@ internal class LocalEchoEventFactory @Inject constructor( } } */ - fun createRedactEvent(roomId: String, eventId: String, reason: String?, withRelations: List? = null, additionalContent: Content? = null): Event { + fun createRedactEvent(roomId: String, eventId: String, reason: String?, withRelTypes: List? = null, additionalContent: Content? = null): Event { val localId = LocalEcho.createLocalEchoId() - val content = if (reason != null || withRelations != null) { + val content = if (reason != null || withRelTypes != null) { EventRedactBody( reason = reason, - withRelations = withRelations, + unstableWithRelTypes = withRelTypes, ).toContent().plus(additionalContent.orEmpty()) } else { additionalContent diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt index 576f31c64c..270d3a228e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/RedactEventWorker.kt @@ -43,7 +43,7 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters, ses val roomId: String, val eventId: String, val reason: String?, - val withRelations: List? = null, + val withRelTypes: List? = null, override val lastFailureMessage: String? = null ) : SessionWorkerParams @@ -63,7 +63,7 @@ internal class RedactEventWorker(context: Context, params: WorkerParameters, ses roomId = params.roomId, eventId = params.eventId, reason = params.reason, - withRelations = params.withRelations, + withRelTypes = params.withRelTypes, ) ) }.fold( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/model/EventRedactBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/model/EventRedactBody.kt index cf2bc0dc4f..2ed5c9f363 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/model/EventRedactBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/model/EventRedactBody.kt @@ -25,5 +25,10 @@ internal data class EventRedactBody( val reason: String? = null, @Json(name = "org.matrix.msc3912.with_relations") - val withRelations: List? = null, -) + val unstableWithRelTypes: List? = null, + + @Json(name = "with_rel_types") + val withRelTypes: List? = null, +) { + fun getBestWithRelTypes() = withRelTypes ?: unstableWithRelTypes +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessor.kt index b285e90c9a..90d78a51e0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessor.kt @@ -26,9 +26,9 @@ internal interface EventSenderProcessor : SessionLifecycleObserver { fun postEvent(event: Event, encrypt: Boolean): Cancelable - fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelations: List? = null): Cancelable + fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelTypes: List? = null): Cancelable - fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?, withRelations: List? = null): Cancelable + fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?, withRelTypes: List? = null): Cancelable fun postTask(task: QueuedTask): Cancelable diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt index 9ce29c3c08..a4e3773eb9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt @@ -101,8 +101,8 @@ internal class EventSenderProcessorCoroutine @Inject constructor( return postTask(task) } - override fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelations: List?): Cancelable { - return postRedaction(redactionLocalEcho.eventId!!, redactionLocalEcho.redacts!!, redactionLocalEcho.roomId!!, reason, withRelations) + override fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelTypes: List?): Cancelable { + return postRedaction(redactionLocalEcho.eventId!!, redactionLocalEcho.redacts!!, redactionLocalEcho.roomId!!, reason, withRelTypes) } override fun postRedaction( @@ -110,9 +110,9 @@ internal class EventSenderProcessorCoroutine @Inject constructor( eventToRedactId: String, roomId: String, reason: String?, - withRelations: List? + withRelTypes: List? ): Cancelable { - val task = queuedTaskFactory.createRedactTask(redactionLocalEchoId, eventToRedactId, roomId, reason, withRelations) + val task = queuedTaskFactory.createRedactTask(redactionLocalEchoId, eventToRedactId, roomId, reason, withRelTypes) return postTask(task) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueueMemento.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueueMemento.kt index a900e4ae5d..85238ae944 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueueMemento.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueueMemento.kt @@ -118,7 +118,7 @@ internal class QueueMemento @Inject constructor( eventId = it.redacts, roomId = it.roomId, reason = body?.reason, - withRelations = body?.withRelations, + withRelTypes = body?.getBestWithRelTypes(), ) ) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueuedTaskFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueuedTaskFactory.kt index 46df7e29f3..e79808ee3f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueuedTaskFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueuedTaskFactory.kt @@ -43,13 +43,13 @@ internal class QueuedTaskFactory @Inject constructor( ) } - fun createRedactTask(redactionLocalEcho: String, eventId: String, roomId: String, reason: String?, withRelations: List? = null): QueuedTask { + fun createRedactTask(redactionLocalEcho: String, eventId: String, roomId: String, reason: String?, withRelTypes: List? = null): QueuedTask { return RedactQueuedTask( redactionLocalEchoId = redactionLocalEcho, toRedactEventId = eventId, roomId = roomId, reason = reason, - withRelations = withRelations, + withRelTypes = withRelTypes, redactEventTask = redactEventTask, localEchoRepository = localEchoRepository, cancelSendTracker = cancelSendTracker diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/RedactQueuedTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/RedactQueuedTask.kt index f484c24aae..b51a04f863 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/RedactQueuedTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/RedactQueuedTask.kt @@ -26,14 +26,14 @@ internal class RedactQueuedTask( val redactionLocalEchoId: String, private val roomId: String, private val reason: String?, - private val withRelations: List?, + private val withRelTypes: List?, private val redactEventTask: RedactEventTask, private val localEchoRepository: LocalEchoRepository, private val cancelSendTracker: CancelSendTracker ) : QueuedTask(queueIdentifier = roomId, taskIdentifier = redactionLocalEchoId) { override suspend fun doExecute() { - redactEventTask.execute(RedactEventTask.Params(redactionLocalEchoId, roomId, toRedactEventId, reason, withRelations)) + redactEventTask.execute(RedactEventTask.Params(redactionLocalEchoId, roomId, toRedactEventId, reason, withRelTypes)) } override fun onTaskFailed() { From 1b43087eb3ebc423a0136049f7a3ab4968caad1c Mon Sep 17 00:00:00 2001 From: Edgars Andersons Date: Wed, 5 Jul 2023 08:41:00 +0000 Subject: [PATCH 187/234] Translated using Weblate (Latvian) Currently translated at 68.5% (1807 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/lv/ --- .../ui-strings/src/main/res/values-lv/strings.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/ui-strings/src/main/res/values-lv/strings.xml b/library/ui-strings/src/main/res/values-lv/strings.xml index 0d0fcda97f..d7bd13416b 100644 --- a/library/ui-strings/src/main/res/values-lv/strings.xml +++ b/library/ui-strings/src/main/res/values-lv/strings.xml @@ -2073,4 +2073,18 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka. %1$d atlasīti %1$s nomainīja attēlojamo vārdu uz %2$s + Nav ļauts pievienoties šai istabai + Mainīt vietu + Sākotnējais sinhronizēšanas pieprasījums + Visas tērzēšanas + Izpētīt istabas + Izvērst %s apakšvienumus + + %d servera ACL izmaiņu + %d servera ACL izmaiņa + %d servera ACL izmaiņas + + Sakļaut %s apakšvienumus + Uzsākt tērzēšanu + Izveidot istabu \ No newline at end of file From 85d0837f3b2f8ee3f7422c9a531ca58b29508313 Mon Sep 17 00:00:00 2001 From: Edgars Andersons Date: Wed, 5 Jul 2023 11:33:44 +0000 Subject: [PATCH 188/234] Translated using Weblate (Latvian) Currently translated at 68.6% (1810 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/lv/ --- library/ui-strings/src/main/res/values-lv/strings.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-lv/strings.xml b/library/ui-strings/src/main/res/values-lv/strings.xml index d7bd13416b..2760d06bc3 100644 --- a/library/ui-strings/src/main/res/values-lv/strings.xml +++ b/library/ui-strings/src/main/res/values-lv/strings.xml @@ -59,7 +59,7 @@ Jūs izveidojāt istabu %1$s izveidoja istabu Jūsu uzaicinājums - Jūs ieslēdzāt pilnīgu šifrēšanu (neatpazīts algoritms %1$s). + Ir ieslēgta pilnīga šifrēšana (neatpazīts algoritms %1$s). %1$s ieslēdza pilnīgu šifrēšanu (neatpazīts algoritms %2$s). Jūs ieslēdzāt pilnīgu šifrēšanu. %1$s ieslēdza pilnīgu šifrēšanu. @@ -2087,4 +2087,9 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Sakļaut %s apakšvienumus Uzsākt tērzēšanu Izveidot istabu + ${app_name} ir nepieciešams veikt kešatmiņas tīrīšanu, lai būtu pašreizēja, šī iemesla dēļ: +\n%s +\n +\nJāņem vērā, ka šī darbība pārsāknēs lietotni, un tas var aizņemt kādu laiku. + - atsevišķi lietotāji atkal tiek ņemti vērā \ No newline at end of file From fedbfe4931243afa3a83deb718678ba65eefe96e Mon Sep 17 00:00:00 2001 From: Dimitris Vagiakakos Date: Wed, 5 Jul 2023 21:49:54 +0000 Subject: [PATCH 189/234] Translated using Weblate (Greek) Currently translated at 16.0% (425 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/el/ --- .../src/main/res/values-el/strings.xml | 80 ++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-el/strings.xml b/library/ui-strings/src/main/res/values-el/strings.xml index f4973f4b95..5f7d5df4b8 100644 --- a/library/ui-strings/src/main/res/values-el/strings.xml +++ b/library/ui-strings/src/main/res/values-el/strings.xml @@ -383,4 +383,82 @@ Άνοιγμα με Αποστολή αυτοκόλλητου %1$s δημιούργησε το δωμάτιο - + Εισήλθες + Αποχώρησες από το δωμάτιο + %1$s αποχώρισε από το δωμάτιο + Έχετε απορρίψει την πρόσκληση + Ορίσατε το όνομά σας ω; %1$s + Η πρόσκλησή σου + Δημιούργησες αυτό το δωμάτιο + %1$s δημιούργησε την συζήτηση + "Προσκάλεσες τον χρήστη %1$s" + Έχετε αποκλείσει τον χρήστη %1$s + Αλλάξατε το άβατάρ σας + Άλλαξες το θέμα σε: %1$s + Δωμάτιο/Χώρος + Σύνδεση + + %1$d επιλέχθηκε + %1$d επιλέχθηκαν + + + %d ACLs του server άλλαξε + %d ACLs του server άλλαξαν + + Πραγματοποιείται σύνδεση στην συσκευή + Δεν ταιριάζει; + Προσπάθησε ξανά + "Οι servers που περιλαμβάνουν %s επιτρέπονται." + Δημιούργησες αυτή την συζήτηση + Αποχώρισες από το δωμάτιο + Ο χρήστης %1$s αφαίρεσε τον αποκλείσμο του χρήστη %2$s + Άλλαξες το όνομα του δωματίου σε: %1$s + Έχετε ξεκινήσει μία βιντεοκλήση. + Το μελλοντικό ιστορικό του δωματίου θα είναι εμφανή στο χρήστη %1$s + Έχετε ξεκινησει μία κλήση. + Ο χρήστης %s αναβάθμισε αυτό το δωμάτιο. + Η εύρεση server που περιλαμβάνει %s είναι απεκλεισμένη. + "• Οι servers οπού περιλαμβάνουν %s είναι τώρα απεκλεισμένοι." + Επιβεβαίωση + Παρακαλώ επιβεβαιώστε ότι γνωρίζετε την προέλευση του κώδικα αυτού. Όταν συνδέετε νέες συσκευές, ενδεχομένως να δίνετε σε κάποιον άλλο πλήρης πρόσβαση στον λογαριασμό σας. + Εκαθάρριση προσωπικών δεδομένων + Αφαιρέσατε τον χρήστη %1$s + Ο χρήστης %1$s άλλαξε το όνομά του σε %2$s + %1$s άλλαξε το άβαταρ του δωματίου + Άλλαξες το άβαταρ του δωματίου + "%s απέστειλε δεδομένα ώστε να πραγματοποιηθεί η κλήση." + Απέστειλες δεδομένα ώστε να ξεκινήσει η κλήση. + Απάντησες στην κλήση. + Ο χρήστης %1$s έκανε τα μελλοντικά μηνύματα διαθέσιμα στον χρήστη %2$s + Έχετε αναβαθμίσει αυτό το δωμάτιο. + %s αναβαθμίστηκε εδώ. + Αναβαθμίστηκες εδώ. + %s όρισε τα ACLs αυτού του server σε αυτό το δωμάτιο. + Έχεις ορίσει το ACL του server για αυτό το δωμάτιο. + "• Οι servers που περιλαμβάνονται αυτή την IP είναι απεκλεισμένοι." + %s άλλαξε τα ACLs του server γι αυτό το δωμάτιο. + Άλλαξες τα ACLs του server γι αυτό το δωμάτιο. + Κωδικός Πρόσβασης + Οι διαχειριστές του server σας (%1$s), σας έχουν αποσυνδέσει από τον λογαριασμό σας %2$s (%3$s). + Η πειργραφή είναι πολύ σύντομη + Έχετε αποσυνδεθεί + Επιπρόσθετες ρυθμίσεις + Λειτουργίες Προγραμματιστή + Τρέχουσα συνεδρία + Διαγραφή δεδομένων + Άλλες συνεδρίες + Πραγματοποιείται η σύνδεση + Συμμετέχεις σε αυτό το δωμάτιο + %1$s εισήλθε + Έχετε αφαιρέσει τον αποκλεισμό από τον χρήστη %1$s + Αφαιρέσατε την πρόσκληση του χρήστη %1$s + Άλλαξες το όνομά σου από %1$s σε %2$s + Αφαίρεσες το όνομά όπου εμφανιζόταν ο λογαριασμός σου ( προηγουμένως ήταν %1$s) + .Τερμάτισες την κλήση. + Έκανες τα μελλοντικά μηνύματα διαθέσιμα στον χρήστη %1$s + Ορισμός συνδέσμου + Συνδεθείτε ξανά + Σύνδεση + Διαγρφή όλων των δεδομένων + Ρυθμίσεις + \ No newline at end of file From 87f2a69fb1f3261949216bace264de9e96c6fc14 Mon Sep 17 00:00:00 2001 From: Theo Date: Wed, 5 Jul 2023 17:10:27 +0000 Subject: [PATCH 190/234] Translated using Weblate (Greek) Currently translated at 16.0% (425 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/el/ --- library/ui-strings/src/main/res/values-el/strings.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/ui-strings/src/main/res/values-el/strings.xml b/library/ui-strings/src/main/res/values-el/strings.xml index 5f7d5df4b8..3b22a60a54 100644 --- a/library/ui-strings/src/main/res/values-el/strings.xml +++ b/library/ui-strings/src/main/res/values-el/strings.xml @@ -360,11 +360,11 @@ \nΜε την απενεργοποίηση του λογαρισμού σας δεν θα ξεχαστούν τα μηνύματά που έχετε στείλει. Εάν θα θέλατε να ξεχαστούν, τότε δηλώστε το στο κουτί πιο κάτω. \n \nΗ ορατότητα μηνυμάτων δουλεύει σαν το ηλεκτρονικό ταχυδρομείο. Το να ξεχαστούν τα μηνύματα σημαίνει οτι μηνύματα τα οποία έχετε στείλει δεν θα σταλούν σε νέους ή μη-εγγεγραμμένους χρήστες, αλλα εγγεγραμμένοι χρήστες οι οποίοι έχουν ήδη πρόσβαση σε αυτά τα μηνύματα θα μπορούν ακόμα να τα δούν.
- Αυτό το δωμάτιο έχει αντικατασταθεί και δεν είναι πια ενεργό + Αυτό το δωμάτιο έχει αντικατασταθεί και δεν είναι πια ενεργό. Παράβλεψη Αποσύνδεση Δεν εμπιστεύομαι - Δεν έχετε εξουσιοδότηση να δημοσιεύσετε σε αυτό το δωμάτιο + Δεν έχετε εξουσιοδότηση να δημοσιεύσετε σε αυτό το δωμάτιο. %1$s & %2$s & άλλοι γράφουν… %s γράφει… %1$s & %2$s γράφουν… @@ -461,4 +461,6 @@ Σύνδεση Διαγρφή όλων των δεδομένων Ρυθμίσεις + Γενικά + Γενικά \ No newline at end of file From 1ef2de0356df7f52d1124b1bae60e4b239dd4aea Mon Sep 17 00:00:00 2001 From: walito-arch Date: Wed, 5 Jul 2023 08:53:04 +0000 Subject: [PATCH 191/234] Translated using Weblate (Swahili) Currently translated at 1.0% (28 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/sw/ --- .../src/main/res/values-sw/strings.xml | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-sw/strings.xml b/library/ui-strings/src/main/res/values-sw/strings.xml index d1938c5896..923cfac661 100644 --- a/library/ui-strings/src/main/res/values-sw/strings.xml +++ b/library/ui-strings/src/main/res/values-sw/strings.xml @@ -11,4 +11,24 @@ %1$d Iliyochaguliwa %1$d Ziliyochaguliwa - + %1$s Andaa chumba + Umeandaa chumba + %1$s anzisha mjadala + Ulianzisha mjadala + %1$s Walioalikwa %2$s + %1$s jiunge na mjadala + %1$s Acha mjadala + Umetoka kwenye mjadala + %1$s Acha mjadala + Umeacha mjadala + %1$s hujazuiliwa %2$s + Hujazuiliwa %1$s + %1$s huruhusiwi %2$s + Huruhusiwi %1$s + Sitisha %1$s\'s mwaliko + %s\'s Mwaliko + Umejiunga na mjadala + %1$s sitisha %2$s\'s mmwaliko + Mwaliko wako + Umealika %1$s + \ No newline at end of file From c1e77c6dc9433b5b646b7d85840f9b99bbc9ed90 Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Fri, 7 Jul 2023 08:46:33 +0000 Subject: [PATCH 192/234] Translated using Weblate (Russian) Currently translated at 99.6% (2628 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- library/ui-strings/src/main/res/values-ru/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/ui-strings/src/main/res/values-ru/strings.xml b/library/ui-strings/src/main/res/values-ru/strings.xml index b48e72cbba..12b038129d 100644 --- a/library/ui-strings/src/main/res/values-ru/strings.xml +++ b/library/ui-strings/src/main/res/values-ru/strings.xml @@ -3032,7 +3032,7 @@ Сообщение в %s Сообщение в комнате Комната/Пространство - Аккаунт + Учётная запись Аватар профиля пользователя %1$s Продолжайте, только если вы уверены, что ваш ключ утерян, а доступ к другим активным устройствам отсустствует. Пока пользователь не верифицировал эту сессию, отправленные и полученные сообщения отмечаются предупреждениями. @@ -3046,13 +3046,13 @@ При изменении настроек уведомлений произошла ошибка. Попробуйте ещё раз. Когда приглашенные пользователи присоединятся к ${app_name}, вы сможете писать им с использованием сквозного шифрования Сброс ваших ключей верификации не может быть отменен. После сброса, вы не будете иметь доступа к старым зашифрованным сообщениям, а все ваши контакты, верифицировавшие вас ранее, увидят предупреждение о повторной верификации. - Зашифрованно неактивным устройством + Зашифровано прерванным сеансом Защищенный обмен сообщениями был обновлен. Пожалуйста, повторно верифицируйте ваше устройство. Не удается расшифровать голосовое сообщение. Обзор опроса во времени Сообщение - Подтвердить с помощью активного устройства + Сверить с другим сеансом Возобновить - %1$s изменил отображаемое имя на %2$s + %1$s изменил(а) имя на %2$s Запрос на верификацию не найден. Возможно, он был отменен или обработан другим сеансом. \ No newline at end of file From c3752f529a76753a00c0a9c3d4ca1e9f17b04c17 Mon Sep 17 00:00:00 2001 From: KuriakiMariaHere Date: Fri, 7 Jul 2023 21:36:13 +0000 Subject: [PATCH 193/234] Translated using Weblate (Greek) Currently translated at 16.7% (442 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/el/ --- .../src/main/res/values-el/strings.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/library/ui-strings/src/main/res/values-el/strings.xml b/library/ui-strings/src/main/res/values-el/strings.xml index 3b22a60a54..028c73750e 100644 --- a/library/ui-strings/src/main/res/values-el/strings.xml +++ b/library/ui-strings/src/main/res/values-el/strings.xml @@ -463,4 +463,22 @@ Ρυθμίσεις Γενικά Γενικά + %1$s Έχει αφαιρεθεί το avatar του δωματίου + Έχεις αφαιρέσει το avatar του δωματίου + Καμία αλλαγή. + Έχεις αφαίρεσει το όνομα του δωματίου + Ο χρήστης %1$s προσκάλεσε τον χρήστη %2$s + Προσκάλεσες τον χρήστη %1$s + Διαχειριστής + Moderator + Άλλαξες το power του level %1$s. + Οι Servers που ταιριάζουν με %s έχουν αφαιρεθεί από την επιτρεπόμενη λίστα. + Οι Servers που ταιριάζουν με το IP έχουν αποκλειστικοί. + Έχεις αφαιρέσει το θέμα του δωματίου + Αποδέχτηκες την πρόσκληση για το %1$s + Προεπιλογή + Custom (%1$d) + Προσαρμοσμένο + 🎉Όλοι οι Servers έχουν αποκλειστεί από συμμετέχοντες!Το δωμάτιο αυτό δεν μπορεί πια να χρησιμοποιηθεί. + Έστειλες μια πρόσκληση στο %1$s για να συνδεθείς στο δωμάτιο \ No newline at end of file From 2bbd5ee7d9ec44cf20d610449dca921003736e4d Mon Sep 17 00:00:00 2001 From: KuriakiMariaHere Date: Sat, 8 Jul 2023 15:59:27 +0000 Subject: [PATCH 194/234] Translated using Weblate (Greek) Currently translated at 17.0% (451 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/el/ --- .../ui-strings/src/main/res/values-el/strings.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/library/ui-strings/src/main/res/values-el/strings.xml b/library/ui-strings/src/main/res/values-el/strings.xml index 028c73750e..3d148ae2bf 100644 --- a/library/ui-strings/src/main/res/values-el/strings.xml +++ b/library/ui-strings/src/main/res/values-el/strings.xml @@ -481,4 +481,16 @@ Προσαρμοσμένο 🎉Όλοι οι Servers έχουν αποκλειστεί από συμμετέχοντες!Το δωμάτιο αυτό δεν μπορεί πια να χρησιμοποιηθεί. Έστειλες μια πρόσκληση στο %1$s για να συνδεθείς στο δωμάτιο + Το μήνυμα στάλθηκε + Δημιουργώ ένα δωμάτιο + Δεν επιτρέπεται να συνδεθείς σε αυτό το δωμάτιο + %1$s,%2$s και %3$s + Αλλάζω το Space + %1$s, %2$s, %3$s και %4$s + Ερευνάω τα δωμάτια + -Κάποιοι χρήστες έχουν αγνοηθεί + + %1$s, %2$s, %3$s και %4$d άλλος χρήστης + %1$s, %2$s, %3$s και %4$d άλλοι χρήστες + \ No newline at end of file From 99e171dbee6118ed81673638ccfb11105a7641fc Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Sat, 8 Jul 2023 13:29:53 +0000 Subject: [PATCH 195/234] Translated using Weblate (Russian) Currently translated at 99.6% (2628 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- library/ui-strings/src/main/res/values-ru/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ui-strings/src/main/res/values-ru/strings.xml b/library/ui-strings/src/main/res/values-ru/strings.xml index 12b038129d..210d60a827 100644 --- a/library/ui-strings/src/main/res/values-ru/strings.xml +++ b/library/ui-strings/src/main/res/values-ru/strings.xml @@ -3020,7 +3020,7 @@ Не удалось записать голосовое сообщение Убедиться что Ваш аккаунт в безопасности Получить последнюю сборку (у вас могут быть проблемы со входом) - История опроса + Опросы Голосовая трансляция начата Ваш домашний сервер не поддерживает список обсуждений. Остановить From eef01ad8f9cc9941a584fd1bd6ddef61202b2dcd Mon Sep 17 00:00:00 2001 From: KuriakiMariaHere Date: Sat, 8 Jul 2023 21:05:33 +0000 Subject: [PATCH 196/234] Translated using Weblate (Greek) Currently translated at 17.1% (452 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/el/ --- library/ui-strings/src/main/res/values-el/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-el/strings.xml b/library/ui-strings/src/main/res/values-el/strings.xml index 3d148ae2bf..807a62c10c 100644 --- a/library/ui-strings/src/main/res/values-el/strings.xml +++ b/library/ui-strings/src/main/res/values-el/strings.xml @@ -493,4 +493,5 @@ %1$s, %2$s, %3$s και %4$d άλλος χρήστης %1$s, %2$s, %3$s και %4$d άλλοι χρήστες + Το μήνυμα στέλνεται… \ No newline at end of file From 6fd589440d0956a0d1476851b615e100d8abdd32 Mon Sep 17 00:00:00 2001 From: KuriakiMariaHere Date: Sun, 9 Jul 2023 20:17:38 +0000 Subject: [PATCH 197/234] Translated using Weblate (Greek) Currently translated at 17.6% (465 of 2640 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/el/ --- .../src/main/res/values-el/strings.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/ui-strings/src/main/res/values-el/strings.xml b/library/ui-strings/src/main/res/values-el/strings.xml index 807a62c10c..3c8ec19a78 100644 --- a/library/ui-strings/src/main/res/values-el/strings.xml +++ b/library/ui-strings/src/main/res/values-el/strings.xml @@ -494,4 +494,21 @@ %1$s, %2$s, %3$s και %4$d άλλοι χρήστες Το μήνυμα στέλνεται… + Μύνημα + Δημιουργώ έναν σύνδεσμο + Σύνδεσμος + Στέλνω ένα αρχείο. + Μύνημα από τον χρήστη %s + Στέλνω ένα ηχητικό μύνημα. + Στέλνω μια εικόνα. + + Πρόσθεσες εναλλακτική διεύθυνση %1$ για αυτό το δωμάτιο. + Πρόσθεσες εναλλακτικές διευθύνσεις %1$ για αυτό το δωμάτιο. + + Στέλνω ένα βίντεο. + Στέλνω ένα αρχείο ήχου. + Επεξεργάζομαι ένα σύνδεσμο + Κείμενο + Στέλνω ένα αυτοκόλλητο. + Σκανάρω ένα QR code \ No newline at end of file From c08b99a4f1dd4cd29fb92a523417152f87e370f8 Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Mon, 10 Jul 2023 08:27:08 +0000 Subject: [PATCH 198/234] Translated using Weblate (Russian) Currently translated at 99.7% (2629 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- library/ui-strings/src/main/res/values-ru/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ui-strings/src/main/res/values-ru/strings.xml b/library/ui-strings/src/main/res/values-ru/strings.xml index 210d60a827..71b95e0e28 100644 --- a/library/ui-strings/src/main/res/values-ru/strings.xml +++ b/library/ui-strings/src/main/res/values-ru/strings.xml @@ -3055,4 +3055,5 @@ Возобновить %1$s изменил(а) имя на %2$s Запрос на верификацию не найден. Возможно, он был отменен или обработан другим сеансом. + Цитата \ No newline at end of file From 841028774e596b4c14d9f5cc207819580f059f22 Mon Sep 17 00:00:00 2001 From: Nui Harime Date: Mon, 10 Jul 2023 13:46:44 +0000 Subject: [PATCH 199/234] Translated using Weblate (Russian) Currently translated at 99.8% (2633 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/ --- library/ui-strings/src/main/res/values-ru/strings.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/ui-strings/src/main/res/values-ru/strings.xml b/library/ui-strings/src/main/res/values-ru/strings.xml index 71b95e0e28..33814ca5bf 100644 --- a/library/ui-strings/src/main/res/values-ru/strings.xml +++ b/library/ui-strings/src/main/res/values-ru/strings.xml @@ -3056,4 +3056,8 @@ %1$s изменил(а) имя на %2$s Запрос на верификацию не найден. Возможно, он был отменен или обработан другим сеансом. Цитата + Версия шифрования + Блок кода + Подпункт + Пункт \ No newline at end of file From 8eccae44e5eaea319e059ac92d5d5aeb7b3427ad Mon Sep 17 00:00:00 2001 From: Edgars Andersons Date: Tue, 11 Jul 2023 05:31:31 +0000 Subject: [PATCH 200/234] Translated using Weblate (Latvian) Currently translated at 69.9% (1844 of 2636 strings) Translation: Element Android/Element Android App Translate-URL: https://translate.element.io/projects/element-android/element-app/lv/ --- .../src/main/res/values-lv/strings.xml | 58 ++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/library/ui-strings/src/main/res/values-lv/strings.xml b/library/ui-strings/src/main/res/values-lv/strings.xml index 2760d06bc3..4570016bc6 100644 --- a/library/ui-strings/src/main/res/values-lv/strings.xml +++ b/library/ui-strings/src/main/res/values-lv/strings.xml @@ -312,7 +312,7 @@ Noraidīt Pāriet uz pirmo neizlasīto ziņu Pamest istabu - Vai tiešām vēlies pamest istabu\? + Vai tiešām pamest istabu\? TIEŠIE ČATI Uzaicināt Nobanot @@ -342,7 +342,7 @@ Istabas dalībnieku filtrs Rezultātu nav Visas ziņas - Pievienot uz galvenā ekrāna + Pievienot sākumekrānam Profila attēls Attēlojamais vārds Pievienot epasta adresi @@ -585,10 +585,10 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Drošība Ziņas šeit ir nodrošinātas ar pilnīgu šifrēšanu. \n -\nJūsu ziņas tiek nodrošinātas ar slēdzenēm, un tikai jums un saņēmējam ir unikālas atslēgas, lai tās atbloķētu. +\nZiņas tiek nodrošinātas ar slēdzenēm, un tikai sūtītājam un saņēmējam ir neatkārtojamas atslēgas, lai tās atslēgtu.
Ziņas šeit ir nodrošinātas ar pilnīgu šifrēšanu. \n -\nJūsu ziņas tiek nodrošinātas ar slēdzenēm, un tikai jums un saņēmējam ir unikālas atslēgas, lai tās atbloķētu. +\nZiņas tiek nodrošinātas ar slēdzenēm, un tikai sūtītājam un saņēmējam ir neatkārtojamas atslēgas, lai tās atslēgtu.
Ziņas šeit nav nodrošinātas ar pilnīgu šifrēšanu. Ziņām šajā istabā netiek piemērota pilnīga šifrēšana. Jūs akceptējāt @@ -694,7 +694,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Deaktivizēt kontu Nomaina jūsu parādāmo vārdu Padzen lietotāju ar norādīto id - Atstāj istabu + Pamest istabu Uzaicina lietotāju ar norādīto id uz pašreizējo istabu Atceļ operatora statusu lietotājam ar norādīto Id Definē lietotāja statusu @@ -751,7 +751,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Jūs nevarēsiet atcelt šīs izmaiņas pēc sava statusa pazemināšanas. Gadījumā, ja esat pēdējais priviliģētais lietotājs istabā, būs neiespējami atgūt šīs privilēģijas. Padzīt Atcelt uzaicinājumu - Šī istaba nav publiska un jūs nevarēsiet atkārtoti pievienoties bez uzaicinājuma. + Šī istaba nav publiska. Tai nebūs iespējams atkārtoti pievienoties bez uzaicinājuma. Atļaujiet piekļuvi savām kontaktpersonām. Lai skenētu QR kodu, jums jāatļauj piekļuve kamerai. Notiek video zvans… @@ -967,7 +967,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Istabu katalogs Jaunā vērtība Pārslēgt - Jūs nevarat uzsākt zvanu ar sevi, pagaidiet, kamēr dalībnieki akceptēs uzaicinājumu + Nevar uzsākt zvanu ar sevi, jāpagaida, līdz dalībnieki apstiprinās uzaicinājumu Jūs nevarat uzsākt zvanu ar sevi Sūtīt uzlīmi Sakarā ar pilnīgu šifrēšanu, jums var būt nepieciešams sagaidīt ziņu no kāda, jo šifrēšanas atslēgas netika pareizi nosūtītas jums. @@ -1007,7 +1007,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Izmantot atkopšanās frāzveida paroli vai atslēgu Izmantojiet citu sesiju šis sesijas verifikācijai, tādējādi dodot piekļuvi šifrētām ziņām. Iespējot šifrēšanu - Pēc iespējošanas šifrēšana istabai nevar tikt izslēgta. Šifrētā istabā sūtītas ziņas nav redzamas serverim, tikai istabas dalībniekiem. Šifrēšanas iespējošana var neļaut pareizi strādāt daudzus botiem un tiltiem. + Tiklīdz iespējots, istabas šifrēšanu nevar atspējot. Šifrētā istabā sūtītas ziņas nav redzamas serverim, tikai istabas dalībniekiem. Šifrēšanas iespējošana var neļaut pareizi strādāt daudzām robotprogrammatūrām un tiltiem. Jums nav atļaujas, lai iespējotu šifrēšanu šajā istabā. Viena persona @@ -1387,11 +1387,11 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Lūdzu ievadiet paroli. Lūdzu ievadiet lietotājvārdu. Lūdzu aizmirst visas ziņas, ko esmu nosūtījis, kad mans konts ir deaktivizēts (Brīdinājums: šis nākotnes lietotājiem neļaus redzēt visu sarunu kontekstu) - Tas padarīs jūsu kontu nelietojamu. Jūs nevarēsiet ierakstīties, un neviens nevarēs atkārtoti reģistrēt to pašu lietotāja ID. Tas liks jūsu kontu atstāt visas istabas, kurās piedalās, un tas noņems jūsu konta datus no jūsu identitātes servera. Šī darbība ir neatgriezeniska . + Tas padarīs kontu neizmantojamu. Nebūs iespējams pieteikties, un neviens nevarēs atkārtoti reģistrēties ar to pašu lietotāja identifikatoru. Tas liks kontam atstāt visas istabas, kurās piedalās, un tas noņems konta datus no identitātes servera. Šī darbība ir neatgriezeniska . \n -\nDeaktivizējot savu kontu , pēc noklusējuma, neliek mums aizmirst jūsu nosūtītās ziņas . Ja jūs vēlētos, lai mēs aizmirstu jūsu ziņas, lūdzu, atzīmējiet zemāk redzamo lodziņu. +\nKonta deaktivēšana pēc noklusējuma neliek mums aizmirst nosūtītās ziņas . Ja vēlme, lai mēs aizmirstu ziņas, lūgums atzīmēt zemāk esošo lodziņu. \n -\nZiņu redzamība Matrix ir līdzīga e-pastam. Mums aizmirst jūsu ziņas nozīmē, ka ziņas, ko esat nosūtījis, netiks rādītas jauniem vai nereģistrētiem lietotājiem, bet reģistrētiem lietotājiem, kuriem jau ir piekļuve šīm ziņām, joprojām būs piekļuve to kopijai. +\nZiņu redzamība Matrix ir līdzīga e-pastam. Ziņu aizmiršana nozīmē, ka nosūtītās ziņas netiks rādītas jauniem vai nereģistrētiem lietotājiem, bet reģistrētiem lietotājiem, kuriem jau ir piekļuve šīm ziņām, joprojām būs piekļuve to kopijai. Atslēgas Dalīšanās Pieprasījums Nav aktīvu logrīku Izmantot mikrofonu @@ -1399,7 +1399,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Bloķēt Visu Atļaut Šis logrīks vēlas izmantos tālāk norādītos resursus: - Iziet no pašreizējās konferences un pāriet uz citu\? + Pamest pašreizējo apspriedi un pārslēgties uz otru\? Atvainojiet, konferences zvani ar Jitsi netiek atbalstīti vecās ierīces (ierīces ar Android OS zem 6.0) Istabas ID Logrīka ID @@ -1661,7 +1661,7 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
Priekšskatīt failu pirms nosūtīšanas ${app_name} sinhronizēsies fonā periodiski, precīzi, noteiktā laikā (konfigurējams). \nTas ietekmēs radio un akumulatora izmantošanu, tiks parādīts pastāvīgs paziņojums par to, ka ${app_name} klausās notikumus. - Ja lietotājs kādu laiku atstāj ierīci atvienotu no tīkla un nekustīgu, ar izslēgtu ekrānu, ierīcē tiek ieslēgts dīkstāves režīms. Tas neļauj lietotnēm piekļūt tīklam un atliek to darbu izpildi, sinhronizāciju un standarta trauksmes signālus. + Ja lietotājs kādu laiku atstāj ierīci atvienotu no tīkla un nekustīgu, ar izslēgtu ekrānu, ierīcē tiek ieslēgts dīkstāves režīms. Tas neļauj lietotnēm piekļūt tīklam un atliek to darbu izpildi, sinhronizāciju un standarta brīdinājumus. Pakalpojums nesāksies, kad ierīce tiks restartēta, jūs nesaņemsiet paziņojumus, kamēr vismaz vienreiz nebūsiet atvēris ${app_name}. Lūdzu, noklikšķiniet uz paziņojuma. Ja paziņojums nav redzams, pārbaudiet sistēmas iestatījumus. @@ -2092,4 +2092,36 @@ Nākotnē šī pārbaudes procedūra plānota sarežģītāka.
\n \nJāņem vērā, ka šī darbība pārsāknēs lietotni, un tas var aizņemt kādu laiku.
- atsevišķi lietotāji atkal tiek ņemti vērā + Ne tagad + Skatīt pavedienus + Jā, apturēt + Pamest + h + Nākamais + Nepamest neko + Izmēģināt + Uzzināt vairāk + Skatīt istabā + Ievietot pavediena saiti starpliktuvē + Atspējot + Nekad nesūtīt šifrētas ziņas uz neapstiprinātām šīs istabas sesijām. + Izkārtojuma uzstādījumi + Rādīt nesenos + Kārtot pēc + Vienalga atteikties + Iespējot + Atlasīt visu + Noņemt visas atzīmes + Pamest istabu ar norādīto identifikatoru (vai pašreizējo istabu, ja tāda nav) + Pamest visu + Vai tiešām pamest %s\? + Serveris nav sasniedzams. Ja vienalga tiks veikta atteikšanās, šī ierīce netiks izdzēsta no ierīču saraksta, tādēļ nepieciešamības gadījumā tā ir noņemama citā klientā. + Tu šeit esi vienīgais cilvēks. Ja pametīsi, neviens vairs nevarēs pievienoties, ieskaitot Tevi. + Aptauju vēsture + min. + sek. + Turpināt, lai atiestatītu + Skaidrs + Rādīt atlasītājus + Darbība \ No newline at end of file From 2a5df54ae42980924b659e72a4eafbfd484e0148 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 15 Jun 2023 14:15:06 +0200 Subject: [PATCH 201/234] Fix crash: show an error message with a Retry button when there is no network when displaying the BootstrapBottomSheet. --- .../crypto/recover/BootstrapActions.kt | 1 + .../crypto/recover/BootstrapBottomSheet.kt | 5 ++ .../crypto/recover/BootstrapErrorFragment.kt | 54 ++++++++++++++ .../recover/BootstrapSharedViewModel.kt | 71 ++++++++++++------- .../features/crypto/recover/BootstrapStep.kt | 2 + .../res/layout/fragment_bootstrap_error.xml | 33 +++++++++ 6 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapErrorFragment.kt create mode 100644 vector/src/main/res/layout/fragment_bootstrap_error.xml diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapActions.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapActions.kt index 395b4d0475..fd61bdd5dd 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapActions.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapActions.kt @@ -20,6 +20,7 @@ import im.vector.app.core.platform.VectorViewModelAction import java.io.OutputStream sealed class BootstrapActions : VectorViewModelAction { + object Retry : BootstrapActions() // Navigation diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt index be02737ef8..586f60beaf 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt @@ -212,6 +212,11 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment { + views.bootstrapIcon.isVisible = true + views.bootstrapTitleText.text = getString(R.string.bottom_sheet_setup_secure_backup_title) + showFragment(BootstrapErrorFragment::class) + } } super.invalidate() } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapErrorFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapErrorFragment.kt new file mode 100644 index 0000000000..26b29d449a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapErrorFragment.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.crypto.recover + +import android.view.LayoutInflater +import android.view.ViewGroup +import com.airbnb.mvrx.parentFragmentViewModel +import com.airbnb.mvrx.withState +import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.R +import im.vector.app.core.epoxy.onClick +import im.vector.app.core.extensions.setTextOrHide +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentBootstrapErrorBinding + +@AndroidEntryPoint +class BootstrapErrorFragment : + VectorBaseFragment() { + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentBootstrapErrorBinding { + return FragmentBootstrapErrorBinding.inflate(inflater, container, false) + } + + val sharedViewModel: BootstrapSharedViewModel by parentFragmentViewModel() + + override fun invalidate() = withState(sharedViewModel) { state -> + when (state.step) { + is BootstrapStep.Error -> { + views.bootstrapDescriptionText.setTextOrHide(errorFormatter.toHumanReadable(state.step.error)) + } + else -> { + // Should not happen, show a generic error + views.bootstrapDescriptionText.setTextOrHide(getString(R.string.unknown_error)) + } + } + views.bootstrapRetryButton.onClick { + sharedViewModel.handle(BootstrapActions.Retry) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt index b3d83b948b..c9c2c5ce9a 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt @@ -54,6 +54,7 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromR import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth +import timber.log.Timber import java.io.OutputStream import kotlin.coroutines.Continuation import kotlin.coroutines.resumeWithException @@ -118,37 +119,48 @@ class BootstrapSharedViewModel @AssistedInject constructor( } } SetupMode.NORMAL -> { - // need to check if user have an existing keybackup - setState { - copy(step = BootstrapStep.CheckingMigration) - } + checkMigration() + } + } + } + + private fun checkMigration() { + // need to check if user have an existing keybackup + setState { + copy(step = BootstrapStep.CheckingMigration) + } - // We need to check if there is an existing backup - viewModelScope.launch(Dispatchers.IO) { - val version = tryOrNull { session.cryptoService().keysBackupService().getCurrentVersion() }?.toKeysVersionResult() - if (version == null) { - // we just resume plain bootstrap - doesKeyBackupExist = false + // We need to check if there is an existing backup + viewModelScope.launch(Dispatchers.IO) { + try { + val version = tryOrNull { session.cryptoService().keysBackupService().getCurrentVersion() }?.toKeysVersionResult() + if (version == null) { + // we just resume plain bootstrap + doesKeyBackupExist = false + setState { + copy(step = BootstrapStep.FirstForm(keyBackUpExist = doesKeyBackupExist, methods = this.secureBackupMethod)) + } + } else { + // we need to get existing backup passphrase/key and convert to SSSS + val keyVersion = tryOrNull { + session.cryptoService().keysBackupService().getVersion(version.version) + } + if (keyVersion == null) { + // strange case... just finish? + _viewEvents.post(BootstrapViewEvents.Dismiss(false)) + } else { + doesKeyBackupExist = true + isBackupCreatedFromPassphrase = keyVersion.getAuthDataAsMegolmBackupAuthData()?.privateKeySalt != null setState { copy(step = BootstrapStep.FirstForm(keyBackUpExist = doesKeyBackupExist, methods = this.secureBackupMethod)) } - } else { - // we need to get existing backup passphrase/key and convert to SSSS - val keyVersion = tryOrNull { - session.cryptoService().keysBackupService().getVersion(version.version) - } - if (keyVersion == null) { - // strange case... just finish? - _viewEvents.post(BootstrapViewEvents.Dismiss(false)) - } else { - doesKeyBackupExist = true - isBackupCreatedFromPassphrase = keyVersion.getAuthDataAsMegolmBackupAuthData()?.privateKeySalt != null - setState { - copy(step = BootstrapStep.FirstForm(keyBackUpExist = doesKeyBackupExist, methods = this.secureBackupMethod)) - } - } } } + } catch (failure: Throwable) { + Timber.e(failure, "Error while checking key backup") + setState { + copy(step = BootstrapStep.Error(failure)) + } } } } @@ -268,6 +280,9 @@ class BootstrapSharedViewModel @AssistedInject constructor( copy(step = BootstrapStep.AccountReAuth(stringProvider.getString(R.string.authentication_error))) } } + BootstrapActions.Retry -> { + checkMigration() + } } } @@ -568,6 +583,12 @@ class BootstrapSharedViewModel @AssistedInject constructor( ) } } + is BootstrapStep.Error -> { + // do we let you cancel from here? + if (state.canLeave) { + _viewEvents.post(BootstrapViewEvents.SkipBootstrap(state.passphrase != null)) + } + } } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapStep.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapStep.kt index 3975f0e9a2..b807acc0ba 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapStep.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapStep.kt @@ -105,6 +105,8 @@ sealed class BootstrapStep { object Initializing : BootstrapStep() data class SaveRecoveryKey(val isSaved: Boolean) : BootstrapStep() object DoneSuccess : BootstrapStep() + + data class Error(val error: Throwable) : BootstrapStep() } fun BootstrapStep.GetBackupSecretForMigration.useKey(): Boolean { diff --git a/vector/src/main/res/layout/fragment_bootstrap_error.xml b/vector/src/main/res/layout/fragment_bootstrap_error.xml new file mode 100644 index 0000000000..02c944fed2 --- /dev/null +++ b/vector/src/main/res/layout/fragment_bootstrap_error.xml @@ -0,0 +1,33 @@ + + + + + +